Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

MDL-31901: moved filepicker html to files/renderer.php, pass template…

…s once per page
  • Loading branch information...
commit d1d186917c6098f93fb3116b4d53ea4bb6faa4e5 1 parent 906e7d8
Marina Glancy marinaglancy authored
420 files/renderer.php
@@ -95,9 +95,9 @@ public function render_files_tree_viewer(files_tree_viewer $tree) {
95 95 * @param form_filemanager $fm File manager to render
96 96 * @return string HTML fragment
97 97 */
98   - function render_form_filemanager($fm) {
  98 + public function render_form_filemanager($fm) {
99 99 static $filemanagertemplateloaded;
100   - $html = $this->file_manager_html($fm);
  100 + $html = $this->fm_print_generallayout($fm);
101 101 $module = array(
102 102 'name'=>'form_filemanager',
103 103 'fullpath'=>'/lib/form/filemanager.js',
@@ -165,7 +165,7 @@ function render_form_filemanager($fm) {
165 165 * @param form_filemanager $fm
166 166 * @return string
167 167 */
168   - private function file_manager_html($fm) {
  168 + private function fm_print_generallayout($fm) {
169 169 global $OUTPUT;
170 170 $options = $fm->options;
171 171 $client_id = $options->client_id;
@@ -176,7 +176,7 @@ private function file_manager_html($fm) {
176 176 $strnofilesattached = get_string('nofilesattached', 'repository');
177 177 $strdroptoupload = get_string('droptoupload', 'moodle');
178 178 $icon_progress = $OUTPUT->pix_icon('i/loading_small', $strloading).'';
179   - $restrictions = $this->file_manager_restrictions($fm);
  179 + $restrictions = $this->fm_print_restrictions($fm);
180 180 $strdndenabled = get_string('dndenabled_insentence', 'moodle').$OUTPUT->help_icon('dndenabled');
181 181 $strdndenabledinbox = get_string('dndenabled_inbox', 'moodle');
182 182 $loading = get_string('loading', 'repository');
@@ -213,7 +213,7 @@ private function file_manager_html($fm) {
213 213 * @param form_filemanager $fm
214 214 * @return string
215 215 */
216   - private function file_manager_restrictions($fm) {
  216 + private function fm_print_restrictions($fm) {
217 217 $maxbytes = display_size($fm->options->maxbytes);
218 218 if (empty($options->maxfiles) || $options->maxfiles == -1) {
219 219 $maxsize = get_string('maxfilesize', 'moodle', $maxbytes);
@@ -226,8 +226,416 @@ private function file_manager_restrictions($fm) {
226 226 // TODO MDL-32020 also should say about 'File types accepted'
227 227 return '<span>'. $maxsize. '</span>';
228 228 }
229   -}
230 229
  230 + /**
  231 + * Template for FilePicker with general layout (not QuickUpload).
  232 + *
  233 + * Must have one top element containing everything else (recommended <div class="file-picker">),
  234 + * CSS for this element must define width and height of the filepicker window. Or CSS must
  235 + * define min-width, max-width, min-height and max-height and in this case the filepicker
  236 + * window will be resizeable;
  237 + *
  238 + * Element with class 'fp-viewbar' will have the class 'enabled' or 'disabled' when view mode
  239 + * can be changed or not;
  240 + * Inside element with class 'fp-viewbar' there are expected elements with classes
  241 + * 'fp-vb-icons', 'fp-vb-tree' and 'fp-vb-details'. They will handle onclick events to switch
  242 + * between the view modes, the last clicked element will have the class 'checked';
  243 + *
  244 + * Element with class 'fp-repo' is a template for displaying one repository. Other repositories
  245 + * will be attached as siblings (classes first/last/even/odd will be added respectfully).
  246 + * The currently selected repostory will have class 'active'. Contents of element with class
  247 + * 'fp-repo-name' will be replaced with repository name, source of image with class
  248 + * 'fp-repo-icon' will be replaced with repository icon;
  249 + *
  250 + * Element with class 'fp-content' is obligatory and will hold the current contents;
  251 + *
  252 + * Element with class 'fp-paging' will contain page navigation (will be deprecated soon);
  253 + *
  254 + * Element with class 'fp-path-folder' will contain template for one folder in path toolbar.
  255 + * It will hold mouse click event and will be assigned classes first/last/even/odd respectfully.
  256 + * The content of element with class 'fp-path-folder-name' will be substituted with folder name;
  257 + * Parent element will receive class 'empty' when there are no folders to be displayed;
  258 + *
  259 + * Element with class 'fp-toolbar' will have class 'empty' if all 'Back', 'Search', 'Refresh',
  260 + * 'Logout', 'Manage' and 'Help' are unavailable for this repo;
  261 + *
  262 + * Inside fp-toolbar there are expected elements with classes fp-tb-back, fp-tb-search,
  263 + * fp-tb-refresh, fp-tb-logout, fp-tb-manage and fp-tb-help. Each of them will have
  264 + * class 'enabled' or 'disabled' if particular repository has this functionality.
  265 + * Element with class 'fp-tb-search' must contain empty form inside, it's contents will
  266 + * be substituted with the search form returned by repository (in the most cases it
  267 + * is generated with template core_repository_renderer::repository_default_searchform);
  268 + * Other elements must have either <a> or <button> element inside, it will hold onclick
  269 + * event for corresponding action; labels for fp-tb-back and fp-tb-logout may be
  270 + * replaced with those specified by repository;
  271 + *
  272 + * @return string
  273 + */
  274 + private function fp_js_template_generallayout() {
  275 + $rv = '
  276 +<div class="file-picker fp-generallayout">
  277 + <div>
  278 + <div class="{!}fp-viewbar" style="float:none;">
  279 + <span class=""><button class="{!}fp-vb-icons">'.get_string('iconview', 'repository').'</button></span>
  280 + <span class=""><button class="{!}fp-vb-tree">'.get_string('listview', 'repository').'</button></span>
  281 + <span class=""><button class="{!}fp-vb-details">'.get_string('detailview', 'repository').'</button></span>
  282 + </div>
  283 + </div>
  284 + <div style="vertical-align:top;">
  285 + <div style="width:200px;height:400px;display:inline-block;overflow:auto;">
  286 + <ul class="fp-list">
  287 + <li class="{!}fp-repo"><img class="{!}fp-repo-icon" width="16" height="16" />&nbsp;<span class="{!}fp-repo-name"></span></li>
  288 + </ul>
  289 + </div>
  290 + <div style="width:480px;height:400px;display:inline-block;vertical-align:top;">
  291 + <div class="{!}fp-toolbar">
  292 + <div class="{!}fp-tb-back"><a>'.get_string('back', 'repository').'</a></div>
  293 + <div class="{!}fp-tb-search">
  294 + <img src="'.$this->pix_url('a/search').'" />
  295 + <form/>
  296 + </div>
  297 + <div class="{!}fp-tb-refresh"><a><img src="'.$this->pix_url('a/refresh').'" />'.get_string('refresh', 'repository').'</a></div>
  298 + <div class="{!}fp-tb-logout"><img src="'.$this->pix_url('a/logout').'" /><a></a></div>
  299 + <div class="{!}fp-tb-manage"><a><img src="'.$this->pix_url('a/setting').'" /> '.get_string('manageurl', 'repository').'</a></div>
  300 + <div class="{!}fp-tb-help"><a><img src="'.$this->pix_url('a/help').'" /> '.get_string('help').'</a></div>
  301 + </div>
  302 + <div class="fp-pathbar" style="background:#ddffdd">
  303 + <span class="{!}fp-path-folder"><a class="{!}fp-path-folder-name"></a><span>/</span></span>
  304 + </div>
  305 + <div class="{!}fp-content"></div>
  306 + </div>
  307 + </div>
  308 +</div>';
  309 + return preg_replace('/\{\!\}/', '', $rv);
  310 + }
  311 +
  312 + /**
  313 + * FilePicker JS template for displaying list of files in 'icon view' mode.
  314 + *
  315 + * Element with class 'fp-file' is a template for displaying one file and indicates a place
  316 + * where files shall be output. It also will hold mouse events (click, over, out, etc.);
  317 + *
  318 + * the element with class 'fp-thumbnail' will be resized to the repository thumbnail size
  319 + * (both width and height, unless min-width and/or min-height is set in CSS) and the content of
  320 + * an element will be replaced with an appropriate img;
  321 + *
  322 + * the width of element with class 'fp-filename' will be set to the repository thumbnail width
  323 + * (unless min-width is set in css) and the content of an element will be replaced with filename
  324 + * supplied by repository;
  325 + *
  326 + * @return string
  327 + */
  328 + private function fp_js_template_iconview() {
  329 + $rv = '<div class="fp-iconview">
  330 +<div class="{!}fp-file">
  331 + <div class="{!}fp-thumbnail"></div>
  332 + <div class="{!}fp-filename"></div>
  333 +</div>
  334 + </div>';
  335 + return preg_replace('/\{\!\}/', '', $rv);
  336 + }
  337 +
  338 + /**
  339 + * FilePicker JS template for displaying file name in 'table view' and 'tree view' modes.
  340 + *
  341 + * content of the element with class 'fp-icon' will be replaced with an appropriate img;
  342 + *
  343 + * content of element with class 'fp-filename' will be replaced with filename supplied by
  344 + * repository;
  345 + *
  346 + * Note that tree view and table view are the YUI widgets and therefore there are no
  347 + * other templates. The widgets will be wrapped in <div> with class fp-treeview or
  348 + * fp-tableview (respectfully).
  349 + *
  350 + * @return string
  351 + */
  352 + private function fp_js_template_listfilename() {
  353 + $rv = '<span class="{!}fp-icon"></span> <span class="{!}fp-filename"></span>';
  354 + return preg_replace('/\{\!\}/', '', $rv);
  355 + }
  356 +
  357 + /**
  358 + * FilePicker JS template for displaying link/loading progress for fetching of the next page
  359 + *
  360 + * This text is added to .fp-content AFTER .fp-iconview/.fp-treeview/.fp-tableview
  361 + *
  362 + * Must have one parent element with class 'fp-nextpage'. It will be assigned additional
  363 + * class 'loading' during loading of the next page (it is recommended that in this case the link
  364 + * becomes unavailable). Also must contain one element <a> or <button> that will hold
  365 + * onclick event for displaying of the next page. The event will be triggered automatically
  366 + * when user scrolls to this link.
  367 + *
  368 + * @return string
  369 + */
  370 + private function fp_js_template_nextpage() {
  371 + $rv = '<div class="{!}fp-nextpage">
  372 + <div class="fp-nextpage-link"><a href="#">'.get_string('more').'</a></div>
  373 + <div class="fp-nextpage-loading">
  374 + <img src="'.$this->pix_url('i/loading').'" />
  375 + <p>'.get_string('loading', 'repository').'</p>
  376 + </div>
  377 +</div>';
  378 + return preg_replace('/\{\!\}/', '', $rv);
  379 + }
  380 +
  381 + /**
  382 + * Template for window appearing to select a file.
  383 + *
  384 + * All content must be enclosed in an element with class 'fp-select', CSS for this class
  385 + * must define width and height of the window;
  386 + *
  387 + * Thumbnail image will be added as content to the element with class 'fp-thumbnail';
  388 + *
  389 + * Inside the window the elements with the following classnames must be present:
  390 + * 'fp-saveas', 'fp-linkexternal', 'fp-setauthor', 'fp-setlicense'. Inside each of them must have
  391 + * one input element (or select in case of fp-setlicense). They may also have labels.
  392 + * The elements will be assign with class 'uneditable' and input/select element will become
  393 + * disabled if they are not applicable for the particular file;
  394 + *
  395 + * There may be present elements with classes 'fp-datemodified', 'fp-datecreated', 'fp-size',
  396 + * 'fp-license', 'fp-author'. They will receive additional class 'fp-unknown' if information
  397 + * is unavailable. If there is information available, the content of embedded element
  398 + * with class 'fp-value' will be substituted with the value;
  399 + *
  400 + * Elements with classes 'fp-select-confirm' and 'fp-select-cancel' will hold corresponding
  401 + * onclick events;
  402 + *
  403 + * When confirm button is pressed and file is being selected, the top element receives
  404 + * additional class 'loading'. It is removed when response from server is received.
  405 + *
  406 + * @return string
  407 + */
  408 + private function fp_js_template_selectlayout() {
  409 + $rv = '<div class="{!}fp-select">
  410 +<div class="fp-select-loading">
  411 +<img src="'.$this->pix_url('i/loading').'" />
  412 +<p>'.get_string('loading', 'repository').'</p>
  413 +</div>
  414 +<form>
  415 +<p class="{!}fp-thumbnail"></p>
  416 +<table width="100%">
  417 +<tr class="{!}fp-saveas"><td class="mdl-right"><label>'.get_string('saveas', 'repository').'</label>:</td>
  418 +<td class="mdl-left"><input type="text"/></td></tr>
  419 +<tr class="{!}fp-linkexternal"><td></td>
  420 +<td class="mdl-left"><input type="checkbox"/><label>'.get_string('linkexternal', 'repository').'</label></td></tr>
  421 +<tr class="{!}fp-setauthor"><td class="mdl-right"><label>'.get_string('author', 'repository').'</label>:</td>
  422 +<td class="mdl-left"><input type="text" /></td></tr>
  423 +<tr class="{!}fp-setlicense"><td class="mdl-right"><label>'.get_string('chooselicense', 'repository').'</label>:</td>
  424 +<td class="mdl-left"><select></select></td></tr>
  425 +</table>
  426 +<p><button class="{!}fp-select-confirm" >'.get_string('getfile', 'repository').'</button>
  427 +<button class="{!}fp-select-cancel" >'.get_string('cancel').'</button></p>
  428 +</form>
  429 +<div class="{!}fp-datemodified">'.get_string('lastmodified', 'moodle').': <span class="fp-value"/></div>
  430 +<div class="{!}fp-datecreated">'.get_string('datecreated', 'repository').': <span class="fp-value"/></div>
  431 +<div class="{!}fp-size">'.get_string('size', 'repository').': <span class="fp-value"/></div>
  432 +<div class="{!}fp-license">'.get_string('license', 'moodle').': <span class="fp-value"/></div>
  433 +<div class="{!}fp-author">'.get_string('author', 'repository').': <span class="fp-value"/></div>
  434 +<div class="{!}fp-dimensions">'.get_string('dimensions', 'repository').': <span class="fp-value"/></div>
  435 +</div>';
  436 + return preg_replace('/\{\!\}/', '', $rv);
  437 + }
  438 +
  439 + /**
  440 + * FilePicker JS template for 'Upload file' repository
  441 + *
  442 + * Content to display when user chooses 'Upload file' repository (will be nested inside
  443 + * element with class 'fp-content').
  444 + *
  445 + * Must contain form (enctype="multipart/form-data" method="POST")
  446 + *
  447 + * The elements with the following classnames must be present:
  448 + * 'fp-file', 'fp-saveas', 'fp-setauthor', 'fp-setlicense'. Inside each of them must have
  449 + * one input element (or select in case of fp-setlicense). They may also have labels.
  450 + *
  451 + * Element with class 'fp-upload-btn' will hold onclick event for uploading the file;
  452 + *
  453 + * Please note that some fields may be hidden using CSS if this is part of quickupload form
  454 + *
  455 + * @return string
  456 + */
  457 + private function fp_js_template_uploadform() {
  458 + $rv = '<div class="fp-upload-form mdl-align">
  459 +<form enctype="multipart/form-data" method="POST">
  460 + <table width="100%">
  461 + <tr class="{!}fp-file">
  462 + <td class="mdl-right"><label>'.get_string('attachment', 'repository').'</label>:</td>
  463 + <td class="mdl-left"><input type="file"/></td>
  464 + </tr>
  465 + <tr class="{!}fp-saveas">
  466 + <td class="mdl-right"><label>'.get_string('saveas', 'repository').'</label>:</td>
  467 + <td class="mdl-left"><input type="text"/></td>
  468 + </tr>
  469 + <tr class="{!}fp-setauthor">
  470 + <td class="mdl-right"><label>'.get_string('author', 'repository').'</label>:</td>
  471 + <td class="mdl-left"><input type="text"/></td>
  472 + </tr>
  473 + <tr class="{!}fp-setlicense">
  474 + <td class="mdl-right"><label>'.get_string('chooselicense', 'repository').'</label>:</td>
  475 + <td class="mdl-left"><select/></td>
  476 + </tr>
  477 + </table>
  478 +</form>
  479 +<div><button class="{!}fp-upload-btn">'.get_string('upload', 'repository').'</button></div>
  480 +</div> ';
  481 + return preg_replace('/\{\!\}/', '', $rv);
  482 + }
  483 +
  484 + /**
  485 + * FilePicker JS template to display during loading process (inside element with class 'fp-content').
  486 + *
  487 + * @return string
  488 + */
  489 + private function fp_js_template_loading() {
  490 + return '<div style="text-align:center">
  491 +<img src="'.$this->pix_url('i/loading').'" />
  492 +<p>'.get_string('loading', 'repository').'</p>
  493 +</div>';
  494 + }
  495 +
  496 + /**
  497 + * FilePicker JS template for error (inside element with class 'fp-content').
  498 + *
  499 + * must have element with class 'fp-error', its content will be replaced with error text
  500 + * and the error code will be assigned as additional class to this element
  501 + * used errors: invalidjson, nofilesavailable, norepositoriesavailable
  502 + *
  503 + * @return string
  504 + */
  505 + private function fp_js_template_error() {
  506 + $rv = '<div class="{!}fp-error" />';
  507 + return preg_replace('/\{\!\}/', '', $rv);
  508 + }
  509 +
  510 + /**
  511 + * FilePicker JS template for error/info message displayed as a separate popup window.
  512 + *
  513 + * Must be wrapped in an element with class 'fp-msg', CSS for this element must define
  514 + * width and height of the window. It will be assigned with an additional class 'fp-msg-error'
  515 + * or 'fp-msg-info' depending on message type;
  516 + *
  517 + * content of element with class 'fp-msg-text' will be replaced with error/info text;
  518 + *
  519 + * element with class 'fp-msg-butok' will hold onclick event
  520 + *
  521 + * @return string
  522 + */
  523 + private function fp_js_template_message() {
  524 + $rv = '<div class="{!}fp-msg">
  525 + <div class="{!}fp-msg-text"></div>
  526 + <div><button class="{!}fp-msg-butok">'.get_string('ok').'</button></div>
  527 + </div>';
  528 + return preg_replace('/\{\!\}/', '', $rv);
  529 + }
  530 +
  531 + /**
  532 + * FilePicker JS template for popup dialogue window asking for action when file with the same name already exists.
  533 + *
  534 + * Must be wrapped in an element with class 'fp-dlg', CSS for this element must define width
  535 + * and height of the window;
  536 + *
  537 + * content of element with class 'fp-dlg-text' will be replaced with dialog text;
  538 + * elements with classes 'fp-dlg-butoverwrite', 'fp-dlg-butrename' and 'fp-dlg-butcancel' will
  539 + * hold onclick events;
  540 + *
  541 + * content of element with class 'fp-dlg-butrename' will be substituted with appropriate string
  542 + * (Note that it may have long text)
  543 + *
  544 + * @return string
  545 + */
  546 + private function fp_js_template_processexistingfile() {
  547 + $rv = '<div class="{!}fp-dlg"><div class="{!}fp-dlg-text"></div>
  548 +<div class="fp-dlg-but"><button class="{!}fp-dlg-butoverwrite" >'.get_string('overwrite', 'repository').'</button></div>
  549 +<div class="fp-dlg-but"><button class="{!}fp-dlg-butrename" /></div>
  550 +<div class="fp-dlg-but"><button class="{!}fp-dlg-butcancel" >'.get_string('cancel').'</button></div>
  551 +</div>';
  552 + return preg_replace('/\{\!\}/', '', $rv);
  553 + }
  554 +
  555 + /**
  556 + * FilePicker JS template for repository login form including templates for each element type
  557 + *
  558 + * Must contain one <form> element with templates for different input types inside:
  559 + * Elements with classes 'fp-login-popup', 'fp-login-textarea', 'fp-login-select' and
  560 + * 'fp-login-input' are templates for displaying respective login form elements. Inside
  561 + * there must be exactly one element with type <button>, <textarea>, <select> or <input>
  562 + * (i.e. fp-login-popup should have <button>, fp-login-textarea should have <textarea>, etc.);
  563 + * They may also contain the <label> element and it's content will be substituted with
  564 + * label;
  565 + *
  566 + * You can also define elements with classes 'fp-login-checkbox', 'fp-login-text'
  567 + * but if they are not found, 'fp-login-input' will be used;
  568 + *
  569 + * Element with class 'fp-login-radiogroup' will be used for group of radio inputs. Inside
  570 + * it should hava a template for one radio input (with class 'fp-login-radio');
  571 + *
  572 + * Element with class 'fp-login-submit' will hold on click mouse event (form submission). It
  573 + * will be removed if at least one popup element is present;
  574 + *
  575 + * @return string
  576 + */
  577 + private function fp_js_template_loginform() {
  578 + $rv = '
  579 +<div class="fp-login-form">
  580 + <form>
  581 + <table width="100%">
  582 + <tr class="{!}fp-login-popup">
  583 + <td colspan="2">
  584 + <label>'.get_string('popup', 'repository').'</label>
  585 + <p class="fp-popup"><button class="{!}fp-login-popup-but">'.get_string('login', 'repository').'</button></p>
  586 + </td>
  587 + </tr>
  588 + <tr class="{!}fp-login-textarea">
  589 + <td colspan="2"><p><textarea></textarea></p></td>
  590 + </tr>
  591 + <tr class="{!}fp-login-select">
  592 + <td align="right"><label></label></td>
  593 + <td align="left"><select></select></td>
  594 + </tr>
  595 + <tr class="{!}fp-login-input">
  596 + <td align="right" width="30%" valign="center"><label /></td>
  597 + <td align="left"><input/></td>
  598 + </tr>
  599 + <tr class="{!}fp-login-radiogroup">
  600 + <td align="right" width="30%" valign="top"><label /></td>
  601 + <td align="left" valign="top">
  602 + <p class="{!}fp-login-radio"><input /> <label /></p>
  603 + </td>
  604 + </tr>
  605 + </table>
  606 + <p><button class="{!}fp-login-submit">'.get_string('submit', 'repository').'</button></p>
  607 + </form>
  608 +</div>';
  609 + return preg_replace('/\{\!\}/', '', $rv);
  610 + }
  611 +
  612 + /**
  613 + * Returns all FilePicker JavaScript templates as an array.
  614 + *
  615 + * @return array
  616 + */
  617 + public function filepicker_js_templates() {
  618 + $class_methods = get_class_methods($this);
  619 + $templates = array();
  620 + foreach ($class_methods as $method_name) {
  621 + if (preg_match('/^fp_js_template_(.*)$/', $method_name, $matches))
  622 + $templates[$matches[1]] = $this->$method_name();
  623 + }
  624 + return $templates;
  625 + }
  626 +
  627 + /**
  628 + * Returns HTML for default repository searchform to be passed to Filepicker
  629 + *
  630 + * This will be used as contents for search form defined in generallayout template
  631 + * (form with id {TOOLSEARCHID}).
  632 + * Default contents is one text input field with name="s"
  633 + */
  634 + public function repository_default_searchform() {
  635 + $str = '<label>'.get_string('keyword', 'repository').': </label><br/><input name="s" value="" /><br/>';
  636 + return $str;
  637 + }
  638 +}
231 639
232 640 /**
233 641 * Data structure representing a general moodle file tree viewer
10 repository/filepicker.js
@@ -65,6 +65,11 @@ M.core_filepicker.show = function(Y, options) {
65 65 M.core_filepicker.instances[options.client_id].show();
66 66 };
67 67
  68 +M.core_filepicker.set_templates = function(Y, templates) {
  69 + for (var templid in templates) {
  70 + M.core_filepicker.templates[templid] = templates[templid];
  71 + }
  72 +}
68 73
69 74 /**
70 75 * Add new file picker to current instances
@@ -100,11 +105,6 @@ M.core_filepicker.init = function(Y, options) {
100 105 return this;
101 106 }
102 107
103   - if (options.templates);
104   - for (var templid in options.templates) {
105   - this.templates[templid] = options.templates[templid];
106   - }
107   -
108 108 var FilePickerHelper = function(options) {
109 109 FilePickerHelper.superclass.constructor.apply(this, arguments);
110 110 };
12 repository/lib.php
@@ -1889,7 +1889,7 @@ public function print_login(){
1889 1889 */
1890 1890 public function print_search() {
1891 1891 global $PAGE;
1892   - $renderer = $PAGE->get_renderer('core', 'repository');
  1892 + $renderer = $PAGE->get_renderer('core', 'files');
1893 1893 return $renderer->repository_default_searchform();
1894 1894 }
1895 1895
@@ -2408,6 +2408,7 @@ public function validation($data, $files) {
2408 2408 */
2409 2409 function initialise_filepicker($args) {
2410 2410 global $CFG, $USER, $PAGE, $OUTPUT;
  2411 + static $templatesinitialized;
2411 2412 require_once($CFG->libdir . '/licenselib.php');
2412 2413
2413 2414 $return = new stdClass();
@@ -2474,8 +2475,13 @@ function initialise_filepicker($args) {
2474 2475 // JavaScript a lot, the key NEEDS to be the repository id.
2475 2476 $return->repositories[$repository->id] = $meta;
2476 2477 }
2477   - $fprenderer = $PAGE->get_renderer('core', 'repository');
2478   - $return->templates = $fprenderer->filepicker_templates();
  2478 + if (!$templatesinitialized) {
  2479 + // we need to send filepicker templates to the browser just once
  2480 + $fprenderer = $PAGE->get_renderer('core', 'files');
  2481 + $templates = $fprenderer->filepicker_js_templates();
  2482 + $PAGE->requires->js_init_call('M.core_filepicker.set_templates', array($templates), true);
  2483 + $templatesinitialized = true;
  2484 + }
2479 2485 return $return;
2480 2486 }
2481 2487 /**
441 repository/renderer.php
... ... @@ -1,441 +0,0 @@
1   -<?php
2   -// This file is part of Moodle - http://moodle.org/
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   -/**
18   - * Renderer for filepicker and base repositories output.
19   - *
20   - * @package core_repository
21   - * @copyright 2012 Marina Glancy
22   - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23   - */
24   -
25   -defined('MOODLE_INTERNAL') || die;
26   -
27   -/**
28   - * The core repository renderer
29   - *
30   - * Can be retrieved with the following:
31   - * $renderer = $PAGE->get_renderer('core', 'repository');
32   - */
33   -class core_repository_renderer extends plugin_renderer_base {
34   -
35   - /**
36   - * Template for FilePicker with general layout (not QuickUpload).
37   - *
38   - * Must have one top element containing everything else (recommended <div class="file-picker">),
39   - * CSS for this element must define width and height of the filepicker window. Or CSS must
40   - * define min-width, max-width, min-height and max-height and in this case the filepicker
41   - * window will be resizeable;
42   - *
43   - * Element with class 'fp-viewbar' will have the class 'enabled' or 'disabled' when view mode
44   - * can be changed or not;
45   - * Inside element with class 'fp-viewbar' there are expected elements with classes
46   - * 'fp-vb-icons', 'fp-vb-tree' and 'fp-vb-details'. They will handle onclick events to switch
47   - * between the view modes, the last clicked element will have the class 'checked';
48   - *
49   - * Element with class 'fp-repo' is a template for displaying one repository. Other repositories
50   - * will be attached as siblings (classes first/last/even/odd will be added respectfully).
51   - * The currently selected repostory will have class 'active'. Contents of element with class
52   - * 'fp-repo-name' will be replaced with repository name, source of image with class
53   - * 'fp-repo-icon' will be replaced with repository icon;
54   - *
55   - * Element with class 'fp-content' is obligatory and will hold the current contents;
56   - *
57   - * Element with class 'fp-paging' will contain page navigation (will be deprecated soon);
58   - *
59   - * Element with class 'fp-path-folder' will contain template for one folder in path toolbar.
60   - * It will hold mouse click event and will be assigned classes first/last/even/odd respectfully.
61   - * The content of element with class 'fp-path-folder-name' will be substituted with folder name;
62   - * Parent element will receive class 'empty' when there are no folders to be displayed;
63   - *
64   - * Element with class 'fp-toolbar' will have class 'empty' if all 'Back', 'Search', 'Refresh',
65   - * 'Logout', 'Manage' and 'Help' are unavailable for this repo;
66   - *
67   - * Inside fp-toolbar there are expected elements with classes fp-tb-back, fp-tb-search,
68   - * fp-tb-refresh, fp-tb-logout, fp-tb-manage and fp-tb-help. Each of them will have
69   - * class 'enabled' or 'disabled' if particular repository has this functionality.
70   - * Element with class 'fp-tb-search' must contain empty form inside, it's contents will
71   - * be substituted with the search form returned by repository (in the most cases it
72   - * is generated with template core_repository_renderer::repository_default_searchform);
73   - * Other elements must have either <a> or <button> element inside, it will hold onclick
74   - * event for corresponding action; labels for fp-tb-back and fp-tb-logout may be
75   - * replaced with those specified by repository;
76   - *
77   - * @return string
78   - */
79   - public function js_template_generallayout() {
80   - $rv = '
81   -<div class="file-picker fp-generallayout">
82   - <div>
83   - <div class="{!}fp-viewbar" style="float:none;">
84   - <span class=""><button class="{!}fp-vb-icons">'.get_string('iconview', 'repository').'</button></span>
85   - <span class=""><button class="{!}fp-vb-tree">'.get_string('listview', 'repository').'</button></span>
86   - <span class=""><button class="{!}fp-vb-details">'.get_string('detailview', 'repository').'</button></span>
87   - </div>
88   - </div>
89   - <div style="vertical-align:top;">
90   - <div style="width:200px;height:400px;display:inline-block;overflow:auto;">
91   - <ul class="fp-list">
92   - <li class="{!}fp-repo"><img class="{!}fp-repo-icon" width="16" height="16" />&nbsp;<span class="{!}fp-repo-name"></span></li>
93   - </ul>
94   - </div>
95   - <div style="width:480px;height:400px;display:inline-block;vertical-align:top;">
96   - <div class="{!}fp-toolbar">
97   - <div class="{!}fp-tb-back"><a>'.get_string('back', 'repository').'</a></div>
98   - <div class="{!}fp-tb-search">
99   - <img src="'.$this->pix_url('a/search').'" />
100   - <form/>
101   - </div>
102   - <div class="{!}fp-tb-refresh"><a><img src="'.$this->pix_url('a/refresh').'" />'.get_string('refresh', 'repository').'</a></div>
103   - <div class="{!}fp-tb-logout"><img src="'.$this->pix_url('a/logout').'" /><a></a></div>
104   - <div class="{!}fp-tb-manage"><a><img src="'.$this->pix_url('a/setting').'" /> '.get_string('manageurl', 'repository').'</a></div>
105   - <div class="{!}fp-tb-help"><a><img src="'.$this->pix_url('a/help').'" /> '.get_string('help').'</a></div>
106   - </div>
107   - <div class="fp-pathbar" style="background:#ddffdd">
108   - <span class="{!}fp-path-folder"><a class="{!}fp-path-folder-name"></a><span>/</span></span>
109   - </div>
110   - <div class="{!}fp-content"></div>
111   - </div>
112   - </div>
113   -</div>';
114   - return preg_replace('/\{\!\}/', '', $rv);
115   - }
116   -
117   - /**
118   - * Template for displaying list of files in 'icon view' mode.
119   - *
120   - * Element with class 'fp-file' is a template for displaying one file and indicates a place
121   - * where files shall be output. It also will hold mouse events (click, over, out, etc.);
122   - *
123   - * the element with class 'fp-thumbnail' will be resized to the repository thumbnail size
124   - * (both width and height, unless min-width and/or min-height is set in CSS) and the content of
125   - * an element will be replaced with an appropriate img;
126   - *
127   - * the width of element with class 'fp-filename' will be set to the repository thumbnail width
128   - * (unless min-width is set in css) and the content of an element will be replaced with filename
129   - * supplied by repository;
130   - *
131   - * @return string
132   - */
133   - public function js_template_iconview() {
134   - $rv = '<div class="fp-iconview">
135   -<div class="{!}fp-file">
136   - <div class="{!}fp-thumbnail"></div>
137   - <div class="{!}fp-filename"></div>
138   -</div>
139   - </div>';
140   - return preg_replace('/\{\!\}/', '', $rv);
141   - }
142   -
143   - /**
144   - * Template for displaying file name in 'table view' and 'tree view' modes.
145   - *
146   - * content of the element with class 'fp-icon' will be replaced with an appropriate img;
147   - *
148   - * content of element with class 'fp-filename' will be replaced with filename supplied by
149   - * repository;
150   - *
151   - * Note that tree view and table view are the YUI widgets and therefore there are no
152   - * other templates. The widgets will be wrapped in <div> with class fp-treeview or
153   - * fp-tableview (respectfully).
154   - *
155   - * @return string
156   - */
157   - public function js_template_listfilename() {
158   - $rv = '<span class="{!}fp-icon"></span> <span class="{!}fp-filename"></span>';
159   - return preg_replace('/\{\!\}/', '', $rv);
160   - }
161   -
162   - /**
163   - * Template for displaying link/loading progress for fetching of the next page
164   - *
165   - * This text is added to .fp-content AFTER .fp-iconview/.fp-treeview/.fp-tableview
166   - *
167   - * Must have one parent element with class 'fp-nextpage'. It will be assigned additional
168   - * class 'loading' during loading of the next page (it is recommended that in this case the link
169   - * becomes unavailable). Also must contain one element <a> or <button> that will hold
170   - * onclick event for displaying of the next page. The event will be triggered automatically
171   - * when user scrolls to this link.
172   - *
173   - * @return string
174   - */
175   - public function js_template_nextpage() {
176   - $rv = '<div class="{!}fp-nextpage">
177   - <div class="fp-nextpage-link"><a href="#">'.get_string('more').'</a></div>
178   - <div class="fp-nextpage-loading">
179   - <img src="'.$this->pix_url('i/loading').'" />
180   - <p>'.get_string('loading', 'repository').'</p>
181   - </div>
182   -</div>';
183   - return preg_replace('/\{\!\}/', '', $rv);
184   - }
185   -
186   - /**
187   - * Template for window appearing to select a file.
188   - *
189   - * All content must be enclosed in an element with class 'fp-select', CSS for this class
190   - * must define width and height of the window;
191   - *
192   - * Thumbnail image will be added as content to the element with class 'fp-thumbnail';
193   - *
194   - * Inside the window the elements with the following classnames must be present:
195   - * 'fp-saveas', 'fp-linkexternal', 'fp-setauthor', 'fp-setlicense'. Inside each of them must have
196   - * one input element (or select in case of fp-setlicense). They may also have labels.
197   - * The elements will be assign with class 'uneditable' and input/select element will become
198   - * disabled if they are not applicable for the particular file;
199   - *
200   - * There may be present elements with classes 'fp-datemodified', 'fp-datecreated', 'fp-size',
201   - * 'fp-license', 'fp-author'. They will receive additional class 'fp-unknown' if information
202   - * is unavailable. If there is information available, the content of embedded element
203   - * with class 'fp-value' will be substituted with the value;
204   - *
205   - * Elements with classes 'fp-select-confirm' and 'fp-select-cancel' will hold corresponding
206   - * onclick events;
207   - *
208   - * When confirm button is pressed and file is being selected, the top element receives
209   - * additional class 'loading'. It is removed when response from server is received.
210   - *
211   - * @return string
212   - */
213   - public function js_template_selectlayout() {
214   - $rv = '<div class="{!}fp-select">
215   -<div class="fp-select-loading">
216   -<img src="'.$this->pix_url('i/loading').'" />
217   -<p>'.get_string('loading', 'repository').'</p>
218   -</div>
219   -<form>
220   -<p class="{!}fp-thumbnail"></p>
221   -<table width="100%">
222   -<tr class="{!}fp-saveas"><td class="mdl-right"><label>'.get_string('saveas', 'repository').'</label>:</td>
223   -<td class="mdl-left"><input type="text"/></td></tr>
224   -<tr class="{!}fp-linkexternal"><td></td>
225   -<td class="mdl-left"><input type="checkbox"/><label>'.get_string('linkexternal', 'repository').'</label></td></tr>
226   -<tr class="{!}fp-setauthor"><td class="mdl-right"><label>'.get_string('author', 'repository').'</label>:</td>
227   -<td class="mdl-left"><input type="text" /></td></tr>
228   -<tr class="{!}fp-setlicense"><td class="mdl-right"><label>'.get_string('chooselicense', 'repository').'</label>:</td>
229   -<td class="mdl-left"><select></select></td></tr>
230   -</table>
231   -<p><button class="{!}fp-select-confirm" >'.get_string('getfile', 'repository').'</button>
232   -<button class="{!}fp-select-cancel" >'.get_string('cancel').'</button></p>
233   -</form>
234   -<div class="{!}fp-datemodified">'.get_string('lastmodified', 'moodle').': <span class="fp-value"/></div>
235   -<div class="{!}fp-datecreated">'.get_string('datecreated', 'repository').': <span class="fp-value"/></div>
236   -<div class="{!}fp-size">'.get_string('size', 'repository').': <span class="fp-value"/></div>
237   -<div class="{!}fp-license">'.get_string('license', 'moodle').': <span class="fp-value"/></div>
238   -<div class="{!}fp-author">'.get_string('author', 'repository').': <span class="fp-value"/></div>
239   -<div class="{!}fp-dimensions">'.get_string('dimensions', 'repository').': <span class="fp-value"/></div>
240   -</div>';
241   - return preg_replace('/\{\!\}/', '', $rv);
242   - }
243   -
244   - /**
245   - * Content to display when user chooses 'Upload file' repository (will be nested inside
246   - * element with class 'fp-content').
247   - *
248   - * Must contain form (enctype="multipart/form-data" method="POST")
249   - *
250   - * The elements with the following classnames must be present:
251   - * 'fp-file', 'fp-saveas', 'fp-setauthor', 'fp-setlicense'. Inside each of them must have
252   - * one input element (or select in case of fp-setlicense). They may also have labels.
253   - *
254   - * Element with class 'fp-upload-btn' will hold onclick event for uploading the file;
255   - *
256   - * Please note that some fields may be hidden using CSS if this is part of quickupload form
257   - *
258   - * @return string
259   - */
260   - public function js_template_uploadform() {
261   - $rv = '<div class="fp-upload-form mdl-align">
262   -<form enctype="multipart/form-data" method="POST">
263   - <table width="100%">
264   - <tr class="{!}fp-file">
265   - <td class="mdl-right"><label>'.get_string('attachment', 'repository').'</label>:</td>
266   - <td class="mdl-left"><input type="file"/></td>
267   - </tr>
268   - <tr class="{!}fp-saveas">
269   - <td class="mdl-right"><label>'.get_string('saveas', 'repository').'</label>:</td>
270   - <td class="mdl-left"><input type="text"/></td>
271   - </tr>
272   - <tr class="{!}fp-setauthor">
273   - <td class="mdl-right"><label>'.get_string('author', 'repository').'</label>:</td>
274   - <td class="mdl-left"><input type="text"/></td>
275   - </tr>
276   - <tr class="{!}fp-setlicense">
277   - <td class="mdl-right"><label>'.get_string('chooselicense', 'repository').'</label>:</td>
278   - <td class="mdl-left"><select/></td>
279   - </tr>
280   - </table>
281   -</form>
282   -<div><button class="{!}fp-upload-btn">'.get_string('upload', 'repository').'</button></div>
283   -</div> ';
284   - return preg_replace('/\{\!\}/', '', $rv);
285   - }
286   -
287   - /**
288   - * Content to display during loading process in filepicker (inside element with class 'fp-content').
289   - *
290   - * @return string
291   - */
292   - public function js_template_loading() {
293   - return '<div style="text-align:center">
294   -<img src="'.$this->pix_url('i/loading').'" />
295   -<p>'.get_string('loading', 'repository').'</p>
296   -</div>';
297   - }
298   -
299   - /**
300   - * Template for error displayed in filepicker (inside element with class 'fp-content').
301   - *
302   - * must have element with class 'fp-error', its content will be replaced with error text
303   - * and the error code will be assigned as additional class to this element
304   - * used errors: invalidjson, nofilesavailable, norepositoriesavailable
305   - *
306   - * @return string
307   - */
308   - public function js_template_error() {
309   - $rv = '<div class="{!}fp-error" />';
310   - return preg_replace('/\{\!\}/', '', $rv);
311   - }
312   -
313   - /**
314   - * Template for error/info message displayed as a separate popup window.
315   - *
316   - * Must be wrapped in an element with class 'fp-msg', CSS for this element must define
317   - * width and height of the window. It will be assigned with an additional class 'fp-msg-error'
318   - * or 'fp-msg-info' depending on message type;
319   - *
320   - * content of element with class 'fp-msg-text' will be replaced with error/info text;
321   - *
322   - * element with class 'fp-msg-butok' will hold onclick event
323   - *
324   - * @return string
325   - */
326   - public function js_template_message() {
327   - $rv = '<div class="{!}fp-msg">
328   - <div class="{!}fp-msg-text"></div>
329   - <div><button class="{!}fp-msg-butok">'.get_string('ok').'</button></div>
330   - </div>';
331   - return preg_replace('/\{\!\}/', '', $rv);
332   - }
333   -
334   - /**
335   - * Template for popup dialogue window asking for action when file with the same name already exists.
336   - *
337   - * Must be wrapped in an element with class 'fp-dlg', CSS for this element must define width
338   - * and height of the window;
339   - *
340   - * content of element with class 'fp-dlg-text' will be replaced with dialog text;
341   - * elements with classes 'fp-dlg-butoverwrite', 'fp-dlg-butrename' and 'fp-dlg-butcancel' will
342   - * hold onclick events;
343   - *
344   - * content of element with class 'fp-dlg-butrename' will be substituted with appropriate string
345   - * (Note that it may have long text)
346   - *
347   - * @return string
348   - */
349   - public function js_template_processexistingfile() {
350   - $rv = '<div class="{!}fp-dlg"><div class="{!}fp-dlg-text"></div>
351   -<div class="fp-dlg-but"><button class="{!}fp-dlg-butoverwrite" >'.get_string('overwrite', 'repository').'</button></div>
352   -<div class="fp-dlg-but"><button class="{!}fp-dlg-butrename" /></div>
353   -<div class="fp-dlg-but"><button class="{!}fp-dlg-butcancel" >'.get_string('cancel').'</button></div>
354   -</div>';
355   - return preg_replace('/\{\!\}/', '', $rv);
356   - }
357   -
358   - /**
359   - * Template for repository login form including templates for each element type
360   - *
361   - * Must contain one <form> element with templates for different input types inside:
362   - * Elements with classes 'fp-login-popup', 'fp-login-textarea', 'fp-login-select' and
363   - * 'fp-login-input' are templates for displaying respective login form elements. Inside
364   - * there must be exactly one element with type <button>, <textarea>, <select> or <input>
365   - * (i.e. fp-login-popup should have <button>, fp-login-textarea should have <textarea>, etc.);
366   - * They may also contain the <label> element and it's content will be substituted with
367   - * label;
368   - *
369   - * You can also define elements with classes 'fp-login-checkbox', 'fp-login-text'
370   - * but if they are not found, 'fp-login-input' will be used;
371   - *
372   - * Element with class 'fp-login-radiogroup' will be used for group of radio inputs. Inside
373   - * it should hava a template for one radio input (with class 'fp-login-radio');
374   - *
375   - * Element with class 'fp-login-submit' will hold on click mouse event (form submission). It
376   - * will be removed if at least one popup element is present;
377   - *
378   - * @return string
379   - */
380   - public function js_template_loginform() {
381   - $rv = '
382   -<div class="fp-login-form">
383   - <form>
384   - <table width="100%">
385   - <tr class="{!}fp-login-popup">
386   - <td colspan="2">
387   - <label>'.get_string('popup', 'repository').'</label>
388   - <p class="fp-popup"><button class="{!}fp-login-popup-but">'.get_string('login', 'repository').'</button></p>
389   - </td>
390   - </tr>
391   - <tr class="{!}fp-login-textarea">
392   - <td colspan="2"><p><textarea></textarea></p></td>
393   - </tr>
394   - <tr class="{!}fp-login-select">
395   - <td align="right"><label></label></td>
396   - <td align="left"><select></select></td>
397   - </tr>
398   - <tr class="{!}fp-login-input">
399   - <td align="right" width="30%" valign="center"><label /></td>
400   - <td align="left"><input/></td>
401   - </tr>
402   - <tr class="{!}fp-login-radiogroup">
403   - <td align="right" width="30%" valign="top"><label /></td>
404   - <td align="left" valign="top">
405   - <p class="{!}fp-login-radio"><input /> <label /></p>
406   - </td>
407   - </tr>
408   - </table>
409   - <p><button class="{!}fp-login-submit">'.get_string('submit', 'repository').'</button></p>
410   - </form>
411   -</div>';
412   - return preg_replace('/\{\!\}/', '', $rv);
413   - }
414   -
415   - /**
416   - * Returns all Javascript templates as an array.
417   - *
418   - * @return array
419   - */
420   - public function filepicker_templates() {
421   - $class_methods = get_class_methods($this);
422   - $templates = array();
423   - foreach ($class_methods as $method_name) {
424   - if (preg_match('/^js_template_(.*)$/', $method_name, $matches))
425   - $templates[$matches[1]] = $this->$method_name();
426   - }
427   - return $templates;
428   - }
429   -
430   - /**
431   - * Outputs HTML for default repository searchform.
432   - *
433   - * This will be used as contents for search form defined in generallayout template
434   - * (form with id {TOOLSEARCHID}).
435   - * Default contents is one text input field with name="s"
436   - */
437   - public function repository_default_searchform() {
438   - $str = '<label>'.get_string('keyword', 'repository').': </label><br/><input name="s" value="" /><br/>';
439   - return $str;
440   - }
441   -}

0 comments on commit d1d1869

Please sign in to comment.
Something went wrong with that request. Please try again.