|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 // This file is part of Moodle - http://moodle.org/ 00003 // 00004 // Moodle is free software: you can redistribute it and/or modify 00005 // it under the terms of the GNU General Public License as published by 00006 // the Free Software Foundation, either version 3 of the License, or 00007 // (at your option) any later version. 00008 // 00009 // Moodle is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00016 00035 include_once ($CFG->dirroot. '/mod/choice/renderer.php'); 00036 00037 class theme_mymobile_renderer extends plugin_renderer_base { 00038 00045 public function settings_tree(settings_navigation $navigation) { 00046 $content = $this->navigation_node($navigation, array('class' => 'settings')); 00047 if (has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM))) { 00048 // TODO: Work out whether something is missing from here. 00049 } 00050 return $content; 00051 } 00052 00059 public function navigation_tree(global_navigation $navigation) { 00060 return $this->navigation_node($navigation, array()); 00061 } 00062 00070 protected function navigation_node(navigation_node $node, $attrs = array()) { 00071 $items = $node->children; 00072 00073 // exit if empty, we don't want an empty ul element 00074 if ($items->count() == 0) { 00075 return ''; 00076 } 00077 00078 // array of nested li elements 00079 $lis = array(); 00080 foreach ($items as $item) { 00081 if (!$item->display) { 00082 continue; 00083 } 00084 00085 $isbranch = ($item->children->count() > 0 || $item->nodetype == navigation_node::NODETYPE_BRANCH); 00086 $item->hideicon = true; 00087 00088 $content = $this->output->render($item); 00089 $content .= $this->navigation_node($item); 00090 00091 if ($isbranch && !(is_string($item->action) || empty($item->action))) { 00092 $content = html_writer::tag('li', $content, array('data-role' => 'list-divider', 'class' => (string)$item->key)); 00093 } else if($isbranch) { 00094 $content = html_writer::tag('li', $content, array('data-role' => 'list-divider')); 00095 } else { 00096 $content = html_writer::tag('li', $content, array('class' => (string)$item->text)); 00097 } 00098 $lis[] = $content; 00099 } 00100 if (!count($lis)) { 00101 return ''; 00102 } 00103 return implode("\n", $lis); 00104 } 00105 } 00106 00115 class theme_mymobile_core_renderer extends core_renderer { 00116 00122 protected function theme_swatch() { 00123 $showswatch = 'light'; 00124 if (!empty($this->page->theme->settings->colourswatch)) { 00125 $showswatch = $this->page->theme->settings->colourswatch; 00126 } 00127 if ($showswatch == 'light') { 00128 $dtheme = 'b'; 00129 } else { 00130 $dtheme = 'd'; 00131 } 00132 return $dtheme; 00133 } 00134 00144 public function heading($text, $level = 2, $classes = 'main', $id = null) { 00145 if ($classes == 'helpheading') { 00146 // Keeps wrap from help headings in dialog. 00147 $content = parent::heading($text, $level, $classes, $id); 00148 } else { 00149 $content = html_writer::start_tag('div', array('class' => 'headingwrap ui-bar-'.$this->theme_swatch() .' ui-footer')); 00150 $content .= parent::heading($text, $level, $classes.' ui-title', $id); 00151 $content .= html_writer::end_tag('div'); 00152 } 00153 return $content; 00154 } 00155 00163 public function block(block_contents $bc, $region) { 00164 // Avoid messing up the object passed in. 00165 $bc = clone($bc); 00166 // The mymobile theme does not support collapsible blocks. 00167 $bc->collapsible = block_contents::NOT_HIDEABLE; 00168 // There are no controls that are usable within the 00169 $bc->controls = array(); 00170 00171 // TODO: Do we still need to support accessibility here? Surely screen 00172 // readers don't present themselves as mobile devices too often. 00173 $skiptitle = strip_tags($bc->title); 00174 if (empty($skiptitle)) { 00175 $output = ''; 00176 $skipdest = ''; 00177 } else { 00178 $output = html_writer::tag('a', get_string('skipa', 'access', $skiptitle), array('href' => '#sb-' . $bc->skipid, 'class' => 'skip-block')); 00179 $skipdest = html_writer::tag('span', '', array('id' => 'sb-' . $bc->skipid, 'class' => 'skip-block-to')); 00180 } 00181 $testb = $bc->attributes['class']; 00182 00183 // TODO: Find a better solution to this hardcoded block checks 00184 if ($testb == "block_calendar_month2 block") { 00185 $output = html_writer::start_tag('span'); 00186 } else if ($testb == "block_course_overview block") { 00187 $output = html_writer::start_tag('div'); 00188 } else { 00189 if (!empty($this->page->theme->settings->colourswatch)) { 00190 $showswatch = $this->page->theme->settings->colourswatch; 00191 } else { 00192 $showswatch = ''; 00193 } 00194 if ($showswatch == 'light') { 00195 $dtheme = 'd'; 00196 } else { 00197 $dtheme = 'c'; 00198 } 00199 $output = html_writer::start_tag('div', array('data-role' => 'collapsible', 'data-collapsed' => 'true', 'data-content-theme' => $dtheme)); 00200 } 00201 00202 $output .= html_writer::tag('h1', $this->block_header($bc)); 00203 $output .= html_writer::start_tag('div', $bc->attributes); 00204 $output .= $this->block_content($bc); 00205 $output .= html_writer::end_tag('div'); 00206 $output .= html_writer::end_tag('div'); 00207 00208 $output .= $this->block_annotation($bc); 00209 00210 $output .= $skipdest; 00211 00212 return $output; 00213 } 00214 00221 protected function block_header(block_contents $bc) { 00222 $title = ''; 00223 if (!$bc->title) { 00224 return ' '; 00225 } 00226 $output = html_writer::start_tag('div', array('class' => 'header')); 00227 $output .= html_writer::tag('div', html_writer::tag('div', '', array('class'=>'block_action')). $bc->title, array('class' => 'title')); 00228 $output .= html_writer::end_tag('div'); 00229 return $output; 00230 } 00231 00237 protected function init_block_hider_js(block_contents $bc) { 00238 // The mymobile theme in no shape or form supports the hiding of blocks 00239 // this function has been defined and left empty intentionally so that 00240 // the block hider JS is not even included. 00241 } 00242 00248 public function navbar() { 00249 $items = $this->page->navbar->get_items(); 00250 00251 $htmlblocks = array(html_writer::tag('option', get_string('navigation'), array('data-placeholder' => 'true', 'value' => '-1'))); 00252 // Iterate the navarray and display each node 00253 $itemcount = count($items); 00254 $separator = ""; 00255 00256 for ($i = 0; $i < $itemcount; $i++) { 00257 $item = $items[$i]; 00258 $item->hideicon = true; 00259 if ($i === 0) { 00260 $content = html_writer::tag('option', $this->render($item), array('value' => (string)$item->action)); 00261 } else if (!empty($item->action)) { 00262 $content = html_writer::tag('option', $this->render($item), array('value' => (string)$item->action)); 00263 } else { 00264 $content = ''; 00265 } 00266 $htmlblocks[] = $content; 00267 } 00268 00269 $navbarcontent = html_writer::start_tag('form', array('id' => 'navselectform')); 00270 $navbarcontent .= html_writer::start_tag('select', array('id' => 'navselect', 'data-theme' => 'c', 'data-inline' => 'false', 'data-icon' => 'false')); 00271 $navbarcontent .= join('', $htmlblocks); 00272 $navbarcontent .= html_writer::end_tag('select'); 00273 $navbarcontent .= html_writer::end_tag('form'); 00274 // XHTML 00275 return $navbarcontent; 00276 } 00277 00286 protected function render_navigation_node(navigation_node $item) { 00287 // Generate the content normally 00288 $content = parent::render_navigation_node($item); 00289 // Strip out any tabindex's 00290 $content = str_replace(' tabindex="0"', '', $content); 00291 $content = str_replace(' tabindex=\'0\'', '', $content); 00292 // Return the cleaned content 00293 return $content; 00294 } 00295 00301 public function login_info() { 00302 global $USER, $CFG, $DB, $SESSION; 00303 00304 if (during_initial_install()) { 00305 return ''; 00306 } 00307 00308 $course = $this->page->course; 00309 00310 if (session_is_loggedinas()) { 00311 $realuser = session_get_realuser(); 00312 $fullname = fullname($realuser, true); 00313 $realuserinfo = " [<a href=\"$CFG->wwwroot/course/loginas.php?id=$course->id&sesskey=".sesskey()."\">$fullname</a>] "; 00314 } else { 00315 $realuserinfo = ''; 00316 } 00317 00318 $loginurl = get_login_url(); 00319 00320 if (empty($course->id)) { 00321 // $course->id is not defined during installation 00322 return ''; 00323 } else if (isloggedin()) { 00324 $context = get_context_instance(CONTEXT_COURSE, $course->id); 00325 $fullname = fullname($USER, true); 00326 00327 // Since Moodle 2.0 this link always goes to the public profile page (not the course profile page) 00328 // TODO: Test what happens when someone is using this via mnet [for this as well as login_info_footer] 00329 // TODO: Test what happens when you use the loginas feature [for this as well as login_info_footer] 00330 $username = ""; 00331 if (is_mnet_remote_user($USER) and $idprovider = $DB->get_record('mnet_host', array('id'=>$USER->mnethostid))) { 00332 $username .= " from <a href=\"{$idprovider->wwwroot}\">{$idprovider->name}</a>"; 00333 } 00334 if (isguestuser()) { 00335 $loggedinas = $realuserinfo.get_string('loggedinasguest')." (<a href=\"$loginurl\">".get_string('login').'</a>)'; 00336 } else if (is_role_switched($course->id)) { // Has switched roles 00337 $rolename = ''; 00338 if ($role = $DB->get_record('role', array('id'=>$USER->access['rsw'][$context->path]))) { 00339 $rolename = ': '.format_string($role->name); 00340 } 00341 } else { 00342 $loggedinas = $realuserinfo.$username.' <a id="mypower" data-inline="true" data-role="button" data-icon="mypower" data-ajax="false" class="ui-btn-right mypower" href="'.$CFG->wwwroot.'/login/logout.php?sesskey='.sesskey().'\">'.get_string('logout').'</a>'; 00343 } 00344 } else { 00345 $loggedinas = '<a data-role="button" data-icon="alert" class="ui-btn-right nolog" href="'.$loginurl.'" data-ajax="false">'.get_string('login').'</a>'; 00346 } 00347 00348 // TODO: Enable $CFG->displayloginfailures and test as admin what happens after you succesfully 00349 // log in after a failed log in attempt. [for this as well as login_info_footer] 00350 // This is probably totally unneeded 00351 if (isset($SESSION->justloggedin)) { 00352 unset($SESSION->justloggedin); 00353 if (!empty($CFG->displayloginfailures)) { 00354 if (!isguestuser()) { 00355 if ($count = count_login_failures($CFG->displayloginfailures, $USER->username, $USER->lastlogin)) { 00356 $loggedinas .= ' <div class="loginfailures">'; 00357 if (empty($count->accounts)) { 00358 $loggedinas .= get_string('failedloginattempts', '', $count); 00359 } else { 00360 $loggedinas .= get_string('failedloginattemptsall', '', $count); 00361 } 00362 if (has_capability('coursereport/log:view', get_context_instance(CONTEXT_SYSTEM))) { 00363 $loggedinas .= ' (<a href="'.$CFG->wwwroot.'/course/report/log/index.php?chooselog=1&id=1&modid=site_errors">'.get_string('logs').'</a>)'; 00364 } 00365 $loggedinas .= '</div>'; 00366 } 00367 } 00368 } 00369 } 00370 00371 return $loggedinas; 00372 } 00373 00379 public function login_info_footer() { 00380 global $USER, $CFG, $DB, $SESSION; 00381 00382 if (during_initial_install()) { 00383 return ''; 00384 } 00385 00386 $loginpage = ((string)$this->page->url === get_login_url()); 00387 $course = $this->page->course; 00388 00389 if (session_is_loggedinas()) { 00390 $realuser = session_get_realuser(); 00391 $fullname = fullname($realuser, true); 00392 $realuserinfo = ' [<a href="'.$CFG->wwwroot.'/course/loginas.php?id=$course->id&sesskey='.sesskey().'">$fullname</a>] '; 00393 } else { 00394 $realuserinfo = ''; 00395 } 00396 00397 $loginurl = get_login_url(); 00398 00399 if (empty($course->id)) { 00400 // $course->id is not defined during installation 00401 return ''; 00402 } else if (isloggedin()) { 00403 $context = get_context_instance(CONTEXT_COURSE, $course->id); 00404 00405 $fullname = fullname($USER, true); 00406 // Since Moodle 2.0 this link always goes to the public profile page (not the course profile page) 00407 $username = '<a href="'.$CFG->wwwroot.'/user/profile.php?id='.$USER->id.'">'.$fullname.'</a>'; 00408 if (is_mnet_remote_user($USER) and $idprovider = $DB->get_record('mnet_host', array('id'=>$USER->mnethostid))) { 00409 $username .= " from <a href=\"{$idprovider->wwwroot}\">{$idprovider->name}</a>"; 00410 } 00411 if (isguestuser()) { 00412 $loggedinas = $realuserinfo.get_string('loggedinasguest'); 00413 if (!$loginpage) { 00414 $loggedinas .= " (<a href=\"$loginurl\">".get_string('login').'</a>)'; 00415 } 00416 } else if (is_role_switched($course->id)) { // Has switched roles 00417 $rolename = ''; 00418 if ($role = $DB->get_record('role', array('id'=>$USER->access['rsw'][$context->path]))) { 00419 $rolename = ': '.format_string($role->name); 00420 } 00421 $loggedinas = get_string('loggedinas', 'moodle', $username).$rolename." (<a href=\"$CFG->wwwroot/course/view.php?id=$course->id&switchrole=0&sesskey=".sesskey()."\">".get_string('switchrolereturn').'</a>)'; 00422 } else { 00423 $loggedinas = $realuserinfo.get_string('loggedinas', 'moodle', $username).' '." (<a href=\"$CFG->wwwroot/login/logout.php?sesskey=".sesskey()."\" data-ajax=\"false\">".get_string('logout').'</a>)'; 00424 } 00425 } else { 00426 $loggedinas = get_string('loggedinnot', 'moodle'); 00427 if (!$loginpage) { 00428 $loggedinas .= " (<a href=\"$loginurl\" data-ajax=\"false\">".get_string('login').'</a>)'; 00429 } 00430 } 00431 00432 $loggedinas = '<div class="logininfo">'.$loggedinas.'</div>'; 00433 00434 if (isset($SESSION->justloggedin)) { 00435 unset($SESSION->justloggedin); 00436 if (!empty($CFG->displayloginfailures)) { 00437 if (!isguestuser()) { 00438 if ($count = count_login_failures($CFG->displayloginfailures, $USER->username, $USER->lastlogin)) { 00439 $loggedinas .= ' <div class="loginfailures">'; 00440 if (empty($count->accounts)) { 00441 $loggedinas .= get_string('failedloginattempts', '', $count); 00442 } else { 00443 $loggedinas .= get_string('failedloginattemptsall', '', $count); 00444 } 00445 if (has_capability('coursereport/log:view', get_context_instance(CONTEXT_SYSTEM))) { 00446 $loggedinas .= ' (<a href="'.$CFG->wwwroot.'/course/report/log/index.php?chooselog=1&id=1&modid=site_errors">'.get_string('logs').'</a>)'; 00447 } 00448 $loggedinas .= '</div>'; 00449 } 00450 } 00451 } 00452 } 00453 00454 return $loggedinas; 00455 } 00456 00466 public function redirect_message($encodedurl, $message, $delay, $debugdisableredirect) { 00467 global $CFG; 00468 $url = str_replace('&', '&', $encodedurl); 00469 // TODO: Find a much better solution for this... looks like it is just removing 00470 // the anchor from the link. 00471 // The below to fix redirect issues with ajax... John 00472 $encodedurl = str_replace('#', '&', $encodedurl); 00473 00474 switch ($this->page->state) { 00475 case moodle_page::STATE_BEFORE_HEADER : 00476 // No output yet it is safe to delivery the full arsenal of redirect methods 00477 if (!$debugdisableredirect) { 00478 // Don't use exactly the same time here, it can cause problems when both redirects fire at the same time. 00479 $this->metarefreshtag = '<meta http-equiv="refresh" content="'. $delay .'; url='. $encodedurl .'" />'."\n"; 00480 } 00481 $output = $this->header(); 00482 break; 00483 case moodle_page::STATE_PRINTING_HEADER : 00484 // We should hopefully never get here 00485 throw new coding_exception('You cannot redirect while printing the page header'); 00486 break; 00487 case moodle_page::STATE_IN_BODY : 00488 // We really shouldn't be here but we can deal with this 00489 debugging("You should really redirect before you start page output"); 00490 if (!$debugdisableredirect) { 00491 $this->page->requires->js_function_call('document.location.replace', array($url), false, $delay); 00492 } 00493 $output = $this->opencontainers->pop_all_but_last(); 00494 break; 00495 case moodle_page::STATE_DONE : 00496 // Too late to be calling redirect now 00497 throw new coding_exception('You cannot redirect after the entire page has been generated'); 00498 break; 00499 } 00500 00501 $output .= $this->notification($message, 'redirectmessage'); 00502 $output .= '<div class="continuebutton"><a data-ajax="false" data-role="button" href="'. $encodedurl .'">'. get_string('continue') .'</a></div>'; 00503 if ($debugdisableredirect) { 00504 $output .= '<p><strong>Error output, so disabling automatic redirect.</strong></p>'; 00505 } 00506 $output .= $this->footer(); 00507 return $output; 00508 } 00509 00516 protected function render_help_icon(help_icon $helpicon) { 00517 global $CFG; 00518 00519 // first get the help image icon 00520 $src = $this->pix_url('help'); 00521 00522 $title = get_string($helpicon->identifier, $helpicon->component); 00523 00524 if (empty($helpicon->linktext)) { 00525 $alt = $title; 00526 } else { 00527 $alt = get_string('helpwiththis'); 00528 } 00529 00530 $attributes = array('src'=>$src, 'alt'=>$alt, 'class'=>'iconhelp', 'data-role'=>'button', 'data-inline'=>'true'); 00531 $output = html_writer::empty_tag('img', $attributes); 00532 00533 // add the link text if given 00534 if (!empty($helpicon->linktext)) { 00535 // the spacing has to be done through CSS 00536 $output .= $helpicon->linktext; 00537 } 00538 00539 // now create the link around it 00540 // TODO: Do we need to specify the theme in the help.php link? 00541 $url = new moodle_url('/help.php', array('component' => $helpicon->component, 'identifier' => $helpicon->identifier, 'lang'=>current_language(), 'theme'=>'mymobile')); 00542 00543 // note: this title is displayed only if JS is disabled, otherwise the link will have the new ajax tooltip 00544 $title = get_string('helpprefix2', '', trim($title, ". \t")); 00545 00546 $attributes = array('href'=>$url, 'title'=>$title); 00547 $id = html_writer::random_id('helpicon'); 00548 $attributes['id'] = $id; 00549 $attributes['rel'] = 'notexternal'; 00550 $attributes['data-rel'] = 'dialog'; 00551 $attributes['data-transition'] = 'slideup'; 00552 $output = html_writer::tag('a', $output, $attributes); 00553 00554 // and finally span 00555 return html_writer::tag('span', $output, array('class' => 'helplink2')); 00556 } 00557 00564 protected function render_single_button(single_button $button) { 00565 $attributes = array( 00566 'type' => 'submit', 00567 'value' => $button->label, 00568 'disabled' => $button->disabled ? 'disabled' : null, 00569 'title' => $button->tooltip 00570 ); 00571 00572 if ($button->actions) { 00573 $id = html_writer::random_id('single_button'); 00574 $attributes['id'] = $id; 00575 foreach ($button->actions as $action) { 00576 $this->add_action_handler($action, $id); 00577 } 00578 } 00579 00580 // first the input element 00581 $output = html_writer::empty_tag('input', $attributes); 00582 00583 // then hidden fields 00584 $params = $button->url->params(); 00585 if ($button->method === 'post') { 00586 $params['sesskey'] = sesskey(); 00587 } 00588 foreach ($params as $var => $val) { 00589 $output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => $var, 'value' => $val)); 00590 } 00591 00592 // then div wrapper for xhtml strictness 00593 $output = html_writer::tag('div', $output, array('rel' => $button->url->out_omit_querystring())); 00594 00595 // TODO: Test a single_button that has an anchor and is set to use post 00596 // now the form itself around it 00597 $url = $button->url->out_omit_querystring(); // url without params 00598 00599 if ($url === '') { 00600 $url = '#'; // there has to be always some action 00601 } 00602 00603 // TODO: This is surely a bug that needs fixing.. all of a sudden we've switched 00604 // to the pages URL. 00605 // Test an single button with an external URL as its url 00606 // If the url has http, cool, if not we need to add it, JOHN 00607 $urlcheck = substr($url, 0, 4); 00608 if ($urlcheck != 'http') { 00609 $url = $this->page->url->out_omit_querystring(); 00610 } 00611 00612 $attributes = array( 00613 'method' => $button->method, 00614 'action' => $url, 00615 'id' => $button->formid 00616 ); 00617 $output = html_writer::tag('form', $output, $attributes); 00618 00619 // and finally one more wrapper with class 00620 return html_writer::tag('div', $output, array('class' => $button->class)); 00621 } 00622 00628 public function header() { 00629 global $USER, $CFG; 00630 00631 if (session_is_loggedinas()) { 00632 $this->page->add_body_class('userloggedinas'); 00633 } 00634 00635 $this->page->set_state(moodle_page::STATE_PRINTING_HEADER); 00636 00637 // Find the appropriate page layout file, based on $this->page->pagelayout. 00638 $layoutfile = $this->page->theme->layout_file($this->page->pagelayout); 00639 // Render the layout using the layout file. 00640 $rendered = $this->render_page_layout($layoutfile); 00641 00642 // Slice the rendered output into header and footer. 00643 $cutpos = strpos($rendered, $this->unique_main_content_token); 00644 if ($cutpos === false) { 00645 $cutpos = strpos($rendered, self::MAIN_CONTENT_TOKEN); 00646 $token = self::MAIN_CONTENT_TOKEN; 00647 } else { 00648 $token = $this->unique_main_content_token; 00649 } 00650 00651 if ($cutpos === false) { 00652 // TODO: Search for a better solution to this... check this is even needed? 00653 // The following code will lead to header containing nothing, and 00654 // footer containing all of the content for the template. 00655 // turned off error by john for ajax load of blocks without main content. 00656 // throw new coding_exception('page layout file ' . $layoutfile . 00657 // ' does not contain the string "' . self::MAIN_CONTENT_TOKEN . '".'); 00658 } 00659 $header = substr($rendered, 0, $cutpos); 00660 $footer = substr($rendered, $cutpos + strlen($token)); 00661 00662 if (empty($this->contenttype)) { 00663 debugging('The page layout file did not call $OUTPUT->doctype()'); 00664 $header = $this->doctype() . $header; 00665 } 00666 00667 send_headers($this->contenttype, $this->page->cacheable); 00668 00669 $this->opencontainers->push('header/footer', $footer); 00670 $this->page->set_state(moodle_page::STATE_IN_BODY); 00671 00672 return $header . $this->skip_link_target('maincontent'); 00673 } 00674 00682 public function notification($message, $classes = 'notifyproblem') { 00683 return html_writer::tag('div', clean_text($message), array('data-role'=>'none', 'data-icon'=>'alert', 'data-theme'=>'d', 'class' => renderer_base::prepare_classes($classes))); 00684 } 00685 00692 public function blocks_for_region($region) { 00693 $blockcontents = $this->page->blocks->get_content_for_region($region, $this); 00694 00695 $output = ''; 00696 foreach ($blockcontents as $bc) { 00697 if ($bc instanceof block_contents) { 00698 // We don't want to print navigation and settings blocks here. 00699 if ($bc->attributes['class'] != 'block_settings block' && $bc->attributes['class'] != 'block_navigation block') { 00700 $output .= $this->block($bc, $region); 00701 } 00702 } else if ($bc instanceof block_move_target) { 00703 $output .= $this->block_move_target($bc); 00704 } else { 00705 throw new coding_exception('Unexpected type of thing (' . get_class($bc) . ') found in list of block contents.'); 00706 } 00707 } 00708 00709 return $output; 00710 } 00711 00718 protected function render_single_select(single_select $select) { 00719 $select = clone($select); 00720 if (empty($select->formid)) { 00721 $select->formid = html_writer::random_id('single_select_f'); 00722 } 00723 00724 $output = ''; 00725 $params = $select->url->params(); 00726 if ($select->method === 'post') { 00727 $params['sesskey'] = sesskey(); 00728 } 00729 foreach ($params as $name=>$value) { 00730 $output .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>$name, 'value'=>$value)); 00731 } 00732 00733 if (empty($select->attributes['id'])) { 00734 $select->attributes['id'] = html_writer::random_id('single_select'); 00735 //$select->attributes['data-native-menu'] = 'false'; 00736 //above by john for select elements to use native style and help performance? 00737 } 00738 00739 if ($select->disabled) { 00740 $select->attributes['disabled'] = 'disabled'; 00741 } 00742 00743 if ($select->tooltip) { 00744 $select->attributes['title'] = $select->tooltip; 00745 } 00746 00747 if ($select->label) { 00748 $output .= html_writer::label($select->label, $select->attributes['id']); 00749 } 00750 00751 if ($select->helpicon instanceof help_icon) { 00752 $output .= $this->render($select->helpicon); 00753 } else if ($select->helpicon instanceof old_help_icon) { 00754 $output .= $this->render($select->helpicon); 00755 } 00756 00757 $output .= html_writer::select($select->options, $select->name, $select->selected, $select->nothing, $select->attributes); 00758 00759 //by john show go button to fix selects 00760 $go = ''; 00761 $output .= html_writer::empty_tag('input data-inline="true"', array('type' => 'submit', 'value' => get_string('go'))); 00762 $output .= html_writer::tag('noscript', html_writer::tag('div', $go), array('style' => 'inline')); 00763 00764 $nothing = empty($select->nothing) ? false : key($select->nothing); 00765 $this->page->requires->js_init_call('M.util.init_select_autosubmit', array($select->formid, $select->attributes['id'], $nothing)); 00766 00767 // then div wrapper for xhtml strictness 00768 $output = html_writer::tag('div', $output); 00769 00770 // now the form itself around it 00771 $formattributes = array( 00772 'method' => $select->method, 00773 'action' => $select->url->out_omit_querystring(), 00774 'id' => $select->formid 00775 ); 00776 $output = html_writer::tag('form', $output, $formattributes); 00777 00778 // and finally one more wrapper with class 00779 return html_writer::tag('div', $output, array('class' => $select->class)); 00780 } 00781 } 00782 00791 class theme_mymobile_mod_choice_renderer extends mod_choice_renderer { 00792 00800 public function display_options($options, $coursemoduleid, $vertical = false) { 00801 $layoutclass = 'horizontal'; 00802 if ($vertical) { 00803 $layoutclass = 'vertical'; 00804 } 00805 $target = new moodle_url('/mod/choice/view.php'); 00806 //changed below to post from target john 00807 $attributes = array('method'=>'POST', 'action'=>$target, 'class'=> $layoutclass); 00808 00809 $html = html_writer::start_tag('form', $attributes); 00810 $html .= html_writer::start_tag('ul', array('class'=>'choices', 'data-role'=>'controlgroup' )); 00811 00812 $availableoption = count($options['options']); 00813 foreach ($options['options'] as $option) { 00814 $html .= html_writer::start_tag('li', array('class'=>'option')); 00815 $option->attributes->name = 'answer'; 00816 $option->attributes->type = 'radio'; 00817 $option->attributes->id = 'answer'.html_writer::random_id(); 00818 00819 $labeltext = $option->text; 00820 if (!empty($option->attributes->disabled)) { 00821 $labeltext .= ' ' . get_string('full', 'choice'); 00822 $availableoption--; 00823 } 00824 00825 $html .= html_writer::empty_tag('input', (array)$option->attributes); 00826 $html .= html_writer::tag('label', $labeltext, array('for'=>$option->attributes->id)); 00827 $html .= html_writer::end_tag('li'); 00828 } 00829 $html .= html_writer::tag('li','', array('class'=>'clearfloat')); 00830 $html .= html_writer::end_tag('ul'); 00831 $html .= html_writer::tag('div', '', array('class'=>'clearfloat')); 00832 $html .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'sesskey', 'value'=>sesskey())); 00833 $html .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'id', 'value'=>$coursemoduleid)); 00834 00835 if (!empty($options['hascapability']) && ($options['hascapability'])) { 00836 if ($availableoption < 1) { 00837 $html .= html_writer::tag('label', get_string('choicefull', 'choice')); 00838 } else { 00839 $html .= html_writer::empty_tag('input', array('type'=>'submit', 'value'=>get_string('savemychoice','choice'), 'class'=>'button')); 00840 } 00841 00842 if (!empty($options['allowupdate']) && ($options['allowupdate'])) { 00843 $url = new moodle_url('view.php', array('id'=>$coursemoduleid, 'action'=>'delchoice', 'sesskey'=>sesskey())); 00844 $html .= html_writer::link($url, get_string('removemychoice','choice')); 00845 } 00846 } else { 00847 $html .= html_writer::tag('label', get_string('havetologin', 'choice')); 00848 } 00849 00850 $html .= html_writer::end_tag('ul'); 00851 $html .= html_writer::end_tag('form'); 00852 00853 return $html; 00854 } 00855 00867 public function display_publish_name_vertical($choices) { 00868 $html =''; 00869 $html .= html_writer::tag('h2',format_string(get_string("responses", "choice")), array('class'=>'main')); 00870 00871 $attributes = array('method'=>'POST'); 00872 $attributes['action'] = new moodle_url('/mod/choice/view.php'); 00873 $attributes['id'] = 'attemptsform'; 00874 00875 if ($choices->viewresponsecapability) { 00876 $html .= html_writer::start_tag('form', $attributes); 00877 $html .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'id', 'value'=> $choices->coursemoduleid)); 00878 $html .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'sesskey', 'value'=> sesskey())); 00879 $html .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'mode', 'value'=>'overview')); 00880 } 00881 00882 $table = new html_table(); 00883 $table->cellpadding = 0; 00884 $table->cellspacing = 0; 00885 $table->attributes['class'] = 'results names '; 00886 $table->tablealign = 'center'; 00887 $table->data = array(); 00888 00889 $count = 0; 00890 ksort($choices->options); 00891 00892 $columns = array(); 00893 foreach ($choices->options as $optionid => $options) { 00894 $coldata = ''; 00895 if ($choices->showunanswered && $optionid == 0) { 00896 $coldata .= html_writer::tag('div', format_string(get_string('notanswered', 'choice')), array('class'=>'option')); 00897 } else if ($optionid > 0) { 00898 $coldata .= html_writer::tag('div', format_string($choices->options[$optionid]->text), array('class'=>'option')); 00899 } 00900 $numberofuser = 0; 00901 if (!empty($options->user) && count($options->user) > 0) { 00902 $numberofuser = count($options->user); 00903 } 00904 00905 $coldata .= html_writer::tag('div', ' ('.$numberofuser. ')', array('class'=>'numberofuser', 'title' => get_string('numberofuser', 'choice'))); 00906 $columns[] = $coldata; 00907 } 00908 00909 $table->head = $columns; 00910 00911 $coldata = ''; 00912 $columns = array(); 00913 foreach ($choices->options as $optionid => $options) { 00914 $coldata = ''; 00915 if ($choices->showunanswered || $optionid > 0) { 00916 if (!empty($options->user)) { 00917 foreach ($options->user as $user) { 00918 $data = ''; 00919 if (empty($user->imagealt)){ 00920 $user->imagealt = ''; 00921 } 00922 00923 if ($choices->viewresponsecapability && $choices->deleterepsonsecapability && $optionid > 0) { 00924 $attemptaction = html_writer::checkbox('attemptid[]', $user->id,''); 00925 $data .= html_writer::tag('div', $attemptaction, array('class'=>'attemptaction')); 00926 } 00927 $userimage = $this->output->user_picture($user, array('courseid'=>$choices->courseid)); 00928 $data .= html_writer::tag('div', $userimage, array('class'=>'image')); 00929 00930 $userlink = new moodle_url('/user/view.php', array('id'=>$user->id,'course'=>$choices->courseid)); 00931 $name = html_writer::tag('a', fullname($user, $choices->fullnamecapability), array('href'=>$userlink, 'class'=>'username')); 00932 $data .= html_writer::tag('div', $name, array('class'=>'fullname')); 00933 $data .= html_writer::tag('div','', array('class'=>'clearfloat')); 00934 $coldata .= html_writer::tag('div', $data, array('class'=>'user')); 00935 } 00936 } 00937 } 00938 00939 $columns[] = $coldata; 00940 $count++; 00941 } 00942 00943 $table->data[] = $columns; 00944 foreach ($columns as $d) { 00945 $table->colclasses[] = 'data'; 00946 } 00947 $html .= html_writer::tag('div', html_writer::table($table), array('class'=>'response')); 00948 00949 $actiondata = ''; 00950 if ($choices->viewresponsecapability && $choices->deleterepsonsecapability) { 00951 $selecturl = new moodle_url('#'); 00952 00953 $selectallactions = new component_action('click',"select_all_in", array('div',null,'tablecontainer')); 00954 $selectall = new action_link($selecturl, get_string('selectall'), $selectallactions); 00955 $actiondata .= $this->output->render($selectall) . ' / '; 00956 00957 $deselectallactions = new component_action('click',"deselect_all_in", array('div',null,'tablecontainer')); 00958 $deselectall = new action_link($selecturl, get_string('deselectall'), $deselectallactions); 00959 $actiondata .= $this->output->render($deselectall); 00960 //below john fixed 00961 $actiondata .= html_writer::tag('label', ' ' . get_string('withselected', 'choice') . ' ', array('for'=>'menuaction')); 00962 00963 $actionurl = new moodle_url('/mod/choice/view.php', array('sesskey'=>sesskey(), 'action'=>'delete_confirmation()')); 00964 $select = new single_select($actionurl, 'action', array('delete'=>get_string('delete')), null, array(''=>get_string('moveselectedusersto', 'choice')), 'attemptsform'); 00965 00966 $actiondata .= $this->output->render($select); 00967 } 00968 $html .= html_writer::tag('div', $actiondata, array('class'=>'responseaction')); 00969 00970 if ($choices->viewresponsecapability) { 00971 $html .= html_writer::end_tag('form'); 00972 } 00973 00974 return $html; 00975 } 00976 }