diff --git a/lib/dropdown.js b/lib/dropdown.js deleted file mode 100644 index 617693f23b532..0000000000000 --- a/lib/dropdown.js +++ /dev/null @@ -1,113 +0,0 @@ -/**** -Author: Jerome Mouneyrac -Bug Reference: http://tracker.moodle.org/browse/MDL-14439 -IE and Opera fire the onchange when ever you move into a dropdwown list with the keyboard. -These functions fix this problem. -****/ - -/* -global variables - -Note: -if I didn't use global variables, we would need to pass them as parameter: -=> in initSelect(): - I would write "theSelect.onchange = selectChanged(...);" - This code causes a javascript error on IE. (not firefox) -so I had to write theSelect.onchange = selectChanged; It's why I use global variables . -Because I use global variables, I didn't put this code in javascript-static.js. -This file is loaded in javascript.php. -*/ -var select_formid; -var select_targetwindow; - -//we redefine all user actions on the dropdown list -//onfocus, onchange, onkeydown, and onclick -function initSelect(formId,targetWindow) -{ - //initialise global variables - select_formid=formId; - select_targetwindow=targetWindow; - - var theSelect = document.getElementById(select_formid+"_jump"); - - theSelect.changed = false; - - selectFocussed(); - - theSelect.onchange = selectChanged; - theSelect.onkeydown = selectKeyed; - theSelect.onclick = selectClicked; - - return true; -} - -function selectChanged(theElement) -{ - var theSelect; - - if (theElement && theElement.value) - { - theSelect = theElement; - } - else - { - theSelect = this; - } - - if (!theSelect.changed) - { - return false; - } - - //here is the onchange redirection - select_targetwindow.location=document.getElementById(select_formid).jump.options[document.getElementById(select_formid).jump.selectedIndex].value; - - return true; -} - -function selectClicked() -{ - this.changed = true; -} - -function selectFocussed() -{ - this.initValue = this.value; - - return true; -} - -//we keep Firefox behaviors: onchange is fired when we press "Enter", "Esc", or "Tab"" keys. -//note that is probably not working on Mac (keyCode could be different) -function selectKeyed(e) -{ - var theEvent; - var keyCodeTab = "9"; - var keyCodeEnter = "13"; - var keyCodeEsc = "27"; - - if (e) - { - theEvent = e; - } - else - { - theEvent = event; - } - - if ((theEvent.keyCode == keyCodeEnter || theEvent.keyCode == keyCodeTab) && this.value != this.initValue) - { - this.changed = true; - selectChanged(this); - } - else if (theEvent.keyCode == keyCodeEsc) - { - this.value = this.initValue; - } - else - { - this.changed = false; - } - - return true; -} \ No newline at end of file diff --git a/lib/javascript-static.js b/lib/javascript-static.js index 1d5927341fee6..ecb07e0979b47 100644 --- a/lib/javascript-static.js +++ b/lib/javascript-static.js @@ -381,6 +381,19 @@ M.util.init_maximised_embed = function(Y, id) { }; }; +/** + * Attach handler to single_select + */ +M.util.init_single_select = function(Y, formid, selectid, nothing) { + YUI(M.yui.loader).use('node', function(Y) { + Y.on('change', function() { + if ((nothing == false && Y.Lang.isBoolean(nothing)) || Y.one('#'+selectid).get('value') != nothing) { + Y.one('#'+formid).submit(); + } + }, + '#'+selectid); + }); +}; //=== old legacy JS code, hopefully to be replaced soon by M.xx.yy and YUI3 code === diff --git a/lib/outputcomponents.php b/lib/outputcomponents.php index d2f5f4313a975..8902c7d14f184 100644 --- a/lib/outputcomponents.php +++ b/lib/outputcomponents.php @@ -262,6 +262,120 @@ public function add_action(component_action $action) { } +/** + * Simple form with just one select field that gets submitted automatically. + * If JS not enabled small go button is printed too. + * + * @copyright 2009 Petr Skoda + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since Moodle 2.0 + */ +class single_select implements renderable { + /** + * Target url - includes hidden fields + * @var moodle_url + */ + var $url; + /** + * Name of the select element. + * @var string + */ + var $name; + /** + * @var array $options associative array value=>label ex.: + * array(1=>'One, 2=>Two) + * it is also possible to specify optgroup as complex label array ex.: + * array(array('Odd'=>array(1=>'One', 3=>'Three)), array('Even'=>array(2=>'Two'))) + * array(1=>'One', '--1uniquekey'=>array('More'=>array(2=>'Two', 3=>'Three'))) + */ + var $options; + /** + * Selected option + * @var string + */ + var $selected; + /** + * Nothing selected + * @var array + */ + var $nothing; + /** + * Extra select field attributes + * @var array + */ + var $attributes = array(); + /** + * Button label + * @var string + */ + var $label = ''; + /** + * Form submit method + * @var string post or get + */ + var $method = 'get'; + /** + * Wrapping div class + * @var string + * */ + var $class = 'singleselect'; + /** + * True if button disabled, false if normal + * @var boolean + */ + var $disabled = false; + /** + * Button tooltip + * @var string + */ + var $tooltip = null; + /** + * Form id + * @var string + */ + var $formid = null; + /** + * List of attached actions + * @var array of component_action + */ + var $helpicon = null; + /** + * Constructor + * @param moodle_url $url form action target, includes hidden fields + * @param string $name name of selection field - the changing parameter in url + * @param array $options list of options + * @param string $selected selected element + * @param array $nothing + */ + public function __construct(moodle_url $url, $name, array $options, $selected='', $nothing=array(''=>'choosedots')) { + $this->url = $url; + $this->name = $name; + $this->options = $options; + $this->selected = $selected; + $this->nothing = $nothing; + } + + /** + * Shortcut for adding a JS confirm dialog when the button is clicked. + * The message must be a yes/no question. + * @param string $message The yes/no confirmation question. If "Yes" is clicked, the original action will occur. + * @return void + */ + public function add_confirm_action($confirmmessage) { + $this->add_action(new component_action('submit', 'M.util.show_confirm_dialog', array('message' => $confirmmessage))); + } + + /** + * Add action to the button. + * @param component_action $action + * @return void + */ + public function add_action(component_action $action) { + $this->actions[] = $action; + } +} + + /** * Data structure describing html link with special action attached. * @copyright 2010 Petr Skoda @@ -546,7 +660,7 @@ public static function script($jscode, $url=null) { } else if ($url) { $attributes = array('type'=>'text/javascript', 'src'=>$url); return self::tag('script', $attributes, '') . "\n"; - + } else { return ''; } diff --git a/lib/outputrenderers.php b/lib/outputrenderers.php index 0c5055ab2117f..30cd9bdb408e6 100644 --- a/lib/outputrenderers.php +++ b/lib/outputrenderers.php @@ -717,10 +717,10 @@ public function lang_menu() { return ''; } - $select = html_select::make_popup_form($this->page->url, 'lang', $langs, 'chooselang', $currlang); - $select->nothinglabel = false; - $select->set_label(get_accesshide(get_string('language'))); - return '
'.$this->select($select).'
'; + $s = new single_select($this->page->url, 'lang', $langs, $currlang, null); + $s->label = get_accesshide(get_string('language')); + $s->class = 'langmenu'; + return $this->render($s); } /** @@ -1081,6 +1081,81 @@ protected function render_single_button(single_button $button) { return html_writer::tag('div', array('class' => $button->class), $output); } + /** + * Returns a form with a single button. + * @param moodle_url $url form action target, includes hidden fields + * @param string $name name of selection field - the changing parameter in url + * @param array $options list of options + * @param string $selected selected element + * @param array $nothing + * @return string HTML fragment + */ + public function single_select($url, $name, array $options, $selected='', $nothing=array(''=>'choosedots')) { + if (!($url instanceof moodle_url)) { + $url = new moodle_url($url); + } + $select = new single_select($url, $url, $name, $options, $selected, $nothing); + + return $this->render($select); + } + + /** + * Internal implementation of single_select rendering + * @param single_select $select + * @return string HTML fragment + */ + protected function render_single_select(single_select $select) { + $select = clone($select); + if (empty($select->formid)) { + $select->formid = html_writer::random_id('single_select_f'); + } + + $output = ''; + $params = $select->url->params(); + if ($select->method === 'post') { + $params['sesskey'] = sesskey(); + } + foreach ($params as $name=>$value) { + $output .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>$name, 'value'=>$value)); + } + + if (empty($select->attributes['id'])) { + $select->attributes['id'] = html_writer::random_id('single_select'); + } + + if ($select->tooltip) { + $select->attributes['title'] = $select->tooltip; + } + + if ($select->label) { + $output .= html_writer::tag('label', array('for'=>$select->attributes['id']), $select->label); + } + + if ($select->helpicon instanceof help_icon) { + $output .= $this->render($select->helpicon); + } + + $output .= html_writer::select($select->options, $select->name, $select->selected, $select->nothing, $select->attributes); + + $go = html_writer::empty_tag('input', array('type'=>'submit', 'value'=>get_string('go'))); + $output .= html_writer::tag('noscript', array('style'=>'inline'), $go); + + $nothing = empty($select->nothing) ? false : key($select->nothing); + $output .= $this->page->requires->js_init_call('M.util.init_single_select', array($select->formid, $select->attributes['id'], $nothing)); + + // then div wrapper for xhtml strictness + $output = html_writer::tag('div', array(), $output); + + // now the form itself around it + $formattributes = array('method' => $select->method, + 'action' => $select->url->out_omit_querystring(), + 'id' => $select->formid); + $output = html_writer::tag('form', $formattributes, $output); + + // and finally one more wrapper with class + return html_writer::tag('div', array('class' => $select->class), $output); + } + /** * Given a html_form component and an optional rendered submit button, * outputs a HTML form with correct divs and inputs and a single submit button. @@ -1110,7 +1185,7 @@ public function form(html_form $form, $contents=null) { 'id' => $form->button->id); if ($form->jssubmitaction) { - $buttonattributes['class'] .= ' hiddenifjs'; + $buttonattributes['class'] .= ' hiddenifjs'; } $buttonoutput = html_writer::empty_tag('input', $buttonattributes);