PageSourceSearch

http://www.realvalue.in/real_files/popups00.js

js realvalue.in collected 2026-10-03 22:38:42 UTC 37,653 bytes, 1,163 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.