Mercurial > defr > drupal > popups
comparison popups.js @ 1:4215c43e74eb
Popups: Mise à jour en version alpha6
author | Franck Deroche <franck@defr.org> |
---|---|
date | Fri, 31 Dec 2010 13:44:00 +0100 |
parents | 76f9b43738f2 |
children | 09e998f65556 |
comparison
equal
deleted
inserted
replaced
0:76f9b43738f2 | 1:4215c43e74eb |
---|---|
1 // $Id: popups.js,v 1.9.8.12 2009/03/21 00:57:15 starbow Exp $ | 1 // $Id: popups.js,v 1.9.8.19 2010/12/10 02:51:17 drewish Exp $ |
2 | 2 |
3 /** | 3 /** |
4 * Popup Modal Dialog API | 4 * Popup Modal Dialog API |
5 * | 5 * |
6 * Provide an API for building and displaying JavaScript, in-page, popups modal dialogs. | 6 * Provide an API for building and displaying JavaScript, in-page, popups modal dialogs. |
25 * The jQuery object to apply the behaviors to. | 25 * The jQuery object to apply the behaviors to. |
26 */ | 26 */ |
27 | 27 |
28 Drupal.behaviors.popups = function(context) { | 28 Drupal.behaviors.popups = function(context) { |
29 Popups.saveSettings(); | 29 Popups.saveSettings(); |
30 | 30 |
31 var $body = $('body'); | 31 var $body = $('body'); |
32 if(!$body.hasClass('popups-processed')) { | 32 if(!$body.hasClass('popups-processed')) { |
33 $body.addClass('popups-processed'); | 33 $body.addClass('popups-processed'); |
34 $(document).bind('keydown', Popups.keyHandle); | 34 $(document).bind('keydown', Popups.keyHandle); |
35 var $popit = $('#popit'); | 35 var $popit = $('#popit'); |
36 if ($popit.length) { | 36 if ($popit.length) { |
37 $popit.remove(); | 37 $popit.remove(); |
38 Popups.message($popit.html()); | 38 Popups.message($popit.html()); |
39 } | 39 } |
40 } | 40 |
41 | 41 // Make note of all the CSS and JS on the page so when we load a popup we |
42 // don't try to add them a second time. | |
43 $('link[rel="stylesheet"][href]').each(function(i, v) { | |
44 Popups.originalCSS[$(this).attr('href').replace(/^(\/.+)\?\w$/, '$1')] = 1; | |
45 }); | |
46 if (Drupal.settings.popups && Drupal.settings.popups.originalCSS) { | |
47 $.extend(Popups.originalCSS, Drupal.settings.popups.originalCSS); | |
48 } | |
49 $('script[src]').each(function(i, v) { | |
50 Popups.originalJS[$(this).attr('src').replace(/^(\/.+)\?\w$/, '$1')] = 1; | |
51 }); | |
52 if (Drupal.settings.popups && Drupal.settings.popups.originalJS) { | |
53 $.extend(Popups.originalJS, Drupal.settings.popups.originalJS); | |
54 } | |
55 } | |
56 | |
42 // Add the popups-link-in-dialog behavior to links defined in Drupal.settings.popups.links array. | 57 // Add the popups-link-in-dialog behavior to links defined in Drupal.settings.popups.links array. |
43 // Get these from current Drupal.settings, not Popups.originalSettings, as each page has it's own hooks. | 58 // Get these from current Drupal.settings, not Popups.originalSettings, as each page has it's own hooks. |
44 if (Drupal.settings.popups && Drupal.settings.popups.links) { | 59 if (Drupal.settings.popups && Drupal.settings.popups.links) { |
45 jQuery.each(Drupal.settings.popups.links, function (link, options) { | 60 jQuery.each(Drupal.settings.popups.links, function (link, options) { |
46 Popups.attach(context, link, Popups.options(options)); | 61 Popups.attach(context, link, Popups.options(options)); |
47 }); | 62 }); |
48 } | 63 } |
49 | 64 |
50 Popups.attach(context, '.popups', Popups.options({updateMethod: 'none'})); | 65 Popups.attach(context, '.popups', Popups.options({updateMethod: 'none'})); |
51 Popups.attach(context, '.popups-form', Popups.options({updateMethod: 'ajax'})); // ajax reload. | 66 Popups.attach(context, '.popups-form', Popups.options({updateMethod: 'ajax'})); // ajax reload. |
52 Popups.attach(context, '.popups-form-reload', Popups.options({updateMethod: 'reload'})); // whole page reload. | 67 Popups.attach(context, '.popups-form-reload', Popups.options({updateMethod: 'reload'})); // whole page reload. |
53 Popups.attach(context, '.popups-form-noupdate', Popups.options({updateMethod: 'none'})); // no reload at all. | 68 Popups.attach(context, '.popups-form-noupdate', Popups.options({updateMethod: 'none'})); // no reload at all. |
54 }; | 69 }; |
55 | 70 |
56 // *************************************************************************** | 71 // *************************************************************************** |
57 // Popups Namespace ********************************************************** | 72 // Popups Namespace ********************************************************** |
65 Popups = function(){}; | 80 Popups = function(){}; |
66 | 81 |
67 /** | 82 /** |
68 * Static variables in the Popups namespace. | 83 * Static variables in the Popups namespace. |
69 */ | 84 */ |
70 Popups.popupStack = []; | 85 Popups.popupStack = []; |
71 Popups.addedCSS = []; | 86 Popups.addedCSS = {}; |
72 Popups.addedJS = []; | 87 Popups.addedJS = {}; |
88 Popups.originalCSS = {}; | |
89 Popups.originalJS = {}; | |
73 Popups.originalSettings = null; // The initial popup options of the page. | 90 Popups.originalSettings = null; // The initial popup options of the page. |
74 /** | 91 /** |
75 * Each popup object gets it's own set of options. | 92 * Each popup object gets it's own set of options. |
76 * These are the defaults. | 93 * These are the defaults. |
77 */ | 94 */ |
78 Popups.defaultOptions = { | 95 Popups.defaultOptions = { |
79 doneTest: null, // null, *path*, *regexp*. how do we know when a multiform flow is done? | 96 doneTest: null, // null, *path*, *regexp*. how do we know when a multiform flow is done? |
80 updateMethod: 'ajax', // none, ajax, reload, *callback* | 97 updateMethod: 'ajax', // none, ajax, reload, *callback* |
81 updateSource: 'initial', // initial, final. Only used if updateMethod != none. | 98 updateSource: 'initial', // initial, final. Only used if updateMethod != none. |
82 href: null, | 99 onUpdate: '', // Only used if updateMethod == callback. |
100 href: null, | |
83 width: null, // Override the width specified in the css. | 101 width: null, // Override the width specified in the css. |
84 targetSelectors: null, // Hash of jQuery selectors that define the content to be swapped out. | 102 targetSelectors: null, // Hash of jQuery selectors that define the content to be swapped out. |
85 titleSelectors: null, // Array of jQuery selectors to place the new page title. | 103 titleSelectors: null, // Array of jQuery selectors to place the new page title. |
86 reloadOnError: false, // Force the entire page to reload if the popup href is unaccessable. | 104 reloadOnError: false, // Force the entire page to reload if the popup href is unaccessable. |
87 noMessage: false, // Don't show drupal_set_message messages. | 105 noMessage: false, // Don't show drupal_set_message messages. |
88 skipDirtyCheck: false, // If true, this popup will not check for edits on the originating page. | 106 skipDirtyCheck: false, // If true, this popup will not check for edits on the originating page. |
89 hijackDestination: true // Use the destiination param to force a form submit to return to the originating page. | 107 hijackDestination: true // Use the destiination param to force a form submit to return to the originating page. |
90 }; | 108 }; |
91 | 109 |
92 // *************************************************************************** | 110 // *************************************************************************** |
93 // Popups.Popup Object ******************************************************* | 111 // Popups.Popup Object ******************************************************* |
94 // *************************************************************************** | 112 // *************************************************************************** |
96 * A Popup is a single modal dialog. | 114 * A Popup is a single modal dialog. |
97 * The popup object encapslated all the info about a single popup. | 115 * The popup object encapslated all the info about a single popup. |
98 */ | 116 */ |
99 Popups.Popup = function() { | 117 Popups.Popup = function() { |
100 this.id = 'popups-' + Popups.nextCounter(); | 118 this.id = 'popups-' + Popups.nextCounter(); |
101 | 119 |
102 // These properties are needed if the popup contains a form that will be ajax submitted. | 120 // These properties are needed if the popup contains a form that will be ajax submitted. |
103 this.parent = null; // The popup that spawned this one. If parent is null, this popup was spawned by the original page. | 121 this.parent = null; // The popup that spawned this one. If parent is null, this popup was spawned by the original page. |
104 this.path = null; // If popup is showing content from a url, this is that path. | 122 this.path = null; // If popup is showing content from a url, this is that path. |
105 this.element = null; // The DOM element that was clicked to launch this popup. | 123 this.element = null; // The DOM element that was clicked to launch this popup. |
106 this.options = null; // An option array that control how the popup behaves. See Popups.defaultOptions for explainations. | 124 this.options = null; // An option array that control how the popup behaves. See Popups.defaultOptions for explainations. |
124 return $('#' + this.id + ' .popups-footer'); | 142 return $('#' + this.id + ' .popups-footer'); |
125 }; | 143 }; |
126 | 144 |
127 /** | 145 /** |
128 * Create the jQuery wrapped html at the heart of the popup object. | 146 * Create the jQuery wrapped html at the heart of the popup object. |
129 * | 147 * |
130 * @param title | 148 * @param title |
131 * String | 149 * String |
132 * @param body | 150 * @param body |
133 * String/HTML | 151 * String/HTML |
134 * @param buttons | 152 * @param buttons |
139 Popups.Popup.prototype.fill = function(title, body, buttons) { | 157 Popups.Popup.prototype.fill = function(title, body, buttons) { |
140 return $(Drupal.theme('popupDialog', this.id, title, body, buttons)); | 158 return $(Drupal.theme('popupDialog', this.id, title, body, buttons)); |
141 } | 159 } |
142 | 160 |
143 /** | 161 /** |
144 * Hide the popup by pushing it off to the side. | 162 * Hide the popup by pushing it off to the side. |
145 * Just making it display:none causes flash in FF2. | 163 * Just making it display:none causes flash in FF2. |
146 */ | 164 */ |
147 Popups.Popup.prototype.hide = function() { | 165 Popups.Popup.prototype.hide = function() { |
148 this.$popup().css('left', '-9999px'); | 166 this.$popup().css('left', '-9999px'); |
149 }; | 167 }; |
154 | 172 |
155 Popups.Popup.prototype.open = function(title, body, buttons, width){ | 173 Popups.Popup.prototype.open = function(title, body, buttons, width){ |
156 return Popups.open(this, title, body, buttons, width); | 174 return Popups.open(this, title, body, buttons, width); |
157 }; | 175 }; |
158 | 176 |
159 Popups.Popup.prototype.removePopup = function() { | 177 Popups.Popup.prototype.removePopup = function() { |
160 Popups.removePopup(this); | 178 Popups.removePopup(this); |
161 }; | 179 }; |
162 | 180 |
163 /** | 181 /** |
164 * Remove everything. | 182 * Remove everything. |
165 */ | 183 */ |
166 Popups.Popup.prototype.close = function() { | 184 Popups.Popup.prototype.close = function() { |
181 $focus.focus(); | 199 $focus.focus(); |
182 }; | 200 }; |
183 | 201 |
184 /** | 202 /** |
185 * Return a selector that will find target content on the layer that spawned this popup. | 203 * Return a selector that will find target content on the layer that spawned this popup. |
186 * This is needed for the popup to do ajax updates. | 204 * This is needed for the popup to do ajax updates. |
187 */ | 205 */ |
188 Popups.Popup.prototype.targetLayerSelector = function() { | 206 Popups.Popup.prototype.targetLayerSelector = function() { |
189 if (this.parent === null) { | 207 if (this.parent === null) { |
190 return 'body'; // Select content in the original page. | 208 return 'body'; // Select content in the original page. |
191 } | 209 } |
192 else { | 210 else { |
193 return '#' + this.parent.id; // Select content in the parent popup. | 211 return '#' + this.parent.id; // Select content in the parent popup. |
194 } | 212 } |
195 }; | 213 }; |
196 | 214 |
197 /** | 215 /** |
198 * Determine if we are at an end point of a form flow, or just moving from one popups to another. | 216 * Determine if we are at an end point of a form flow, or just moving from one popups to another. |
199 * | 217 * |
200 * @param path | 218 * @param path |
201 * The path of the page that the form flow has moved to. | 219 * The path of the page that the form flow has moved to. |
202 * This path is relative to the base_path. | 220 * This path is relative to the base_path. |
203 * Ex: node/add/story, not http://localhost/drupal6/node/add/story or drupa6/node/add/story. | 221 * Ex: node/add/story, not http://localhost/drupal6/node/add/story or drupa6/node/add/story. |
204 * @return bool | 222 * @return bool |
205 */ | 223 */ |
206 Popups.Popup.prototype.isDone = function(path) { | 224 Popups.Popup.prototype.isDone = function(path) { |
207 // console.log("Doing isDone for popup: " + this.id + ", now at " + path ); | |
208 var done; | 225 var done; |
209 if (this.options.doneTest) { | 226 if (this.options.doneTest) { |
210 // Test if we are at the path specified by doneTest. | 227 // Test if we are at the path specified by doneTest. |
211 done = (path === this.options.doneTest || path.match(this.options.doneTest)); | 228 done = (path === this.options.doneTest || path.match(this.options.doneTest)); |
212 } | 229 } |
213 else { | 230 else { |
214 if (this.parent) { | 231 if (this.parent) { |
215 // Test if we are back to the parent popup's path. | 232 // Test if we are back to the parent popup's path. |
216 done = (path === this.parent.path); | 233 done = (path === this.parent.path); |
217 // console.log("Lookin at parent: " + this.parent.path + ". Done = " + done); | |
218 } | 234 } |
219 else { | 235 else { |
220 // Test if we are back to the original page's path. | 236 // Test if we are back to the original page's path. |
221 done = (path === Popups.originalSettings.popups.originalPath); | 237 done = (path === Popups.originalSettings.popups.originalPath); |
222 // console.log("Lookin at original page: " + Popups.originalSettings.popups.originalPath + ". Done = " + done); | 238 } |
223 } | 239 }; |
224 }; | 240 return done; |
225 return done; | |
226 }; | 241 }; |
227 | 242 |
228 | 243 |
229 // *************************************************************************** | 244 // *************************************************************************** |
230 // Popups Functions ********************************************************** | 245 // Popups Functions ********************************************************** |
231 // *************************************************************************** | 246 // *************************************************************************** |
232 | 247 |
233 /** | 248 /** |
234 * Test if the param has been set. | 249 * Test if the param has been set. |
235 * Used to distinguish between a value set to null or false and on not yet unset. | 250 * Used to distinguish between a value set to null or false and on not yet unset. |
236 */ | 251 */ |
237 Popups.isset = function(v) { | 252 Popups.isset = function(v) { |
238 return (typeof(v) !== 'undefined'); | 253 return (typeof(v) !== 'undefined'); |
239 }; | 254 }; |
262 return Popups.popupStack.pop(); | 277 return Popups.popupStack.pop(); |
263 }; | 278 }; |
264 | 279 |
265 /** | 280 /** |
266 * Build an options hash from defaults. | 281 * Build an options hash from defaults. |
267 * | 282 * |
268 * @param overrides | 283 * @param overrides |
269 * Hash of values to override the defaults. | 284 * Hash of values to override the defaults. |
270 */ | 285 */ |
271 Popups.options = function(overrides) { | 286 Popups.options = function(overrides) { |
272 var defaults = Popups.defaultOptions; | 287 var defaults = Popups.defaultOptions; |
273 return Popups.overrideOptions(defaults, overrides); | 288 return Popups.overrideOptions(defaults, overrides); |
274 } | 289 } |
275 | 290 |
276 /** | 291 /** |
277 * Build an options hash. | 292 * Build an options hash. |
278 * Also maps deprecated options to current options. | 293 * Also maps deprecated options to current options. |
279 * | 294 * |
280 * @param defaults | 295 * @param defaults |
281 * Hash of default values | 296 * Hash of default values |
282 * @param overrides | 297 * @param overrides |
283 * Hash of values to override the defaults with. | 298 * Hash of values to override the defaults with. |
284 */ | 299 */ |
287 for(var option in defaults) { | 302 for(var option in defaults) { |
288 var value; | 303 var value; |
289 if (Popups.isset(overrides[option])) { | 304 if (Popups.isset(overrides[option])) { |
290 options[option] = overrides[option]; | 305 options[option] = overrides[option]; |
291 } | 306 } |
292 else { | 307 else { |
293 options[option] = defaults[option]; | 308 options[option] = defaults[option]; |
294 } | 309 } |
295 } | 310 } |
296 // Map deprecated options. | 311 // Map deprecated options. |
297 if (overrides['noReload'] || overrides['noUpdate']) { | 312 if (overrides['noReload'] || overrides['noUpdate']) { |
298 options['updateMethod'] = 'none'; | 313 options['updateMethod'] = 'none'; |
299 } | 314 } |
300 if (overrides['reloadWhenDone']) { | 315 if (overrides['reloadWhenDone']) { |
301 options['updateMethod'] = 'reload'; | 316 options['updateMethod'] = 'reload'; |
302 } | 317 } |
303 if (overrides['afterSubmit']) { | 318 if (overrides['afterSubmit']) { |
304 options['updateMethod'] = 'callback'; | 319 options['updateMethod'] = 'callback'; |
305 options['onUpdate'] = overrides['afterSubmit']; | 320 options['onUpdate'] = overrides['afterSubmit']; |
306 } | 321 } |
307 if (overrides['forceReturn']) { | 322 if (overrides['forceReturn']) { |
308 options['doneTest'] = overrides['forceReturn']; | 323 options['doneTest'] = overrides['forceReturn']; |
309 } | 324 } |
310 return options; | 325 return options; |
311 } | 326 } |
312 | 327 |
313 /** | 328 /** |
314 * Attach the popups behavior to all elements inside the context that match the selector. | 329 * Attach the popups behavior to all elements inside the context that match the selector. |
319 * jQuery selector for elements to attach popups behavior to. | 334 * jQuery selector for elements to attach popups behavior to. |
320 * @param options | 335 * @param options |
321 * Hash of options associated with these links. | 336 * Hash of options associated with these links. |
322 */ | 337 */ |
323 Popups.attach = function(context, selector, options) { | 338 Popups.attach = function(context, selector, options) { |
324 // console.log(options); | |
325 $(selector, context).not('.popups-processed').each(function() { | 339 $(selector, context).not('.popups-processed').each(function() { |
326 var $element = $(this); | 340 var $element = $(this); |
327 | 341 |
328 // Mark the element as processed. | 342 // Mark the element as processed. |
329 $element.addClass('popups-processed'); | 343 $element.addClass('popups-processed'); |
330 | 344 |
331 // Append note to link title. | 345 // Append note to link title. |
332 var title = ''; | 346 var title = ''; |
333 if ($element.attr('title')) { | 347 if ($element.attr('title')) { |
334 title = $element.attr('title') + ' '; | 348 title = $element.attr('title') + ' '; |
335 } | 349 } |
336 title += Drupal.t('[Popup]'); | 350 title += Drupal.t('[Popup]'); |
337 $element.attr('title', title); | 351 $element.attr('title', title); |
338 | 352 |
339 // Attach the on-click popup behavior to the element. | 353 // Attach the on-click popup behavior to the element. |
340 $element.click(function(event){ | 354 $element.click(function(event){ |
341 return Popups.clickPopupElement(this, options); | 355 return Popups.clickPopupElement(this, options); |
342 }); | 356 }); |
343 }); | 357 }); |
344 }; | 358 }; |
345 | 359 |
346 /** | 360 /** |
347 * Respond to click by opening a popup. | 361 * Respond to click by opening a popup. |
348 * | 362 * |
349 * @param element | 363 * @param element |
350 * The element that was clicked. | 364 * The element that was clicked. |
351 * @param options | 365 * @param options |
352 * Hash of options associated with the element. | 366 * Hash of options associated with the element. |
353 */ | 367 */ |
354 Popups.clickPopupElement = function(element, options) { | 368 Popups.clickPopupElement = function(element, options) { |
355 Popups.saveSettings(); | 369 Popups.saveSettings(); |
356 | 370 |
357 // If the element contains a on-popups-options attribute, override default options param. | 371 // If the element contains a on-popups-options attribute, override default options param. |
358 if ($(element).attr('on-popups-options')) { | 372 if ($(element).attr('on-popups-options')) { |
359 var overrides = Drupal.parseJson($(element).attr('on-popups-options')); | 373 var overrides = Drupal.parseJson($(element).attr('on-popups-options')); |
360 options = Popups.overrideOptions(options, overrides); | 374 options = Popups.overrideOptions(options, overrides); |
361 } | 375 } |
362 | 376 |
363 // The parent of the new popup is the currently active popup. | 377 // The parent of the new popup is the currently active popup. |
364 var parent = Popups.activePopup(); | 378 var parent = Popups.activePopup(); |
365 | 379 |
366 // If the option is distructive, check if the page is already modified, and offer to save. | 380 // If the option is distructive, check if the page is already modified, and offer to save. |
367 var willModifyOriginal = !(options.updateMethod === 'none' || options.skipDirtyCheck); | 381 var willModifyOriginal = !(options.updateMethod === 'none' || options.skipDirtyCheck); |
368 if (willModifyOriginal && Popups.activeLayerIsEdited()) { | 382 if (willModifyOriginal && Popups.activeLayerIsEdited()) { |
369 // The user will lose modifications, so show dialog offering to save current state. | 383 // The user will lose modifications, so show dialog offering to save current state. |
370 Popups.offerToSave(element, options, parent); | 384 Popups.offerToSave(element, options, parent); |
371 } | 385 } |
372 else { | 386 else { |
373 // Page is clean, or popup is safe, so just open it. | 387 // Page is clean, or popup is safe, so just open it. |
374 Popups.openPath(element, options, parent); | 388 Popups.openPath(element, options, parent); |
375 } | 389 } |
376 return false; | 390 return false; |
377 }; | 391 }; |
378 | 392 |
379 /** | 393 /** |
380 * Test if the active layer been edited. | 394 * Test if the active layer been edited. |
381 * Active layer is either the original page, or the active Popup. | 395 * Active layer is either the original page, or the active Popup. |
382 */ | 396 */ |
383 Popups.activeLayerIsEdited = function() { | 397 Popups.activeLayerIsEdited = function() { |
384 var layer = Popups.activePopup(); | 398 var layer = Popups.activePopup(); |
385 var $context = Popups.getLayerContext(layer); | 399 var $context = Popups.getLayerContext(layer); |
386 // TODO: better test for edited page, maybe capture change event on :inputs. | 400 // TODO: better test for edited page, maybe capture change event on :inputs. |
387 var edited = $context.find('span.tabledrag-changed').length; | 401 var edited = $context.find('span.tabledrag-changed').length; |
388 return edited; | 402 return edited; |
389 } | 403 } |
390 | 404 |
391 /** | 405 /** |
392 * Show dialog offering to save form on parent layer. | 406 * Show dialog offering to save form on parent layer. |
393 * | 407 * |
394 * @param element | 408 * @param element |
395 * The DOM element that was clicked. | 409 * The DOM element that was clicked. |
396 * @param options | 410 * @param options |
397 * The options associated with that element. | 411 * The options associated with that element. |
398 * @param parent | 412 * @param parent |
404 var buttons = { | 418 var buttons = { |
405 'popup_save': {title: Drupal.t('Save Changes'), func: function(){Popups.saveFormOnLayer(element, options, parent);}}, | 419 'popup_save': {title: Drupal.t('Save Changes'), func: function(){Popups.saveFormOnLayer(element, options, parent);}}, |
406 'popup_submit': {title: Drupal.t('Continue'), func: function(){popup.removePopup(); Popups.openPath(element, options, parent);}}, | 420 'popup_submit': {title: Drupal.t('Continue'), func: function(){popup.removePopup(); Popups.openPath(element, options, parent);}}, |
407 'popup_cancel': {title: Drupal.t('Cancel'), func: function(){popup.close();}} | 421 'popup_cancel': {title: Drupal.t('Cancel'), func: function(){popup.close();}} |
408 }; | 422 }; |
409 popup.open(Drupal.t('Warning: Please Confirm'), body, buttons); | 423 popup.open(Drupal.t('Warning: Please Confirm'), body, buttons); |
410 }; | 424 }; |
411 | 425 |
412 /** | 426 /** |
413 * Generic dialog builder. | 427 * Generic dialog builder. |
414 * Adds the newly built popup into the DOM. | 428 * Adds the newly built popup into the DOM. |
415 * | 429 * |
416 * TODO: capture the focus if it tabs out of the dialog. | 430 * TODO: capture the focus if it tabs out of the dialog. |
417 * | 431 * |
418 * @param popup | 432 * @param popup |
419 * Popups.Popup object to fill with content, place in the DOM, and show on the screen. | 433 * Popups.Popup object to fill with content, place in the DOM, and show on the screen. |
420 * @param String title | 434 * @param String title |
423 * String: body of new dialog. | 437 * String: body of new dialog. |
424 * @param buttons (optional) | 438 * @param buttons (optional) |
425 * Hash of button parameters. | 439 * Hash of button parameters. |
426 * @param width (optional) | 440 * @param width (optional) |
427 * Width of new dialog. | 441 * Width of new dialog. |
428 * | 442 * |
429 * @return popup object | 443 * @return popup object |
430 */ | 444 */ |
431 Popups.open = function(popup, title, body, buttons, width){ | 445 Popups.open = function(popup, title, body, buttons, width){ |
432 Popups.addOverlay(); | 446 Popups.addOverlay(); |
433 | 447 |
434 if (Popups.activePopup()) { | 448 if (Popups.activePopup()) { |
435 // Hiding previously active popup. | 449 // Hiding previously active popup. |
436 Popups.activePopup().hide(); | 450 Popups.activePopup().hide(); |
437 } | 451 } |
438 | 452 |
439 if (!popup) { | 453 if (!popup) { |
440 // Popup object was not handed in, so create a new one. | 454 // Popup object was not handed in, so create a new one. |
441 popup = new Popups.Popup(); | 455 popup = new Popups.Popup(); |
442 } | 456 } |
443 Popups.push(popup); // Put this popup at the top of the stack. | 457 Popups.push(popup); // Put this popup at the top of the stack. |
447 popup.hide(); // Hide the new popup until it is finished and sized. | 461 popup.hide(); // Hide the new popup until it is finished and sized. |
448 | 462 |
449 if (width) { | 463 if (width) { |
450 $popup.css('width', width); | 464 $popup.css('width', width); |
451 } | 465 } |
452 | 466 |
453 // Add the new popup to the DOM. | 467 // Add the new popup to the DOM. |
454 $('body').append($popup); | 468 $('body').append($popup); |
455 | 469 |
456 // Add button function callbacks. | 470 // Add button function callbacks. |
457 if (buttons) { | 471 if (buttons) { |
458 jQuery.each(buttons, function(id, button){ | 472 jQuery.each(buttons, function(id, button){ |
459 $('#' + id).click(button.func); | 473 $('#' + id).click(button.func); |
460 }); | 474 }); |
461 } | 475 } |
462 | 476 |
463 // Add the default click-to-close behavior. | 477 // Add the default click-to-close behavior. |
464 popup.$popupClose().click(function(){ | 478 popup.$popupClose().click(function(){ |
465 return Popups.close(popup); | 479 return Popups.close(popup); |
466 }); | 480 }); |
467 | 481 |
468 Popups.resizeAndCenter(popup); | 482 Popups.resizeAndCenter(popup); |
469 | 483 |
470 // Focus on the first input element in the popup window. | 484 // Focus on the first input element in the popup window. |
471 popup.refocus(); | 485 popup.refocus(); |
472 | 486 |
473 // TODO - this isn't the place for this - should mirror addLoading calls. | 487 // TODO - this isn't the place for this - should mirror addLoading calls. |
474 // Remove the loading image. | 488 // Remove the loading image. |
475 Popups.removeLoading(); | 489 Popups.removeLoading(); |
476 | 490 |
477 return popup; | 491 return popup; |
478 }; | 492 }; |
479 | 493 |
480 /** | 494 /** |
481 * Adjust the popup's height to fit it's content. | 495 * Adjust the popup's height to fit it's content. |
482 * Move it to be centered on the screen. | 496 * Move it to be centered on the screen. |
483 * This undoes the effects of popup.hide(). | 497 * This undoes the effects of popup.hide(). |
484 * | 498 * |
485 * @param popup | 499 * @param popup |
486 */ | 500 */ |
487 Popups.resizeAndCenter = function(popup) { | 501 Popups.resizeAndCenter = function(popup) { |
488 var $popup = popup.$popup(); | 502 var $popup = popup.$popup(); |
489 | 503 |
490 // center on the screen, adding in offsets if the window has been scrolled | 504 // center on the screen, adding in offsets if the window has been scrolled |
491 var popupWidth = $popup.width(); | 505 var popupWidth = $popup.width(); |
492 var windowWidth = Popups.windowWidth(); | 506 var windowWidth = Popups.windowWidth(); |
493 var left = (windowWidth / 2) - (popupWidth / 2) + Popups.scrollLeft(); | 507 var left = (windowWidth / 2) - (popupWidth / 2) + Popups.scrollLeft(); |
494 | 508 |
495 // Get popups's height on the page. | 509 // Get popups's height on the page. |
496 $popup.css('height', 'auto'); // Reset height. | 510 $popup.css('height', 'auto'); // Reset height. |
497 var popupHeight = $popup.height(); | 511 var popupHeight = $popup.height(); |
498 $popup.height(popupHeight); | 512 $popup.height(popupHeight); |
499 var windowHeight = Popups.windowHeight(); | 513 var windowHeight = Popups.windowHeight(); |
500 | 514 |
501 if (popupHeight > (0.9 * windowHeight) ) { // Must fit in 90% of window. | 515 if (popupHeight > (0.9 * windowHeight) ) { // Must fit in 90% of window. |
502 popupHeight = 0.9 * windowHeight; | 516 popupHeight = 0.9 * windowHeight; |
503 $popup.height(popupHeight); | 517 $popup.height(popupHeight); |
504 } | 518 } |
505 var top = (windowHeight / 2) - (popupHeight / 2) + Popups.scrollTop(); | 519 var top = (windowHeight / 2) - (popupHeight / 2) + Popups.scrollTop(); |
506 | 520 |
507 $popup.css('top', top).css('left', left); // Position the popups to be visible. | 521 $popup.css('top', top).css('left', left); // Position the popups to be visible. |
508 }; | 522 }; |
509 | 523 |
510 | 524 |
511 /** | 525 /** |
512 * Create and show a simple popup dialog that functions like the browser's alert box. | 526 * Create and show a simple popup dialog that functions like the browser's alert box. |
513 */ | 527 */ |
514 Popups.message = function(title, message) { | 528 Popups.message = function(title, message) { |
547 }; | 561 }; |
548 | 562 |
549 /***************************************************************************** | 563 /***************************************************************************** |
550 * Appearence Functions (overlay, loading graphic, remove popups) ********* | 564 * Appearence Functions (overlay, loading graphic, remove popups) ********* |
551 *****************************************************************************/ | 565 *****************************************************************************/ |
552 | 566 |
553 /** | 567 /** |
554 * Add full page div between the page and the dialog, to make the popup modal. | 568 * Add full page div between the page and the dialog, to make the popup modal. |
555 */ | 569 */ |
556 Popups.addOverlay = function() { | 570 Popups.addOverlay = function() { |
557 var $overlay = $('#popups-overlay'); | 571 var $overlay = $('#popups-overlay'); |
558 if (!$overlay.length) { // Overlay does not already exist, so create it. | 572 if (!$overlay.length) { // Overlay does not already exist, so create it. |
559 $overlay = $(Drupal.theme('popupOverlay')); | 573 $overlay = $(Drupal.theme('popupOverlay')); |
560 $overlay.css('opacity', '0.4'); // for ie6(?) | 574 $overlay.css('opacity', '0.4'); // for ie6(?) |
561 // Doing absolute positioning, so make overlay's size equal the entire body. | 575 // Doing absolute positioning, so make overlay's size equal the entire body. |
562 var $doc = $(document); | 576 var $doc = $(document); |
563 $overlay.width($doc.width()).height($doc.height()); | 577 $overlay.width($doc.width()).height($doc.height()); |
564 $overlay.click(function(){Popups.close();}); | 578 $overlay.click(function(){Popups.close();}); |
565 $('body').prepend($overlay); | 579 $('body').prepend($overlay); |
566 } | 580 } |
567 }; | 581 }; |
568 | 582 |
594 Popups.removeLoading = function() { | 608 Popups.removeLoading = function() { |
595 $('#popups-loading').remove(); | 609 $('#popups-loading').remove(); |
596 }; | 610 }; |
597 | 611 |
598 // Should I fold this function into Popups.pop? | 612 // Should I fold this function into Popups.pop? |
599 Popups.removePopup = function(popup) { | 613 Popups.removePopup = function(popup) { |
600 // console.log("Popups.removePopup: " + popup); | |
601 if (!Popups.isset(popup)) { | 614 if (!Popups.isset(popup)) { |
602 popup = Popups.activePopup(); | 615 popup = Popups.activePopup(); |
603 } | 616 } |
604 if (popup) { | 617 if (popup) { |
605 // console.log('removing '+popup.id); | |
606 popup.$popup().remove(); | 618 popup.$popup().remove(); |
607 Popups.popupStack.splice(Popups.popupStack.indexOf(popup), 1); // Remove popup from stack. Probably should rework into .pop() | 619 Popups.popupStack.splice(jQuery.inArray(popup,Popups.popupStack), 1); // Remove popup from stack. Probably should rework into .pop() |
608 } | 620 } |
609 // else { | 621 }; |
610 // console.log("Popups.removePopup - there is no popup to remove."); | |
611 // } | |
612 }; | |
613 | 622 |
614 /** | 623 /** |
615 * Remove everything. | 624 * Remove everything. |
616 */ | 625 */ |
617 Popups.close = function(popup) { | 626 Popups.close = function(popup) { |
642 | 651 |
643 /** | 652 /** |
644 * Restore the page's original Drupal.settings. | 653 * Restore the page's original Drupal.settings. |
645 */ | 654 */ |
646 Popups.restoreSettings = function() { | 655 Popups.restoreSettings = function() { |
647 Drupal.settings = Popups.originalSettings; | 656 Drupal.settings = Popups.originalSettings; |
648 }; | 657 }; |
649 | 658 |
650 /** | 659 /** |
651 * Remove as much of the effects of jit loading as possible. | 660 * Remove as much of the effects of jit loading as possible. |
652 */ | 661 */ |
653 Popups.restorePage = function() { | 662 Popups.restorePage = function() { |
654 Popups.restoreSettings(); | 663 Popups.restoreSettings(); |
655 // Remove the CSS files that were jit loaded for popup. | 664 // Remove the CSS files that were jit loaded for popup. |
656 for (var i in Popups.addedCSS) { | 665 for (var i in Popups.addedCSS) if (Popups.addedCSS.hasOwnProperty(i)) { |
657 var link = Popups.addedCSS[i]; | 666 $('link[href='+ Popups.addedCSS[i] + ']').remove(); |
658 $('link[href='+ $(link).attr('href') + ']').remove(); | |
659 } | 667 } |
660 Popups.addedCSS = []; | 668 Popups.addedCSS = []; |
661 }; | 669 }; |
662 | 670 |
663 | 671 |
682 /** | 690 /** |
683 * Get the height of the browser window. | 691 * Get the height of the browser window. |
684 * Fixes jQuery & Opera bug - http://drupal.org/node/366093 | 692 * Fixes jQuery & Opera bug - http://drupal.org/node/366093 |
685 */ | 693 */ |
686 Popups.windowHeight = function() { | 694 Popups.windowHeight = function() { |
687 if ($.browser.opera && $.browser.version > "9.5" && $.fn.jquery <= "1.2.6") { | 695 if ($.browser.opera && $.browser.version > "9.5" && $.fn.jquery <= "1.2.6") { |
688 return document.documentElement.clientHeight; | 696 return document.documentElement.clientHeight; |
689 } | 697 } |
690 return $(window).height(); | 698 return $(window).height(); |
691 }; | 699 }; |
692 | 700 |
693 /** | 701 /** |
694 * Get the height of the browser window. | 702 * Get the height of the browser window. |
695 * Fixes jQuery & Opera bug - http://drupal.org/node/366093 | 703 * Fixes jQuery & Opera bug - http://drupal.org/node/366093 |
696 */ | 704 */ |
697 Popups.windowWidth = function() { | 705 Popups.windowWidth = function() { |
698 if ($.browser.opera && $.browser.version > "9.5" && $.fn.jquery <= "1.2.6") { | 706 if ($.browser.opera && $.browser.version > "9.5" && $.fn.jquery <= "1.2.6") { |
699 return document.documentElement.clientWidth; | 707 return document.documentElement.clientWidth; |
700 } | 708 } |
701 return $(window).width(); | 709 return $(window).width(); |
702 }; | 710 }; |
703 | 711 |
718 /** | 726 /** |
719 * Add additional CSS to the page. | 727 * Add additional CSS to the page. |
720 */ | 728 */ |
721 Popups.addCSS = function(css) { | 729 Popups.addCSS = function(css) { |
722 Popups.addedCSS = []; | 730 Popups.addedCSS = []; |
723 for (var type in css) { | 731 for (var type in css) if (css.hasOwnProperty(type)) { |
724 for (var file in css[type]) { | 732 for (var file in css[type]) if (css[type].hasOwnProperty(file)) { |
725 var link = css[type][file]; | 733 var link = css[type][file]; |
734 var href = $(link).attr('href'); | |
726 // Does the page already contain this stylesheet? | 735 // Does the page already contain this stylesheet? |
727 if (!$('link[href='+ $(link).attr('href') + ']').length) { | 736 if (!Popups.originalCSS[href.replace(/^(\/.+)\?\w$/, '$1')] && !Popups.addedCSS[href]) { |
728 $('head').append(link); | 737 $('head').append(link); |
729 Popups.addedCSS.push(link); // Keep a list, so we can remove them later. | 738 Popups.addedCSS[href] = 1; // Keep a list, so we can remove them later. |
730 } | 739 } |
731 } | 740 } |
732 } | 741 } |
733 }; | 742 }; |
734 | 743 |
737 */ | 746 */ |
738 Popups.addJS = function(js) { | 747 Popups.addJS = function(js) { |
739 // Parse the json info about the new context. | 748 // Parse the json info about the new context. |
740 var scripts = []; | 749 var scripts = []; |
741 var inlines = []; | 750 var inlines = []; |
742 for (var type in js) { | 751 var src; |
752 for (var type in js) if (js.hasOwnProperty(type)) { | |
743 if (type != 'setting') { | 753 if (type != 'setting') { |
744 for (var file in js[type]) { | 754 for (var file in js[type]) if (js[type].hasOwnProperty(file)) { |
745 if (type == 'inline') { | 755 if (type == 'inline') { |
746 inlines.push($(js[type][file]).text()); | 756 inlines.push($(js[type][file]).text()); |
747 } | 757 } |
748 else { | 758 else { |
749 scripts.push($(js[type][file]).attr('src')); | 759 src = $(js[type][file]).attr('src'); |
760 if (!Popups.originalJS[src.replace(/^(\/.+)\?\w$/, '$1')] && !Popups.addedJS[src]) { | |
761 // Get the script from the server and execute it. | |
762 $.ajax({ | |
763 type: 'GET', | |
764 url: src, | |
765 dataType: 'script', | |
766 async : false, | |
767 success: function(script) { | |
768 eval(script); | |
769 } | |
770 }); | |
771 // Mark the js as added to the underlying page. | |
772 Popups.addedJS[src] = 1; | |
773 } | |
750 } | 774 } |
751 } | 775 } |
752 } | 776 } |
753 } | 777 } |
754 | 778 |
755 // Add new JS settings to the page, needed for #ahah properties to work. | 779 // Add new JS settings to the page, needed for #ahah properties to work. |
756 Drupal.settings = js.setting; | 780 Drupal.settings = js.setting; |
757 // console.log('js.setting...'); | |
758 // console.log(js.setting); | |
759 | |
760 for (var i in scripts) { | |
761 var src = scripts[i]; | |
762 if (!$('script[src='+ src + ']').length && !Popups.addedJS[src]) { | |
763 // Get the script from the server and execute it. | |
764 $.ajax({ | |
765 type: 'GET', | |
766 url: src, | |
767 dataType: 'script', | |
768 async : false, | |
769 success: function(script) { | |
770 eval(script); | |
771 } | |
772 }); | |
773 // Mark the js as added to the underlying page. | |
774 Popups.addedJS[src] = true; | |
775 } | |
776 } | |
777 | 781 |
778 return inlines; | 782 return inlines; |
779 }; | 783 }; |
780 | 784 |
781 /** | 785 /** |
782 * Execute the jit loaded inline scripts. | 786 * Execute the jit loaded inline scripts. |
783 * Q: Do we want to re-excute the ones already in the page? | 787 * Q: Do we want to re-excute the ones already in the page? |
784 * | 788 * |
785 * @param inlines | 789 * @param inlines |
786 * Array of inline scripts. | 790 * Array of inline scripts. |
787 */ | 791 */ |
788 Popups.addInlineJS = function(inlines) { | 792 Popups.addInlineJS = function(inlines) { |
789 // Load the inlines into the page. | 793 // Load the inlines into the page. |
790 for (var n in inlines) { | 794 for (var n in inlines) { |
791 // If the script is not already in the page, execute it. | 795 // If the script is not already in the page, execute it. |
792 if (!$('script:not([src]):contains(' + inlines[n] + ')').length) { | 796 //if (!$('script:not([src]):contains(' + inlines[n] + ')').length) { |
793 eval(inlines[n]); | 797 eval(inlines[n]); |
794 } | 798 //} |
795 } | 799 } |
796 }; | 800 }; |
797 | 801 |
798 Popups.beforeSend = function(xhr) { | 802 Popups.beforeSend = function(xhr) { |
799 xhr.setRequestHeader("X-Drupal-Render-Mode", 'json/popups'); | 803 xhr.setRequestHeader("X-Drupal-Render-Mode", 'json/popups'); |
825 Popups.openPath = function(element, options, parent) { | 829 Popups.openPath = function(element, options, parent) { |
826 Popups.saveSettings(); | 830 Popups.saveSettings(); |
827 | 831 |
828 // Let the user know something is happening. | 832 // Let the user know something is happening. |
829 $('body').css("cursor", "wait"); | 833 $('body').css("cursor", "wait"); |
830 | 834 |
831 // TODO - get nonmodal working. | 835 // TODO - get nonmodal working. |
832 if (!options.nonModal) { | 836 if (!options.nonModal) { |
833 Popups.addOverlay(); | 837 Popups.addOverlay(); |
834 } | 838 } |
835 Popups.addLoading(); | 839 Popups.addLoading(); |
836 | 840 |
837 var href = options.href ? options.href : element.href; | 841 var href = options.href ? options.href : element.href; |
838 $(document).trigger('popups_open_path', [element, href]); // Broadcast Popup Open Path event. | 842 $(document).trigger('popups_open_path', [element, href]); // Broadcast Popup Open Path event. |
839 | 843 |
840 var params = {}; | 844 var params = {}; |
841 // Force the popups to return back to the orignal page when forms are done, unless hijackDestination option is set to FALSE. | 845 // Force the popups to return back to the orignal page when forms are done, unless hijackDestination option is set to FALSE. |
842 if (options.hijackDestination) { | 846 if (options.hijackDestination) { |
843 var returnPath; | 847 var returnPath; |
844 if (parent) { | 848 if (parent) { |
845 returnPath = parent.path; | 849 returnPath = parent.path; |
846 // console.log('Popup parent is ...'); | |
847 // console.log(parent); | |
848 } | 850 } |
849 else { // No parent, so bring flow back to original page. | 851 else { // No parent, so bring flow back to original page. |
850 returnPath = Popups.originalSettings.popups.originalPath; | 852 returnPath = Popups.originalSettings.popups.originalPath; |
851 } | 853 } |
852 href = href.replace(/destination=[^;&]*[;&]?/, ''); // Strip out any existing destination param. | 854 href = href.replace(/destination=[^;&]*[;&]?/, ''); // Strip out any existing destination param. |
853 // console.log("Hijacking destination to " + returnPath); | 855 params.destination = returnPath; // Set the destination to return to the parent's path. |
854 params.destination = returnPath; // Set the destination to return to the parent's path. | |
855 } | 856 } |
856 | 857 |
857 var ajaxOptions = { | 858 var ajaxOptions = { |
858 url: href, | 859 url: href, |
859 dataType: 'json', | 860 dataType: 'json', |
860 data: params, | 861 data: params, |
861 beforeSend: Popups.beforeSend, | 862 beforeSend: Popups.beforeSend, |
862 success: function(json) { | 863 success: function(json) { |
863 // Add additional CSS to the page. | 864 // Add additional CSS to the page. |
864 Popups.addCSS(json.css); | 865 Popups.addCSS(json.css); |
865 var inlines = Popups.addJS(json.js); | 866 var inlines = Popups.addJS(json.js); |
866 var popup = Popups.openPathContent(json.path, json.title, json.messages + json.content, element, options, parent); | 867 var popup = Popups.openPathContent(json.path, json.title, json.messages + json.content, element, options, parent); |
867 Popups.addInlineJS(inlines); | 868 Popups.addInlineJS(inlines); |
868 // Broadcast an event that the path was opened. | 869 // Broadcast an event that the path was opened. |
869 $(document).trigger('popups_open_path_done', [element, href, popup]); | 870 $(document).trigger('popups_open_path_done', [element, href, popup]); |
870 }, | 871 }, |
871 complete: function() { | 872 complete: function() { |
872 $('body').css("cursor", "auto"); // Return the cursor to normal state. | 873 $('body').css("cursor", "auto"); // Return the cursor to normal state. |
873 } | 874 } |
874 }; | 875 }; |
875 | 876 |
876 var ajaxOptions; | 877 var ajaxOptions; |
877 if (options.reloadOnError) { | 878 if (options.reloadOnError) { |
878 ajaxOptions.error = function() { | 879 ajaxOptions.error = function() { |
879 location.reload(); // Reload on error. Is this working? | 880 location.reload(); // Reload on error. Is this working? |
880 }; | 881 }; |
881 } | 882 } |
882 else { | 883 else { |
883 ajaxOptions.error = function() { | 884 ajaxOptions.error = function() { |
884 Popups.message("Unable to open: " + href); | 885 Popups.message("Unable to open: " + href); |
885 }; | 886 }; |
886 } | 887 } |
887 $.ajax(ajaxOptions); | 888 $.ajax(ajaxOptions); |
888 | 889 |
889 return false; | 890 return false; |
890 }; | 891 }; |
891 | 892 |
892 /** | 893 /** |
893 * Open path's content in an ajax popups. | 894 * Open path's content in an ajax popups. |
894 * | 895 * |
895 * @param title | 896 * @param title |
896 * String title of the popups. | 897 * String title of the popups. |
897 * @param content | 898 * @param content |
898 * HTML to show in the popups. | 899 * HTML to show in the popups. |
899 * @param element | 900 * @param element |
900 * A DOM object containing the element that was clicked to initiate the popup. | 901 * A DOM object containing the element that was clicked to initiate the popup. |
901 * @param options | 902 * @param options |
902 * Hash of options controlling how the popups interacts with the underlying page. | 903 * Hash of options controlling how the popups interacts with the underlying page. |
903 * @param parent | 904 * @param parent |
904 * Spawning popup, or null if spawned from original page. | 905 * Spawning popup, or null if spawned from original page. |
905 */ | 906 */ |
906 Popups.openPathContent = function(path, title, content, element, options, parent) { | 907 Popups.openPathContent = function(path, title, content, element, options, parent) { |
907 var popup = new Popups.Popup(); | 908 var popup = new Popups.Popup(); |
908 Popups.open(popup, title, content, null, options.width); | 909 Popups.open(popup, title, content, null, options.width); |
909 | 910 |
910 // Set properties on new popup. | 911 // Set properties on new popup. |
911 popup.parent = parent; | 912 popup.parent = parent; |
912 popup.path = path; | 913 popup.path = path; |
913 // console.log("Setting popup " + popup.id + " originalPath to " + path); | |
914 popup.options = options; | 914 popup.options = options; |
915 popup.element = element; | 915 popup.element = element; |
916 | 916 |
917 // Add behaviors to content in popups. | 917 // Add behaviors to content in popups. |
918 delete Drupal.behaviors.tableHeader; // Work-around for bug in tableheader.js (http://drupal.org/node/234377) | 918 delete Drupal.behaviors.tableHeader; // Work-around for bug in tableheader.js (http://drupal.org/node/234377) |
919 delete Drupal.behaviors.teaser; // Work-around for bug in teaser.js (sigh). | 919 delete Drupal.behaviors.teaser; // Work-around for bug in teaser.js (sigh). |
920 Drupal.attachBehaviors(popup.$popupBody()); | 920 Drupal.attachBehaviors(popup.$popupBody()); |
921 // Adding collapse moves focus. | 921 // Adding collapse moves focus. |
922 popup.refocus(); | 922 popup.refocus(); |
923 | 923 |
924 // If the popups contains a form, capture submits. | 924 // If the popups contains a form, capture submits. |
925 var $form = $('form', popup.$popupBody()); | 925 var $form = $('form', popup.$popupBody()); |
926 if ($form.length) { | 926 if ($form.length) { |
927 $form.ajaxForm({ | 927 $form.ajaxForm({ |
928 dataType: 'json', | 928 dataType: 'json', |
929 beforeSubmit: Popups.beforeSubmit, | 929 beforeSubmit: Popups.beforeSubmit, |
930 beforeSend: Popups.beforeSend, | 930 beforeSend: Popups.beforeSend, |
931 success: function(json, status) { | 931 success: function(json, status) { |
932 Popups.formSuccess(popup, json); | 932 Popups.formSuccess(popup, json); |
933 }, | 933 }, |
941 | 941 |
942 /** | 942 /** |
943 * The form in the popups was successfully submitted | 943 * The form in the popups was successfully submitted |
944 * Update the originating page. | 944 * Update the originating page. |
945 * Show any messages in a popups. | 945 * Show any messages in a popups. |
946 * | 946 * |
947 * @param popup | 947 * @param popup |
948 * The popup object that contained the form that was just submitted. | 948 * The popup object that contained the form that was just submitted. |
949 * @param data | 949 * @param data |
950 * JSON object from server with status of form submission. | 950 * JSON object from server with status of form submission. |
951 */ | 951 */ |
952 Popups.formSuccess = function(popup, data) { | 952 Popups.formSuccess = function(popup, data) { |
953 // Determine if we are at an end point, or just moving from one popups to another. | 953 // Determine if we are at an end point, or just moving from one popups to another. |
954 var done = popup.isDone(data.path); | 954 var done = popup.isDone(data.path); |
955 if (!done) { // Not done yet, so show new page in new popups. | 955 if (!done) { // Not done yet, so show new page in new popups. |
956 Popups.removeLoading(); | 956 Popups.removeLoading(); |
957 Popups.openPathContent(data.path, data.title, data.messages + data.content, popup.element, popup.options, popup.parent); | 957 Popups.openPathContent(data.path, data.title, data.messages + data.content, popup.element, popup.options, popup.parent); |
958 } | 958 } |
959 else { // We are done with popup flow. | 959 else { // We are done with popup flow. |
960 // Execute the onUpdate callback if available. | 960 // Execute the onUpdate callback if available. |
961 if (popup.options.updateMethod === 'callback' && popup.options.onUpdate) { | 961 if (popup.options.updateMethod === 'callback' && popup.options.onUpdate) { |
962 var result = eval(popup.options.onUpdate +'(data, popup.options, popup.element)'); | 962 var result = eval(popup.options.onUpdate +'(data, popup.options, popup.element)'); |
963 if (result === false) { // Give onUpdate callback a chance to skip normal processing. | 963 if (result === false) { // Give onUpdate callback a chance to skip normal processing. |
964 return; | 964 return; |
965 } | 965 } |
966 } | 966 } |
968 if (popup.options.updateMethod === 'reload') { // Force a complete, non-ajax reload of the page. | 968 if (popup.options.updateMethod === 'reload') { // Force a complete, non-ajax reload of the page. |
969 if (popup.options.updateSource === 'final') { | 969 if (popup.options.updateSource === 'final') { |
970 location.href = Drupal.settings.basePath + data.path; // TODO: Need to test this. | 970 location.href = Drupal.settings.basePath + data.path; // TODO: Need to test this. |
971 } | 971 } |
972 else { // Reload originating page. | 972 else { // Reload originating page. |
973 location.reload(); | 973 location.reload(); |
974 } | 974 } |
975 } | 975 } |
976 else { // Normal, targeted ajax, reload behavior. | 976 else { // Normal, targeted ajax, reload behavior. |
977 var showingMessagePopup = false; | |
977 // Show messages in dialog and embed the results in the original page. | 978 // Show messages in dialog and embed the results in the original page. |
978 var showMessage = data.messages.length && !popup.options.noMessage; | 979 // TODO - should seperate these two functions. |
979 if (showMessage) { | 980 // var showMessage = data.messages.length && !popup.options.noMessage; |
980 var messagePopup = Popups.message(data.messages); // Popup message. | 981 if (data.messages.length) { |
981 if (Popups.originalSettings.popups.autoCloseFinalMessage) { | 982 // If we just dismissed the last popup dialog. |
982 setTimeout(function(){Popups.close(messagePopup);}, 2500); // Autoclose the message box in 2.5 seconds. | 983 if (!Popups.activePopup() && !popup.options.noMessage) { |
984 // Show drupal_set_message in message popup. | |
985 var messagePopup = Popups.message(data.messages); | |
986 if (Popups.originalSettings.popups.autoCloseFinalMessage) { | |
987 setTimeout(function(){Popups.close(messagePopup);}, 2500); // Autoclose the message box in 2.5 seconds. | |
988 } | |
989 showingMessagePopup = true; | |
983 } | 990 } |
984 | 991 |
985 // Insert the message into the page above the content. | 992 |
993 // Insert the message into the parent layer, above the content. | |
986 // Might not be the standard spot, but it is the easiest to find. | 994 // Might not be the standard spot, but it is the easiest to find. |
987 var $next; | 995 var $next; |
988 if (popup.targetLayerSelector() === 'body') { | 996 if (popup.targetLayerSelector() === 'body') { |
989 $next = $('body').find(Popups.originalSettings.popups.defaultTargetSelector); | 997 $next = $('body').find(Popups.originalSettings.popups.defaultTargetSelector); |
990 } | 998 } |
992 $next = $(popup.targetLayerSelector()).find('.popups-body'); | 1000 $next = $(popup.targetLayerSelector()).find('.popups-body'); |
993 } | 1001 } |
994 $next.parent().find('div.messages').remove(); // Remove the existing messages. | 1002 $next.parent().find('div.messages').remove(); // Remove the existing messages. |
995 $next.before(data.messages); // Insert new messages. | 1003 $next.before(data.messages); // Insert new messages. |
996 } | 1004 } |
997 | 1005 |
998 // Update the content area (defined by 'targetSelectors'). | 1006 // Update the content area (defined by 'targetSelectors'). |
999 if (popup.options.updateMethod !== 'none') { | 1007 if (popup.options.updateMethod !== 'none') { |
1000 Popups.testContentSelector(); // Kick up warning message if selector is bad. | 1008 Popups.testContentSelector(); // Kick up warning message if selector is bad. |
1001 | 1009 |
1002 Popups.restoreSettings(); // Need to restore original Drupal.settings.popups.links before running attachBehaviors. This probably has CSS side effects! | 1010 Popups.restoreSettings(); // Need to restore original Drupal.settings.popups.links before running attachBehaviors. This probably has CSS side effects! |
1003 if (popup.options.targetSelectors) { // Pick and choose what returned content goes where. | 1011 if (popup.options.targetSelectors) { // Pick and choose what returned content goes where. |
1004 jQuery.each(popup.options.targetSelectors, function(t_new, t_old) { | 1012 jQuery.each(popup.options.targetSelectors, function(t_new, t_old) { |
1005 if(!isNaN(t_new)) { | 1013 if(!isNaN(t_new)) { |
1006 t_new = t_old; // handle case where targetSelectors is an array, not a hash. | 1014 t_new = t_old; // handle case where targetSelectors is an array, not a hash. |
1007 } | 1015 } |
1008 // console.log("Updating target " + t_old + ' with ' + t_new); | |
1009 var new_content = $(t_new, data.content); | 1016 var new_content = $(t_new, data.content); |
1010 // console.log("new content... "); | |
1011 // console.log(new_content); | |
1012 var $c = $(popup.targetLayerSelector()).find(t_old).html(new_content); // Inject the new content into the original page. | 1017 var $c = $(popup.targetLayerSelector()).find(t_old).html(new_content); // Inject the new content into the original page. |
1013 | 1018 |
1014 Drupal.attachBehaviors($c); | 1019 Drupal.attachBehaviors($c); |
1015 }); | 1020 }); |
1016 } | 1021 } |
1017 else { // Put the entire new content into default content area. | 1022 else { // Put the entire new content into default content area. |
1018 var $c = $(popup.targetLayerSelector()).find(Popups.originalSettings.popups.defaultTargetSelector).html(data.content); | 1023 var $c = $(popup.targetLayerSelector()).find(Popups.originalSettings.popups.defaultTargetSelector).html(data.content); |
1019 // console.log("updating entire content area.") | 1024 Drupal.attachBehaviors($c); |
1020 Drupal.attachBehaviors($c); | |
1021 } | 1025 } |
1022 } | 1026 } |
1023 | 1027 |
1024 // Update the title of the page. | 1028 // Update the title of the page. |
1025 if (popup.options.titleSelectors) { | 1029 if (popup.options.titleSelectors) { |
1026 jQuery.each(popup.options.titleSelectors, function() { | 1030 jQuery.each(popup.options.titleSelectors, function() { |
1027 $(''+this).html(data.title); | 1031 $(''+this).html(data.title); |
1028 }); | 1032 }); |
1029 } | 1033 } |
1030 | 1034 |
1031 // Done with changes to the original page, remove effects. | 1035 // Done with changes to the original page, remove effects. |
1032 Popups.removeLoading(); | 1036 Popups.removeLoading(); |
1033 if (!showMessage) { | 1037 if (!showingMessagePopup) { |
1034 // If there is not a messages popups, close current layer. | 1038 // If there is not a messages popups, pop the stack. |
1035 Popups.close(); | 1039 // Sending in null to Popups.close reveales the next popup in the stack. |
1040 // If the stack is empty, it will remove the overlay. | |
1041 Popups.close(null); | |
1036 } | 1042 } |
1037 } | 1043 } |
1038 | 1044 |
1039 // Broadcast an event that popup form was done and successful. | 1045 // Broadcast an event that popup form was done and successful. |
1040 $(document).trigger('popups_form_success', [popup]); | 1046 $(document).trigger('popups_form_success', [popup]); |
1041 | 1047 |
1042 } // End of updating spawning layer. | 1048 } // End of updating spawning layer. |
1043 }; | 1049 }; |
1044 | 1050 |
1045 | 1051 |
1046 /** | 1052 /** |
1047 * Get a jQuery object for the content of a layer. | 1053 * Get a jQuery object for the content of a layer. |
1048 * @param layer | 1054 * @param layer |
1049 * Either a popup, or null to signify the original page. | 1055 * Either a popup, or null to signify the original page. |
1050 */ | 1056 */ |
1051 Popups.getLayerContext = function(layer) { | 1057 Popups.getLayerContext = function(layer) { |
1052 var $context; | 1058 var $context; |
1053 if (!layer) { | 1059 if (!layer) { |
1054 $context = $('body').find(Popups.originalSettings.popups.defaultTargetSelector); | 1060 $context = $('body').find(Popups.originalSettings.popups.defaultTargetSelector); |
1055 } | 1061 } |
1056 else { | 1062 else { |
1065 * @param element | 1071 * @param element |
1066 * Element that was clicked to open a new popup. | 1072 * Element that was clicked to open a new popup. |
1067 * @param options | 1073 * @param options |
1068 * Hash of options controlling how the popups interacts with the underlying page. | 1074 * Hash of options controlling how the popups interacts with the underlying page. |
1069 * @param layer | 1075 * @param layer |
1070 * Popup with form to save, or null if form is on original page. | 1076 * Popup with form to save, or null if form is on original page. |
1071 */ | 1077 */ |
1072 Popups.saveFormOnLayer = function(element, options, layer) { | 1078 Popups.saveFormOnLayer = function(element, options, layer) { |
1073 var $context = Popups.getLayerContext(layer); | 1079 var $context = Popups.getLayerContext(layer); |
1074 var $form = $context.find('form'); | 1080 var $form = $context.find('form'); |
1075 var ajaxOptions = { | 1081 var ajaxOptions = { |
1076 dataType: 'json', | 1082 dataType: 'json', |
1077 beforeSubmit: Popups.beforeSubmit, | 1083 beforeSubmit: Popups.beforeSubmit, |
1078 beforeSend: Popups.beforeSend, | 1084 beforeSend: Popups.beforeSend, |
1079 success: function(response, status) { | 1085 success: function(response, status) { |
1080 // Sync up the current page contents with the submit. | 1086 // Sync up the current page contents with the submit. |
1081 var $c = $context.html(response.content); // Inject the new content into the page. | 1087 var $c = $context.html(response.content); // Inject the new content into the page. |
1082 Drupal.attachBehaviors($c); | 1088 Drupal.attachBehaviors($c); |
1083 // The form has been saved, the page reloaded, now safe to show the triggering link in a popup. | 1089 // The form has been saved, the page reloaded, now safe to show the triggering link in a popup. |
1084 Popups.openPath(element, options, layer); | 1090 Popups.openPath(element, options, layer); |
1085 } | 1091 } |
1086 }; | 1092 }; |
1087 $form.ajaxSubmit(ajaxOptions); // Submit the form. | 1093 $form.ajaxSubmit(ajaxOptions); // Submit the form. |
1088 }; | 1094 }; |
1089 | 1095 |
1090 /** | 1096 /** |
1091 * Warn the user if ajax updates will not work | 1097 * Warn the user if ajax updates will not work |
1092 * due to mismatch between the theme and the theme's popup setting. | 1098 * due to mismatch between the theme and the theme's popup setting. |
1100 msg += Drupal.t('There is no element that matches ') + '"' + target + '"\n'; | 1106 msg += Drupal.t('There is no element that matches ') + '"' + target + '"\n'; |
1101 } | 1107 } |
1102 else if (hits > 1) { | 1108 else if (hits > 1) { |
1103 msg += Drupal.t('There are multiple elements that match: ') + '"' + target + '"\n'; | 1109 msg += Drupal.t('There are multiple elements that match: ') + '"' + target + '"\n'; |
1104 } | 1110 } |
1105 msg += Drupal.t('Go to admin/build/themes/settings, select your theme, and edit the "Content Selector" field'); | 1111 msg += Drupal.t('Go to admin/build/themes/settings, select your theme, and edit the "Content Selector" field'); |
1106 alert(msg); | 1112 alert(msg); |
1107 } | 1113 } |
1108 }; | 1114 }; |
1109 | 1115 |
1110 | 1116 |
1128 }; | 1134 }; |
1129 | 1135 |
1130 Drupal.theme.prototype.popupDialog = function(popupId, title, body, buttons) { | 1136 Drupal.theme.prototype.popupDialog = function(popupId, title, body, buttons) { |
1131 var template = Drupal.theme('popupTemplate', popupId); | 1137 var template = Drupal.theme('popupTemplate', popupId); |
1132 var popups = template.replace('%title', title).replace('%body', body); | 1138 var popups = template.replace('%title', title).replace('%body', body); |
1133 | 1139 |
1134 var themedButtons = ''; | 1140 var themedButtons = ''; |
1135 if (buttons) { | 1141 if (buttons) { |
1136 jQuery.each(buttons, function (id, button) { | 1142 jQuery.each(buttons, function (id, button) { |
1137 themedButtons += Drupal.theme('popupButton', button.title, id); | 1143 themedButtons += Drupal.theme('popupButton', button.title, id); |
1138 }); | 1144 }); |
1139 } | 1145 } |
1140 popups = popups.replace('%buttons', themedButtons); | 1146 popups = popups.replace('%buttons', themedButtons); |
1141 return popups; | 1147 return popups; |
1142 }; | 1148 }; |
1143 | 1149 |
1144 Drupal.theme.prototype.popupTemplate = function(popupId) { | 1150 Drupal.theme.prototype.popupTemplate = function(popupId) { |
1145 var template; | 1151 var template; |
1153 template += ' <div class="popups-buttons">%buttons</div>'; | 1159 template += ' <div class="popups-buttons">%buttons</div>'; |
1154 template += ' <div class="popups-footer"></div>'; | 1160 template += ' <div class="popups-footer"></div>'; |
1155 template += '</div>'; | 1161 template += '</div>'; |
1156 return template; | 1162 return template; |
1157 }; | 1163 }; |
1158 |