annotate popups.js @ 6:e02de6b2566e

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