dialogs.js 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272
  1. /* global alert */
  2. /* eslint-disable */
  3. /*
  4. * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
  5. * @copyright Copyright (c) 2019 Gary Kim <gary@garykim.dev>
  6. *
  7. * @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
  8. * @author Gary Kim <gary@garykim.dev>
  9. *
  10. * @license GNU AGPL version 3 or any later version
  11. *
  12. * This program is free software: you can redistribute it and/or modify
  13. * it under the terms of the GNU Affero General Public License as
  14. * published by the Free Software Foundation, either version 3 of the
  15. * License, or (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU Affero General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU Affero General Public License
  23. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  24. */
  25. import _ from 'underscore'
  26. import $ from 'jquery'
  27. import OC from './index'
  28. import OCA from '../OCA/index'
  29. /**
  30. * this class to ease the usage of jquery dialogs
  31. */
  32. const Dialogs = {
  33. // dialog button types
  34. YES_NO_BUTTONS: 70,
  35. OK_BUTTONS: 71,
  36. FILEPICKER_TYPE_CHOOSE: 1,
  37. FILEPICKER_TYPE_MOVE: 2,
  38. FILEPICKER_TYPE_COPY: 3,
  39. FILEPICKER_TYPE_COPY_MOVE: 4,
  40. // used to name each dialog
  41. dialogsCounter: 0,
  42. /**
  43. * displays alert dialog
  44. * @param {string} text content of dialog
  45. * @param {string} title dialog title
  46. * @param {function} callback which will be triggered when user presses OK
  47. * @param {boolean} [modal] make the dialog modal
  48. */
  49. alert: function(text, title, callback, modal) {
  50. this.message(
  51. text,
  52. title,
  53. 'alert',
  54. Dialogs.OK_BUTTON,
  55. callback,
  56. modal
  57. )
  58. },
  59. /**
  60. * displays info dialog
  61. * @param {string} text content of dialog
  62. * @param {string} title dialog title
  63. * @param {function} callback which will be triggered when user presses OK
  64. * @param {boolean} [modal] make the dialog modal
  65. */
  66. info: function(text, title, callback, modal) {
  67. this.message(text, title, 'info', Dialogs.OK_BUTTON, callback, modal)
  68. },
  69. /**
  70. * displays confirmation dialog
  71. * @param {string} text content of dialog
  72. * @param {string} title dialog title
  73. * @param {function} callback which will be triggered when user presses OK (true or false would be passed to callback respectively)
  74. * @param {boolean} [modal] make the dialog modal
  75. * @returns {Promise}
  76. */
  77. confirm: function(text, title, callback, modal) {
  78. return this.message(
  79. text,
  80. title,
  81. 'notice',
  82. Dialogs.YES_NO_BUTTONS,
  83. callback,
  84. modal
  85. )
  86. },
  87. /**
  88. * displays confirmation dialog
  89. * @param {string} text content of dialog
  90. * @param {string} title dialog title
  91. * @param {{type: Int, confirm: String, cancel: String, confirmClasses: String}} buttons text content of buttons
  92. * @param {function} callback which will be triggered when user presses OK (true or false would be passed to callback respectively)
  93. * @param {boolean} [modal] make the dialog modal
  94. * @returns {Promise}
  95. */
  96. confirmDestructive: function(text, title, buttons, callback, modal) {
  97. return this.message(
  98. text,
  99. title,
  100. 'none',
  101. buttons,
  102. callback,
  103. modal
  104. )
  105. },
  106. /**
  107. * displays confirmation dialog
  108. * @param {string} text content of dialog
  109. * @param {string} title dialog title
  110. * @param {function} callback which will be triggered when user presses OK (true or false would be passed to callback respectively)
  111. * @param {boolean} [modal] make the dialog modal
  112. * @returns {Promise}
  113. */
  114. confirmHtml: function(text, title, callback, modal) {
  115. return this.message(
  116. text,
  117. title,
  118. 'notice',
  119. Dialogs.YES_NO_BUTTONS,
  120. callback,
  121. modal,
  122. true
  123. )
  124. },
  125. /**
  126. * displays prompt dialog
  127. * @param {string} text content of dialog
  128. * @param {string} title dialog title
  129. * @param {function} callback which will be triggered when user presses OK (true or false would be passed to callback respectively)
  130. * @param {boolean} [modal] make the dialog modal
  131. * @param {string} name name of the input field
  132. * @param {boolean} password whether the input should be a password input
  133. * @returns {Promise}
  134. */
  135. prompt: function(text, title, callback, modal, name, password) {
  136. return $.when(this._getMessageTemplate()).then(function($tmpl) {
  137. var dialogName = 'oc-dialog-' + Dialogs.dialogsCounter + '-content'
  138. var dialogId = '#' + dialogName
  139. var $dlg = $tmpl.octemplate({
  140. dialog_name: dialogName,
  141. title: title,
  142. message: text,
  143. type: 'notice'
  144. })
  145. var input = $('<input/>')
  146. input.attr('type', password ? 'password' : 'text').attr('id', dialogName + '-input').attr('placeholder', name)
  147. var label = $('<label/>').attr('for', dialogName + '-input').text(name + ': ')
  148. $dlg.append(label)
  149. $dlg.append(input)
  150. if (modal === undefined) {
  151. modal = false
  152. }
  153. $('body').append($dlg)
  154. // wrap callback in _.once():
  155. // only call callback once and not twice (button handler and close
  156. // event) but call it for the close event, if ESC or the x is hit
  157. if (callback !== undefined) {
  158. callback = _.once(callback)
  159. }
  160. var buttonlist = [{
  161. text: t('core', 'No'),
  162. click: function() {
  163. if (callback !== undefined) {
  164. // eslint-disable-next-line standard/no-callback-literal
  165. callback(false, input.val())
  166. }
  167. $(dialogId).ocdialog('close')
  168. }
  169. }, {
  170. text: t('core', 'Yes'),
  171. click: function() {
  172. if (callback !== undefined) {
  173. // eslint-disable-next-line standard/no-callback-literal
  174. callback(true, input.val())
  175. }
  176. $(dialogId).ocdialog('close')
  177. },
  178. defaultButton: true
  179. }]
  180. $(dialogId).ocdialog({
  181. closeOnEscape: true,
  182. modal: modal,
  183. buttons: buttonlist,
  184. close: function() {
  185. // callback is already fired if Yes/No is clicked directly
  186. if (callback !== undefined) {
  187. // eslint-disable-next-line standard/no-callback-literal
  188. callback(false, input.val())
  189. }
  190. }
  191. })
  192. input.focus()
  193. Dialogs.dialogsCounter++
  194. })
  195. },
  196. /**
  197. * show a file picker to pick a file from
  198. *
  199. * In order to pick several types of mime types they need to be passed as an
  200. * array of strings.
  201. *
  202. * When no mime type filter is given only files can be selected. In order to
  203. * be able to select both files and folders "['*', 'httpd/unix-directory']"
  204. * should be used instead.
  205. *
  206. * @param {string} title dialog title
  207. * @param {function} callback which will be triggered when user presses Choose
  208. * @param {boolean} [multiselect] whether it should be possible to select multiple files
  209. * @param {string[]} [mimetypeFilter] mimetype to filter by - directories will always be included
  210. * @param {boolean} [modal] make the dialog modal
  211. * @param {string} [type] Type of file picker : Choose, copy, move, copy and move
  212. * @param {string} [path] path to the folder that the the file can be picket from
  213. * @param {Object} [options] additonal options that need to be set
  214. */
  215. filepicker: function(title, callback, multiselect, mimetypeFilter, modal, type, path, options) {
  216. var self = this
  217. this.filepicker.sortField = 'name'
  218. this.filepicker.sortOrder = 'asc'
  219. // avoid opening the picker twice
  220. if (this.filepicker.loading) {
  221. return
  222. }
  223. if (type === undefined) {
  224. type = this.FILEPICKER_TYPE_CHOOSE
  225. }
  226. var emptyText = t('core', 'No files in here')
  227. var newText = t('files', 'New folder')
  228. if (type === this.FILEPICKER_TYPE_COPY || type === this.FILEPICKER_TYPE_MOVE || type === this.FILEPICKER_TYPE_COPY_MOVE) {
  229. emptyText = t('core', 'No more subfolders in here')
  230. }
  231. this.filepicker.loading = true
  232. this.filepicker.filesClient = (OCA.Sharing && OCA.Sharing.PublicApp && OCA.Sharing.PublicApp.fileList) ? OCA.Sharing.PublicApp.fileList.filesClient : OC.Files.getClient()
  233. this.filelist = null
  234. path = path || ''
  235. options = Object.assign({
  236. allowDirectoryChooser: false
  237. }, options)
  238. $.when(this._getFilePickerTemplate()).then(function($tmpl) {
  239. self.filepicker.loading = false
  240. var dialogName = 'oc-dialog-filepicker-content'
  241. if (self.$filePicker) {
  242. self.$filePicker.ocdialog('close')
  243. }
  244. if (mimetypeFilter === undefined || mimetypeFilter === null) {
  245. mimetypeFilter = []
  246. }
  247. if (typeof (mimetypeFilter) === 'string') {
  248. mimetypeFilter = [mimetypeFilter]
  249. }
  250. self.$filePicker = $tmpl.octemplate({
  251. dialog_name: dialogName,
  252. title: title,
  253. emptytext: emptyText,
  254. newtext: newText,
  255. nameCol: t('core', 'Name'),
  256. sizeCol: t('core', 'Size'),
  257. modifiedCol: t('core', 'Modified')
  258. }).data('path', path).data('multiselect', multiselect).data('mimetype', mimetypeFilter).data('allowDirectoryChooser', options.allowDirectoryChooser)
  259. if (modal === undefined) {
  260. modal = false
  261. }
  262. if (multiselect === undefined) {
  263. multiselect = false
  264. }
  265. // No grid for IE!
  266. if (OC.Util.isIE()) {
  267. self.$filePicker.find('#picker-view-toggle').remove()
  268. self.$filePicker.find('#picker-filestable').removeClass('view-grid')
  269. }
  270. $('body').append(self.$filePicker)
  271. self.$showGridView = $('input#picker-showgridview')
  272. self.$showGridView.on('change', _.bind(self._onGridviewChange, self))
  273. if (!OC.Util.isIE()) {
  274. self._getGridSettings()
  275. }
  276. var newButton = self.$filePicker.find('.actions.creatable .button-add')
  277. if (type === self.FILEPICKER_TYPE_CHOOSE) {
  278. newButton.hide()
  279. }
  280. newButton.on('focus', function() {
  281. self.$filePicker.ocdialog('setEnterCallback', function() {
  282. event.stopImmediatePropagation()
  283. event.preventDefault()
  284. newButton.click()
  285. })
  286. })
  287. newButton.on('blur', function() {
  288. self.$filePicker.ocdialog('unsetEnterCallback')
  289. })
  290. OC.registerMenu(newButton, self.$filePicker.find('.menu'), function() {
  291. $input.focus()
  292. self.$filePicker.ocdialog('setEnterCallback', function() {
  293. event.stopImmediatePropagation()
  294. event.preventDefault()
  295. self.$form.submit()
  296. })
  297. var newName = $input.val()
  298. var lastPos = newName.lastIndexOf('.')
  299. if (lastPos === -1) {
  300. lastPos = newName.length
  301. }
  302. $input.selectRange(0, lastPos)
  303. })
  304. var $form = self.$filePicker.find('.filenameform')
  305. var $input = $form.find('input[type=\'text\']')
  306. var $submit = $form.find('input[type=\'submit\']')
  307. $submit.on('click', function(event) {
  308. event.stopImmediatePropagation()
  309. event.preventDefault()
  310. $form.submit()
  311. })
  312. var checkInput = function() {
  313. var filename = $input.val()
  314. try {
  315. if (!Files.isFileNameValid(filename)) {
  316. // Files.isFileNameValid(filename) throws an exception itself
  317. } else if (self.filelist.find(function(file) {
  318. return file.name === this
  319. }, filename)) {
  320. throw t('files', '{newName} already exists', { newName: filename }, undefined, {
  321. escape: false
  322. })
  323. } else {
  324. return true
  325. }
  326. } catch (error) {
  327. $input.attr('title', error)
  328. $input.tooltip({
  329. placement: 'right',
  330. trigger: 'manual',
  331. 'container': '.newFolderMenu'
  332. })
  333. $input.tooltip('fixTitle')
  334. $input.tooltip('show')
  335. $input.addClass('error')
  336. }
  337. return false
  338. }
  339. $form.on('submit', function(event) {
  340. event.stopPropagation()
  341. event.preventDefault()
  342. if (checkInput()) {
  343. var newname = $input.val()
  344. self.filepicker.filesClient.createDirectory(self.$filePicker.data('path') + "/" + newname).always(function (status) {
  345. self._fillFilePicker(self.$filePicker.data('path') + "/" + newname)
  346. })
  347. OC.hideMenus()
  348. self.$filePicker.ocdialog('unsetEnterCallback')
  349. self.$filePicker.click()
  350. $input.val(newText)
  351. }
  352. })
  353. $input.keypress(function(event) {
  354. if (event.keyCode === 13 || event.which === 13) {
  355. event.stopImmediatePropagation()
  356. event.preventDefault()
  357. $form.submit()
  358. }
  359. })
  360. self.$filePicker.ready(function() {
  361. self.$fileListHeader = self.$filePicker.find('.filelist thead tr')
  362. self.$filelist = self.$filePicker.find('.filelist tbody')
  363. self.$filelistContainer = self.$filePicker.find('.filelist-container')
  364. self.$dirTree = self.$filePicker.find('.dirtree')
  365. self.$dirTree.on('click', 'div:not(:last-child)', self, function(event) {
  366. self._handleTreeListSelect(event, type)
  367. })
  368. self.$filelist.on('click', 'tr', function(event) {
  369. self._handlePickerClick(event, $(this), type)
  370. })
  371. self.$fileListHeader.on('click', 'a', function(event) {
  372. var dir = self.$filePicker.data('path')
  373. self.filepicker.sortField = $(event.currentTarget).data('sort')
  374. self.filepicker.sortOrder = self.filepicker.sortOrder === 'asc' ? 'desc' : 'asc'
  375. self._fillFilePicker(dir)
  376. })
  377. self._fillFilePicker(path)
  378. })
  379. // build buttons
  380. var functionToCall = function(returnType) {
  381. if (callback !== undefined) {
  382. var datapath
  383. if (multiselect === true) {
  384. datapath = []
  385. self.$filelist.find('tr.filepicker_element_selected').each(function(index, element) {
  386. datapath.push(self.$filePicker.data('path') + '/' + $(element).data('entryname'))
  387. })
  388. } else {
  389. datapath = self.$filePicker.data('path')
  390. var selectedName = self.$filelist.find('tr.filepicker_element_selected').data('entryname')
  391. if (selectedName) {
  392. datapath += '/' + selectedName
  393. }
  394. }
  395. callback(datapath, returnType)
  396. self.$filePicker.ocdialog('close')
  397. }
  398. }
  399. var chooseCallback = function() {
  400. functionToCall(Dialogs.FILEPICKER_TYPE_CHOOSE)
  401. }
  402. var copyCallback = function() {
  403. functionToCall(Dialogs.FILEPICKER_TYPE_COPY)
  404. }
  405. var moveCallback = function() {
  406. functionToCall(Dialogs.FILEPICKER_TYPE_MOVE)
  407. }
  408. var buttonlist = []
  409. if (type === Dialogs.FILEPICKER_TYPE_CHOOSE) {
  410. buttonlist.push({
  411. text: t('core', 'Choose'),
  412. click: chooseCallback,
  413. defaultButton: true
  414. })
  415. } else {
  416. if (type === Dialogs.FILEPICKER_TYPE_COPY || type === Dialogs.FILEPICKER_TYPE_COPY_MOVE) {
  417. buttonlist.push({
  418. text: t('core', 'Copy'),
  419. click: copyCallback,
  420. defaultButton: false
  421. })
  422. }
  423. if (type === Dialogs.FILEPICKER_TYPE_MOVE || type === Dialogs.FILEPICKER_TYPE_COPY_MOVE) {
  424. buttonlist.push({
  425. text: t('core', 'Move'),
  426. click: moveCallback,
  427. defaultButton: true
  428. })
  429. }
  430. }
  431. self.$filePicker.ocdialog({
  432. closeOnEscape: true,
  433. // max-width of 600
  434. width: 600,
  435. height: 500,
  436. modal: modal,
  437. buttons: buttonlist,
  438. style: {
  439. buttons: 'aside'
  440. },
  441. close: function() {
  442. try {
  443. $(this).ocdialog('destroy').remove()
  444. } catch (e) {
  445. }
  446. self.$filePicker = null
  447. }
  448. })
  449. // We can access primary class only from oc-dialog.
  450. // Hence this is one of the approach to get the choose button.
  451. var getOcDialog = self.$filePicker.closest('.oc-dialog')
  452. var buttonEnableDisable = getOcDialog.find('.primary')
  453. if (self.$filePicker.data('mimetype').indexOf('httpd/unix-directory') !== -1 || self.$filePicker.data('allowDirectoryChooser')) {
  454. buttonEnableDisable.prop('disabled', false)
  455. } else {
  456. buttonEnableDisable.prop('disabled', true)
  457. }
  458. })
  459. .fail(function(status, error) {
  460. // If the method is called while navigating away
  461. // from the page, it is probably not needed ;)
  462. self.filepicker.loading = false
  463. if (status !== 0) {
  464. alert(t('core', 'Error loading file picker template: {error}', { error: error }))
  465. }
  466. })
  467. },
  468. /**
  469. * Displays raw dialog
  470. * You better use a wrapper instead ...
  471. */
  472. message: function(content, title, dialogType, buttons, callback, modal, allowHtml) {
  473. return $.when(this._getMessageTemplate()).then(function($tmpl) {
  474. var dialogName = 'oc-dialog-' + Dialogs.dialogsCounter + '-content'
  475. var dialogId = '#' + dialogName
  476. var $dlg = $tmpl.octemplate({
  477. dialog_name: dialogName,
  478. title: title,
  479. message: content,
  480. type: dialogType
  481. }, allowHtml ? { escapeFunction: '' } : {})
  482. if (modal === undefined) {
  483. modal = false
  484. }
  485. $('body').append($dlg)
  486. var buttonlist = []
  487. switch (buttons) {
  488. case Dialogs.YES_NO_BUTTONS:
  489. buttonlist = [{
  490. text: t('core', 'No'),
  491. click: function() {
  492. if (callback !== undefined) {
  493. callback(false)
  494. }
  495. $(dialogId).ocdialog('close')
  496. }
  497. },
  498. {
  499. text: t('core', 'Yes'),
  500. click: function() {
  501. if (callback !== undefined) {
  502. callback(true)
  503. }
  504. $(dialogId).ocdialog('close')
  505. },
  506. defaultButton: true
  507. }]
  508. break
  509. case Dialogs.OK_BUTTON:
  510. var functionToCall = function() {
  511. $(dialogId).ocdialog('close')
  512. if (callback !== undefined) {
  513. callback()
  514. }
  515. }
  516. buttonlist[0] = {
  517. text: t('core', 'OK'),
  518. click: functionToCall,
  519. defaultButton: true
  520. }
  521. break
  522. default:
  523. if (typeof(buttons) === 'object') {
  524. switch (buttons.type) {
  525. case Dialogs.YES_NO_BUTTONS:
  526. buttonlist = [{
  527. text: buttons.cancel || t('core', 'No'),
  528. click: function() {
  529. if (callback !== undefined) {
  530. callback(false)
  531. }
  532. $(dialogId).ocdialog('close')
  533. }
  534. },
  535. {
  536. text: buttons.confirm || t('core', 'Yes'),
  537. click: function() {
  538. if (callback !== undefined) {
  539. callback(true)
  540. }
  541. $(dialogId).ocdialog('close')
  542. },
  543. defaultButton: true,
  544. classes: buttons.confirmClasses
  545. }]
  546. break
  547. }
  548. }
  549. break
  550. }
  551. $(dialogId).ocdialog({
  552. closeOnEscape: true,
  553. modal: modal,
  554. buttons: buttonlist
  555. })
  556. Dialogs.dialogsCounter++
  557. })
  558. .fail(function(status, error) {
  559. // If the method is called while navigating away from
  560. // the page, we still want to deliver the message.
  561. if (status === 0) {
  562. alert(title + ': ' + content)
  563. } else {
  564. alert(t('core', 'Error loading message template: {error}', { error: error }))
  565. }
  566. })
  567. },
  568. _fileexistsshown: false,
  569. /**
  570. * Displays file exists dialog
  571. * @param {object} data upload object
  572. * @param {object} original file with name, size and mtime
  573. * @param {object} replacement file with name, size and mtime
  574. * @param {object} controller with onCancel, onSkip, onReplace and onRename methods
  575. * @returns {Promise} jquery promise that resolves after the dialog template was loaded
  576. */
  577. fileexists: function(data, original, replacement, controller) {
  578. var self = this
  579. var dialogDeferred = new $.Deferred()
  580. var getCroppedPreview = function(file) {
  581. var deferred = new $.Deferred()
  582. // Only process image files.
  583. var type = file.type && file.type.split('/').shift()
  584. if (window.FileReader && type === 'image') {
  585. var reader = new FileReader()
  586. reader.onload = function(e) {
  587. var blob = new Blob([e.target.result])
  588. window.URL = window.URL || window.webkitURL
  589. var originalUrl = window.URL.createObjectURL(blob)
  590. var image = new Image()
  591. image.src = originalUrl
  592. image.onload = function() {
  593. var url = crop(image)
  594. deferred.resolve(url)
  595. }
  596. }
  597. reader.readAsArrayBuffer(file)
  598. } else {
  599. deferred.reject()
  600. }
  601. return deferred
  602. }
  603. var crop = function(img) {
  604. var canvas = document.createElement('canvas')
  605. var targetSize = 96
  606. var width = img.width
  607. var height = img.height
  608. var x; var y; var size
  609. // Calculate the width and height, constraining the proportions
  610. if (width > height) {
  611. y = 0
  612. x = (width - height) / 2
  613. } else {
  614. y = (height - width) / 2
  615. x = 0
  616. }
  617. size = Math.min(width, height)
  618. // Set canvas size to the cropped area
  619. canvas.width = size
  620. canvas.height = size
  621. var ctx = canvas.getContext('2d')
  622. ctx.drawImage(img, x, y, size, size, 0, 0, size, size)
  623. // Resize the canvas to match the destination (right size uses 96px)
  624. resampleHermite(canvas, size, size, targetSize, targetSize)
  625. return canvas.toDataURL('image/png', 0.7)
  626. }
  627. /**
  628. * Fast image resize/resample using Hermite filter with JavaScript.
  629. *
  630. * @author: ViliusL
  631. *
  632. * @param {*} canvas
  633. * @param {number} W
  634. * @param {number} H
  635. * @param {number} W2
  636. * @param {number} H2
  637. */
  638. var resampleHermite = function(canvas, W, H, W2, H2) {
  639. W2 = Math.round(W2)
  640. H2 = Math.round(H2)
  641. var img = canvas.getContext('2d').getImageData(0, 0, W, H)
  642. var img2 = canvas.getContext('2d').getImageData(0, 0, W2, H2)
  643. var data = img.data
  644. var data2 = img2.data
  645. var ratio_w = W / W2
  646. var ratio_h = H / H2
  647. var ratio_w_half = Math.ceil(ratio_w / 2)
  648. var ratio_h_half = Math.ceil(ratio_h / 2)
  649. for (var j = 0; j < H2; j++) {
  650. for (var i = 0; i < W2; i++) {
  651. var x2 = (i + j * W2) * 4
  652. var weight = 0
  653. var weights = 0
  654. var weights_alpha = 0
  655. var gx_r = 0
  656. var gx_g = 0
  657. var gx_b = 0
  658. var gx_a = 0
  659. var center_y = (j + 0.5) * ratio_h
  660. for (var yy = Math.floor(j * ratio_h); yy < (j + 1) * ratio_h; yy++) {
  661. var dy = Math.abs(center_y - (yy + 0.5)) / ratio_h_half
  662. var center_x = (i + 0.5) * ratio_w
  663. var w0 = dy * dy // pre-calc part of w
  664. for (var xx = Math.floor(i * ratio_w); xx < (i + 1) * ratio_w; xx++) {
  665. var dx = Math.abs(center_x - (xx + 0.5)) / ratio_w_half
  666. var w = Math.sqrt(w0 + dx * dx)
  667. if (w >= -1 && w <= 1) {
  668. // hermite filter
  669. weight = 2 * w * w * w - 3 * w * w + 1
  670. if (weight > 0) {
  671. dx = 4 * (xx + yy * W)
  672. // alpha
  673. gx_a += weight * data[dx + 3]
  674. weights_alpha += weight
  675. // colors
  676. if (data[dx + 3] < 255) { weight = weight * data[dx + 3] / 250 }
  677. gx_r += weight * data[dx]
  678. gx_g += weight * data[dx + 1]
  679. gx_b += weight * data[dx + 2]
  680. weights += weight
  681. }
  682. }
  683. }
  684. }
  685. data2[x2] = gx_r / weights
  686. data2[x2 + 1] = gx_g / weights
  687. data2[x2 + 2] = gx_b / weights
  688. data2[x2 + 3] = gx_a / weights_alpha
  689. }
  690. }
  691. canvas.getContext('2d').clearRect(0, 0, Math.max(W, W2), Math.max(H, H2))
  692. canvas.width = W2
  693. canvas.height = H2
  694. canvas.getContext('2d').putImageData(img2, 0, 0)
  695. }
  696. var addConflict = function($conflicts, original, replacement) {
  697. var $conflict = $conflicts.find('.template').clone().removeClass('template').addClass('conflict')
  698. var $originalDiv = $conflict.find('.original')
  699. var $replacementDiv = $conflict.find('.replacement')
  700. $conflict.data('data', data)
  701. $conflict.find('.filename').text(original.name)
  702. $originalDiv.find('.size').text(humanFileSize(original.size))
  703. $originalDiv.find('.mtime').text(formatDate(original.mtime))
  704. // ie sucks
  705. if (replacement.size && replacement.lastModifiedDate) {
  706. $replacementDiv.find('.size').text(humanFileSize(replacement.size))
  707. $replacementDiv.find('.mtime').text(formatDate(replacement.lastModifiedDate))
  708. }
  709. var path = original.directory + '/' + original.name
  710. var urlSpec = {
  711. file: path,
  712. x: 96,
  713. y: 96,
  714. c: original.etag,
  715. forceIcon: 0
  716. }
  717. var previewpath = Files.generatePreviewUrl(urlSpec)
  718. // Escaping single quotes
  719. previewpath = previewpath.replace(/'/g, '%27')
  720. $originalDiv.find('.icon').css({ 'background-image': "url('" + previewpath + "')" })
  721. getCroppedPreview(replacement).then(
  722. function(path) {
  723. $replacementDiv.find('.icon').css('background-image', 'url(' + path + ')')
  724. }, function() {
  725. path = OC.MimeType.getIconUrl(replacement.type)
  726. $replacementDiv.find('.icon').css('background-image', 'url(' + path + ')')
  727. }
  728. )
  729. // connect checkboxes with labels
  730. var checkboxId = $conflicts.find('.conflict').length
  731. $originalDiv.find('input:checkbox').attr('id', 'checkbox_original_' + checkboxId)
  732. $replacementDiv.find('input:checkbox').attr('id', 'checkbox_replacement_' + checkboxId)
  733. $conflicts.append($conflict)
  734. // set more recent mtime bold
  735. // ie sucks
  736. if (replacement.lastModifiedDate && replacement.lastModifiedDate.getTime() > original.mtime) {
  737. $replacementDiv.find('.mtime').css('font-weight', 'bold')
  738. } else if (replacement.lastModifiedDate && replacement.lastModifiedDate.getTime() < original.mtime) {
  739. $originalDiv.find('.mtime').css('font-weight', 'bold')
  740. } else {
  741. // TODO add to same mtime collection?
  742. }
  743. // set bigger size bold
  744. if (replacement.size && replacement.size > original.size) {
  745. $replacementDiv.find('.size').css('font-weight', 'bold')
  746. } else if (replacement.size && replacement.size < original.size) {
  747. $originalDiv.find('.size').css('font-weight', 'bold')
  748. } else {
  749. // TODO add to same size collection?
  750. }
  751. // TODO show skip action for files with same size and mtime in bottom row
  752. // always keep readonly files
  753. if (original.status === 'readonly') {
  754. $originalDiv
  755. .addClass('readonly')
  756. .find('input[type="checkbox"]')
  757. .prop('checked', true)
  758. .prop('disabled', true)
  759. $originalDiv.find('.message')
  760. .text(t('core', 'read-only'))
  761. }
  762. }
  763. // var selection = controller.getSelection(data.originalFiles);
  764. // if (selection.defaultAction) {
  765. // controller[selection.defaultAction](data);
  766. // } else {
  767. var dialogName = 'oc-dialog-fileexists-content'
  768. var dialogId = '#' + dialogName
  769. if (this._fileexistsshown) {
  770. // add conflict
  771. var $conflicts = $(dialogId + ' .conflicts')
  772. addConflict($conflicts, original, replacement)
  773. var count = $(dialogId + ' .conflict').length
  774. var title = n('core',
  775. '{count} file conflict',
  776. '{count} file conflicts',
  777. count,
  778. { count: count }
  779. )
  780. $(dialogId).parent().children('.oc-dialog-title').text(title)
  781. // recalculate dimensions
  782. $(window).trigger('resize')
  783. dialogDeferred.resolve()
  784. } else {
  785. // create dialog
  786. this._fileexistsshown = true
  787. $.when(this._getFileExistsTemplate()).then(function($tmpl) {
  788. var title = t('core', 'One file conflict')
  789. var $dlg = $tmpl.octemplate({
  790. dialog_name: dialogName,
  791. title: title,
  792. type: 'fileexists',
  793. allnewfiles: t('core', 'New Files'),
  794. allexistingfiles: t('core', 'Already existing files'),
  795. why: t('core', 'Which files do you want to keep?'),
  796. what: t('core', 'If you select both versions, the copied file will have a number added to its name.')
  797. })
  798. $('body').append($dlg)
  799. if (original && replacement) {
  800. var $conflicts = $dlg.find('.conflicts')
  801. addConflict($conflicts, original, replacement)
  802. }
  803. var buttonlist = [{
  804. text: t('core', 'Cancel'),
  805. classes: 'cancel',
  806. click: function() {
  807. if (typeof controller.onCancel !== 'undefined') {
  808. controller.onCancel(data)
  809. }
  810. $(dialogId).ocdialog('close')
  811. }
  812. },
  813. {
  814. text: t('core', 'Continue'),
  815. classes: 'continue',
  816. click: function() {
  817. if (typeof controller.onContinue !== 'undefined') {
  818. controller.onContinue($(dialogId + ' .conflict'))
  819. }
  820. $(dialogId).ocdialog('close')
  821. }
  822. }]
  823. $(dialogId).ocdialog({
  824. width: 500,
  825. closeOnEscape: true,
  826. modal: true,
  827. buttons: buttonlist,
  828. closeButton: null,
  829. close: function() {
  830. self._fileexistsshown = false
  831. $(this).ocdialog('destroy').remove()
  832. }
  833. })
  834. $(dialogId).css('height', 'auto')
  835. var $primaryButton = $dlg.closest('.oc-dialog').find('button.continue')
  836. $primaryButton.prop('disabled', true)
  837. function updatePrimaryButton() {
  838. var checkedCount = $dlg.find('.conflicts .checkbox:checked').length
  839. $primaryButton.prop('disabled', checkedCount === 0)
  840. }
  841. // add checkbox toggling actions
  842. $(dialogId).find('.allnewfiles').on('click', function() {
  843. var $checkboxes = $(dialogId).find('.conflict .replacement input[type="checkbox"]')
  844. $checkboxes.prop('checked', $(this).prop('checked'))
  845. })
  846. $(dialogId).find('.allexistingfiles').on('click', function() {
  847. var $checkboxes = $(dialogId).find('.conflict .original:not(.readonly) input[type="checkbox"]')
  848. $checkboxes.prop('checked', $(this).prop('checked'))
  849. })
  850. $(dialogId).find('.conflicts').on('click', '.replacement,.original:not(.readonly)', function() {
  851. var $checkbox = $(this).find('input[type="checkbox"]')
  852. $checkbox.prop('checked', !$checkbox.prop('checked'))
  853. })
  854. $(dialogId).find('.conflicts').on('click', '.replacement input[type="checkbox"],.original:not(.readonly) input[type="checkbox"]', function() {
  855. var $checkbox = $(this)
  856. $checkbox.prop('checked', !$checkbox.prop('checked'))
  857. })
  858. // update counters
  859. $(dialogId).on('click', '.replacement,.allnewfiles', function() {
  860. var count = $(dialogId).find('.conflict .replacement input[type="checkbox"]:checked').length
  861. if (count === $(dialogId + ' .conflict').length) {
  862. $(dialogId).find('.allnewfiles').prop('checked', true)
  863. $(dialogId).find('.allnewfiles + .count').text(t('core', '(all selected)'))
  864. } else if (count > 0) {
  865. $(dialogId).find('.allnewfiles').prop('checked', false)
  866. $(dialogId).find('.allnewfiles + .count').text(t('core', '({count} selected)', { count: count }))
  867. } else {
  868. $(dialogId).find('.allnewfiles').prop('checked', false)
  869. $(dialogId).find('.allnewfiles + .count').text('')
  870. }
  871. updatePrimaryButton()
  872. })
  873. $(dialogId).on('click', '.original,.allexistingfiles', function() {
  874. var count = $(dialogId).find('.conflict .original input[type="checkbox"]:checked').length
  875. if (count === $(dialogId + ' .conflict').length) {
  876. $(dialogId).find('.allexistingfiles').prop('checked', true)
  877. $(dialogId).find('.allexistingfiles + .count').text(t('core', '(all selected)'))
  878. } else if (count > 0) {
  879. $(dialogId).find('.allexistingfiles').prop('checked', false)
  880. $(dialogId).find('.allexistingfiles + .count')
  881. .text(t('core', '({count} selected)', { count: count }))
  882. } else {
  883. $(dialogId).find('.allexistingfiles').prop('checked', false)
  884. $(dialogId).find('.allexistingfiles + .count').text('')
  885. }
  886. updatePrimaryButton()
  887. })
  888. dialogDeferred.resolve()
  889. })
  890. .fail(function() {
  891. dialogDeferred.reject()
  892. alert(t('core', 'Error loading file exists template'))
  893. })
  894. }
  895. // }
  896. return dialogDeferred.promise()
  897. },
  898. // get the gridview setting and set the input accordingly
  899. _getGridSettings: function() {
  900. var self = this
  901. $.get(OC.generateUrl('/apps/files/api/v1/showgridview'), function(response) {
  902. self.$showGridView.get(0).checked = response.gridview
  903. self.$showGridView.next('#picker-view-toggle')
  904. .removeClass('icon-toggle-filelist icon-toggle-pictures')
  905. .addClass(response.gridview ? 'icon-toggle-filelist' : 'icon-toggle-pictures')
  906. $('.list-container').toggleClass('view-grid', response.gridview)
  907. })
  908. },
  909. _onGridviewChange: function() {
  910. var show = this.$showGridView.is(':checked')
  911. // only save state if user is logged in
  912. if (OC.currentUser) {
  913. $.post(OC.generateUrl('/apps/files/api/v1/showgridview'), {
  914. show: show
  915. })
  916. }
  917. this.$showGridView.next('#picker-view-toggle')
  918. .removeClass('icon-toggle-filelist icon-toggle-pictures')
  919. .addClass(show ? 'icon-toggle-filelist' : 'icon-toggle-pictures')
  920. $('.list-container').toggleClass('view-grid', show)
  921. },
  922. _getFilePickerTemplate: function() {
  923. var defer = $.Deferred()
  924. if (!this.$filePickerTemplate) {
  925. var self = this
  926. $.get(OC.filePath('core', 'templates', 'filepicker.html'), function(tmpl) {
  927. self.$filePickerTemplate = $(tmpl)
  928. self.$listTmpl = self.$filePickerTemplate.find('.filelist tbody tr:first-child').detach()
  929. defer.resolve(self.$filePickerTemplate)
  930. })
  931. .fail(function(jqXHR, textStatus, errorThrown) {
  932. defer.reject(jqXHR.status, errorThrown)
  933. })
  934. } else {
  935. defer.resolve(this.$filePickerTemplate)
  936. }
  937. return defer.promise()
  938. },
  939. _getMessageTemplate: function() {
  940. var defer = $.Deferred()
  941. if (!this.$messageTemplate) {
  942. var self = this
  943. $.get(OC.filePath('core', 'templates', 'message.html'), function(tmpl) {
  944. self.$messageTemplate = $(tmpl)
  945. defer.resolve(self.$messageTemplate)
  946. })
  947. .fail(function(jqXHR, textStatus, errorThrown) {
  948. defer.reject(jqXHR.status, errorThrown)
  949. })
  950. } else {
  951. defer.resolve(this.$messageTemplate)
  952. }
  953. return defer.promise()
  954. },
  955. _getFileExistsTemplate: function() {
  956. var defer = $.Deferred()
  957. if (!this.$fileexistsTemplate) {
  958. var self = this
  959. $.get(OC.filePath('files', 'templates', 'fileexists.html'), function(tmpl) {
  960. self.$fileexistsTemplate = $(tmpl)
  961. defer.resolve(self.$fileexistsTemplate)
  962. })
  963. .fail(function() {
  964. defer.reject()
  965. })
  966. } else {
  967. defer.resolve(this.$fileexistsTemplate)
  968. }
  969. return defer.promise()
  970. },
  971. _getFileList: function(dir, mimeType) { // this is only used by the spreedme app atm
  972. if (typeof (mimeType) === 'string') {
  973. mimeType = [mimeType]
  974. }
  975. return $.getJSON(
  976. OC.filePath('files', 'ajax', 'list.php'),
  977. {
  978. dir: dir,
  979. mimetypes: JSON.stringify(mimeType)
  980. }
  981. )
  982. },
  983. /**
  984. * fills the filepicker with files
  985. */
  986. _fillFilePicker: function(dir) {
  987. var self = this
  988. this.$filelist.empty()
  989. this.$filePicker.find('.emptycontent').hide()
  990. this.$filelistContainer.addClass('icon-loading')
  991. this.$filePicker.data('path', dir)
  992. var filter = this.$filePicker.data('mimetype')
  993. if (typeof (filter) === 'string') {
  994. filter = [filter]
  995. }
  996. self.$fileListHeader.find('.sort-indicator').addClass('hidden').removeClass('icon-triangle-n').removeClass('icon-triangle-s')
  997. self.$fileListHeader.find('[data-sort=' + self.filepicker.sortField + '] .sort-indicator').removeClass('hidden')
  998. if (self.filepicker.sortOrder === 'asc') {
  999. self.$fileListHeader.find('[data-sort=' + self.filepicker.sortField + '] .sort-indicator').addClass('icon-triangle-n')
  1000. } else {
  1001. self.$fileListHeader.find('[data-sort=' + self.filepicker.sortField + '] .sort-indicator').addClass('icon-triangle-s')
  1002. }
  1003. self.filepicker.filesClient.getFolderContents(dir).then(function(status, files) {
  1004. self.filelist = files
  1005. if (filter && filter.length > 0 && filter.indexOf('*') === -1) {
  1006. files = files.filter(function(file) {
  1007. return file.type === 'dir' || filter.indexOf(file.mimetype) !== -1
  1008. })
  1009. }
  1010. var Comparators = {
  1011. name: function(fileInfo1, fileInfo2) {
  1012. if (fileInfo1.type === 'dir' && fileInfo2.type !== 'dir') {
  1013. return -1
  1014. }
  1015. if (fileInfo1.type !== 'dir' && fileInfo2.type === 'dir') {
  1016. return 1
  1017. }
  1018. return OC.Util.naturalSortCompare(fileInfo1.name, fileInfo2.name)
  1019. },
  1020. size: function(fileInfo1, fileInfo2) {
  1021. return fileInfo1.size - fileInfo2.size
  1022. },
  1023. mtime: function(fileInfo1, fileInfo2) {
  1024. return fileInfo1.mtime - fileInfo2.mtime
  1025. }
  1026. }
  1027. var comparator = Comparators[self.filepicker.sortField] || Comparators.name
  1028. files = files.sort(function(file1, file2) {
  1029. var isFavorite = function(fileInfo) {
  1030. return fileInfo.tags && fileInfo.tags.indexOf(OC.TAG_FAVORITE) >= 0
  1031. }
  1032. if (isFavorite(file1) && !isFavorite(file2)) {
  1033. return -1
  1034. } else if (!isFavorite(file1) && isFavorite(file2)) {
  1035. return 1
  1036. }
  1037. return self.filepicker.sortOrder === 'asc' ? comparator(file1, file2) : -comparator(file1, file2)
  1038. })
  1039. self._fillSlug()
  1040. if (files.length === 0) {
  1041. self.$filePicker.find('.emptycontent').show()
  1042. self.$fileListHeader.hide()
  1043. } else {
  1044. self.$filePicker.find('.emptycontent').hide()
  1045. self.$fileListHeader.show()
  1046. }
  1047. $.each(files, function(idx, entry) {
  1048. entry.icon = OC.MimeType.getIconUrl(entry.mimetype)
  1049. var simpleSize, sizeColor
  1050. if (typeof (entry.size) !== 'undefined' && entry.size >= 0) {
  1051. simpleSize = humanFileSize(parseInt(entry.size, 10), true)
  1052. sizeColor = Math.round(160 - Math.pow((entry.size / (1024 * 1024)), 2))
  1053. } else {
  1054. simpleSize = t('files', 'Pending')
  1055. sizeColor = 80
  1056. }
  1057. // split the filename in half if the size is bigger than 20 char
  1058. // for ellipsis
  1059. if (entry.name.length >= 10) {
  1060. // leave maximum 10 letters
  1061. var split = Math.min(Math.floor(entry.name.length / 2), 10)
  1062. var filename1 = entry.name.substr(0, entry.name.length - split)
  1063. var filename2 = entry.name.substr(entry.name.length - split)
  1064. } else {
  1065. var filename1 = entry.name
  1066. var filename2 = ''
  1067. }
  1068. var $row = self.$listTmpl.octemplate({
  1069. type: entry.type,
  1070. dir: dir,
  1071. filename: entry.name,
  1072. filename1: filename1,
  1073. filename2: filename2,
  1074. date: OC.Util.relativeModifiedDate(entry.mtime),
  1075. size: simpleSize,
  1076. sizeColor: sizeColor,
  1077. icon: entry.icon
  1078. })
  1079. if (entry.type === 'file') {
  1080. var urlSpec = {
  1081. file: dir + '/' + entry.name,
  1082. x: 100,
  1083. y: 100
  1084. }
  1085. var img = new Image()
  1086. var previewUrl = OC.generateUrl('/core/preview.png?') + $.param(urlSpec)
  1087. img.onload = function() {
  1088. if (img.width > 5) {
  1089. $row.find('td.filename').attr('style', 'background-image:url(' + previewUrl + ')')
  1090. }
  1091. }
  1092. img.src = previewUrl
  1093. }
  1094. self.$filelist.append($row)
  1095. })
  1096. self.$filelistContainer.removeClass('icon-loading')
  1097. })
  1098. },
  1099. /**
  1100. * fills the tree list with directories
  1101. */
  1102. _fillSlug: function() {
  1103. this.$dirTree.empty()
  1104. var self = this
  1105. var dir
  1106. var path = this.$filePicker.data('path')
  1107. var $template = $('<div data-dir="{dir}"><a>{name}</a></div>').addClass('crumb')
  1108. if (path) {
  1109. var paths = path.split('/')
  1110. $.each(paths, function(index, dir) {
  1111. dir = paths.pop()
  1112. if (dir === '') {
  1113. return false
  1114. }
  1115. self.$dirTree.prepend($template.octemplate({
  1116. dir: paths.join('/') + '/' + dir,
  1117. name: dir
  1118. }))
  1119. })
  1120. }
  1121. $template.octemplate({
  1122. dir: '',
  1123. name: '' // Ugly but works ;)
  1124. }, { escapeFunction: null }).prependTo(this.$dirTree)
  1125. },
  1126. /**
  1127. * handle selection made in the tree list
  1128. */
  1129. _handleTreeListSelect: function(event, type) {
  1130. var self = event.data
  1131. var dir = $(event.target).closest('.crumb').data('dir')
  1132. self._fillFilePicker(dir)
  1133. var getOcDialog = (event.target).closest('.oc-dialog')
  1134. var buttonEnableDisable = $('.primary', getOcDialog)
  1135. this._changeButtonsText(type, dir.split(/[/]+/).pop())
  1136. if (this.$filePicker.data('mimetype').indexOf('httpd/unix-directory') !== -1 || this.$filePicker.data('allowDirectoryChooser')) {
  1137. buttonEnableDisable.prop('disabled', false)
  1138. } else {
  1139. buttonEnableDisable.prop('disabled', true)
  1140. }
  1141. },
  1142. /**
  1143. * handle clicks made in the filepicker
  1144. */
  1145. _handlePickerClick: function(event, $element, type) {
  1146. var getOcDialog = this.$filePicker.closest('.oc-dialog')
  1147. var buttonEnableDisable = getOcDialog.find('.primary')
  1148. if ($element.data('type') === 'file') {
  1149. if (this.$filePicker.data('multiselect') !== true || !event.ctrlKey) {
  1150. this.$filelist.find('.filepicker_element_selected').removeClass('filepicker_element_selected')
  1151. }
  1152. $element.toggleClass('filepicker_element_selected')
  1153. buttonEnableDisable.prop('disabled', false)
  1154. } else if ($element.data('type') === 'dir') {
  1155. this._fillFilePicker(this.$filePicker.data('path') + '/' + $element.data('entryname'))
  1156. this._changeButtonsText(type, $element.data('entryname'))
  1157. if (this.$filePicker.data('mimetype').indexOf('httpd/unix-directory') !== -1 || this.$filePicker.data('allowDirectoryChooser')) {
  1158. buttonEnableDisable.prop('disabled', false)
  1159. } else {
  1160. buttonEnableDisable.prop('disabled', true)
  1161. }
  1162. }
  1163. },
  1164. /**
  1165. * Handle
  1166. * @param type of action
  1167. * @param dir on which to change buttons text
  1168. * @private
  1169. */
  1170. _changeButtonsText: function(type, dir) {
  1171. var copyText = dir === '' ? t('core', 'Copy') : t('core', 'Copy to {folder}', { folder: dir })
  1172. var moveText = dir === '' ? t('core', 'Move') : t('core', 'Move to {folder}', { folder: dir })
  1173. var buttons = $('.oc-dialog-buttonrow button')
  1174. switch (type) {
  1175. case this.FILEPICKER_TYPE_CHOOSE:
  1176. break
  1177. case this.FILEPICKER_TYPE_COPY:
  1178. buttons.text(copyText)
  1179. break
  1180. case this.FILEPICKER_TYPE_MOVE:
  1181. buttons.text(moveText)
  1182. break
  1183. case this.FILEPICKER_TYPE_COPY_MOVE:
  1184. buttons.eq(0).text(copyText)
  1185. buttons.eq(1).text(moveText)
  1186. break
  1187. }
  1188. }
  1189. }
  1190. export default Dialogs