oc-dialogs.js 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /**
  2. * ownCloud
  3. *
  4. * @author Bartek Przybylski, Christopher Schäpers, Thomas Tanghus
  5. * @copyright 2012 Bartek Przybylski bartek@alefzero.eu
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
  9. * License as published by the Free Software Foundation; either
  10. * version 3 of the License, or any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
  16. *
  17. * You should have received a copy of the GNU Affero General Public
  18. * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  19. *
  20. */
  21. /**
  22. * this class to ease the usage of jquery dialogs
  23. */
  24. var OCdialogs = {
  25. // dialog button types
  26. YES_NO_BUTTONS: 70,
  27. OK_BUTTONS: 71,
  28. // used to name each dialog
  29. dialogs_counter: 0,
  30. /**
  31. * displays alert dialog
  32. * @param text content of dialog
  33. * @param title dialog title
  34. * @param callback which will be triggered when user presses OK
  35. * @param modal make the dialog modal
  36. */
  37. alert:function(text, title, callback, modal) {
  38. this.message(text, title, 'alert', OCdialogs.OK_BUTTON, callback, modal);
  39. },
  40. /**
  41. * displays info dialog
  42. * @param text content of dialog
  43. * @param title dialog title
  44. * @param callback which will be triggered when user presses OK
  45. * @param modal make the dialog modal
  46. */
  47. info:function(text, title, callback, modal) {
  48. this.message(text, title, 'info', OCdialogs.OK_BUTTON, callback, modal);
  49. },
  50. /**
  51. * displays confirmation dialog
  52. * @param text content of dialog
  53. * @param title dialog title
  54. * @param callback which will be triggered when user presses YES or NO (true or false would be passed to callback respectively)
  55. * @param modal make the dialog modal
  56. */
  57. confirm:function(text, title, callback, modal) {
  58. this.message(text, title, 'notice', OCdialogs.YES_NO_BUTTONS, callback, modal);
  59. },
  60. /**
  61. * show a file picker to pick a file from
  62. * @param title dialog title
  63. * @param callback which will be triggered when user presses Choose
  64. * @param multiselect whether it should be possible to select multiple files
  65. * @param mimetype_filter mimetype to filter by
  66. * @param modal make the dialog modal
  67. */
  68. filepicker:function(title, callback, multiselect, mimetype_filter, modal) {
  69. var self = this;
  70. $.when(this._getFilePickerTemplate()).then(function($tmpl) {
  71. var dialog_name = 'oc-dialog-filepicker-content';
  72. var dialog_id = '#' + dialog_name;
  73. if(self.$filePicker) {
  74. self.$filePicker.ocdialog('close');
  75. }
  76. self.$filePicker = $tmpl.octemplate({
  77. dialog_name: dialog_name,
  78. title: title
  79. }).data('path', '');
  80. if (modal === undefined) { modal = false };
  81. if (multiselect === undefined) { multiselect = false };
  82. if (mimetype_filter === undefined) { mimetype_filter = '' };
  83. $('body').append(self.$filePicker);
  84. self.$filePicker.ready(function() {
  85. self.$filelist = self.$filePicker.find('.filelist');
  86. self.$dirTree = self.$filePicker.find('.dirtree');
  87. self.$dirTree.on('click', 'span:not(:last-child)', self, self._handleTreeListSelect);
  88. self.$filelist.on('click', 'li', function(event) {
  89. self._handlePickerClick(event, $(this));
  90. });
  91. self._fillFilePicker('');
  92. }).data('multiselect', multiselect).data('mimetype',mimetype_filter);
  93. // build buttons
  94. var functionToCall = function() {
  95. if (callback !== undefined) {
  96. var datapath;
  97. if (multiselect === true) {
  98. datapath = [];
  99. self.$filelist.find('.filepicker_element_selected .filename').each(function(index, element) {
  100. datapath.push(self.$filePicker.data('path') + '/' + $(element).text());
  101. });
  102. } else {
  103. var datapath = self.$filePicker.data('path');
  104. datapath += '/' + self.$filelist.find('.filepicker_element_selected .filename').text();
  105. }
  106. callback(datapath);
  107. self.$filePicker.ocdialog('close');
  108. }
  109. };
  110. var buttonlist = [{
  111. text: t('core', 'Choose'),
  112. click: functionToCall,
  113. defaultButton: true
  114. },
  115. {
  116. text: t('core', 'Cancel'),
  117. click: function(){self.$filePicker.ocdialog('close'); }
  118. }];
  119. self.$filePicker.ocdialog({
  120. closeOnEscape: true,
  121. width: (4/9)*$(document).width(),
  122. height: 420,
  123. modal: modal,
  124. buttons: buttonlist,
  125. close: function(event, ui) {
  126. try {
  127. $(this).ocdialog('destroy').remove();
  128. } catch(e) {}
  129. self.$filePicker = null;
  130. }
  131. });
  132. })
  133. .fail(function() {
  134. alert(t('core', 'Error loading file picker template'));
  135. });
  136. },
  137. /**
  138. * Displays raw dialog
  139. * You better use a wrapper instead ...
  140. */
  141. message:function(content, title, dialog_type, buttons, callback, modal) {
  142. $.when(this._getMessageTemplate()).then(function($tmpl) {
  143. var dialog_name = 'oc-dialog-' + OCdialogs.dialogs_counter + '-content';
  144. var dialog_id = '#' + dialog_name;
  145. var $dlg = $tmpl.octemplate({
  146. dialog_name: dialog_name,
  147. title: title,
  148. message: content,
  149. type: dialog_type
  150. });
  151. if (modal === undefined) { modal = false };
  152. $('body').append($dlg);
  153. var buttonlist = [];
  154. switch (buttons) {
  155. case OCdialogs.YES_NO_BUTTONS:
  156. buttonlist = [{
  157. text: t('core', 'Yes'),
  158. click: function(){
  159. if (callback !== undefined) { callback(true) };
  160. $(dialog_id).ocdialog('close');
  161. },
  162. defaultButton: true
  163. },
  164. {
  165. text: t('core', 'No'),
  166. click: function(){
  167. if (callback !== undefined) { callback(false) };
  168. $(dialog_id).ocdialog('close');
  169. }
  170. }];
  171. break;
  172. case OCdialogs.OK_BUTTON:
  173. var functionToCall = function() {
  174. $(dialog_id).ocdialog('close');
  175. if(callback !== undefined) { callback() };
  176. };
  177. buttonlist[0] = {
  178. text: t('core', 'Ok'),
  179. click: functionToCall,
  180. defaultButton: true
  181. };
  182. break;
  183. };
  184. $(dialog_id).ocdialog({
  185. closeOnEscape: true,
  186. modal: modal,
  187. buttons: buttonlist
  188. });
  189. OCdialogs.dialogs_counter++;
  190. })
  191. .fail(function() {
  192. alert(t('core', 'Error loading file picker template'));
  193. });
  194. },
  195. _getFilePickerTemplate: function() {
  196. var defer = $.Deferred();
  197. if(!this.$filePickerTemplate) {
  198. var self = this;
  199. $.get(OC.filePath('core', 'templates', 'filepicker.html'), function(tmpl) {
  200. self.$filePickerTemplate = $(tmpl);
  201. self.$listTmpl = self.$filePickerTemplate.find('.filelist li:first-child').detach();
  202. defer.resolve(self.$filePickerTemplate);
  203. })
  204. .fail(function() {
  205. defer.reject();
  206. });
  207. } else {
  208. defer.resolve(this.$filePickerTemplate);
  209. }
  210. return defer.promise();
  211. },
  212. _getMessageTemplate: function() {
  213. var defer = $.Deferred();
  214. if(!this.$messageTemplate) {
  215. var self = this;
  216. $.get(OC.filePath('core', 'templates', 'message.html'), function(tmpl) {
  217. self.$messageTemplate = $(tmpl);
  218. defer.resolve(self.$messageTemplate);
  219. })
  220. .fail(function() {
  221. defer.reject();
  222. });
  223. } else {
  224. defer.resolve(this.$messageTemplate);
  225. }
  226. return defer.promise();
  227. },
  228. _getFileList: function(dir, mimeType) {
  229. return $.getJSON(
  230. OC.filePath('files', 'ajax', 'rawlist.php'),
  231. {dir: dir, mimetype: mimeType}
  232. );
  233. },
  234. _determineValue: function(element) {
  235. if ( $(element).attr('type') === 'checkbox' ) {
  236. return element.checked;
  237. } else {
  238. return $(element).val();
  239. }
  240. },
  241. /**
  242. * fills the filepicker with files
  243. */
  244. _fillFilePicker:function(dir) {
  245. var dirs = [];
  246. var others = [];
  247. var self = this;
  248. this.$filelist.empty().addClass('loading');
  249. this.$filePicker.data('path', dir);
  250. $.when(this._getFileList(dir, this.$filePicker.data('mimetype'))).then(function(response) {
  251. $.each(response.data, function(index, file) {
  252. if (file.type === 'dir') {
  253. dirs.push(file);
  254. } else {
  255. others.push(file);
  256. }
  257. });
  258. self._fillSlug();
  259. var sorted = dirs.concat(others);
  260. $.each(sorted, function(idx, entry) {
  261. $li = self.$listTmpl.octemplate({
  262. type: entry.type,
  263. dir: dir,
  264. filename: entry.name,
  265. date: OC.mtime2date(entry.mtime)
  266. });
  267. $li.find('img').attr('src', entry.mimetype_icon);
  268. self.$filelist.append($li);
  269. });
  270. self.$filelist.removeClass('loading');
  271. });
  272. },
  273. /**
  274. * fills the tree list with directories
  275. */
  276. _fillSlug: function() {
  277. this.$dirTree.empty();
  278. var self = this
  279. var path = this.$filePicker.data('path');
  280. var $template = $('<span data-dir="{dir}">{name}</span>');
  281. if(path) {
  282. var paths = path.split('/');
  283. $.each(paths, function(index, dir) {
  284. var dir = paths.pop();
  285. if(dir === '') {
  286. return false;
  287. }
  288. self.$dirTree.prepend($template.octemplate({
  289. dir: paths.join('/') + '/' + dir,
  290. name: dir
  291. }));
  292. });
  293. }
  294. $template.octemplate({
  295. dir: '',
  296. name: '&nbsp;&nbsp;&nbsp;&nbsp;' // Ugly but works ;)
  297. }, {escapeFunction: null}).addClass('home svg').prependTo(this.$dirTree);
  298. },
  299. /**
  300. * handle selection made in the tree list
  301. */
  302. _handleTreeListSelect:function(event) {
  303. var self = event.data;
  304. var dir = $(event.target).data('dir');
  305. self._fillFilePicker(dir);
  306. },
  307. /**
  308. * handle clicks made in the filepicker
  309. */
  310. _handlePickerClick:function(event, $element) {
  311. if ($element.data('type') === 'file') {
  312. if (this.$filePicker.data('multiselect') !== true || !event.ctrlKey) {
  313. this.$filelist.find('.filepicker_element_selected').removeClass('filepicker_element_selected');
  314. }
  315. $element.toggleClass('filepicker_element_selected');
  316. return;
  317. } else if ( $element.data('type') === 'dir' ) {
  318. this._fillFilePicker(this.$filePicker.data('path') + '/' + $element.data('entryname'))
  319. }
  320. }
  321. };