files_renderer.php 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913
  1. <?php
  2. // This file is part of The Bootstrap 3 Moodle theme
  3. //
  4. // Moodle is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // Moodle is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
  16. /**
  17. * Rendering of files viewer related widgets.
  18. *
  19. * @package theme_bootstrap
  20. * @copyright 2012
  21. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  22. */
  23. defined('MOODLE_INTERNAL') || die();
  24. require_once($CFG->dirroot . "/files/renderer.php");
  25. class theme_bootstrap_core_files_renderer extends core_files_renderer {
  26. /**
  27. * Returns html for displaying one file manager
  28. *
  29. * The main element in HTML must have id="filemanager-{$client_id}" and
  30. * class="filemanager fm-loading";
  31. * After all necessary code on the page (both html and javascript) is loaded,
  32. * the class fm-loading will be removed and added class fm-loaded;
  33. * The main element (class=filemanager) will be assigned the following classes:
  34. * 'fm-maxfiles' - when filemanager has maximum allowed number of files;
  35. * 'fm-nofiles' - when filemanager has no files at all (although there might be folders);
  36. * 'fm-noitems' - when current view (folder) has no items - neither files nor folders;
  37. * 'fm-updating' - when current view is being updated (usually means that loading icon is to be displayed);
  38. * 'fm-nomkdir' - when 'Make folder' action is unavailable (empty($fm->options->subdirs) == true)
  39. *
  40. * Element with class 'filemanager-container' will be holding evens for dnd upload (dragover, etc.).
  41. * It will have class:
  42. * 'dndupload-ready' - when a file is being dragged over the browser
  43. * 'dndupload-over' - when file is being dragged over this filepicker (additional to 'dndupload-ready')
  44. * 'dndupload-uploading' - during the upload process (note that after dnd upload process is
  45. * over, the file manager will refresh the files list and therefore will have for a while class
  46. * fm-updating. Both waiting processes should look similar so the images don't jump for user)
  47. *
  48. * If browser supports Drag-and-drop, the body element will have class 'dndsupported',
  49. * otherwise - 'dndnotsupported';
  50. *
  51. * Element with class 'fp-content' will be populated with files list;
  52. * Element with class 'fp-btn-add' will hold onclick event for adding a file (opening filepicker);
  53. * Element with class 'fp-btn-mkdir' will hold onclick event for adding new folder;
  54. * Element with class 'fp-btn-download' will hold onclick event for download action;
  55. *
  56. * Element with class 'fp-path-folder' is a template for one folder in path toolbar.
  57. * It will hold mouse click event and will be assigned classes first/last/even/odd respectfully.
  58. * Parent element will receive class 'empty' when there are no folders to be displayed;
  59. * The content of subelement with class 'fp-path-folder-name' will be substituted with folder name;
  60. *
  61. * Element with class 'fp-viewbar' will have the class 'enabled' or 'disabled' when view mode
  62. * can be changed or not;
  63. * Inside element with class 'fp-viewbar' there are expected elements with classes
  64. * 'fp-vb-icons', 'fp-vb-tree' and 'fp-vb-details'. They will handle onclick events to switch
  65. * between the view modes, the last clicked element will have the class 'checked';
  66. *
  67. * @param form_filemanager $fm
  68. * @return string
  69. */
  70. private function fm_print_generallayout($fm) {
  71. global $OUTPUT;
  72. $options = $fm->options;
  73. $client_id = $options->client_id;
  74. $straddfile = get_string('addfile', 'repository');
  75. $strmakedir = get_string('makeafolder', 'moodle');
  76. $strdownload = get_string('downloadfolder', 'repository');
  77. $strloading = get_string('loading', 'repository');
  78. $strdroptoupload = get_string('droptoupload', 'moodle');
  79. $icon_progress = $OUTPUT->pix_icon('i/loading_small', $strloading).'';
  80. $restrictions = $this->fm_print_restrictions($fm);
  81. $strdndnotsupported = get_string('dndnotsupported_insentence', 'moodle').$OUTPUT->help_icon('dndnotsupported');
  82. $strdndenabledinbox = get_string('dndenabled_inbox', 'moodle');
  83. $loading = get_string('loading', 'repository');
  84. $html = '
  85. <div id="filemanager-'.$client_id.'" class="filemanager fm-loading">
  86. <div class="fp-restrictions">
  87. '.$restrictions.'
  88. <span class="dnduploadnotsupported-message"> - '.$strdndnotsupported.' </span>
  89. </div>
  90. <div class="fp-navbar">
  91. <div class="filemanager-toolbar">
  92. <div class="fp-toolbar">
  93. <div class="fp-btn-add">
  94. <a role="button" title="'.$straddfile.'" href="#"><img src="'.$this->pix_url('a/add_file').'" alt="" /></a>
  95. </div>
  96. <div class="fp-btn-mkdir">
  97. <a role="button" title="'.$strmakedir.'" href="#"><img src="'.$this->pix_url('a/create_folder').'" alt="" /></a>
  98. </div>
  99. <div class="fp-btn-download">
  100. <a role="button" title="'.$strdownload.'" href="#"><img src="'.$this->pix_url('a/download_all').'" alt="" /></a>
  101. </div>
  102. </div>
  103. <div class="fp-viewbar">
  104. <a title="'. get_string('displayicons', 'repository') .'" class="fp-vb-icons" href="#">
  105. <img alt="" src="'. $this->pix_url('fp/view_icon_active', 'theme') .'" />
  106. </a>
  107. <a title="'. get_string('displaydetails', 'repository') .'" class="fp-vb-details" href="#">
  108. <img alt="" src="'. $this->pix_url('fp/view_list_active', 'theme') .'" />
  109. </a>
  110. <a title="'. get_string('displaytree', 'repository') .'" class="fp-vb-tree" href="#">
  111. <img alt="" src="'. $this->pix_url('fp/view_tree_active', 'theme') .'" />
  112. </a>
  113. </div>
  114. </div>
  115. <div class="fp-pathbar">
  116. <span class="fp-path-folder"><a class="fp-path-folder-name" href="#"></a></span>
  117. </div>
  118. </div>
  119. <div class="filemanager-loading mdl-align">'.$icon_progress.'</div>
  120. <div class="filemanager-container" >
  121. <div class="fm-content-wrapper">
  122. <div class="fp-content"></div>
  123. <div class="fm-empty-container">
  124. <div class="dndupload-message">'.$strdndenabledinbox.'<br/><div class="dndupload-arrow"></div></div>
  125. </div>
  126. <div class="dndupload-target">'.$strdroptoupload.'<br/><div class="dndupload-arrow"></div></div>
  127. <div class="dndupload-progressbars"></div>
  128. <div class="dndupload-uploadinprogress">'.$icon_progress.'</div>
  129. </div>
  130. <div class="filemanager-updating">'.$icon_progress.'</div>
  131. </div>
  132. </div>';
  133. return $html;
  134. }
  135. /**
  136. * FileManager JS template for displaying one file in 'icon view' mode.
  137. *
  138. * Except for elements described in fp_js_template_iconfilename, this template may also
  139. * contain element with class 'fp-contextmenu'. If context menu is available for this
  140. * file, the top element will receive the additional class 'fp-hascontextmenu' and
  141. * the element with class 'fp-contextmenu' will hold onclick event for displaying
  142. * the context menu.
  143. *
  144. * @see fp_js_template_iconfilename()
  145. * @return string
  146. */
  147. private function fm_js_template_iconfilename() {
  148. $rv = '
  149. <div class="fp-file">
  150. <a href="#">
  151. <div style="position:relative;">
  152. <div class="fp-thumbnail"></div>
  153. <div class="fp-reficons1"></div>
  154. <div class="fp-reficons2"></div>
  155. </div>
  156. <div class="fp-filename-field">
  157. <div class="fp-filename"></div>
  158. </div>
  159. </a>
  160. <a class="fp-contextmenu" href="#">'.$this->pix_icon('i/menu', '▶').'</a>
  161. </div>';
  162. return $rv;
  163. }
  164. /**
  165. * FileManager JS template for displaying file name in 'table view' and 'tree view' modes.
  166. *
  167. * Except for elements described in fp_js_template_listfilename, this template may also
  168. * contain element with class 'fp-contextmenu'. If context menu is available for this
  169. * file, the top element will receive the additional class 'fp-hascontextmenu' and
  170. * the element with class 'fp-contextmenu' will hold onclick event for displaying
  171. * the context menu.
  172. *
  173. * @todo MDL-32736 remove onclick="return false;"
  174. * @see fp_js_template_listfilename()
  175. * @return string
  176. */
  177. private function fm_js_template_listfilename() {
  178. $rv = '
  179. <span class="fp-filename-icon">
  180. <a href="#">
  181. <span class="fp-icon"></span>
  182. <span class="fp-reficons1"></span>
  183. <span class="fp-reficons2"></span>
  184. <span class="fp-filename"></span>
  185. </a>
  186. <a class="fp-contextmenu" href="#" onclick="return false;">'.$this->pix_icon('i/menu', '▶').'</a>
  187. </span>';
  188. return $rv;
  189. }
  190. /**
  191. * FileManager JS template for displaying 'Make new folder' dialog.
  192. *
  193. * Must be wrapped in an element, CSS for this element must define width and height of the window;
  194. *
  195. * Must have one input element with type="text" (for users to enter the new folder name);
  196. *
  197. * content of element with class 'fp-dlg-curpath' will be replaced with current path where
  198. * new folder is about to be created;
  199. * elements with classes 'fp-dlg-butcreate' and 'fp-dlg-butcancel' will hold onclick events;
  200. *
  201. * @return string
  202. */
  203. private function fm_js_template_mkdir() {
  204. $rv = '
  205. <div class="filemanager fp-mkdir-dlg" role="dialog" aria-live="assertive" aria-labelledby="fp-mkdir-dlg-title">
  206. <div class="fp-mkdir-dlg-text">
  207. <label id="fp-mkdir-dlg-title">' . get_string('newfoldername', 'repository') . '</label><br/>
  208. <input type="text" />
  209. </div>
  210. <button class="fp-dlg-butcreate btn-primary btn">'.get_string('makeafolder').'</button>
  211. <button class="fp-dlg-butcancel btn-default btn">'.get_string('cancel').'</button>
  212. </div>';
  213. return $rv;
  214. }
  215. /**
  216. * FileManager JS template for error/info message displayed as a separate popup window.
  217. *
  218. * @see fp_js_template_message()
  219. * @return string
  220. */
  221. private function fm_js_template_message() {
  222. return $this->fp_js_template_message();
  223. }
  224. /**
  225. * FileManager JS template for window with file information/actions.
  226. *
  227. * All content must be enclosed in one element, CSS for this class must define width and
  228. * height of the window;
  229. *
  230. * Thumbnail image will be added as content to the element with class 'fp-thumbnail';
  231. *
  232. * Inside the window the elements with the following classnames must be present:
  233. * 'fp-saveas', 'fp-author', 'fp-license', 'fp-path'. Inside each of them must be
  234. * one input element (or select in case of fp-license and fp-path). They may also have labels.
  235. * The elements will be assign with class 'uneditable' and input/select element will become
  236. * disabled if they are not applicable for the particular file;
  237. *
  238. * There may be present elements with classes 'fp-original', 'fp-datemodified', 'fp-datecreated',
  239. * 'fp-size', 'fp-dimensions', 'fp-reflist'. They will receive additional class 'fp-unknown' if
  240. * information is unavailable. If there is information available, the content of embedded
  241. * element with class 'fp-value' will be substituted with the value;
  242. *
  243. * The value of Original ('fp-original') is loaded in separate request. When it is applicable
  244. * but not yet loaded the 'fp-original' element receives additional class 'fp-loading';
  245. *
  246. * The value of 'Aliases/Shortcuts' ('fp-reflist') is also loaded in separate request. When it
  247. * is applicable but not yet loaded the 'fp-original' element receives additional class
  248. * 'fp-loading'. The string explaining that XX references exist will replace content of element
  249. * 'fp-refcount'. Inside '.fp-reflist .fp-value' each reference will be enclosed in <li>;
  250. *
  251. * Elements with classes 'fp-file-update', 'fp-file-download', 'fp-file-delete', 'fp-file-zip',
  252. * 'fp-file-unzip', 'fp-file-setmain' and 'fp-file-cancel' will hold corresponding onclick
  253. * events (there may be several elements with class 'fp-file-cancel');
  254. *
  255. * When confirm button is pressed and file is being selected, the top element receives
  256. * additional class 'loading'. It is removed when response from server is received.
  257. *
  258. * When any of the input fields is changed, the top element receives class 'fp-changed';
  259. * When current file can be set as main - top element receives class 'fp-cansetmain';
  260. * When current file is folder/zip/file - top element receives respectfully class
  261. * 'fp-folder'/'fp-zip'/'fp-file';
  262. *
  263. * @return string
  264. */
  265. private function fm_js_template_fileselectlayout() {
  266. global $OUTPUT;
  267. $strloading = get_string('loading', 'repository');
  268. $iconprogress = $this->pix_icon('i/loading_small', $strloading).'';
  269. $rv = '
  270. <div class="filemanager fp-select">
  271. <div class="fp-select-loading">
  272. <img src="'.$this->pix_url('i/loading_small').'" />
  273. </div>
  274. <form class="form-horizontal">
  275. <button class="fp-file-download">'.get_string('download').'</button>
  276. <button class="fp-file-delete">'.get_string('delete').'</button>
  277. <button class="fp-file-setmain">'.get_string('setmainfile', 'repository').'</button>
  278. <span class="fp-file-setmain-help">'.$OUTPUT->help_icon('setmainfile', 'repository').'</span>
  279. <button class="fp-file-zip">'.get_string('zip', 'editor').'</button>
  280. <button class="fp-file-unzip">'.get_string('unzip').'</button>
  281. <div class="fp-hr"></div>
  282. <div class="fp-forminset">
  283. <div class="fp-saveas form-group">
  284. <label class="control-label col-md-4">'.get_string('name', 'moodle').':</label>
  285. <div class="controls col-md-8">
  286. <input type="text"/>
  287. </div>
  288. </div>
  289. <div class="fp-author form-group">
  290. <label class="control-label col-md-4">'.get_string('author', 'repository').'</label>
  291. <div class="controls col-md-8">
  292. <input type="text"/>
  293. </div>
  294. </div>
  295. <div class="fp-license form-group">
  296. <label class="control-label col-md-4">'.get_string('chooselicense', 'repository').'</label>
  297. <div class="controls col-md-8">
  298. <select></select>
  299. </div>
  300. </div>
  301. <div class="fp-path form-group">
  302. <label class="control-label col-md-4">'.get_string('path', 'moodle').':</label>
  303. <div class="controls col-md-8">
  304. <select></select>
  305. </div>
  306. </div>
  307. <div class="fp-original form-group">
  308. <label class="control-label col-md-4">'.get_string('original', 'repository').'</label>
  309. <div class="controls col-md-8">
  310. <span class="fp-originloading">'.$iconprogress.' '.$strloading.'</span><span class="fp-value"></span>
  311. </div>
  312. </div>
  313. <div class="fp-reflist form-group">
  314. <label class="control-label col-md-4">'.get_string('referenceslist', 'repository').'</label>
  315. <div class="controls col-md-8">
  316. <p class="fp-refcount"></p>
  317. <span class="fp-reflistloading">'.$iconprogress.' '.$strloading.'</span>
  318. <ul class="fp-value"></ul>
  319. </div>
  320. </div>
  321. </div>
  322. <div class="fp-select-buttons">
  323. <button class="fp-file-update btn-primary btn">'.get_string('update', 'moodle').'</button>
  324. <button class="fp-file-cancel btn-default btn">'.get_string('cancel').'</button>
  325. </div>
  326. </form>
  327. <div class="fp-info clearfix">
  328. <div class="fp-hr"></div>
  329. <p class="fp-thumbnail"></p>
  330. <div class="fp-fileinfo">
  331. <div class="fp-datemodified">'.get_string('lastmodified', 'moodle').': <span class="fp-value"></span></div>
  332. <div class="fp-datecreated">'.get_string('datecreated', 'repository').' <span class="fp-value"></span></div>
  333. <div class="fp-size">'.get_string('size', 'repository').' <span class="fp-value"></span></div>
  334. <div class="fp-dimensions">'.get_string('dimensions', 'repository').' <span class="fp-value"></span></div>
  335. </div>
  336. </div>
  337. </div>';
  338. return $rv;
  339. }
  340. /**
  341. * FileManager JS template for popup confirm dialogue window.
  342. *
  343. * Must have one top element, CSS for this element must define width and height of the window;
  344. *
  345. * content of element with class 'fp-dlg-text' will be replaced with dialog text;
  346. * elements with classes 'fp-dlg-butconfirm' and 'fp-dlg-butcancel' will
  347. * hold onclick events;
  348. *
  349. * @return string
  350. */
  351. private function fm_js_template_confirmdialog() {
  352. $rv = '
  353. <div class="filemanager fp-dlg">
  354. <div class="fp-dlg-text"></div>
  355. <button class="fp-dlg-butconfirm btn-primary btn">'.get_string('ok').'</button>
  356. <button class="fp-dlg-butcancel btn-default btn">'.get_string('cancel').'</button>
  357. </div>';
  358. return $rv;
  359. }
  360. /**
  361. * Returns all FileManager JavaScript templates as an array.
  362. *
  363. * @return array
  364. */
  365. public function filemanager_js_templates() {
  366. $class_methods = get_class_methods($this);
  367. $templates = array();
  368. foreach ($class_methods as $method_name) {
  369. if (preg_match('/^fm_js_template_(.*)$/', $method_name, $matches))
  370. $templates[$matches[1]] = $this->$method_name();
  371. }
  372. return $templates;
  373. }
  374. /**
  375. * Template for FilePicker with general layout (not QuickUpload).
  376. *
  377. * Must have one top element containing everything else (recommended <div class="file-picker">),
  378. * CSS for this element must define width and height of the filepicker window. Or CSS must
  379. * define min-width, max-width, min-height and max-height and in this case the filepicker
  380. * window will be resizeable;
  381. *
  382. * Element with class 'fp-viewbar' will have the class 'enabled' or 'disabled' when view mode
  383. * can be changed or not;
  384. * Inside element with class 'fp-viewbar' there are expected elements with classes
  385. * 'fp-vb-icons', 'fp-vb-tree' and 'fp-vb-details'. They will handle onclick events to switch
  386. * between the view modes, the last clicked element will have the class 'checked';
  387. *
  388. * Element with class 'fp-repo' is a template for displaying one repository. Other repositories
  389. * will be attached as siblings (classes first/last/even/odd will be added respectfully).
  390. * The currently selected repostory will have class 'active'. Contents of element with class
  391. * 'fp-repo-name' will be replaced with repository name, source of image with class
  392. * 'fp-repo-icon' will be replaced with repository icon;
  393. *
  394. * Element with class 'fp-content' is obligatory and will hold the current contents;
  395. *
  396. * Element with class 'fp-paging' will contain page navigation (will be deprecated soon);
  397. *
  398. * Element with class 'fp-path-folder' is a template for one folder in path toolbar.
  399. * It will hold mouse click event and will be assigned classes first/last/even/odd respectfully.
  400. * Parent element will receive class 'empty' when there are no folders to be displayed;
  401. * The content of subelement with class 'fp-path-folder-name' will be substituted with folder name;
  402. *
  403. * Element with class 'fp-toolbar' will have class 'empty' if all 'Back', 'Search', 'Refresh',
  404. * 'Logout', 'Manage' and 'Help' are unavailable for this repo;
  405. *
  406. * Inside fp-toolbar there are expected elements with classes fp-tb-back, fp-tb-search,
  407. * fp-tb-refresh, fp-tb-logout, fp-tb-manage and fp-tb-help. Each of them will have
  408. * class 'enabled' or 'disabled' if particular repository has this functionality.
  409. * Element with class 'fp-tb-search' must contain empty form inside, it's contents will
  410. * be substituted with the search form returned by repository (in the most cases it
  411. * is generated with template core_repository_renderer::repository_default_searchform);
  412. * Other elements must have either <a> or <button> element inside, it will hold onclick
  413. * event for corresponding action; labels for fp-tb-back and fp-tb-logout may be
  414. * replaced with those specified by repository;
  415. *
  416. * @return string
  417. */
  418. private function fp_js_template_generallayout() {
  419. $rv = '
  420. <div tabindex="0" class="file-picker fp-generallayout" role="dialog" aria-live="assertive">
  421. <div class="fp-repo-area">
  422. <ul class="fp-list">
  423. <li class="fp-repo">
  424. <a href="#"><img class="fp-repo-icon" alt=" " width="16" height="16" />&nbsp;<span class="fp-repo-name"></span></a>
  425. </li>
  426. </ul>
  427. </div>
  428. <div class="fp-repo-items" tabindex="0">
  429. <div class="fp-navbar">
  430. <div>
  431. <div class="fp-toolbar">
  432. <div class="fp-tb-back">
  433. <a href="#">'.get_string('back', 'repository').'</a>
  434. </div>
  435. <div class="fp-tb-search">
  436. <form></form>
  437. </div>
  438. <div class="fp-tb-refresh">
  439. <a title="'. get_string('refresh', 'repository') .'" href="#">
  440. <img alt="" src="'.$this->pix_url('a/refresh').'" />
  441. </a>
  442. </div>
  443. <div class="fp-tb-logout">
  444. <a title="'. get_string('logout', 'repository') .'" href="#">
  445. <img alt="" src="'.$this->pix_url('a/logout').'" />
  446. </a>
  447. </div>
  448. <div class="fp-tb-manage">
  449. <a title="'. get_string('settings', 'repository') .'" href="#">
  450. <img alt="" src="'.$this->pix_url('a/setting').'" />
  451. </a>
  452. </div>
  453. <div class="fp-tb-help">
  454. <a title="'. get_string('help', 'repository') .'" href="#">
  455. <img alt="" src="'.$this->pix_url('a/help').'" />
  456. </a>
  457. </div>
  458. <div class="fp-tb-message"></div>
  459. </div>
  460. <div class="fp-viewbar">
  461. <a title="'. get_string('displayicons', 'repository') .'" class="fp-vb-icons" href="#">
  462. <img alt="" src="'. $this->pix_url('fp/view_icon_active', 'theme') .'" />
  463. </a>
  464. <a title="'. get_string('displaydetails', 'repository') .'" class="fp-vb-details" href="#">
  465. <img alt="" src="'. $this->pix_url('fp/view_list_active', 'theme') .'" />
  466. </a>
  467. <a title="'. get_string('displaytree', 'repository') .'" class="fp-vb-tree" href="#">
  468. <img alt="" src="'. $this->pix_url('fp/view_tree_active', 'theme') .'" />
  469. </a>
  470. </div>
  471. <div class="fp-clear-left"></div>
  472. </div>
  473. <div class="fp-pathbar">
  474. <span class="fp-path-folder"><a class="fp-path-folder-name" href="#"></a></span>
  475. </div>
  476. </div>
  477. <div class="fp-content"></div>
  478. </div>
  479. </div>';
  480. return $rv;
  481. }
  482. /**
  483. * FilePicker JS template for displaying one file in 'icon view' mode.
  484. *
  485. * the element with class 'fp-thumbnail' will be resized to the repository thumbnail size
  486. * (both width and height, unless min-width and/or min-height is set in CSS) and the content of
  487. * an element will be replaced with an appropriate img;
  488. *
  489. * the width of element with class 'fp-filename' will be set to the repository thumbnail width
  490. * (unless min-width is set in css) and the content of an element will be replaced with filename
  491. * supplied by repository;
  492. *
  493. * top element(s) will have class fp-folder if the element is a folder;
  494. *
  495. * List of files will have parent <div> element with class 'fp-iconview'
  496. *
  497. * @return string
  498. */
  499. private function fp_js_template_iconfilename() {
  500. $rv = '
  501. <a class="fp-file" href="#" >
  502. <div style="position:relative;">
  503. <div class="fp-thumbnail"></div>
  504. <div class="fp-reficons1"></div>
  505. <div class="fp-reficons2"></div>
  506. </div>
  507. <div class="fp-filename-field">
  508. <p class="fp-filename"></p>
  509. </div>
  510. </a>';
  511. return $rv;
  512. }
  513. /**
  514. * FilePicker JS template for displaying file name in 'table view' and 'tree view' modes.
  515. *
  516. * content of the element with class 'fp-icon' will be replaced with an appropriate img;
  517. *
  518. * content of element with class 'fp-filename' will be replaced with filename supplied by
  519. * repository;
  520. *
  521. * top element(s) will have class fp-folder if the element is a folder;
  522. *
  523. * Note that tree view and table view are the YUI widgets and therefore there are no
  524. * other templates. The widgets will be wrapped in <div> with class fp-treeview or
  525. * fp-tableview (respectfully).
  526. *
  527. * @return string
  528. */
  529. private function fp_js_template_listfilename() {
  530. $rv = '
  531. <span class="fp-filename-icon">
  532. <a href="#">
  533. <span class="fp-icon"></span>
  534. <span class="fp-filename"></span>
  535. </a>
  536. </span>';
  537. return $rv;
  538. }
  539. /**
  540. * FilePicker JS template for displaying link/loading progress for fetching of the next page
  541. *
  542. * This text is added to .fp-content AFTER .fp-iconview/.fp-treeview/.fp-tableview
  543. *
  544. * Must have one parent element with class 'fp-nextpage'. It will be assigned additional
  545. * class 'loading' during loading of the next page (it is recommended that in this case the link
  546. * becomes unavailable). Also must contain one element <a> or <button> that will hold
  547. * onclick event for displaying of the next page. The event will be triggered automatically
  548. * when user scrolls to this link.
  549. *
  550. * @return string
  551. */
  552. private function fp_js_template_nextpage() {
  553. $rv = '
  554. <div class="fp-nextpage">
  555. <div class="fp-nextpage-link"><a href="#">'.get_string('more').'</a></div>
  556. <div class="fp-nextpage-loading">
  557. <img src="'.$this->pix_url('i/loading_small').'" />
  558. </div>
  559. </div>';
  560. return $rv;
  561. }
  562. /**
  563. * FilePicker JS template for window appearing to select a file.
  564. *
  565. * All content must be enclosed in one element, CSS for this class must define width and
  566. * height of the window;
  567. *
  568. * Thumbnail image will be added as content to the element with class 'fp-thumbnail';
  569. *
  570. * Inside the window the elements with the following classnames must be present:
  571. * 'fp-saveas', 'fp-linktype-2', 'fp-linktype-1', 'fp-linktype-4', 'fp-setauthor',
  572. * 'fp-setlicense'. Inside each of them must have one input element (or select in case of
  573. * fp-setlicense). They may also have labels.
  574. * The elements will be assign with class 'uneditable' and input/select element will become
  575. * disabled if they are not applicable for the particular file;
  576. *
  577. * There may be present elements with classes 'fp-datemodified', 'fp-datecreated', 'fp-size',
  578. * 'fp-license', 'fp-author', 'fp-dimensions'. They will receive additional class 'fp-unknown'
  579. * if information is unavailable. If there is information available, the content of embedded
  580. * element with class 'fp-value' will be substituted with the value;
  581. *
  582. * Elements with classes 'fp-select-confirm' and 'fp-select-cancel' will hold corresponding
  583. * onclick events;
  584. *
  585. * When confirm button is pressed and file is being selected, the top element receives
  586. * additional class 'loading'. It is removed when response from server is received.
  587. *
  588. * @return string
  589. */
  590. private function fp_js_template_selectlayout() {
  591. $rv = '
  592. <div class="file-picker fp-select">
  593. <div class="fp-select-loading">
  594. <img src="'.$this->pix_url('i/loading_small').'" />
  595. </div>
  596. <form class="form-horizontal">
  597. <div class="fp-forminset">
  598. <div class="fp-linktype-2 form-group">
  599. <label class="control-label col-md-4">'.get_string('makefileinternal', 'repository').'</label>
  600. <div class="controls col-md-8">
  601. <input type="radio"/>
  602. </div>
  603. </div>
  604. <div class="fp-linktype-1 form-group">
  605. <label class="control-label col-md-4">'.get_string('makefilelink', 'repository').'</label>
  606. <div class="controls col-md-8">
  607. <input type="radio"/>
  608. </div>
  609. </div>
  610. <div class="fp-linktype-4 form-group">
  611. <label class="control-label col-md-4">'.get_string('makefilereference', 'repository').'</label>
  612. <div class="controls col-md-8">
  613. <input type="radio"/>
  614. </div>
  615. </div>
  616. <div class="fp-saveas form-group">
  617. <label class="control-label col-md-4">'.get_string('saveas', 'repository').'</label>
  618. <div class="controls col-md-8">
  619. <input type="text"/>
  620. </div>
  621. </div>
  622. <div class="fp-setauthor form-group">
  623. <label class="control-label col-md-4">'.get_string('author', 'repository').'</label>
  624. <div class="controls col-md-8">
  625. <input type="text"/>
  626. </div>
  627. </div>
  628. <div class="fp-setlicense form-group">
  629. <label class="control-label col-md-4">'.get_string('chooselicense', 'repository').'</label>
  630. <div class="controls col-md-8">
  631. <select></select>
  632. </div>
  633. </div>
  634. </div>
  635. <div class="fp-select-buttons">
  636. <button class="fp-select-confirm btn-primary btn">'.get_string('getfile', 'repository').'</button>
  637. <button class="fp-select-cancel btn-default btn">'.get_string('cancel').'</button>
  638. </div>
  639. </form>
  640. <div class="fp-info clearfix">
  641. <div class="fp-hr"></div>
  642. <p class="fp-thumbnail"></p>
  643. <div class="fp-fileinfo">
  644. <div class="fp-datemodified">'.get_string('lastmodified', 'moodle').':<span class="fp-value"></span></div>
  645. <div class="fp-datecreated">'.get_string('datecreated', 'repository').'<span class="fp-value"></span></div>
  646. <div class="fp-size">'.get_string('size', 'repository').'<span class="fp-value"></span></div>
  647. <div class="fp-license">'.get_string('license', 'moodle').'<span class="fp-value"></span></div>
  648. <div class="fp-author">'.get_string('author', 'repository').'<span class="fp-value"></span></div>
  649. <div class="fp-dimensions">'.get_string('dimensions', 'repository').'<span class="fp-value"></span></div>
  650. </div>
  651. <div>
  652. </div>';
  653. return $rv;
  654. }
  655. /**
  656. * FilePicker JS template for 'Upload file' repository
  657. *
  658. * Content to display when user chooses 'Upload file' repository (will be nested inside
  659. * element with class 'fp-content').
  660. *
  661. * Must contain form (enctype="multipart/form-data" method="POST")
  662. *
  663. * The elements with the following classnames must be present:
  664. * 'fp-file', 'fp-saveas', 'fp-setauthor', 'fp-setlicense'. Inside each of them must have
  665. * one input element (or select in case of fp-setlicense). They may also have labels.
  666. *
  667. * Element with class 'fp-upload-btn' will hold onclick event for uploading the file;
  668. *
  669. * Please note that some fields may be hidden using CSS if this is part of quickupload form
  670. *
  671. * @return string
  672. */
  673. private function fp_js_template_uploadform() {
  674. $rv = '
  675. <div class="fp-upload-form">
  676. <div class="fp-content-center">
  677. <form enctype="multipart/form-data" method="POST" class="form-horizontal">
  678. <div class="fp-formset">
  679. <div class="fp-file form-group">
  680. <label class="control-label col-md-4">'.get_string('attachment', 'repository').'</label>
  681. <div class="controls col-md-8">
  682. <input type="file"/>
  683. </div>
  684. </div>
  685. <div class="fp-saveas form-group">
  686. <label class="control-label col-md-4">'.get_string('saveas', 'repository').'</label>
  687. <div class="controls col-md-8">
  688. <input type="text"/>
  689. </div>
  690. </div>
  691. <div class="fp-setauthor form-group">
  692. <label class="control-label col-md-4">'.get_string('author', 'repository').'</label>
  693. <div class="controls col-md-8">
  694. <input type="text"/>
  695. </div>
  696. </div>
  697. <div class="fp-setlicense form-group">
  698. <label class="control-label col-md-4">'.get_string('chooselicense', 'repository').'</label>
  699. <div class="controls col-md-8">
  700. <select ></select>
  701. </div>
  702. </div>
  703. </div>
  704. </form>
  705. <div class="col-md-8 col-md-offset-4">
  706. <button class="fp-upload-btn btn-primary btn">'.get_string('upload', 'repository').'</button>
  707. </div>
  708. </div>
  709. </div> ';
  710. return $rv;
  711. }
  712. /**
  713. * FilePicker JS template to display during loading process (inside element with class 'fp-content').
  714. *
  715. * @return string
  716. */
  717. private function fp_js_template_loading() {
  718. return '
  719. <div class="fp-content-loading">
  720. <div class="fp-content-center">
  721. <img src="'.$this->pix_url('i/loading_small').'" />
  722. </div>
  723. </div>';
  724. }
  725. /**
  726. * FilePicker JS template for error (inside element with class 'fp-content').
  727. *
  728. * must have element with class 'fp-error', its content will be replaced with error text
  729. * and the error code will be assigned as additional class to this element
  730. * used errors: invalidjson, nofilesavailable, norepositoriesavailable
  731. *
  732. * @return string
  733. */
  734. private function fp_js_template_error() {
  735. $rv = '
  736. <div class="fp-content-error" ><div class="fp-error"></div></div>';
  737. return $rv;
  738. }
  739. /**
  740. * FilePicker JS template for error/info message displayed as a separate popup window.
  741. *
  742. * Must be wrapped in one element, CSS for this element must define
  743. * width and height of the window. It will be assigned with an additional class 'fp-msg-error'
  744. * or 'fp-msg-info' depending on message type;
  745. *
  746. * content of element with class 'fp-msg-text' will be replaced with error/info text;
  747. *
  748. * element with class 'fp-msg-butok' will hold onclick event
  749. *
  750. * @return string
  751. */
  752. private function fp_js_template_message() {
  753. $rv = '
  754. <div class="file-picker fp-msg" role="alertdialog" aria-live="assertive" aria-labelledby="fp-msg-labelledby">
  755. <p class="fp-msg-text" id="fp-msg-labelledby"></p>
  756. <button class="fp-msg-butok btn-primary btn">'.get_string('ok').'</button>
  757. </div>';
  758. return $rv;
  759. }
  760. /**
  761. * FilePicker JS template for popup dialogue window asking for action when file with the same name already exists.
  762. *
  763. * Must have one top element, CSS for this element must define width and height of the window;
  764. *
  765. * content of element with class 'fp-dlg-text' will be replaced with dialog text;
  766. * elements with classes 'fp-dlg-butoverwrite', 'fp-dlg-butrename',
  767. * 'fp-dlg-butoverwriteall', 'fp-dlg-butrenameall' and 'fp-dlg-butcancel' will
  768. * hold onclick events;
  769. *
  770. * content of element with class 'fp-dlg-butrename' will be substituted with appropriate string
  771. * (Note that it may have long text)
  772. *
  773. * @return string
  774. */
  775. private function fp_js_template_processexistingfile() {
  776. $rv = '
  777. <div class="file-picker fp-dlg">
  778. <p class="fp-dlg-text"></p>
  779. <div class="fp-dlg-buttons">
  780. <button class="fp-dlg-butoverwrite btn">'.get_string('overwrite', 'repository').'</button>
  781. <button class="fp-dlg-butrename btn"></button>
  782. <button class="fp-dlg-butcancel btn btn-default">'.get_string('cancel').'</button>
  783. </div>
  784. </div>';
  785. return $rv;
  786. }
  787. /**
  788. * FilePicker JS template for popup dialogue window asking for action when file with the same name already exists (multiple-file version).
  789. *
  790. * Must have one top element, CSS for this element must define width and height of the window;
  791. *
  792. * content of element with class 'fp-dlg-text' will be replaced with dialog text;
  793. * elements with classes 'fp-dlg-butoverwrite', 'fp-dlg-butrename' and 'fp-dlg-butcancel' will
  794. * hold onclick events;
  795. *
  796. * content of element with class 'fp-dlg-butrename' will be substituted with appropriate string
  797. * (Note that it may have long text)
  798. *
  799. * @return string
  800. */
  801. private function fp_js_template_processexistingfilemultiple() {
  802. $rv = '
  803. <div class="file-picker fp-dlg">
  804. <p class="fp-dlg-text"></p>
  805. <a class="fp-dlg-butoverwrite fp-panel-button" href="#">'.get_string('overwrite', 'repository').'</a>
  806. <a class="fp-dlg-butcancel fp-panel-button" href="#">'.get_string('cancel').'</a>
  807. <a class="fp-dlg-butrename fp-panel-button" href="#"></a>
  808. <br/>
  809. <a class="fp-dlg-butoverwriteall fp-panel-button" href="#">'.get_string('overwriteall', 'repository').'</a>
  810. <a class="fp-dlg-butrenameall fp-panel-button" href="#">'.get_string('renameall', 'repository').'</a>
  811. </div>';
  812. return $rv;
  813. }
  814. /**
  815. * FilePicker JS template for repository login form including templates for each element type
  816. *
  817. * Must contain one <form> element with templates for different input types inside:
  818. * Elements with classes 'fp-login-popup', 'fp-login-textarea', 'fp-login-select' and
  819. * 'fp-login-input' are templates for displaying respective login form elements. Inside
  820. * there must be exactly one element with type <button>, <textarea>, <select> or <input>
  821. * (i.e. fp-login-popup should have <button>, fp-login-textarea should have <textarea>, etc.);
  822. * They may also contain the <label> element and it's content will be substituted with
  823. * label;
  824. *
  825. * You can also define elements with classes 'fp-login-checkbox', 'fp-login-text'
  826. * but if they are not found, 'fp-login-input' will be used;
  827. *
  828. * Element with class 'fp-login-radiogroup' will be used for group of radio inputs. Inside
  829. * it should hava a template for one radio input (with class 'fp-login-radio');
  830. *
  831. * Element with class 'fp-login-submit' will hold on click mouse event (form submission). It
  832. * will be removed if at least one popup element is present;
  833. *
  834. * @return string
  835. */
  836. private function fp_js_template_loginform() {
  837. $rv = '
  838. <div class="fp-login-form">
  839. <div class="fp-content-center">
  840. <form class="form-horizontal">
  841. <div class="fp-formset">
  842. <div class="fp-login-popup form-group">
  843. <div class="controls col-md-8 fp-popup">
  844. <button class="fp-login-popup-but btn-primary btn">'.get_string('login', 'repository').'</button>
  845. </div>
  846. </div>
  847. <div class="fp-login-textarea form-group">
  848. <div class="controls col-md-8"><textarea></textarea></div>
  849. </div>
  850. <div class="fp-login-select form-group">
  851. <label class="control-label col-md-4"></label>
  852. <div class="controls col-md-8"><select></select></div>
  853. </div>
  854. <div class="fp-login-input form-group">
  855. <label class="control-label col-md-4"></label>
  856. <div class="controls col-md-8"><input/></div>
  857. </div>
  858. <div class="fp-login-radiogroup form-group">
  859. <label class="control-label col-md-4"></label>
  860. <div class="controls col-md-8 fp-login-radio"><input /> <label></label></div>
  861. </div>
  862. </div>
  863. <div class="col-md-8 col-md-offset-4"><button class="fp-login-submit btn-primary btn">'.get_string('submit', 'repository').'</button></div>
  864. </form>
  865. </div>
  866. </div>';
  867. return $rv;
  868. }
  869. /**
  870. * Returns all FilePicker JavaScript templates as an array.
  871. *
  872. * @return array
  873. */
  874. public function filepicker_js_templates() {
  875. $class_methods = get_class_methods($this);
  876. $templates = array();
  877. foreach ($class_methods as $method_name) {
  878. if (preg_match('/^fp_js_template_(.*)$/', $method_name, $matches))
  879. $templates[$matches[1]] = $this->$method_name();
  880. }
  881. return $templates;
  882. }
  883. }