lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame^] | 1 | /*
|
| 2 | * SimpleModal 1.4.2 - jQuery Plugin
|
| 3 | * http://simplemodal.com/
|
| 4 | * Copyright (c) 2011 Eric Martin
|
| 5 | * Licensed under MIT and GPL
|
| 6 | * Date: Sat, Dec 17 2011 15:35:38 -0800
|
| 7 | */
|
| 8 |
|
| 9 | /**
|
| 10 | * SimpleModal is a lightweight jQuery plugin that provides a simple
|
| 11 | * interface to create a modal dialog.
|
| 12 | *
|
| 13 | * The goal of SimpleModal is to provide developers with a cross-browser
|
| 14 | * overlay and container that will be populated with data provided to
|
| 15 | * SimpleModal.
|
| 16 | *
|
| 17 | * There are two ways to call SimpleModal:
|
| 18 | * 1) As a chained function on a jQuery object, like $('#myDiv').modal();.
|
| 19 | * This call would place the DOM object, #myDiv, inside a modal dialog.
|
| 20 | * Chaining requires a jQuery object. An optional options object can be
|
| 21 | * passed as a parameter.
|
| 22 | *
|
| 23 | * @example $('<div>my data</div>').modal({options});
|
| 24 | * @example $('#myDiv').modal({options});
|
| 25 | * @example jQueryObject.modal({options});
|
| 26 | *
|
| 27 | * 2) As a stand-alone function, like $.modal(data). The data parameter
|
| 28 | * is required and an optional options object can be passed as a second
|
| 29 | * parameter. This method provides more flexibility in the types of data
|
| 30 | * that are allowed. The data could be a DOM object, a jQuery object, HTML
|
| 31 | * or a string.
|
| 32 | *
|
| 33 | * @example $.modal('<div>my data</div>', {options});
|
| 34 | * @example $.modal('my data', {options});
|
| 35 | * @example $.modal($('#myDiv'), {options});
|
| 36 | * @example $.modal(jQueryObject, {options});
|
| 37 | * @example $.modal(document.getElementById('myDiv'), {options});
|
| 38 | *
|
| 39 | * A SimpleModal call can contain multiple elements, but only one modal
|
| 40 | * dialog can be created at a time. Which means that all of the matched
|
| 41 | * elements will be displayed within the modal container.
|
| 42 | *
|
| 43 | * SimpleModal internally sets the CSS needed to display the modal dialog
|
| 44 | * properly in all browsers, yet provides the developer with the flexibility
|
| 45 | * to easily control the look and feel. The styling for SimpleModal can be
|
| 46 | * done through external stylesheets, or through SimpleModal, using the
|
| 47 | * overlayCss, containerCss, and dataCss options.
|
| 48 | *
|
| 49 | * SimpleModal has been tested in the following browsers:
|
| 50 | * - IE 6+
|
| 51 | * - Firefox 2+
|
| 52 | * - Opera 9+
|
| 53 | * - Safari 3+
|
| 54 | * - Chrome 1+
|
| 55 | *
|
| 56 | * @name SimpleModal
|
| 57 | * @type jQuery
|
| 58 | * @requires jQuery v1.2.4
|
| 59 | * @cat Plugins/Windows and Overlays
|
| 60 | * @author Eric Martin (http://ericmmartin.com)
|
| 61 | * @version 1.4.2
|
| 62 | */
|
| 63 |
|
| 64 | ;(function (factory) {
|
| 65 | if (typeof define === 'function' && define.amd) {
|
| 66 | // AMD. Register as an anonymous module.
|
| 67 | define(['jquery'], factory);
|
| 68 | } else {
|
| 69 | // Browser globals
|
| 70 | factory(jQuery);
|
| 71 | }
|
| 72 | }
|
| 73 | (function ($) {
|
| 74 | var d = [],
|
| 75 | doc = $(document),
|
| 76 | ie6 = $.browser.msie && parseInt($.browser.version) === 6 && typeof window['XMLHttpRequest'] !== 'object',
|
| 77 | ie7 = $.browser.msie && parseInt($.browser.version) === 7,
|
| 78 | ieQuirks = null,
|
| 79 | wndw = $(window),
|
| 80 | w = [];
|
| 81 |
|
| 82 | /*
|
| 83 | * Create and display a modal dialog.
|
| 84 | *
|
| 85 | * @param {string, object} data A string, jQuery object or DOM object
|
| 86 | * @param {object} [options] An optional object containing options overrides
|
| 87 | */
|
| 88 | $.modal = function (data, options) {
|
| 89 | return $.modal.impl.init(data, options);
|
| 90 | };
|
| 91 |
|
| 92 | /*
|
| 93 | * Close the modal dialog.
|
| 94 | */
|
| 95 | $.modal.close = function () {
|
| 96 | $.modal.impl.close();
|
| 97 | };
|
| 98 |
|
| 99 | /*
|
| 100 | * Set focus on first or last visible input in the modal dialog. To focus on the last
|
| 101 | * element, call $.modal.focus('last'). If no input elements are found, focus is placed
|
| 102 | * on the data wrapper element.
|
| 103 | */
|
| 104 | $.modal.focus = function (pos) {
|
| 105 | $.modal.impl.focus(pos);
|
| 106 | };
|
| 107 |
|
| 108 | /*
|
| 109 | * Determine and set the dimensions of the modal dialog container.
|
| 110 | * setPosition() is called if the autoPosition option is true.
|
| 111 | */
|
| 112 | $.modal.setContainerDimensions = function () {
|
| 113 | $.modal.impl.setContainerDimensions();
|
| 114 | };
|
| 115 |
|
| 116 | /*
|
| 117 | * Re-position the modal dialog.
|
| 118 | */
|
| 119 | $.modal.setPosition = function () {
|
| 120 | $.modal.impl.setPosition();
|
| 121 | };
|
| 122 |
|
| 123 | /*
|
| 124 | * Update the modal dialog. If new dimensions are passed, they will be used to determine
|
| 125 | * the dimensions of the container.
|
| 126 | *
|
| 127 | * setContainerDimensions() is called, which in turn calls setPosition(), if enabled.
|
| 128 | * Lastly, focus() is called is the focus option is true.
|
| 129 | */
|
| 130 | $.modal.update = function (height, width) {
|
| 131 | $.modal.impl.update(height, width);
|
| 132 | };
|
| 133 |
|
| 134 | /*
|
| 135 | * Chained function to create a modal dialog.
|
| 136 | *
|
| 137 | * @param {object} [options] An optional object containing options overrides
|
| 138 | */
|
| 139 | $.fn.modal = function (options) {
|
| 140 | return $.modal.impl.init(this, options);
|
| 141 | };
|
| 142 |
|
| 143 | /*
|
| 144 | * SimpleModal default options
|
| 145 | *
|
| 146 | * appendTo: (String:'body') The jQuery selector to append the elements to. For .NET, use 'form'.
|
| 147 | * focus: (Boolean:true) Focus in the first visible, enabled element?
|
| 148 | * opacity: (Number:50) The opacity value for the overlay div, from 0 - 100
|
| 149 | * overlayId: (String:'simplemodal-overlay') The DOM element id for the overlay div
|
| 150 | * overlayCss: (Object:{}) The CSS styling for the overlay div
|
| 151 | * containerId: (String:'simplemodal-container') The DOM element id for the container div
|
| 152 | * containerCss: (Object:{}) The CSS styling for the container div
|
| 153 | * dataId: (String:'simplemodal-data') The DOM element id for the data div
|
| 154 | * dataCss: (Object:{}) The CSS styling for the data div
|
| 155 | * minHeight: (Number:null) The minimum height for the container
|
| 156 | * minWidth: (Number:null) The minimum width for the container
|
| 157 | * maxHeight: (Number:null) The maximum height for the container. If not specified, the window height is used.
|
| 158 | * maxWidth: (Number:null) The maximum width for the container. If not specified, the window width is used.
|
| 159 | * autoResize: (Boolean:false) Automatically resize the container if it exceeds the browser window dimensions?
|
| 160 | * autoPosition: (Boolean:true) Automatically position the container upon creation and on window resize?
|
| 161 | * zIndex: (Number: 1000) Starting z-index value
|
| 162 | * close: (Boolean:true) If true, closeHTML, escClose and overClose will be used if set.
|
| 163 | If false, none of them will be used.
|
| 164 | * closeHTML: (String:'<a class="modalCloseImg" title="Close"></a>') The HTML for the default close link.
|
| 165 | SimpleModal will automatically add the closeClass to this element.
|
| 166 | * closeClass: (String:'simplemodal-close') The CSS class used to bind to the close event
|
| 167 | * escClose: (Boolean:true) Allow Esc keypress to close the dialog?
|
| 168 | * overlayClose: (Boolean:false) Allow click on overlay to close the dialog?
|
| 169 | * fixed: (Boolean:true) If true, the container will use a fixed position. If false, it will use a
|
| 170 | absolute position (the dialog will scroll with the page)
|
| 171 | * position: (Array:null) Position of container [top, left]. Can be number of pixels or percentage
|
| 172 | * persist: (Boolean:false) Persist the data across modal calls? Only used for existing
|
| 173 | DOM elements. If true, the data will be maintained across modal calls, if false,
|
| 174 | the data will be reverted to its original state.
|
| 175 | * modal: (Boolean:true) User will be unable to interact with the page below the modal or tab away from the dialog.
|
| 176 | If false, the overlay, iframe, and certain events will be disabled allowing the user to interact
|
| 177 | with the page below the dialog.
|
| 178 | * onOpen: (Function:null) The callback function used in place of SimpleModal's open
|
| 179 | * onShow: (Function:null) The callback function used after the modal dialog has opened
|
| 180 | * onClose: (Function:null) The callback function used in place of SimpleModal's close
|
| 181 | */
|
| 182 | $.modal.defaults = {
|
| 183 | appendTo: 'body',
|
| 184 | focus: true,
|
| 185 | opacity: 50,
|
| 186 | overlayId: 'simplemodal-overlay',
|
| 187 | overlayCss: {},
|
| 188 | containerId: 'simplemodal-container',
|
| 189 | containerCss: {},
|
| 190 | dataId: 'simplemodal-data',
|
| 191 | dataCss: {},
|
| 192 | minHeight: null,
|
| 193 | minWidth: null,
|
| 194 | maxHeight: null,
|
| 195 | maxWidth: null,
|
| 196 | autoResize: false,
|
| 197 | autoPosition: true,
|
| 198 | zIndex: 1000,
|
| 199 | close: true,
|
| 200 | closeHTML: '<a class="modalCloseImg" title="Close"></a>',
|
| 201 | closeClass: 'simplemodal-close',
|
| 202 | escClose: true,
|
| 203 | overlayClose: false,
|
| 204 | fixed: true,
|
| 205 | position: null,
|
| 206 | persist: false,
|
| 207 | modal: true,
|
| 208 | onOpen: null,
|
| 209 | onShow: null,
|
| 210 | onClose: null
|
| 211 | };
|
| 212 |
|
| 213 | /*
|
| 214 | * Main modal object
|
| 215 | * o = options
|
| 216 | */
|
| 217 | $.modal.impl = {
|
| 218 | /*
|
| 219 | * Contains the modal dialog elements and is the object passed
|
| 220 | * back to the callback (onOpen, onShow, onClose) functions
|
| 221 | */
|
| 222 | d: {},
|
| 223 | /*
|
| 224 | * Initialize the modal dialog
|
| 225 | */
|
| 226 | init: function (data, options) {
|
| 227 | var s = this;
|
| 228 |
|
| 229 | // don't allow multiple calls
|
| 230 | if (s.d.data) {
|
| 231 | return false;
|
| 232 | }
|
| 233 |
|
| 234 | // $.boxModel is undefined if checked earlier
|
| 235 | ieQuirks = $.browser.msie && !$.boxModel;
|
| 236 |
|
| 237 | // merge defaults and user options
|
| 238 | s.o = $.extend({}, $.modal.defaults, options);
|
| 239 |
|
| 240 | // keep track of z-index
|
| 241 | s.zIndex = s.o.zIndex;
|
| 242 |
|
| 243 | // set the onClose callback flag
|
| 244 | s.occb = false;
|
| 245 |
|
| 246 | // determine how to handle the data based on its type
|
| 247 | if (typeof data === 'object') {
|
| 248 | // convert DOM object to a jQuery object
|
| 249 | data = data instanceof jQuery ? data : $(data);
|
| 250 | s.d.placeholder = false;
|
| 251 |
|
| 252 | // if the object came from the DOM, keep track of its parent
|
| 253 | if (data.parent().parent().size() > 0) {
|
| 254 | data.before($('<span></span>')
|
| 255 | .attr('id', 'simplemodal-placeholder')
|
| 256 | .css({display: 'none'}));
|
| 257 |
|
| 258 | s.d.placeholder = true;
|
| 259 | s.display = data.css('display');
|
| 260 |
|
| 261 | // persist changes? if not, make a clone of the element
|
| 262 | if (!s.o.persist) {
|
| 263 | s.d.orig = data.clone(true);
|
| 264 | }
|
| 265 | }
|
| 266 | }
|
| 267 | else if (typeof data === 'string' || typeof data === 'number') {
|
| 268 | // just insert the data as innerHTML
|
| 269 | data = $('<div></div>').html(data);
|
| 270 | }
|
| 271 | else {
|
| 272 | // unsupported data type!
|
| 273 | alert('SimpleModal Error: Unsupported data type: ' + typeof data);
|
| 274 | return s;
|
| 275 | }
|
| 276 |
|
| 277 | // create the modal overlay, container and, if necessary, iframe
|
| 278 | s.create(data);
|
| 279 | data = null;
|
| 280 |
|
| 281 | // display the modal dialog
|
| 282 | s.open();
|
| 283 |
|
| 284 | // useful for adding events/manipulating data in the modal dialog
|
| 285 | if ($.isFunction(s.o.onShow)) {
|
| 286 | s.o.onShow.apply(s, [s.d]);
|
| 287 | }
|
| 288 |
|
| 289 | // don't break the chain =)
|
| 290 | return s;
|
| 291 | },
|
| 292 | /*
|
| 293 | * Create and add the modal overlay and container to the page
|
| 294 | */
|
| 295 | create: function (data) {
|
| 296 | var s = this;
|
| 297 |
|
| 298 | // get the window properties
|
| 299 | s.getDimensions();
|
| 300 |
|
| 301 | // add an iframe to prevent select options from bleeding through
|
| 302 | if (s.o.modal && ie6) {
|
| 303 | s.d.iframe = $('<iframe src="javascript:false;"></iframe>')
|
| 304 | .css($.extend(s.o.iframeCss, {
|
| 305 | display: 'none',
|
| 306 | opacity: 0,
|
| 307 | position: 'fixed',
|
| 308 | height: w[0],
|
| 309 | width: w[1],
|
| 310 | zIndex: s.o.zIndex,
|
| 311 | top: 0,
|
| 312 | left: 0
|
| 313 | }))
|
| 314 | .appendTo(s.o.appendTo);
|
| 315 | }
|
| 316 |
|
| 317 | // create the overlay
|
| 318 | s.d.overlay = $('<div></div>')
|
| 319 | .attr('id', s.o.overlayId)
|
| 320 | .addClass('simplemodal-overlay')
|
| 321 | .css($.extend(s.o.overlayCss, {
|
| 322 | display: 'none',
|
| 323 | opacity: s.o.opacity / 100,
|
| 324 | height: s.o.modal ? d[0] : 0,
|
| 325 | width: s.o.modal ? d[1] : 0,
|
| 326 | position: 'fixed',
|
| 327 | left: 0,
|
| 328 | top: 0,
|
| 329 | zIndex: s.o.zIndex + 1
|
| 330 | }))
|
| 331 | .appendTo(s.o.appendTo);
|
| 332 |
|
| 333 | // create the container
|
| 334 | s.d.container = $('<div></div>')
|
| 335 | .attr('id', s.o.containerId)
|
| 336 | .addClass('simplemodal-container')
|
| 337 | .css($.extend(
|
| 338 | {position: s.o.fixed ? 'fixed' : 'absolute'},
|
| 339 | s.o.containerCss,
|
| 340 | {display: 'none', zIndex: s.o.zIndex + 2}
|
| 341 | ))
|
| 342 | .append(s.o.close && s.o.closeHTML
|
| 343 | ? $(s.o.closeHTML).addClass(s.o.closeClass)
|
| 344 | : '')
|
| 345 | .appendTo(s.o.appendTo);
|
| 346 |
|
| 347 | s.d.wrap = $('<div></div>')
|
| 348 | .attr('tabIndex', -1)
|
| 349 | .addClass('simplemodal-wrap')
|
| 350 | .css({height: '100%', outline: 0, width: '100%'})
|
| 351 | .appendTo(s.d.container);
|
| 352 |
|
| 353 | // add styling and attributes to the data
|
| 354 | // append to body to get correct dimensions, then move to wrap
|
| 355 | s.d.data = data
|
| 356 | .attr('id', data.attr('id') || s.o.dataId)
|
| 357 | .addClass('simplemodal-data')
|
| 358 | .css($.extend(s.o.dataCss, {
|
| 359 | display: 'none'
|
| 360 | }))
|
| 361 | .appendTo('body');
|
| 362 | data = null;
|
| 363 |
|
| 364 | s.setContainerDimensions();
|
| 365 | s.d.data.appendTo(s.d.wrap);
|
| 366 |
|
| 367 | // fix issues with IE
|
| 368 | if (ie6 || ieQuirks) {
|
| 369 | s.fixIE();
|
| 370 | }
|
| 371 | },
|
| 372 | /*
|
| 373 | * Bind events
|
| 374 | */
|
| 375 | bindEvents: function () {
|
| 376 | var s = this;
|
| 377 |
|
| 378 | // bind the close event to any element with the closeClass class
|
| 379 | $('.' + s.o.closeClass).bind('click.simplemodal', function (e) {
|
| 380 | e.preventDefault();
|
| 381 | s.close();
|
| 382 | });
|
| 383 |
|
| 384 | // bind the overlay click to the close function, if enabled
|
| 385 | if (s.o.modal && s.o.close && s.o.overlayClose) {
|
| 386 | s.d.overlay.bind('click.simplemodal', function (e) {
|
| 387 | e.preventDefault();
|
| 388 | s.close();
|
| 389 | });
|
| 390 | }
|
| 391 |
|
| 392 | // bind keydown events
|
| 393 | doc.bind('keydown.simplemodal', function (e) {
|
| 394 | if (s.o.modal && e.keyCode === 9) { // TAB
|
| 395 | s.watchTab(e);
|
| 396 | }
|
| 397 | else if ((s.o.close && s.o.escClose) && e.keyCode === 27) { // ESC
|
| 398 | e.preventDefault();
|
| 399 | s.close();
|
| 400 | }
|
| 401 | });
|
| 402 |
|
| 403 | // update window size
|
| 404 | wndw.bind('resize.simplemodal orientationchange.simplemodal', function () {
|
| 405 | // redetermine the window width/height
|
| 406 | s.getDimensions();
|
| 407 |
|
| 408 | // reposition the dialog
|
| 409 | s.o.autoResize ? s.setContainerDimensions() : s.o.autoPosition && s.setPosition();
|
| 410 |
|
| 411 | if (ie6 || ieQuirks) {
|
| 412 | s.fixIE();
|
| 413 | }
|
| 414 | else if (s.o.modal) {
|
| 415 | // update the iframe & overlay
|
| 416 | s.d.iframe && s.d.iframe.css({height: w[0], width: w[1]});
|
| 417 | s.d.overlay.css({height: d[0], width: d[1]});
|
| 418 | }
|
| 419 | });
|
| 420 | },
|
| 421 | /*
|
| 422 | * Unbind events
|
| 423 | */
|
| 424 | unbindEvents: function () {
|
| 425 | $('.' + this.o.closeClass).unbind('click.simplemodal');
|
| 426 | doc.unbind('keydown.simplemodal');
|
| 427 | wndw.unbind('.simplemodal');
|
| 428 | this.d.overlay.unbind('click.simplemodal');
|
| 429 | },
|
| 430 | /*
|
| 431 | * Fix issues in IE6 and IE7 in quirks mode
|
| 432 | */
|
| 433 | fixIE: function () {
|
| 434 | var s = this, p = s.o.position;
|
| 435 |
|
| 436 | // simulate fixed position - adapted from BlockUI
|
| 437 | $.each([s.d.iframe || null, !s.o.modal ? null : s.d.overlay, s.d.container.css('position') === 'fixed' ? s.d.container : null], function (i, el) {
|
| 438 | if (el) {
|
| 439 | var bch = 'document.body.clientHeight', bcw = 'document.body.clientWidth',
|
| 440 | bsh = 'document.body.scrollHeight', bsl = 'document.body.scrollLeft',
|
| 441 | bst = 'document.body.scrollTop', bsw = 'document.body.scrollWidth',
|
| 442 | ch = 'document.documentElement.clientHeight', cw = 'document.documentElement.clientWidth',
|
| 443 | sl = 'document.documentElement.scrollLeft', st = 'document.documentElement.scrollTop',
|
| 444 | s = el[0].style;
|
| 445 |
|
| 446 | s.position = 'absolute';
|
| 447 | if (i < 2) {
|
| 448 | s.removeExpression('height');
|
| 449 | s.removeExpression('width');
|
| 450 | s.setExpression('height','' + bsh + ' > ' + bch + ' ? ' + bsh + ' : ' + bch + ' + "px"');
|
| 451 | s.setExpression('width','' + bsw + ' > ' + bcw + ' ? ' + bsw + ' : ' + bcw + ' + "px"');
|
| 452 | }
|
| 453 | else {
|
| 454 | var te, le;
|
| 455 | if (p && p.constructor === Array) {
|
| 456 | var top = p[0]
|
| 457 | ? typeof p[0] === 'number' ? p[0].toString() : p[0].replace(/px/, '')
|
| 458 | : el.css('top').replace(/px/, '');
|
| 459 | te = top.indexOf('%') === -1
|
| 460 | ? top + ' + (t = ' + st + ' ? ' + st + ' : ' + bst + ') + "px"'
|
| 461 | : parseInt(top.replace(/%/, '')) + ' * ((' + ch + ' || ' + bch + ') / 100) + (t = ' + st + ' ? ' + st + ' : ' + bst + ') + "px"';
|
| 462 |
|
| 463 | if (p[1]) {
|
| 464 | var left = typeof p[1] === 'number' ? p[1].toString() : p[1].replace(/px/, '');
|
| 465 | le = left.indexOf('%') === -1
|
| 466 | ? left + ' + (t = ' + sl + ' ? ' + sl + ' : ' + bsl + ') + "px"'
|
| 467 | : parseInt(left.replace(/%/, '')) + ' * ((' + cw + ' || ' + bcw + ') / 100) + (t = ' + sl + ' ? ' + sl + ' : ' + bsl + ') + "px"';
|
| 468 | }
|
| 469 | }
|
| 470 | else {
|
| 471 | te = '(' + ch + ' || ' + bch + ') / 2 - (this.offsetHeight / 2) + (t = ' + st + ' ? ' + st + ' : ' + bst + ') + "px"';
|
| 472 | le = '(' + cw + ' || ' + bcw + ') / 2 - (this.offsetWidth / 2) + (t = ' + sl + ' ? ' + sl + ' : ' + bsl + ') + "px"';
|
| 473 | }
|
| 474 | s.removeExpression('top');
|
| 475 | s.removeExpression('left');
|
| 476 | s.setExpression('top', te);
|
| 477 | s.setExpression('left', le);
|
| 478 | }
|
| 479 | }
|
| 480 | });
|
| 481 | },
|
| 482 | /*
|
| 483 | * Place focus on the first or last visible input
|
| 484 | */
|
| 485 | focus: function (pos) {
|
| 486 | var s = this, p = pos && $.inArray(pos, ['first', 'last']) !== -1 ? pos : 'first';
|
| 487 |
|
| 488 | // focus on dialog or the first visible/enabled input element
|
| 489 | var input = $(':input:enabled:visible:' + p, s.d.wrap);
|
| 490 | setTimeout(function () {
|
| 491 | input.length > 0 ? input.focus() : s.d.wrap.focus();
|
| 492 | }, 10);
|
| 493 | },
|
| 494 | getDimensions: function () {
|
| 495 | // fix a jQuery/Opera bug with determining the window height
|
| 496 | var s = this,
|
| 497 | h = $.browser.opera && $.browser.version > '9.5' && $.fn.jquery < '1.3'
|
| 498 | || $.browser.opera && $.browser.version < '9.5' && $.fn.jquery > '1.2.6'
|
| 499 | ? wndw[0].innerHeight : wndw.height();
|
| 500 |
|
| 501 | d = [doc.height(), doc.width()];
|
| 502 | w = [h, wndw.width()];
|
| 503 | },
|
| 504 | getVal: function (v, d) {
|
| 505 | return v ? (typeof v === 'number' ? v
|
| 506 | : v === 'auto' ? 0
|
| 507 | : v.indexOf('%') > 0 ? ((parseInt(v.replace(/%/, '')) / 100) * (d === 'h' ? w[0] : w[1]))
|
| 508 | : parseInt(v.replace(/px/, '')))
|
| 509 | : null;
|
| 510 | },
|
| 511 | /*
|
| 512 | * Update the container. Set new dimensions, if provided.
|
| 513 | * Focus, if enabled. Re-bind events.
|
| 514 | */
|
| 515 | update: function (height, width) {
|
| 516 | var s = this;
|
| 517 |
|
| 518 | // prevent update if dialog does not exist
|
| 519 | if (!s.d.data) {
|
| 520 | return false;
|
| 521 | }
|
| 522 |
|
| 523 | // reset orig values
|
| 524 | s.d.origHeight = s.getVal(height, 'h');
|
| 525 | s.d.origWidth = s.getVal(width, 'w');
|
| 526 |
|
| 527 | // hide data to prevent screen flicker
|
| 528 | s.d.data.hide();
|
| 529 | height && s.d.container.css('height', height);
|
| 530 | width && s.d.container.css('width', width);
|
| 531 | s.setContainerDimensions();
|
| 532 | s.d.data.show();
|
| 533 | s.o.focus && s.focus();
|
| 534 |
|
| 535 | // rebind events
|
| 536 | s.unbindEvents();
|
| 537 | s.bindEvents();
|
| 538 | },
|
| 539 | setContainerDimensions: function () {
|
| 540 | var s = this,
|
| 541 | badIE = ie6 || ie7;
|
| 542 |
|
| 543 | // get the dimensions for the container and data
|
| 544 | var ch = s.d.origHeight ? s.d.origHeight : $.browser.opera ? s.d.container.height() : s.getVal(badIE ? s.d.container[0].currentStyle['height'] : s.d.container.css('height'), 'h'),
|
| 545 | cw = s.d.origWidth ? s.d.origWidth : $.browser.opera ? s.d.container.width() : s.getVal(badIE ? s.d.container[0].currentStyle['width'] : s.d.container.css('width'), 'w'),
|
| 546 | dh = s.d.data.outerHeight(true), dw = s.d.data.outerWidth(true);
|
| 547 |
|
| 548 | s.d.origHeight = s.d.origHeight || ch;
|
| 549 | s.d.origWidth = s.d.origWidth || cw;
|
| 550 |
|
| 551 | // mxoh = max option height, mxow = max option width
|
| 552 | var mxoh = s.o.maxHeight ? s.getVal(s.o.maxHeight, 'h') : null,
|
| 553 | mxow = s.o.maxWidth ? s.getVal(s.o.maxWidth, 'w') : null,
|
| 554 | mh = mxoh && mxoh < w[0] ? mxoh : w[0],
|
| 555 | mw = mxow && mxow < w[1] ? mxow : w[1];
|
| 556 |
|
| 557 | // moh = min option height
|
| 558 | var moh = s.o.minHeight ? s.getVal(s.o.minHeight, 'h') : 'auto';
|
| 559 | if (!ch) {
|
| 560 | if (!dh) {ch = moh;}
|
| 561 | else {
|
| 562 | if (dh > mh) {ch = mh;}
|
| 563 | else if (s.o.minHeight && moh !== 'auto' && dh < moh) {ch = moh;}
|
| 564 | else {ch = dh;}
|
| 565 | }
|
| 566 | }
|
| 567 | else {
|
| 568 | ch = s.o.autoResize && ch > mh ? mh : ch < moh ? moh : ch;
|
| 569 | }
|
| 570 |
|
| 571 | // mow = min option width
|
| 572 | var mow = s.o.minWidth ? s.getVal(s.o.minWidth, 'w') : 'auto';
|
| 573 | if (!cw) {
|
| 574 | if (!dw) {cw = mow;}
|
| 575 | else {
|
| 576 | if (dw > mw) {cw = mw;}
|
| 577 | else if (s.o.minWidth && mow !== 'auto' && dw < mow) {cw = mow;}
|
| 578 | else {cw = dw;}
|
| 579 | }
|
| 580 | }
|
| 581 | else {
|
| 582 | cw = s.o.autoResize && cw > mw ? mw : cw < mow ? mow : cw;
|
| 583 | }
|
| 584 |
|
| 585 | s.d.container.css({"min-height": ch, "width": cw});
|
| 586 | // s.d.wrap.css({overflow: (dh > ch || dw > cw) ? 'auto' : 'visible'});
|
| 587 | s.o.autoPosition && s.setPosition();
|
| 588 | },
|
| 589 | setPosition: function () {
|
| 590 | var s = this, top, left,
|
| 591 | hc = (w[0]/2) - (s.d.container.outerHeight(true)/2),
|
| 592 | vc = (w[1]/2) - (s.d.container.outerWidth(true)/2),
|
| 593 | st = s.d.container.css('position') !== 'fixed' ? wndw.scrollTop() : 0;
|
| 594 |
|
| 595 | if (s.o.position && Object.prototype.toString.call(s.o.position) === '[object Array]') {
|
| 596 | top = st + (s.o.position[0] || hc);
|
| 597 | left = s.o.position[1] || vc;
|
| 598 | } else {
|
| 599 | top = st + hc;
|
| 600 | left = vc;
|
| 601 | }
|
| 602 | s.d.container.css({left: left, top: top});
|
| 603 | },
|
| 604 | watchTab: function (e) {
|
| 605 | var s = this;
|
| 606 |
|
| 607 | if ($(e.target).parents('.simplemodal-container').length > 0) {
|
| 608 | // save the list of inputs
|
| 609 | s.inputs = $(':input:enabled:visible:first, :input:enabled:visible:last', s.d.data[0]);
|
| 610 |
|
| 611 | // if it's the first or last tabbable element, refocus
|
| 612 | if ((!e.shiftKey && e.target === s.inputs[s.inputs.length -1]) ||
|
| 613 | (e.shiftKey && e.target === s.inputs[0]) ||
|
| 614 | s.inputs.length === 0) {
|
| 615 | e.preventDefault();
|
| 616 | var pos = e.shiftKey ? 'last' : 'first';
|
| 617 | s.focus(pos);
|
| 618 | }
|
| 619 | }
|
| 620 | else {
|
| 621 | // might be necessary when custom onShow callback is used
|
| 622 | e.preventDefault();
|
| 623 | s.focus();
|
| 624 | }
|
| 625 | },
|
| 626 | /*
|
| 627 | * Open the modal dialog elements
|
| 628 | * - Note: If you use the onOpen callback, you must "show" the
|
| 629 | * overlay and container elements manually
|
| 630 | * (the iframe will be handled by SimpleModal)
|
| 631 | */
|
| 632 | open: function () {
|
| 633 | var s = this;
|
| 634 | // display the iframe
|
| 635 | s.d.iframe && s.d.iframe.show();
|
| 636 |
|
| 637 | if ($.isFunction(s.o.onOpen)) {
|
| 638 | // execute the onOpen callback
|
| 639 | s.o.onOpen.apply(s, [s.d]);
|
| 640 | }
|
| 641 | else {
|
| 642 | // display the remaining elements
|
| 643 | s.d.overlay.show();
|
| 644 | s.d.container.show();
|
| 645 | s.d.data.show();
|
| 646 | }
|
| 647 |
|
| 648 | s.o.focus && s.focus();
|
| 649 |
|
| 650 | // bind default events
|
| 651 | s.bindEvents();
|
| 652 | },
|
| 653 | /*
|
| 654 | * Close the modal dialog
|
| 655 | * - Note: If you use an onClose callback, you must remove the
|
| 656 | * overlay, container and iframe elements manually
|
| 657 | *
|
| 658 | * @param {boolean} external Indicates whether the call to this
|
| 659 | * function was internal or external. If it was external, the
|
| 660 | * onClose callback will be ignored
|
| 661 | */
|
| 662 | close: function () {
|
| 663 | var s = this;
|
| 664 |
|
| 665 | // prevent close when dialog does not exist
|
| 666 | if (!s.d.data) {
|
| 667 | return false;
|
| 668 | }
|
| 669 |
|
| 670 | // remove the default events
|
| 671 | s.unbindEvents();
|
| 672 |
|
| 673 | if ($.isFunction(s.o.onClose) && !s.occb) {
|
| 674 | // set the onClose callback flag
|
| 675 | s.occb = true;
|
| 676 |
|
| 677 | // execute the onClose callback
|
| 678 | s.o.onClose.apply(s, [s.d]);
|
| 679 | }
|
| 680 | else {
|
| 681 | // if the data came from the DOM, put it back
|
| 682 | if (s.d.placeholder) {
|
| 683 | var ph = $('#simplemodal-placeholder');
|
| 684 | // save changes to the data?
|
| 685 | if (s.o.persist) {
|
| 686 | // insert the (possibly) modified data back into the DOM
|
| 687 | ph.replaceWith(s.d.data.removeClass('simplemodal-data').css('display', s.display));
|
| 688 | }
|
| 689 | else {
|
| 690 | // remove the current and insert the original,
|
| 691 | // unmodified data back into the DOM
|
| 692 | s.d.data.hide().remove();
|
| 693 | ph.replaceWith(s.d.orig);
|
| 694 | }
|
| 695 | }
|
| 696 | else {
|
| 697 | // otherwise, remove it
|
| 698 | s.d.data.hide().remove();
|
| 699 | }
|
| 700 |
|
| 701 | // remove the remaining elements
|
| 702 | s.d.container.hide().remove();
|
| 703 | s.d.overlay.hide();
|
| 704 | s.d.iframe && s.d.iframe.hide().remove();
|
| 705 | s.d.overlay.remove();
|
| 706 |
|
| 707 | // reset the dialog object
|
| 708 | s.d = {};
|
| 709 | }
|
| 710 | }
|
| 711 | };
|
| 712 | }));
|