document.api.js 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530
  1. /*
  2. # Documentation API
  3. ## Instanciation
  4. ex:
  5. ``
  6. var document = new DocumentApi('#ma-div',options);
  7. document.load();
  8. ``
  9. ## Informations
  10. document.currentFolder : dossier visualisé
  11. document.currentView : vue en cours
  12. document.selected : item sélectionné
  13. ## Panels
  14. ex:
  15. ``document.showPanel('tree');``
  16. ``document.hidePanel('detail');``
  17. * tree : arborescence de gauche
  18. * files : liste des fichiers
  19. * search : moteur de recherche
  20. * breadcrumb : fil d'arianne
  21. * detail : panel de détail fichier de droite
  22. ## Events
  23. ex:
  24. ``document.on('moved',function(data){ ... });``
  25. * loaded : html de l'interface chargé
  26. * searched : recherche de fichiers {request, response}
  27. * renamed : renommage d'un élement {path ,old_label, label}
  28. * moved : déplacement d'un élements {from, to, response}
  29. * uploaded : upload d'un ou plusieurs fichiers {data};
  30. * folder-created : dossier créé {path, folder, response}
  31. * selected : sélection d'un élement {element, path, type, id}
  32. * deleted : suppression d'un élement {element, response, path}
  33. * executed : execution d'un fichier {element, path};
  34. * opened : ouverture d'un dossier {element, path};
  35. * downloaded : téléchargement d'un élement {element, path};
  36. * properties-showed : affichage des propriétés d'un élement {modal, id ;
  37. * right-saved : ajout d'un droit {uid, read, edit, recursive};
  38. * right-deleted : suppression d'un droit {id,element};
  39. * view-loaded : chargement d'une vue {view:view}
  40. ## Ajouter des bouttons au panel de détail
  41. ### ajout d'un boutton classique :
  42. ex:
  43. ``
  44. var document = new DocumentApi('#ma-div',options);
  45. document.options.panels.detail.buttons.push({
  46. label : 'Custom button',
  47. buttonClass : 'btn-custom',
  48. lineClass : 'li-class-custom',
  49. icon : 'fas fa-times',
  50. });
  51. document.load();
  52. ``
  53. ### ajout d'un boutton pour les dossiers uniquement :
  54. ex:
  55. ``
  56. var document = new DocumentApi('#ma-div',options);
  57. document.options.panels.detail.buttons.push({
  58. label : 'Custom button',
  59. buttonClass : 'btn-custom',
  60. lineClass : 'li-class-custom',
  61. icon : 'fas fa-times',
  62. visibility : ['directory']
  63. });
  64. document.load();
  65. ``
  66. ### custom html :
  67. ``
  68. var document = new DocumentApi('#ma-div',options);
  69. document.options.panels.detail.buttons.push({
  70. html : '<div>Mon htl custom ici</div>',
  71. });
  72. document.load();
  73. ``
  74. ## Ajouter des boutons à la creation d'elements
  75. var document = new DocumentApi('#ma-div',options);
  76. document.options.panels.search.buttons.push({
  77. lineClass : 'create-txt-button',
  78. buttonClass : '',
  79. icon : 'fas fa-pen text-secondary',
  80. label : 'Créer un fichier CUSTOM'
  81. });
  82. document.load();
  83. ## Vues
  84. ### Changer la vue des fichiers
  85. ``
  86. var document = new DocumentApi('#ma-div',options);
  87. document.view('list');
  88. document.load();
  89. ``
  90. ou après chargement
  91. ``
  92. var document = new DocumentApi('#ma-div',options);
  93. document.load();
  94. document.view('list');
  95. ``
  96. Les vues par défaut sont :
  97. * list : affichage en liste classique
  98. * grid : affichage en grille
  99. ### Créer une vue custom
  100. ``
  101. var doc = new DocumentApi('#document-container',urlOptions);
  102. html = '<ul><li data-path="{{path}}" data-type="{{type}}" data-id="{{id}}" class="file-element hidden p-3"><img style="width:20px" class="element-thumbnail" data-src="{{thumbnail}}"/> {{label}} {{sizeReadable}} {{creator}}</li></ul>';
  103. doc.addView({
  104. uid : 'custom',
  105. label : 'Vue personnalisée',
  106. icon : 'fas fa-th',
  107. html : html
  108. });
  109. doc.view('custom');
  110. doc.load();
  111. ``
  112. nb : Le html de la vue doit contenir un élement racine contenant un élement enfant qui servira de model pour l'affichage fichier, cet element
  113. doit contenir les attributs et classes comme dans l'example suivant :
  114. ``
  115. <ul>
  116. <li data-path="{{path}}" data-type="{{type}}" data-id="{{id}}" class="file-element hidden"> hello {{label}} !<li>
  117. </ul>
  118. ``
  119. Une ligne fichier peut contenir les tags suivants :
  120. * childNumber: nombre d'enfants (pour les dossiers uniquement)
  121. * created: timestamp de création ex : 1564997272
  122. * creator: login du créateur ex : "admin"
  123. * extension: extention si fichier ex : "jpg"
  124. * id: id en base de données ex : 68
  125. * label: libellé du fichier ex : "09.jpg"
  126. * path: chemin relative du fichier à partir de la racine des documents ex : "./09.jpg"
  127. * size: taille en octet ex : 533172
  128. * sizeReadable: taille au format human readable ex : "520.68 ko"
  129. * thumbnail: chemin vers l'image d'apercu ex : "plugin/document/img/file-types/image.svg"
  130. * type: type d'élément (file ou directory) ex : "file"
  131. * updatedReadable : Date de derniere modification au format human readable ex : "Vendredi 02 Aout 2019 à 18:02"
  132. * updatedRelative: Date de derniere modification au format relatif ex : Dat "Il y a 2 jours"
  133. * updated: timestamp de la derniere modification
  134. * updater: login du dernier modifieur
  135. ## Récuperation de la vue courante
  136. document.currentView (string)
  137. ## Récuperation de l'élement en cours de sélection
  138. document.selected : {element,id,path,type}
  139. ## Autres options
  140. ``
  141. var document = new DocumentApi('#ma-div',options);
  142. document.options.rootLabel = 'D:';
  143. document.load();
  144. ``
  145. * rootLabel : Libellé de la racine
  146. * rightEdit : Activer l'edition
  147. * rightDelete : Activer la suppression des élements
  148. * rightPermission : Activer la gestion des permissions
  149. */
  150. class DocumentApi {
  151. constructor(element,options) {
  152. this.onEvents = {};
  153. this.currentView = 'list';
  154. this.currentFolder = '.';
  155. this.views = [];
  156. this.selected = null;
  157. this.isProcessing = false;
  158. this.dom = {
  159. container : $(element),
  160. panels : {
  161. tree : null,
  162. detail : null,
  163. search : null,
  164. breadcrumb : null,
  165. files : null
  166. }
  167. }
  168. this.options = {
  169. rootLabel : 'C:',
  170. root : '',
  171. rightEdit : true,
  172. rightDelete : true,
  173. rightPermission : true,
  174. panels : {
  175. detail : {
  176. visible : true,
  177. buttons : []
  178. },
  179. view : {
  180. visible : true,
  181. buttons : []
  182. },
  183. tree : {
  184. visible : true
  185. },
  186. search : {
  187. visible : true,
  188. buttons : []
  189. },
  190. breadcrumb : {
  191. visible : true
  192. }
  193. },
  194. actions : {
  195. template : 'document_load_template',
  196. element_search : 'document_element_search',
  197. folder_create : 'document_folder_create',
  198. element_rename : 'document_element_rename',
  199. element_delete : 'document_element_delete',
  200. element_move : 'document_element_move',
  201. element_share_edit : 'document_element_share_edit',
  202. element_preview : 'document_element_preview',
  203. element_execute : 'document_element_execute',
  204. element_upload : 'document_element_upload',
  205. element_edit : 'document_element_edit',
  206. element_save : 'document_element_save',
  207. properties_show : 'document_properties_show',
  208. right_search : 'document_right_search',
  209. right_save : 'document_right_save',
  210. right_delete : 'document_right_delete',
  211. }
  212. };
  213. if(options) this.options = $.extend(this.options,options);
  214. }
  215. load(){
  216. this.dom.container.html('Chargement...');
  217. var element = this.element;
  218. var object = this;
  219. object.options.panels.detail.buttons.push({
  220. buttonClass : 'btn-primary btn-download',
  221. icon : 'fas fa-arrow-alt-circle-down',
  222. label : 'TÉLÉCHARGER',
  223. visibility : ['file','directory']
  224. });
  225. object.options.panels.detail.buttons.push({
  226. lineClass : 'properties-button directory-button',
  227. buttonClass : 'btn',
  228. icon : 'fas fa-align-justify',
  229. label : 'PROPRIÉTÉS',
  230. visibility : ['file','directory']
  231. });
  232. object.options.panels.search.buttons.push({
  233. lineClass : 'upload-button',
  234. buttonClass : '',
  235. icon : 'far fa-file-alt',
  236. label : 'Envoyer un fichier',
  237. afterHtml : '<form class="box" method="post" action="action.php?action='+object.options.actions.element_upload+'" enctype="multipart/form-data"><input type="file" name="file[]" multiple /></form>'
  238. });
  239. object.options.panels.search.buttons.push({
  240. lineClass : '',
  241. buttonClass : 'add-new-folder',
  242. icon : 'far fa-folder',
  243. label : 'Créer un dossier',
  244. afterHtml : '<div class="new-folder-block hidden"> \
  245. <div class="input-group mb-3">\
  246. <input type="text" class="form-control folder-name" placeholder="Nom du dossier">\
  247. <div class="input-group-append">\
  248. <span class="btn btn-success"><i class="fas fa-check"></i></span>\
  249. </div>\
  250. </div>\
  251. </div>'
  252. });
  253. object.options.panels.search.buttons.push({
  254. lineClass : 'create-txt-button',
  255. buttonClass : '',
  256. icon : 'fas fa-pen text-secondary',
  257. label : 'Créer un fichier'
  258. });
  259. if(object.options.rightPermission){
  260. object.options.panels.detail.buttons.push({
  261. lineClass : 'share-button directory-button',
  262. buttonClass : 'btn',
  263. icon : 'fas fa-share',
  264. label : 'PERMISSIONS',
  265. visibility : ['file','directory']
  266. });
  267. object.options.panels.detail.buttons.push({
  268. html : '<div class="right-panel hidden"><hr/>\
  269. <h6>PARTAGES</h6>\
  270. <div class="element-right-form">\
  271. <input class="uid" class="form-control" type="text" data-type="user" data-types="user,rank" placeholder="Rang ou utilisateur..." />\
  272. <label><input class="read" type="checkbox" data-type="checkbox"> Lecture</label>\
  273. <label><input class="edit" type="checkbox" data-type="checkbox"> Écriture</label>\
  274. <label><input class="recursive" type="checkbox" data-type="checkbox"> Récursif</label>\
  275. <div class="btn btn-add-share btn-light"><i class="fa fa-plus"></i> Ajouter</div>\
  276. </div>\
  277. <ul class="table element-rights" >\
  278. <li data-id="{{id}}" class="hidden p-2">\
  279. {{{uid}}} <br>\
  280. <small class="text-muted p-0">\
  281. <span class="p-2">{{#read}}<i class="fa fa-check text-success"></i>{{/read}}{{^read}}<i class="fa fa-times text-secondary"></i>{{/read}} Lecture </span>\
  282. <span class="p-2">{{#edit}}<i class="fa fa-check text-success"></i>{{/edit}}{{^edit}}<i class="fa fa-times text-secondary"></i>{{/edit}} Écriture </span>\
  283. <span class="p-2">{{#recursive}}<i class="fa fa-check text-success"></i>{{/recursive}}{{^recursive}}<i class="fa fa-times text-secondary"></i>{{/recursive}} Récursif </span>\
  284. <i title="Supprimer la permission" class="fa fa-trash pointer right btn-delete-right" ></i>\
  285. </small>\
  286. </li>\
  287. </ul>\
  288. <hr/></div>',
  289. visibility : ['file','directory']
  290. });
  291. }
  292. if(object.options.rightDelete){
  293. object.options.panels.detail.buttons.push({
  294. buttonClass : 'btn text-danger btn-element-delete',
  295. icon : 'far fa-trash-alt',
  296. label : 'SUPPRIMER',
  297. visibility : ['file','directory']
  298. });
  299. }
  300. object.dom.container.load('action.php?action='+object.options.actions.template,function(){
  301. object.dom.panels = {
  302. tree : $('.tree-panel',object.dom.container),
  303. detail : $('.detail-panel',object.dom.container),
  304. search : $('.search-module',object.dom.container),
  305. breadcrumb : $('.breadcrumb-module',object.dom.container),
  306. files : $('.file-module',object.dom.container)
  307. };
  308. if(object.options.root) $('.document-container').attr('data-root',object.options.root);
  309. if(object.options.panels['tree'].visible === false) object.hidePanel('tree');
  310. if(object.options.panels['detail'].visible === false) object.hidePanel('detail');
  311. if(object.options.panels['search'].visible === false) object.hidePanel('search');
  312. if(object.options.panels['breadcrumb'].visible === false) object.hidePanel('breadcrumb');
  313. $('.root-folder span',object.dom.panels.tree).text(object.options.rootLabel);
  314. object.views.push({
  315. uid : 'list',
  316. icon : 'fas fa-align-justify',
  317. label : 'Vue liste',
  318. html : $('.file-view[data-view="list"]').get(0).outerHTML
  319. });
  320. object.views.push({
  321. uid : 'grid',
  322. icon : 'fas fa-th-large',
  323. label : 'Vue grille',
  324. html : $('.file-view[data-view="grid"]').get(0).outerHTML
  325. });
  326. //Chargement des vues disponibles
  327. object.loadViews();
  328. //Rendu de la vue courante
  329. object.renderView();
  330. //Chargement des fichiers
  331. object.element_search();
  332. //Chargement des boutons ajouter (dossier, fichier..)
  333. $('.document-create-dropdown .dropdown-item:not(.hidden)').remove();
  334. var tpl = $('.document-create-dropdown .dropdown-item.hidden').get(0).outerHTML;
  335. for(var k in object.options.panels.search.buttons){
  336. var data = object.options.panels.search.buttons[k];
  337. var button = $(Mustache.render(tpl,data));
  338. button.removeClass('hidden');
  339. $('.document-create-dropdown').append(button);
  340. }
  341. $('.root-folder',object.dom.container).addClass('folder-focused');
  342. $(document).off('keyup').on('keyup', function(e){
  343. switch(e.keyCode){
  344. case 46:
  345. if(!object.options.rightDelete) break;
  346. object.element_delete();
  347. break;
  348. case 113:
  349. if(!object.options.rightEdit) break;
  350. if ($('.file-view tr').hasClass('element-focused'))
  351. object.element_rename_edit($('.element-rename',object.selected.element));
  352. break;
  353. case 13:
  354. if($('.label-search',object.dom.panels.search).is(":focus"))
  355. object.element_search();
  356. break;
  357. }
  358. });
  359. $('.file-view:visible').sortable_table({
  360. onSort : function(){object.element_search();}
  361. });
  362. //RESET KEYWORD
  363. $(".label-search").on('keyup',function(){
  364. if ($(this).val() != ''){
  365. $('.doc-search-container').addClass('typing');
  366. }else{
  367. $('.doc-search-container').removeClass('typing');
  368. }
  369. });
  370. $(".search-clear").click(function(){
  371. $('.doc-search-container').removeClass('typing');
  372. $(".label-search").val('');
  373. $(".label-search").focus();
  374. object.element_search();
  375. });
  376. $('div.file-panel').on('click',function(e){
  377. if(e.target == (this)) {
  378. $('.file-view:visible tr').removeClass('element-focused');
  379. object.reset_preview();
  380. }
  381. });
  382. // Mapping des events DOM / objet
  383. $('.root-folder',object.dom.panels.tree).click(function(event){object.element_search('.');});
  384. $('.btn-search',object.dom.panels.search).click(function(){object.element_search();});
  385. $('.add-new-folder',object.dom.panels.search).click(function(event){ object.new_folder(event); });
  386. $('.new-folder-block .input-group-append',object.dom.panels.search).click(function(){object.folder_create()});
  387. $('.detail-buttons',object.dom.panels.detail).on('click','.btn-download',function(){object.element_download(null,true)});
  388. $('.detail-buttons',object.dom.panels.detail).on('click','.share-button',function(){object.right_toggle()});
  389. $('.detail-buttons',object.dom.panels.detail).on('click','.properties-button',function(){object.properties_show()});
  390. $('.detail-buttons',object.dom.panels.detail).on('click','.element-right-form .btn-add-share',function(){object.right_save()});
  391. $('.detail-buttons',object.dom.panels.detail).on('click','.btn-delete-right',function(){object.right_delete(this)});
  392. $('.detail-buttons',object.dom.panels.detail).on('click','.btn-element-delete',function(){object.element_delete();});
  393. $('.tree-folders',object.dom.panels.tree).on('click','li',function(event){object.folder_toggle(this,event);});
  394. //editeur
  395. $('.create-txt-button',object.dom.panels.search).click(function(){object.element_edit();});
  396. $('.btn-editor-cancel',object.dom.panels.file).click(function(){ $('.file-editor',object.dom.panels.file).addClass('hidden'); });
  397. $('.btn-editor-save',object.dom.panels.file).click(function(){object.element_edit_save();});
  398. if(!object.options.rightEdit){
  399. $('.document-add-element',object.dom.panels.file).addClass('hidden');
  400. }else{
  401. object.init_upload();
  402. }
  403. object.triggerEvent('loaded');
  404. });
  405. }
  406. triggerEvent(event,options){
  407. if(!this.onEvents[event]) return;
  408. for(var key in this.onEvents[event]){
  409. this.onEvents[event][key](options);
  410. }
  411. }
  412. hidePanel(panel){
  413. var object = this;
  414. object.options.panels[panel].visible = false;
  415. if(object.dom.panels[panel]!=null) object.dom.panels[panel].addClass('hidden');
  416. }
  417. showPanel(panel){
  418. var object = this;
  419. object.options.panels[panel].visible = true;
  420. if(object.dom.panels[panel]!=null) object.dom.panels[panel].removeClass('hidden');
  421. }
  422. //Récuperation d'une liste de element dans le tableau elements
  423. element_search(folderPath){
  424. var object = this;
  425. if(object.isProcessing) return;
  426. $('.file-preloader',object.dom.panels.files).removeClass('hidden');
  427. var keyword = $('.label-search',object.dom.panels.search).val();
  428. //tri
  429. var sort = {};
  430. var sortElement = $('.file-view:visible th[data-sortable][data-sort]',object.dom.panels.files);
  431. if(sortElement.length!=0 && sortElement.attr('data-sort')!=""){
  432. sort.column = sortElement.attr('data-sortable');
  433. sort.sort = sortElement.attr('data-sort');
  434. }
  435. var data = {
  436. /*async: false,*/
  437. action: object.options.actions.element_search,
  438. keyword : keyword,
  439. sort : sort,
  440. root :object.options.root,
  441. folder : folderPath ? folderPath : object.currentFolder
  442. }
  443. data.folder = data.folder == '.' ? '': data.folder;
  444. object.isProcessing = true;
  445. $('.file-view:visible',object.dom.panels.files).fill(data,function(response){
  446. object.currentFolder = data.folder;
  447. $('.file-preloader',object.dom.panels.files).addClass('hidden');
  448. object.triggerEvent('searched',{data:data,response:response});
  449. object.isProcessing = false;
  450. var breadcrumb = null;
  451. if(data.folder) breadcrumb = data.folder.split('/');
  452. //gestion de l'arborescence de gauche (tree)
  453. var tree = $('ul.tree-folders',object.dom.panels.tree);
  454. var tpl = $('li:not(:visible)',tree).get(0).outerHTML;
  455. var recipient = data.folder=='' ? tree : $('> ul li[data-path="'+data.folder+'"] > ul',object.dom.panels.tree) ;
  456. recipient.find('li:visible').remove();
  457. //On n'affiche l'arborcence que si on est pas en mode recherche
  458. if(!data.keyword || data.keyword ==''){
  459. for(var k in response.rows){
  460. var row = response.rows[k];
  461. if(row.type!='directory') continue;
  462. var li = $(Mustache.render(tpl,row));
  463. li.removeClass('hidden');
  464. recipient.append(li);
  465. }
  466. if(data.folder){
  467. $('li',object.dom.panels.tree).removeClass('folder-open folder-focused');
  468. var crumb = '';
  469. for(var k in breadcrumb){
  470. if(k!=0) crumb += '/';
  471. crumb += breadcrumb[k];
  472. $('li[data-path="'+crumb+'"]',object.dom.panels.tree).addClass('folder-open');
  473. }
  474. $('li[data-path="'+data.folder+'"]',object.dom.panels.tree).addClass('folder-focused');
  475. }
  476. }
  477. //
  478. //Fil d'arianne
  479. object.breadcrumb_render(breadcrumb);
  480. //reset panel detail
  481. object.reset_preview();
  482. //EVENTS
  483. //Prévisualisation
  484. $('.file-view:visible .file-element',object.dom.panels.files).click(function(event){ object.element_preview(this, event); });
  485. //Ouverture fichier / dossier
  486. $('.file-view:visible .file-element',object.dom.panels.files).dblclick(function(event){ object.element_execute(this); });
  487. //Renommage
  488. $('.file-view:visible .file-element .element-rename',object.dom.panels.files).click(function(event){
  489. event.stopPropagation();
  490. event.preventDefault();
  491. object.element_rename_edit(this);
  492. });
  493. //Validation du renommage
  494. $('.rename-input',object.dom.panels.files).bind('blur keyup', function(e){
  495. var input = $(this);
  496. var text = input.next('span');
  497. var label = text.text();
  498. if(e.type === 'keyup'){
  499. //adapte la largeur en temps réel de l'input à la largeur du texte avec un max de 320 px et un min de 45px
  500. var width = Math.min(Math.max( input.val().length *5.5 ,45),320);
  501. $(this).width(width+15);
  502. }
  503. if (e.type !== 'blur' && e.keyCode !== 13) return;
  504. var tr = input.closest('.file-element');
  505. var button = tr.find('.element-rename');
  506. var newLabel = input.val().replace(/\s+$/, '');
  507. //Les dossiers ne peuvent finir par un .
  508. if(newLabel.slice(-1) == '.' && tr.attr('data-type') =='directory') newLabel = newLabel.slice(0,-1);
  509. //Check si le label a changé ou non
  510. if(newLabel == label){
  511. text.text(label).removeClass('hidden');
  512. input.addClass('hidden');
  513. button.removeClass('hidden');
  514. return;
  515. }
  516. //Attribution nouveau label
  517. text.text(newLabel).removeClass('hidden');
  518. input.addClass('hidden');
  519. $.action({
  520. action : object.options.actions.element_rename,
  521. path : tr.attr('data-path'),
  522. label : newLabel
  523. }, function(r){
  524. button.removeClass('hidden');
  525. $('.tree-folders li[data-path="'+ tr.attr('data-path')+'"]').attr('data-path',r.element.path).find('span').text(newLabel);
  526. tr.attr('data-path', r.element.path);
  527. object.triggerEvent('renamed',{
  528. path : tr.attr('data-path'),
  529. old_label : label,
  530. label : newLabel
  531. });
  532. }, function(r){
  533. text.text(label);
  534. button.removeClass('hidden');
  535. });
  536. });
  537. //Maj du placeholder de la recherche
  538. $('.label-search').attr('placeholder','Rechercher'+(breadcrumb ? ' dans '+breadcrumb[breadcrumb.length-1]:''));
  539. if(!object.options.rightEdit){
  540. $('.element-rename',object.dom.panels.file).addClass('hidden');
  541. }else{
  542. //Drag & Drop fichiers
  543. var viewElement = $(".file-view:visible");
  544. var droppableContainer = viewElement.get(0).tagName == 'TABLE' ? ' tbody': '';
  545. $(".file-view:visible"+droppableContainer,object.dom.panels.files).sortable({
  546. distance: 5,
  547. opacity: 0.75,
  548. start: function(e, ui) {
  549. var placeholder = ui.item.clone().addClass('original-placeholder').removeAttr('style');
  550. ui.item.after(placeholder);
  551. },
  552. stop: function(e, ui) {
  553. $('.original-placeholder').remove();
  554. $(e.originalEvent.target).one('click', function(e){
  555. e.stopImmediatePropagation();
  556. });
  557. }
  558. }).disableSelection();
  559. $(".file-view:visible .file-element",object.dom.panels.files).droppable({
  560. tolerance: "pointer",
  561. hoverClass: "folder-receive-element",
  562. drop: function(event, ui) {
  563. var from = $(ui.draggable["0"]);
  564. var to = $(this);
  565. if(to.attr('data-type') != 'directory') return;
  566. $.action({
  567. action : object.options.actions.element_move,
  568. from : from.attr('data-path'),
  569. to : to.attr('data-path'),
  570. }, function(response){
  571. if (response.element !== null && typeof response.element === 'object') {
  572. object.triggerEvent('moved',{from:from,to:to,response:response});
  573. from.remove();
  574. object.remove_treeline(from);
  575. object.reset_preview();
  576. } else {
  577. alert('Action impossible, un élément existe déjà avec ce nom dans le dossier.');
  578. }
  579. });
  580. }
  581. });
  582. //Drag & drop arborescence
  583. $("li",object.dom.panels.tree).droppable({
  584. tolerance: "pointer",
  585. greedy: true,
  586. over: function(e, ui){
  587. var to = $(this);
  588. var toPath = to.hasClass('root-folder') ? '.' : to.attr('data-path');
  589. to.addClass( to.hasClass('root-folder') ?'folder-focused':'folder-hover');
  590. },
  591. out: function(e, ui){
  592. var to = $(this);
  593. if( to.hasClass('root-folder') && to.hasClass('folder-focused'))
  594. to.removeClass('folder-focused');
  595. if(to.hasClass('folder-hover'))
  596. to.removeClass('folder-hover');
  597. },
  598. drop: function(event, ui) {
  599. var from = $(ui.draggable["0"]);
  600. var fromPath = from.attr('data-path');
  601. var to = $(this);
  602. var toPath = to.hasClass('root-folder') ? '.' : to.attr('data-path');
  603. if( to.hasClass('root-folder') && to.hasClass('folder-focused'))
  604. to.removeClass('folder-focused');
  605. if(to.hasClass('folder-hover'))
  606. to.removeClass('folder-hover');
  607. $('.tree-panel li').removeClass('folder-hover');
  608. if(fromPath == toPath) {
  609. $.message('error', 'Impossible de déplacer un dossier dans lui-même.');
  610. return;
  611. }
  612. $.action({
  613. action : object.options.actions.element_move,
  614. from : fromPath,
  615. to : toPath,
  616. }, function(response){
  617. if (response.element !== null && typeof response.element === 'object') {
  618. object.triggerEvent('moved',{from:from,to:to,response:response});
  619. // Suppression de la ligne dans le panneau arborescence
  620. object.remove_treeline(from);
  621. // Ajout d'une ligne dans le panneau de l'arborescence
  622. if(from.attr('data-type') == 'directory') {
  623. var fromLabel = $('span', from).text();
  624. var tpl = $('.tree-folders li:not(:visible)',object.dom.panels.tree).get(0).outerHTML;
  625. var toContainer = toPath == '.' ? $('ul.tree-folders',object.dom.panels.tree) : $('>ul.folders-container', to);
  626. toContainer.parent().addClass('folder-open');
  627. $('i.far.fa-folder',toContainer.parent()).removeClass('fa-folder').addClass('fa-folder-open');
  628. var li = $(Mustache.render(tpl,{label:fromLabel,path:toPath+'/'+fromLabel}));
  629. li.removeClass('hidden');
  630. toContainer.append(li);
  631. }
  632. // Suppression de la ligne dans le panneau d'élément
  633. from.remove();
  634. // Reset de la preview
  635. object.reset_preview();
  636. }
  637. else
  638. alert('Action impossible, un élément existe déjà avec ce nom dans le dossier.');
  639. });
  640. }
  641. });
  642. }
  643. });
  644. }
  645. //Draw du fil d'Ariane
  646. breadcrumb_render(breadcrumb){
  647. var object = this;
  648. if(!object.dom.panels.breadcrumb) return;
  649. if(breadcrumb === null) breadcrumb = ['.'];
  650. if(breadcrumb[0]!='.') breadcrumb.unshift('.');
  651. $('ul li:visible',object.dom.panels.breadcrumb).remove();
  652. var tpl = $('li:not(:visible)',object.dom.panels.breadcrumb).get(0).outerHTML;
  653. for(var key in breadcrumb){
  654. var label = breadcrumb[key];
  655. if(label == '.') label = '<i class="fas fa-home"></i>';
  656. var currentpath = breadcrumb.slice(0,key);
  657. currentpath.push(breadcrumb[key]);
  658. currentpath = currentpath.join('/');
  659. var li = $(Mustache.render(tpl,{label:label,path:currentpath}));
  660. if(key == breadcrumb.length-1) li.attr('title', 'Dossier courant');
  661. $('ul',object.dom.panels.breadcrumb).append(li);
  662. li.removeClass('hidden');
  663. }
  664. $('ul > li',object.dom.panels.breadcrumb).click(function(){
  665. object.element_search( $(this).attr('data-path'));
  666. });
  667. }
  668. /** DOSSIER */
  669. folder_toggle(element, event, force){
  670. var object = this;
  671. $('.label-search').val('').blur();
  672. var li = $(element).closest('li');
  673. if (li.hasClass('folder-focused')){
  674. var parent = li.parent().parent();
  675. object.element_search(parent.attr('data-path'));
  676. }else{
  677. object.element_search(li.attr('data-path'));
  678. }
  679. if(event) event.stopPropagation();
  680. }
  681. // Reset du panneau de preview de la GED
  682. reset_preview(){
  683. var object = this;
  684. $('.detail-thumbnail',object.dom.panels.detail).removeAttr('style');
  685. $('> h1',object.dom.panels.detail).text('Aucun fichier sélectionné');
  686. $('> small > span',object.dom.panels.detail).text('-');
  687. $('.detail-buttons',object.dom.panels.detail).addClass('hidden');
  688. }
  689. // Preloader affiché durant l'upload
  690. toggle_preloader_upload(){
  691. var object = this;
  692. var preloader = $('.preloader-upload-container');
  693. if(!preloader.is(':visible')) {
  694. preloader.removeClass('hidden');
  695. preloader.find('.preloader-upload-close').unbind('click').click(function(){
  696. object.toggle_preloader_upload();
  697. });
  698. $('body').css('overflow', 'hidden');
  699. } else {
  700. $('body').css('overflow', '');
  701. preloader.addClass('hidden');
  702. }
  703. }
  704. // Init de l'upload
  705. init_upload(){
  706. var object = this;
  707. var form = $('.upload-button form',object.dom.container);
  708. var input = form.find('input[type="file"]');
  709. var zone = $('.file-panel');
  710. var droppedFiles = null;
  711. var noBlink = null;
  712. var fileQueue = [];
  713. //Upload des images dans le presse papier
  714. window.addEventListener("paste", function(event){
  715. var clipboardData = event.clipboardData || window.clipboardData;
  716. if(clipboardData.getData('Text').length) return;
  717. if(event.clipboardData == false || event.clipboardData.items == undefined) return;
  718. var items = event.clipboardData.items;
  719. if(items.length == 0) return;
  720. fileQueue = [];
  721. for (var i = 0; i < items.length; i++) {
  722. var f = items[i];
  723. if (f.type.indexOf("image") == -1) return;
  724. var file = items[i].getAsFile();
  725. fileQueue.push({
  726. method : 'paste',
  727. file : file
  728. });
  729. }
  730. form.trigger('submit');
  731. }, false);
  732. input.addClass('hidden');
  733. $('.upload-button > div',object.dom.container).click(function(e){
  734. input.trigger('click');
  735. e.preventDefault();
  736. e.stopPropagation();
  737. });
  738. input.on('change', function (e) {
  739. fileQueue = [];
  740. for(var k in this.files){
  741. if(this.files[k].name ==null) break;
  742. fileQueue.push({
  743. method : 'browse',
  744. file : this.files[k]
  745. });
  746. }
  747. form.trigger('submit');
  748. });
  749. zone.on('drag dragstart dragend dragover dragenter dragleave drop', function (e) {
  750. e.preventDefault();
  751. e.stopPropagation();
  752. })
  753. .on('dragover dragenter', function (e) {
  754. clearTimeout(noBlink);
  755. $('.drag-overlay').css('display', 'block');
  756. zone.addClass('drag-over');
  757. e.preventDefault();
  758. e.stopPropagation();
  759. })
  760. .on('dragleave dragend drop', function (e) {
  761. noBlink = setTimeout(function(){
  762. $('.drag-overlay').css('display', 'none');
  763. zone.removeClass('drag-over');
  764. },500);
  765. e.preventDefault();
  766. e.stopPropagation();
  767. })
  768. .on('drop', function (e) {
  769. fileQueue = [];
  770. if(!e.originalEvent.dataTransfer) return;
  771. droppedFiles = e.originalEvent.dataTransfer.files;
  772. for (var i=0, f; f=droppedFiles[i]; ++i) {
  773. if(f.name.indexOf(".")==-1 && f.size%4096 == 0) {
  774. $.message('error', 'Impossible d\'envoyer un dossier.');
  775. return;
  776. }
  777. fileQueue.push({
  778. method : 'drop',
  779. file : droppedFiles[i]
  780. });
  781. }
  782. form.trigger('submit');
  783. });
  784. form.on('submit', function (e) {
  785. $('.drag-overlay').css('display', 'none');
  786. e.preventDefault();
  787. var tpl = $('.upload-files li.hidden').get(0).outerHTML;
  788. $('.upload-files li:not(.hidden)').remove();
  789. var fileProcessed = [];
  790. object.toggle_preloader_upload();
  791. for( var k in fileQueue){
  792. var file = fileQueue[k].file;
  793. var line = $(Mustache.render(tpl,{
  794. label : file.name,
  795. sort : k,
  796. size : readable_size(file.size)
  797. }));
  798. line.removeClass('hidden');
  799. $('.upload-files').append(line);
  800. var ajaxData = new FormData();
  801. ajaxData.append(input.attr('name'), file);
  802. ajaxData.append('method', fileQueue[k].method);
  803. ajaxData.append('path', object.currentFolder =='.' ? '' : object.currentFolder);
  804. ajaxData.append('sort', k);
  805. $.ajax({
  806. url: form.attr('action'),
  807. type: form.attr('method'),
  808. data: ajaxData,
  809. dataType: 'json',
  810. cache: false,
  811. contentType: false,
  812. processData: false,
  813. complete: function (data) {},
  814. success: function (response) {
  815. if(!response.error){
  816. $('.upload-files li[data-sort="'+response.sort+'"] .upload-file-state').addClass('success').html('<i class="far fa-check-circle"></i> Succès');
  817. }else{
  818. $('.upload-files li[data-sort="'+response.sort+'"] .upload-file-state').addClass('error').html('<i class="fas fa-exclamation-circle"></i> Erreur :'+response.error);
  819. }
  820. fileProcessed.push(response);
  821. $('.preloader-upload-container .upload-state span').text(fileProcessed.length+'/'+fileQueue.length+' fichiers envoyés');
  822. if(fileQueue.length==fileProcessed.length){
  823. object.triggerEvent('uploaded',{data:fileProcessed});
  824. $('.document-create-dropdown').removeClass('show');
  825. object.element_search();
  826. //On cache automatiquement le gestionnaire d'upload si aucune erreure.
  827. if($('.upload-file-state.error').length == 0){
  828. setTimeout(function(){
  829. var preloader = $('.preloader-upload-container');
  830. $('body').css('overflow', '');
  831. preloader.addClass('hidden');
  832. },1500);
  833. }
  834. }
  835. },
  836. error: function (data) {
  837. $('.document-create-dropdown').removeClass('show');
  838. $.message('error',data);
  839. },
  840. xhr: function() {
  841. var xhr = new window.XMLHttpRequest();
  842. xhr.sort = k;
  843. xhr.upload.addEventListener("progress", function(evt){
  844. if (evt.lengthComputable) {
  845. var percentComplete = (evt.loaded / evt.total) * 100;
  846. percentComplete = Math.round(percentComplete * 100) / 100;
  847. var progressBar = $('.upload-files li[data-sort="'+xhr.sort+'"] .progress-bar')
  848. .css('width',percentComplete+'%')
  849. .text(percentComplete+'%')
  850. .attr('aria-valuenow',percentComplete);
  851. }
  852. }, false);
  853. return xhr;
  854. }
  855. });
  856. }
  857. });
  858. }
  859. folder_create(){
  860. var object = this;
  861. var path = object.currentFolder =='.' ? '' : object.currentFolder+'/';
  862. path += $('.folder-name').val();
  863. var data = {
  864. action : object.options.actions.folder_create,
  865. path : path,
  866. folder : $('.folder-name',object.dom.panels.search).val()
  867. }
  868. $.action(data,function(response){
  869. object.triggerEvent('folder-created',{path:data.path,folder:data.folder,response:response});
  870. $('.folder-name',object.dom.panels.search).val('').focus();
  871. $('.new-folder-block',object.dom.panels.search).toggleClass('hidden');
  872. $('.dropdown-menu',object.dom.panels.search).trigger('click');
  873. object.element_search();
  874. });
  875. }
  876. new_folder(event){
  877. var object = this;
  878. $('.new-folder-block',object.dom.panels.search).toggleClass('hidden');
  879. $('.new-folder-block input',object.dom.panels.search).focus().enter(function(){object.folder_create()});
  880. event.stopPropagation();
  881. }
  882. /** ELEMENT **/
  883. element_rename_edit(button){
  884. var object = this;
  885. var button = $(button);
  886. var span = button.prev('span');
  887. var text = span.find('span');
  888. var tr = span.closest('.file-element');
  889. var label = span.find('span').text();
  890. var input = $('.rename-input',tr);
  891. //adapte la largeur de l'input à la largeur du texte avec un max de 320 px et un min de 45px
  892. var width = Math.min(Math.max(text.width(),45),320);
  893. button.addClass('hidden');
  894. text.addClass('hidden');
  895. input.removeClass('hidden')
  896. .focus()
  897. .val(label)
  898. .width(width+15)
  899. .click(function(event){
  900. event.stopPropagation();
  901. });
  902. }
  903. // Met à jour l'arborescence (supprime la line dans l'arborescence sur move ou rename)
  904. remove_treeline(from){
  905. var parent = $('.folder-focused ul');
  906. if(parent.length == 0) parent = $('.tree-panel > ul');
  907. $('li',parent).each(function(i,li){
  908. var li = $(li);
  909. if(li.attr('data-path') == from.attr('data-path')) {
  910. li.remove();
  911. }
  912. });
  913. }
  914. //Récuperation d'une liste de element dans le tableau elements
  915. element_preview(element, event){
  916. var object = this;
  917. var line = $(element);
  918. if(line.hasClass('element-focused')) return;
  919. object.selected = {
  920. element : line,
  921. path : line.attr('data-path'),
  922. type : line.attr('data-type'),
  923. id : line.attr('data-id')
  924. }
  925. $('.right-panel',object.dom.panels.detail).addClass('hidden');
  926. $('.detail-buttons',object.dom.panels.detail).removeClass('hidden');
  927. if(object.selected.type =='directory') {
  928. $('.detail-buttons > .directory-button',object.dom.panels.detail).removeClass('hidden');
  929. }else{
  930. $('.detail-buttons > .directory-button',object.dom.panels.detail).addClass('hidden');
  931. }
  932. $('.detail-buttons > li:visible',object.dom.panels.detail).remove();
  933. var buttonTemplate = $('.detail-buttons > li:eq(0).hidden').get(0).outerHTML;
  934. if(object.options.panels.detail.buttons){
  935. for(var i in object.options.panels.detail.buttons){
  936. var data = object.options.panels.detail.buttons[i];
  937. if(data.visibility && data.visibility.indexOf(object.selected.type) == -1 ) continue;
  938. var button = $(Mustache.render(buttonTemplate,data));
  939. button.removeClass('hidden');
  940. $('.detail-buttons').append(button);
  941. }
  942. }
  943. //autoblur sur le rename d'un fichier en cours si existant
  944. var currentRename = $('.file-view:visible .file-element .rename-input:visible');
  945. if(currentRename.length>0) currentRename.trigger('blur');
  946. $('.file-view:visible .file-element',object.dom.panels.files).removeClass('element-focused');
  947. line.addClass('element-focused');
  948. $('.detail-thumbnail .thumbnail-preloader',object.dom.panels.detail).addClass('show');
  949. $.action({
  950. action : object.options.actions.element_preview,
  951. path : line.attr('data-path'),
  952. },function(response){
  953. setTimeout(function(){
  954. $('.detail-thumbnail .thumbnail-preloader',object.dom.panels.detail).removeClass('show');
  955. },100);
  956. $('.detail-thumbnail',object.dom.panels.detail).css('background-image','url('+response.row.thumbnail+')');
  957. var substrings = ['.jpg','.jpeg','.bmp','.gif','.png'];
  958. $('.detail-thumbnail',object.dom.panels.detail).css('background-size','');
  959. if (new RegExp(substrings.join("|")).test(response.row.thumbnail))
  960. $('.detail-thumbnail',object.dom.panels.detail).css('background-size','contain');
  961. $('> h1',object.dom.panels.detail).html(response.row.label).text();
  962. var size = response.row.sizeReadable;
  963. if(response.row.type == 'directory') size = response.row.childNumber+' élement'+(response.row.childNumber>1?'s':'');
  964. $('> small > span',object.dom.panels.detail).text(size+", "+response.row.updatedRelative);
  965. object.triggerEvent('selected',object.selected);
  966. });
  967. }
  968. //Suppression d'un élément de la GED
  969. element_delete(){
  970. var object = this;
  971. if($('span .rename-input:visible',object.selected.element).length) return;
  972. if(object.selected == null) {
  973. $.message('info', 'Sélectionnez d\'abord un élément à supprimer');
  974. return;
  975. }
  976. if(!confirm('Êtes-vous sûr de vouloir supprimer cet élément ?')) return;
  977. $.action({
  978. action : object.options.actions.element_delete,
  979. path : object.selected.path,
  980. },function(response){
  981. object.triggerEvent('deleted',{
  982. element : object.selected.element,
  983. response : response,
  984. path : object.selected.path,
  985. });
  986. object.selected.element.remove();
  987. object.reset_preview();
  988. });
  989. }
  990. element_share_edit(){
  991. var object = this;
  992. if($('span .rename-input:visible',object.selected.element).length) return;
  993. if(object.selected == null) {
  994. $.message('info', 'Sélectionnez d\'abord un élément à partager');
  995. return;
  996. }
  997. $.action({
  998. action : object.options.actions.element_share_edit,
  999. path : object.selected.path,
  1000. });
  1001. }
  1002. //edition d'un fichier texte en ligne
  1003. element_edit(path){
  1004. var object = this;
  1005. $('.file-editor-name',object.dom.panels.file).val('Nouveau Fichier.txt');
  1006. $('.file-editor-input',object.dom.panels.file).val('');
  1007. if(path){
  1008. $('.file-editor-input',object.dom.panels.file).val('Chargement en cours...');
  1009. $.action({
  1010. action : object.options.actions.element_edit,
  1011. path : path,
  1012. },function(r){
  1013. $('.file-editor-name',object.dom.panels.file).val(r.label);
  1014. $('.file-editor-input',object.dom.panels.file).val(r.content);
  1015. });
  1016. }
  1017. $('.file-editor',object.dom.panels.file).removeClass('hidden');
  1018. $('.file-editor-input',object.dom.panels.file).focus();
  1019. }
  1020. //edition d'un fichier texte en ligne
  1021. element_edit_save(){
  1022. var object = this;
  1023. $.action({
  1024. action : object.options.actions.element_save,
  1025. label : $('.file-editor-name',object.dom.panels.file).val(),
  1026. content : $('.file-editor-input',object.dom.panels.file).val(),
  1027. path : object.currentFolder,
  1028. },function(r){
  1029. $('.file-editor',object.dom.panels.file).addClass('hidden');
  1030. object.element_search();
  1031. });
  1032. }
  1033. //Récuperation d'une liste de element dans le tableau elements
  1034. element_execute(element){
  1035. var object = this;
  1036. var inputSearch = $('.label-search',object.dom.panels.search);
  1037. if(inputSearch.val().length) {
  1038. inputSearch.val('').blur();
  1039. $(".search-clear",object.dom.panels.search).removeAttr('style');
  1040. }
  1041. var line = $(element);
  1042. if(line.attr('data-type') == 'directory'){
  1043. object.element_search(line.attr('data-path'));
  1044. object.triggerEvent('opened',{
  1045. element : line,
  1046. path : line.attr('data-path')
  1047. });
  1048. return;
  1049. }
  1050. object.triggerEvent('executed',{
  1051. element : line,
  1052. path : line.attr('data-path')
  1053. });
  1054. var ext = object.selected.path.split('.').pop();
  1055. switch(ext){
  1056. case 'txt':
  1057. object.element_edit(object.selected.path);
  1058. break;
  1059. default:
  1060. object.element_download(line);
  1061. break;
  1062. }
  1063. }
  1064. // Téléchargement d'un élément de la GED
  1065. element_download(line,forceDownload){
  1066. var object = this;
  1067. var line = line ? line : object.selected.element;
  1068. if(line.length == 0) return $.message('info', 'Sélectionnez d\'abord un élément à télécharger');
  1069. object.triggerEvent('downloaded',{
  1070. element : line,
  1071. path : line.attr('data-path')
  1072. });
  1073. var url = 'action.php?action='+object.options.actions.element_execute+'&path='+encodeURIComponent(btoa(line.attr('data-path')));
  1074. if(forceDownload) url+= '&download';
  1075. window.open(url, '_blank');
  1076. }
  1077. /** PROPERTIES **/
  1078. properties_show(){
  1079. var object = this;
  1080. var modal = $('.document-properties-modal');
  1081. var tpl = $('.modal-body-template',modal).html();
  1082. modal.modal('show');
  1083. $('.modal-body',modal).html('Chargement...');
  1084. $.action({
  1085. action : object.options.actions.properties_show,
  1086. id : object.selected.id
  1087. },function(r){
  1088. $('.modal-body',modal).html(Mustache.render(tpl,r.row));
  1089. init_components(modal);
  1090. object.triggerEvent('properties-showed',{
  1091. modal : modal,
  1092. id : object.selected.id
  1093. });
  1094. });
  1095. }
  1096. /** ELEMENTRIGHT **/
  1097. //Récuperation d'une liste de elementright dans le tableau elementrights
  1098. right_toggle(){
  1099. var object = this;
  1100. $('.right-panel',object.dom.panels.detail).toggleClass('hidden');
  1101. init_components('.element-right-form');
  1102. this.right_search();
  1103. }
  1104. //Récuperation d'une liste de elementright dans le tableau elementrights
  1105. right_search(callback){
  1106. var object = this;
  1107. if(object.selected == null) return;
  1108. $('.element-rights').fill({
  1109. action:object.options.actions.right_search,
  1110. id : object.selected.id
  1111. },function(){
  1112. if(callback!=null) callback();
  1113. });
  1114. }
  1115. //Ajout ou modification d'élément elementright
  1116. right_save(){
  1117. var object = this;
  1118. var data = {
  1119. uid : $('.element-right-form input.uid').val(),
  1120. read : $('.element-right-form .read').val(),
  1121. edit : $('.element-right-form .edit').val(),
  1122. recursive : $('.element-right-form .recursive').val()
  1123. }
  1124. data.action = object.options.actions.right_save;
  1125. data.element = object.selected.id;
  1126. $.action(data,function(r){
  1127. $.message('success','Enregistré');
  1128. $('.uid').val('');
  1129. $('.read,.edit,.recursive').prop('checked',false);
  1130. init_components('.element-right-form');
  1131. object.right_search();
  1132. data.id = object.selected.id;
  1133. data.element = object.selected.element;
  1134. object.triggerEvent('right-saved',data);
  1135. });
  1136. }
  1137. //Suppression d'élement elementright
  1138. right_delete(element){
  1139. var object = this;
  1140. if(!confirm('Êtes-vous sûr de vouloir supprimer ce droit ?')) return;
  1141. var line = $(element).closest('li');
  1142. $.action({
  1143. action : object.options.actions.right_delete,
  1144. id : line.attr('data-id')
  1145. },function(r){
  1146. object.triggerEvent('right-deleted',{id:line.attr('data-id'),element:line});
  1147. line.remove();
  1148. });
  1149. }
  1150. //Ajoute un callback sur un evenement de la ged particulier
  1151. on(event,callback){
  1152. if(!this.onEvents[event])this.onEvents[event] = [];
  1153. this.onEvents[event].push(callback);
  1154. }
  1155. /* Gestion des vues */
  1156. //Change la vue courante
  1157. view(view){
  1158. var object = this;
  1159. object.currentView = view;
  1160. object.renderView();
  1161. object.triggerEvent('view-loaded',{view:view});
  1162. }
  1163. //Ajoute une vue custom
  1164. addView(data){
  1165. var object = this;
  1166. data.html = $(data.html);
  1167. data.html.attr('data-view',data.uid);
  1168. if(!data.html.hasClass('file-view')) data.html.addClass('file-view');
  1169. object.views.push(data);
  1170. }
  1171. //affiche le rendu de la vue courante (object.currentView)
  1172. renderView(){
  1173. var object = this;
  1174. if(!object.dom.panels.files) return;
  1175. $('.file-view',object.dom.panels.files).addClass('hidden');
  1176. var viewElement = $('.file-view[data-view="'+object.currentView+'"]');
  1177. $(object.dom.panels.files).attr('data-view',object.currentView);
  1178. $('.view-module > li',object.dom.panels.search).removeClass('selected');
  1179. $('.view-module > li[data-view="'+object.currentView+'"]',object.dom.panels.search).addClass('selected');
  1180. viewElement.removeClass('hidden');
  1181. object.element_search();
  1182. }
  1183. //charge toutes les vues disponibles dans le dom
  1184. loadViews(){
  1185. var object = this;
  1186. //Chargement des bouttons de vue
  1187. $('.view-module > li:visible',object.dom.panels.search).remove();
  1188. var tpl = $('.view-module > li.hidden',object.dom.panels.search).get(0).outerHTML;
  1189. for(var key in object.views){
  1190. var view = object.views[key];
  1191. var button = $(Mustache.render(tpl, view));
  1192. button.removeClass('hidden');
  1193. $('.view-module',object.dom.panels.search).append(button);
  1194. button.click(function(){
  1195. object.view($(this).attr('data-view'));
  1196. });
  1197. if($('.file-view[data-view="'+view.uid+'"]',object.dom.panels.files).length==0)
  1198. object.dom.panels.files.append(view.html);
  1199. }
  1200. }
  1201. }