1 var CHOOSERDIALOGUE = function() {
2 CHOOSERDIALOGUE.superclass.constructor.apply(this, arguments);
5 Y.extend(CHOOSERDIALOGUE, Y.Base, {
9 // The submit button - we disable this until an element is set
12 // The chooserdialogue container
15 // Any event listeners we may need to cancel later
20 instanceconfig : null,
22 setup_chooser_dialogue : function(bodycontent, headercontent, config) {
23 this.bodycontent = bodycontent;
24 this.headercontent = headercontent;
25 this.instanceconfig = config;
28 prepare_chooser : function () {
33 // Set Default options
36 bodyContent : this.bodycontent.get('innerHTML'),
37 headerContent : this.headercontent.get('innerHTML'),
40 visible : false, // Hide by default
41 zindex : 100, // Display in front of other items
42 lightbox : true, // This dialogue should be modal
44 closeButtonTitle : this.get('closeButtonTitle')
47 // Override with additional options
48 for (paramkey in this.instanceconfig) {
49 params[paramkey] = this.instanceconfig[paramkey];
53 this.panel = new M.core.dialogue(params);
55 // Remove the template for the chooser
56 this.bodycontent.remove();
57 this.headercontent.remove();
59 // Hide and then render the panel
64 this.container = this.panel.get('boundingBox').one('.choosercontainer');
65 this.options = this.container.all('.option input[type=radio]');
67 // Add the chooserdialogue class to the container for styling
68 this.panel.get('boundingBox').addClass('chooserdialogue');
72 * Display the module chooser
74 * @param e Event Triggering Event
77 display_chooser : function (e) {
78 var bb, dialogue, thisevent;
79 this.prepare_chooser();
81 // Stop the default event actions before we proceed
84 bb = this.panel.get('boundingBox');
85 dialogue = this.container.one('.alloptions');
87 // This will detect a change in orientation and retrigger centering
88 thisevent = Y.one('document').on('orientationchange', function() {
89 this.center_dialogue(dialogue);
91 this.listenevents.push(thisevent);
93 // Detect window resizes (most browsers)
94 thisevent = Y.one('window').on('resize', function() {
95 this.center_dialogue(dialogue);
97 this.listenevents.push(thisevent);
99 // These will trigger a check_options call to display the correct help
100 thisevent = this.container.on('click', this.check_options, this);
101 this.listenevents.push(thisevent);
102 thisevent = this.container.on('key_up', this.check_options, this);
103 this.listenevents.push(thisevent);
104 thisevent = this.container.on('dblclick', function(e) {
105 if (e.target.ancestor('div.option')) {
106 this.check_options();
108 // Prevent duplicate submissions
109 this.submitbutton.setAttribute('disabled', 'disabled');
110 this.options.setAttribute('disabled', 'disabled');
111 this.cancel_listenevents();
113 this.container.one('form').submit();
116 this.listenevents.push(thisevent);
118 this.container.one('form').on('submit', function() {
119 // Prevent duplicate submissions on submit
120 this.submitbutton.setAttribute('disabled', 'disabled');
121 this.options.setAttribute('disabled', 'disabled');
122 this.cancel_listenevents();
125 // Hook onto the cancel button to hide the form
126 thisevent = this.container.one('.addcancel').on('click', this.cancel_popup, this);
127 this.listenevents.push(thisevent);
129 // Hide will be managed by cancel_popup after restoring the body overflow
130 thisevent = bb.one('button.closebutton').on('click', this.cancel_popup, this);
131 this.listenevents.push(thisevent);
133 // Grab global keyup events and handle them
134 thisevent = Y.one('document').on('keydown', this.handle_key_press, this);
135 this.listenevents.push(thisevent);
137 // Add references to various elements we adjust
138 this.jumplink = this.container.one('.jump');
139 this.submitbutton = this.container.one('.submitbutton');
141 // Disable the submit element until the user makes a selection
142 this.submitbutton.set('disabled', 'true');
144 // Ensure that the options are shown
145 this.options.removeAttribute('disabled');
150 // Re-centre the dialogue after we've shown it.
151 this.center_dialogue(dialogue);
153 // Finally, focus the first radio element - this enables form selection via the keyboard
154 this.container.one('.option input[type=radio]').focus();
156 // Trigger check_options to set the initial jumpurl
157 this.check_options();
161 * Cancel any listen events in the listenevents queue
163 * Several locations add event handlers which should only be called before the form is submitted. This provides
164 * a way of cancelling those events.
168 cancel_listenevents : function () {
169 // Detach all listen events to prevent duplicate triggers
171 while (this.listenevents.length) {
172 thisevent = this.listenevents.shift();
178 * Calculate the optimum height of the chooser dialogue
180 * This tries to set a sensible maximum and minimum to ensure that some options are always shown, and preferably
181 * all, whilst fitting the box within the current viewport.
183 * @param dialogue Y.Node The dialogue
186 center_dialogue : function(dialogue) {
187 var bb = this.panel.get('boundingBox'),
188 winheight = bb.get('winHeight'),
189 newheight, totalheight;
191 if (this.panel.shouldResizeFullscreen()) {
192 // No custom sizing required for a fullscreen dialog.
196 // Try and set a sensible max-height -- this must be done before setting the top
197 // Set a default height of 640px
198 newheight = this.get('maxheight');
199 if (winheight <= newheight) {
200 // Deal with smaller window sizes
201 if (winheight <= this.get('minheight')) {
202 newheight = this.get('minheight');
204 newheight = winheight;
208 // Take off 15px top and bottom for borders, plus 40px each for the title and button area before setting the
210 totalheight = newheight;
211 newheight = newheight - (15 + 15 + 40 + 40);
212 dialogue.setStyle('maxHeight', newheight + 'px');
214 dialogueheight = bb.getStyle('height');
215 if (dialogueheight.match(/.*px$/)) {
216 dialogueheight = dialogueheight.replace(/px$/, '');
218 dialogueheight = totalheight;
221 if (dialogueheight < this.get('baseheight')) {
222 dialogueheight = this.get('baseheight');
223 dialogue.setStyle('height', dialogueheight + 'px');
226 this.panel.centerDialogue();
229 handle_key_press : function(e) {
230 if (e.keyCode === 27) {
231 this.cancel_popup(e);
235 cancel_popup : function (e) {
236 // Prevent normal form submission before hiding
242 // Cancel all listen events
243 this.cancel_listenevents();
245 this.container.detachAll();
249 check_options : function() {
250 // Check which options are set, and change the parent class
251 // to show/hide help as required
252 this.options.each(function(thisoption) {
253 var optiondiv = thisoption.get('parentNode').get('parentNode');
254 if (thisoption.get('checked')) {
255 optiondiv.addClass('selected');
257 // Trigger any events for this option
258 this.option_selected(thisoption);
260 // Ensure that the form may be submitted
261 this.submitbutton.removeAttribute('disabled');
263 // Ensure that the radio remains focus so that keyboard navigation is still possible
266 optiondiv.removeClass('selected');
271 option_selected : function() {
275 NAME : 'moodle-core-chooserdialogue',
287 validator : Y.Lang.isString,
292 M.core = M.core || {};
293 M.core.chooserdialogue = CHOOSERDIALOGUE;