2 * Copyright (c)2005-2009 Matt Kruse (javascripttoolbox.com)
4 * Dual licensed under the MIT and GPL licenses.
5 * This basically means you can use this code however you want for
6 * free, but don't claim to have written it yourself!
7 * Donations always accepted: http://www.JavascriptToolbox.com/donate/
9 * Please do not link to the .js files on javascripttoolbox.com from
10 * your site. Copy the files locally to your server instead.
13 /* ******************************************************************* */
15 /* ******************************************************************* */
16 var Util = {'$VERSION':1.06};
18 // Util functions - these are GLOBAL so they
19 // look like built-in functions.
21 // Determine if an object is an array
23 return (o!=null && typeof(o)=="object" && typeof(o.length)=="number" && (o.length==0 || defined(o[0])));
26 // Determine if an object is an Object
27 function isObject(o) {
28 return (o!=null && typeof(o)=="object" && defined(o.constructor) && o.constructor==Object && !defined(o.nodeName));
31 // Determine if a reference is defined
33 return (typeof(o)!="undefined");
36 // Iterate over an array, object, or list of items and run code against each item
37 // Similar functionality to Perl's map() function
41 if (typeof(func)=="string") {
42 func = new Function('$_',func);
44 for (i=1; i<arguments.length; i++) {
47 for (j=0; j<o.length; j++) {
48 results[results.length] = func(o[j]);
51 else if (isObject(o)) {
53 results[results.length] = func(o[j]);
57 results[results.length] = func(o);
63 // Set default values in an object if they are undefined
64 function setDefaultValues(o,values) {
65 if (!defined(o) || o==null) {
68 if (!defined(values) || values==null) {
71 for (var val in values) {
72 if (!defined(o[val])) {
79 /* ******************************************************************* */
80 /* DEFAULT OBJECT PROTOTYPE ENHANCEMENTS */
81 /* ******************************************************************* */
82 // These functions add useful functionality to built-in objects
83 Array.prototype.contains = function(o) {
85 if (!(l = this.length)) { return false; }
93 /* ******************************************************************* */
95 /* ******************************************************************* */
96 var DOM = (function() {
99 // Get a parent tag with a given nodename
100 dom.getParentByTagName = function(o,tagNames) {
101 if(o==null) { return null; }
102 if (isArray(tagNames)) {
103 tagNames = map("return $_.toUpperCase()",tagNames);
104 while (o=o.parentNode) {
105 if (o.nodeName && tagNames.contains(o.nodeName)) {
111 tagNames = tagNames.toUpperCase();
112 while (o=o.parentNode) {
113 if (o.nodeName && tagNames==o.nodeName) {
121 // Remove a node from its parent
122 dom.removeNode = function(o) {
123 if (o!=null && o.parentNode && o.parentNode.removeChild) {
124 // First remove all attributes which are func references, to avoid memory leaks
126 if (typeof(o[i])=="function") {
130 o.parentNode.removeChild(o);
136 // Get the outer width in pixels of an object, including borders, padding, and margin
137 dom.getOuterWidth = function(o) {
138 if (defined(o.offsetWidth)) {
139 return o.offsetWidth;
144 // Get the outer height in pixels of an object, including borders, padding, and margin
145 dom.getOuterHeight = function(o) {
146 if (defined(o.offsetHeight)) {
147 return o.offsetHeight;
152 // Resolve an item, an array of items, or an object of items
153 dom.resolve = function() {
154 var results = new Array();
156 for (var i=0; i<arguments.length; i++) {
157 var o = arguments[i];
159 if (arguments.length==1) {
162 results[results.length] = null;
164 else if (typeof(o)=='string') {
165 if (document.getElementById) {
166 o = document.getElementById(o);
168 else if (document.all) {
171 if (arguments.length==1) {
174 results[results.length] = o;
176 else if (isArray(o)) {
177 for (j=0; j<o.length; j++) {
178 results[results.length] = o[j];
181 else if (isObject(o)) {
183 results[results.length] = o[j];
186 else if (arguments.length==1) {
190 results[results.length] = o;
200 /* ******************************************************************* */
202 /* ******************************************************************* */
203 var CSS = (function(){
206 // Convert an RGB string in the form "rgb (255, 255, 255)" to "#ffffff"
207 css.rgb2hex = function(rgbString) {
208 if (typeof(rgbString)!="string" || !defined(rgbString.match)) { return null; }
209 var result = rgbString.match(/^\s*rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*/);
210 if (result==null) { return rgbString; }
211 var rgb = +result[1] << 16 | +result[2] << 8 | +result[3];
213 var digits = "0123456789abcdef";
215 hex = digits.charAt(rgb&0xf)+hex;
218 while(hex.length<6) { hex='0'+hex; }
222 // Convert hyphen style names like border-width to camel case like borderWidth
223 css.hyphen2camel = function(property) {
224 if (!defined(property) || property==null) { return null; }
225 if (property.indexOf("-")<0) { return property; }
228 var l = property.length;
229 for (var i=0; i<l; i++) {
230 c = property.charAt(i);
231 str += (c!="-")?c:property.charAt(++i).toUpperCase();
236 // Determine if an object or class string contains a given class.
237 css.hasClass = function(obj,className) {
238 if (!defined(obj) || obj==null || !RegExp) { return false; }
239 var re = new RegExp("(^|\\s)" + className + "(\\s|$)");
240 if (typeof(obj)=="string") {
243 else if (typeof(obj)=="object" && obj.className) {
244 return re.test(obj.className);
249 // Add a class to an object
250 css.addClass = function(obj,className) {
251 if (typeof(obj)!="object" || obj==null || !defined(obj.className)) { return false; }
252 if (obj.className==null || obj.className=='') {
253 obj.className = className;
256 if (css.hasClass(obj,className)) { return true; }
257 obj.className = obj.className + " " + className;
261 // Remove a class from an object
262 css.removeClass = function(obj,className) {
263 if (typeof(obj)!="object" || obj==null || !defined(obj.className) || obj.className==null) { return false; }
264 if (!css.hasClass(obj,className)) { return false; }
265 var re = new RegExp("(^|\\s+)" + className + "(\\s+|$)");
266 obj.className = obj.className.replace(re,' ');
270 // Fully replace a class with a new one
271 css.replaceClass = function(obj,className,newClassName) {
272 if (typeof(obj)!="object" || obj==null || !defined(obj.className) || obj.className==null) { return false; }
273 css.removeClass(obj,className);
274 css.addClass(obj,newClassName);
278 // Get the currently-applied style of an object
279 css.getStyle = function(o, property) {
280 if (o==null) { return null; }
282 var camelProperty = css.hyphen2camel(property);
283 // Handle "float" property as a special case
284 if (property=="float") {
285 val = css.getStyle(o,"cssFloat");
287 val = css.getStyle(o,"styleFloat");
290 else if (o.currentStyle && defined(o.currentStyle[camelProperty])) {
291 val = o.currentStyle[camelProperty];
293 else if (window.getComputedStyle) {
294 val = window.getComputedStyle(o,null).getPropertyValue(property);
296 else if (o.style && defined(o.style[camelProperty])) {
297 val = o.style[camelProperty];
299 // For color values, make the value consistent across browsers
300 // Convert rgb() colors back to hex for consistency
301 if (/^\s*rgb\s*\(/.test(val)) {
302 val = css.rgb2hex(val);
304 // Lowercase all #hex values
305 if (/^#/.test(val)) {
306 val = val.toLowerCase();
310 css.get = css.getStyle;
312 // Set a style on an object
313 css.setStyle = function(o, property, value) {
314 if (o==null || !defined(o.style) || !defined(property) || property==null || !defined(value)) { return false; }
315 if (property=="float") {
316 o.style["cssFloat"] = value;
317 o.style["styleFloat"] = value;
319 else if (property=="opacity") {
320 o.style['-moz-opacity'] = value;
321 o.style['-khtml-opacity'] = value;
322 o.style.opacity = value;
323 if (defined(o.style.filter)) {
324 o.style.filter = "alpha(opacity=" + value*100 + ")";
328 o.style[css.hyphen2camel(property)] = value;
332 css.set = css.setStyle;
334 // Get a unique ID which doesn't already exist on the page
335 css.uniqueIdNumber=1000;
336 css.createId = function(o) {
337 if (defined(o) && o!=null && defined(o.id) && o.id!=null && o.id!="") {
341 while (id==null || document.getElementById(id)!=null) {
342 id = "ID_"+(css.uniqueIdNumber++);
344 if (defined(o) && o!=null && (!defined(o.id)||o.id=="")) {
353 /* ******************************************************************* */
354 /* EVENT FUNCTIONS */
355 /* ******************************************************************* */
357 var Event = (function(){
360 // Resolve an event using IE's window.event if necessary
361 // --------------------------------------------------------------------
362 ev.resolve = function(e) {
363 if (!defined(e) && defined(window.event)) {
369 // Add an event handler to a function
370 // Note: Don't use 'this' within functions added using this method, since
371 // the attachEvent and addEventListener models differ.
372 // --------------------------------------------------------------------
373 ev.add = function( obj, type, fn, capture ) {
374 if (obj.addEventListener) {
375 obj.addEventListener( type, fn, capture );
378 else if (obj.attachEvent) {
379 obj.attachEvent( "on"+type, fn );
385 // Get the mouse position of an event
386 // --------------------------------------------------------------------
387 // PageX/Y, where they exist, are more reliable than ClientX/Y because
388 // of some browser bugs in Opera/Safari
389 ev.getMouseX = function(e) {
391 if (defined(e.pageX)) {
394 if (defined(e.clientX)) {
395 return e.clientX+Screen.getScrollLeft();
399 ev.getMouseY = function(e) {
401 if (defined(e.pageY)) {
404 if (defined(e.clientY)) {
405 return e.clientY+Screen.getScrollTop();
410 // Stop the event from bubbling up to parent elements.
411 // Two method names map to the same function
412 // --------------------------------------------------------------------
413 ev.cancelBubble = function(e) {
415 if (typeof(e.stopPropagation)=="function") { e.stopPropagation(); }
416 if (defined(e.cancelBubble)) { e.cancelBubble = true; }
418 ev.stopPropagation = ev.cancelBubble;
420 // Prevent the default handling of the event to occur
421 // --------------------------------------------------------------------
422 ev.preventDefault = function(e) {
424 if (typeof(e.preventDefault)=="function") { e.preventDefault(); }
425 if (defined(e.returnValue)) { e.returnValue = false; }
431 /* ******************************************************************* */
432 /* SCREEN FUNCTIONS */
433 /* ******************************************************************* */
434 var Screen = (function() {
437 // Get a reference to the body
438 // --------------------------------------------------------------------
439 screen.getBody = function() {
441 return document.body;
443 if (document.getElementsByTagName) {
444 var bodies = document.getElementsByTagName("BODY");
445 if (bodies!=null && bodies.length>0) {
452 // Get the amount that the main document has scrolled from top
453 // --------------------------------------------------------------------
454 screen.getScrollTop = function() {
455 if (document.documentElement && defined(document.documentElement.scrollTop) && document.documentElement.scrollTop>0) {
456 return document.documentElement.scrollTop;
458 if (document.body && defined(document.body.scrollTop)) {
459 return document.body.scrollTop;
464 // Get the amount that the main document has scrolled from left
465 // --------------------------------------------------------------------
466 screen.getScrollLeft = function() {
467 if (document.documentElement && defined(document.documentElement.scrollLeft) && document.documentElement.scrollLeft>0) {
468 return document.documentElement.scrollLeft;
470 if (document.body && defined(document.body.scrollLeft)) {
471 return document.body.scrollLeft;
476 // Util function to default a bad number to 0
477 // --------------------------------------------------------------------
478 screen.zero = function(n) {
479 return (!defined(n) || isNaN(n))?0:n;
482 // Get the width of the entire document
483 // --------------------------------------------------------------------
484 screen.getDocumentWidth = function() {
486 var body = screen.getBody();
487 if (document.documentElement && (!document.compatMode || document.compatMode=="CSS1Compat")) {
488 var rightMargin = parseInt(CSS.get(body,'marginRight'),10) || 0;
489 var leftMargin = parseInt(CSS.get(body,'marginLeft'), 10) || 0;
490 width = Math.max(body.offsetWidth + leftMargin + rightMargin, document.documentElement.clientWidth);
493 width = Math.max(body.clientWidth, body.scrollWidth);
495 if (isNaN(width) || width==0) {
496 width = screen.zero(self.innerWidth);
501 // Get the height of the entire document
502 // --------------------------------------------------------------------
503 screen.getDocumentHeight = function() {
504 var body = screen.getBody();
505 var innerHeight = (defined(self.innerHeight)&&!isNaN(self.innerHeight))?self.innerHeight:0;
506 if (document.documentElement && (!document.compatMode || document.compatMode=="CSS1Compat")) {
507 var topMargin = parseInt(CSS.get(body,'marginTop'),10) || 0;
508 var bottomMargin = parseInt(CSS.get(body,'marginBottom'), 10) || 0;
509 return Math.max(body.offsetHeight + topMargin + bottomMargin, document.documentElement.clientHeight, document.documentElement.scrollHeight, screen.zero(self.innerHeight));
511 return Math.max(body.scrollHeight, body.clientHeight, screen.zero(self.innerHeight));
514 // Get the width of the viewport (viewable area) in the browser window
515 // --------------------------------------------------------------------
516 screen.getViewportWidth = function() {
517 if (document.documentElement && (!document.compatMode || document.compatMode=="CSS1Compat")) {
518 return document.documentElement.clientWidth;
520 else if (document.compatMode && document.body) {
521 return document.body.clientWidth;
523 return screen.zero(self.innerWidth);
526 // Get the height of the viewport (viewable area) in the browser window
527 // --------------------------------------------------------------------
528 screen.getViewportHeight = function() {
529 if (!window.opera && document.documentElement && (!document.compatMode || document.compatMode=="CSS1Compat")) {
530 return document.documentElement.clientHeight;
532 else if (document.compatMode && !window.opera && document.body) {
533 return document.body.clientHeight;
535 return screen.zero(self.innerHeight);
539 })();var Sort = (function(){
541 sort.AlphaNumeric = function(a,b) {
542 if (a==b) { return 0; }
543 if (a<b) { return -1; }
547 sort.Default = sort.AlphaNumeric;
549 sort.NumericConversion = function(val) {
550 if (typeof(val)!="number") {
551 if (typeof(val)=="string") {
552 val = parseFloat(val.replace(/,/g,''));
553 if (isNaN(val) || val==null) { val=0; }
562 sort.Numeric = function(a,b) {
563 return sort.NumericConversion(a)-sort.NumericConversion(b);
566 sort.IgnoreCaseConversion = function(val) {
567 if (val==null) { val=""; }
568 return (""+val).toLowerCase();
571 sort.IgnoreCase = function(a,b) {
572 return sort.AlphaNumeric(sort.IgnoreCaseConversion(a),sort.IgnoreCaseConversion(b));
575 sort.CurrencyConversion = function(val) {
576 if (typeof(val)=="string") {
577 val = val.replace(/^[^\d\.]/,'');
579 return sort.NumericConversion(val);
582 sort.Currency = function(a,b) {
583 return sort.Numeric(sort.CurrencyConversion(a),sort.CurrencyConversion(b));
586 sort.DateConversion = function(val) {
587 // inner util function to parse date formats
588 function getdate(str) {
589 // inner util function to convert 2-digit years to 4
590 function fixYear(yr) {
592 if (yr<50) { yr += 2000; }
593 else if (yr<100) { yr += 1900; }
598 if (ret=str.match(/(\d{2,4})-(\d{1,2})-(\d{1,2})/)) {
599 return (fixYear(ret[1])*10000) + (ret[2]*100) + (+ret[3]);
601 // MM/DD/YY[YY] or MM-DD-YY[YY]
602 if (ret=str.match(/(\d{1,2})[\/-](\d{1,2})[\/-](\d{2,4})/)) {
603 return (fixYear(ret[3])*10000) + (ret[1]*100) + (+ret[2]);
605 return 99999999; // So non-parsed dates will be last, not first
610 sort.Date = function(a,b) {
611 return sort.Numeric(sort.DateConversion(a),sort.DateConversion(b));
617 var Position = (function() {
618 // Resolve a string identifier to an object
619 // ========================================
620 function resolveObject(s) {
621 if (document.getElementById && document.getElementById(s)!=null) {
622 return document.getElementById(s);
624 else if (document.all && document.all[s]!=null) {
625 return document.all[s];
627 else if (document.anchors && document.anchors.length && document.anchors.length>0 && document.anchors[0].x) {
628 for (var i=0; i<document.anchors.length; i++) {
629 if (document.anchors[i].name==s) {
630 return document.anchors[i]
639 // Set the position of an object
640 // =============================
641 pos.set = function(o,left,top) {
642 if (typeof(o)=="string") {
643 o = resolveObject(o);
645 if (o==null || !o.style) {
649 // If the second parameter is an object, it is assumed to be the result of getPosition()
650 if (typeof(left)=="object") {
656 o.style.left = left + "px";
657 o.style.top = top + "px";
661 // Retrieve the position and size of an object
662 // ===========================================
663 pos.get = function(o) {
664 var fixBrowserQuirks = true;
665 // If a string is passed in instead of an object ref, resolve it
666 if (typeof(o)=="string") {
667 o = resolveObject(o);
678 var parentNode = null;
679 var offsetParent = null;
682 offsetParent = o.offsetParent;
683 var originalObject = o;
684 var el = o; // "el" will be nodes as we walk up, "o" will be saved for offsetParent references
685 while (el.parentNode!=null) {
687 if (el.offsetParent==null) {
690 var considerScroll = true;
692 In Opera, if parentNode of the first object is scrollable, then offsetLeft/offsetTop already
693 take its scroll position into account. If elements further up the chain are scrollable, their
694 scroll offsets still need to be added in. And for some reason, TR nodes have a scrolltop value
695 which must be ignored.
697 if (fixBrowserQuirks && window.opera) {
698 if (el==originalObject.parentNode || el.nodeName=="TR") {
699 considerScroll = false;
702 if (considerScroll) {
703 if (el.scrollTop && el.scrollTop>0) {
706 if (el.scrollLeft && el.scrollLeft>0) {
707 left -= el.scrollLeft;
711 // If this node is also the offsetParent, add on the offsets and reset to the new offsetParent
712 if (el == offsetParent) {
713 left += o.offsetLeft;
714 if (el.clientLeft && el.nodeName!="TABLE") {
715 left += el.clientLeft;
718 if (el.clientTop && el.nodeName!="TABLE") {
722 if (o.offsetParent==null) {
724 left += o.offsetLeft;
730 offsetParent = o.offsetParent;
735 if (originalObject.offsetWidth) {
736 width = originalObject.offsetWidth;
738 if (originalObject.offsetHeight) {
739 height = originalObject.offsetHeight;
742 return {'left':left, 'top':top, 'width':width, 'height':height
746 // Retrieve the position of an object's center point
747 // =================================================
748 pos.getCenter = function(o) {
750 if (c==null) { return null; }
751 c.left = c.left + (c.width/2);
752 c.top = c.top + (c.height/2);
757 })();// CLASS CONSTRUCTOR
758 // --------------------------------------------------------------------
759 var Popup = function(div, options) {
760 this.div = defined(div)?div:null;
761 this.index = Popup.maxIndex++;
762 this.ref = "Popup.objects["+this.index+"]";
763 Popup.objects[this.index] = this;
764 // Store a reference to the DIV by id, also
765 if (typeof(this.div)=="string") {
766 Popup.objectsById[this.div] = this;
768 if (defined(this.div) && this.div!=null && defined(this.div.id)) {
769 Popup.objectsById[this.div.id] = this.div.id;
771 // Apply passed-in options
772 if (defined(options) && options!=null && typeof(options)=="object") {
773 for (var i in options) {
774 this[i] = options[i];
781 // --------------------------------------------------------------------
782 // Index of popup objects, to maintain a global reference if necessary
785 Popup.objectsById = {};
787 // The z-index value that popups will start at
788 Popup.minZIndex = 101;
790 // Class names to assign to other objects
791 Popup.screenClass = "PopupScreen";
792 Popup.iframeClass = "PopupIframe";
793 Popup.screenIframeClass = "PopupScreenIframe";
796 // --------------------------------------------------------------------
798 // Hide all currently-visible non-modal dialogs
799 Popup.hideAll = function() {
800 for (var i in Popup.objects) {
801 var p = Popup.objects[i];
802 if (!p.modal && p.autoHide) {
807 // Catch global events as a trigger to hide auto-hide popups
808 Event.add(document, "mouseup", Popup.hideAll, false);
810 // A simple class method to show a popup without creating an instance
811 Popup.show = function(divObject, referenceObject, position, options, modal) {
813 if (defined(divObject)) {
814 popup = new Popup(divObject);
818 popup.destroyDivOnHide = true;
820 if (defined(referenceObject)) { popup.reference = DOM.resolve(referenceObject); }
821 if (defined(position)) { popup.position = position; }
822 if (defined(options) && options!=null && typeof(options)=="object") {
823 for (var i in options) {
824 popup[i] = options[i];
827 if (typeof(modal)=="boolean") {
830 popup.destroyObjectsOnHide = true;
835 // A simple class method to show a modal popup
836 Popup.showModal = function(divObject, referenceObject, position, options) {
837 Popup.show(divObject, referenceObject, position, options, true);
840 // A method to retrieve a popup object based on a div ID
841 Popup.get = function(divId) {
842 if (defined(Popup.objectsById[divId])) {
843 return Popup.objectsById[divId];
848 // A method to hide a popup based on a div id
849 Popup.hide = function(divId) {
850 var popup = Popup.get(divId);
856 // PROTOTYPE PROPERTIES
857 // --------------------------------------------------------------------
858 Popup.prototype.content = null;
859 Popup.prototype.className = "PopupDiv";
860 Popup.prototype.style = null; // Styles to be applied to the DIV
861 Popup.prototype.width = null;
862 Popup.prototype.height = null;
863 Popup.prototype.top = null;
864 Popup.prototype.left = null;
865 Popup.prototype.offsetLeft = 0;
866 Popup.prototype.offsetTop = 0;
867 Popup.prototype.constrainToScreen = true;
868 Popup.prototype.autoHide = true;
869 Popup.prototype.useIframeShim = false; /*@cc_on @*/ /*@if (@_win32) {Popup.prototype.useIframeShim = true;} @end @*/
870 Popup.prototype.iframe = null;
871 Popup.prototype.position = null; // vertical: "above top center bottom below", horizontal: "adjacent-left,left,center,right,adjacent-right"
872 Popup.prototype.reference = null;
873 Popup.prototype.modal = false;
874 Popup.prototype.destroyDivOnHide = false;
875 Popup.prototype.destroyObjectsOnHide = false;
876 Popup.prototype.screen = null;
877 Popup.prototype.screenIframeShim = null;
878 Popup.prototype.screenOpacity=.4;
879 Popup.prototype.screenColor="#cccccc";
882 // --------------------------------------------------------------------
885 // --------------------------------------------------------------------
886 Popup.prototype.show = function(options, modal) {
887 this.modal = this.modal || (typeof(modal)=="boolean" && modal);
888 if (defined(options) && options!=null && typeof(options)=="object") {
889 for (var i in options) {
890 this[i] = options[i];
893 this.div = DOM.resolve(this.div);
894 CSS.setStyle(this.div,'position','absolute');
896 // If there is no div pre-defined to use, create one
897 if (this.div==null) {
898 this.div = this.createDiv();
900 if (this.content!=null) {
901 this.div.innerHTML = this.content;
904 if (this.className!=null) {
905 this.div.className = this.className;
907 if (this.style!=null) {
910 if (this.width!=null) {
911 this.div.style.width = this.width+"px";
912 this.div.style.overflowX="auto";
914 if (this.height!=null) {
915 this.div.style.height = this.height+"px";
916 this.div.style.overflowY="auto";
919 // Do the actual display - this is a separate method so display transitions can be implemented
922 // Make sure clicks on the DIV don't bubble up to the document
923 this.div.onclick = function(e) {
924 Event.cancelBubble(Event.resolve(e));
926 this.div.onmouseup = this.div.onclick;
928 // Focus to the DIV if possible
929 if (this.modal && this.div.focus) {
934 // Show the popup but make it modal
935 // --------------------------------------------------------------------
936 Popup.prototype.transition = function() {
941 // Make the DIV displayed but hidden so its size can be measured
942 CSS.setStyle(this.div,'visibility','hidden');
943 CSS.setStyle(this.div,'display','block');
945 // Position the popup
948 // Add the shim if necessary
949 if (this.useIframeShim) {
950 this.addIframeShim();
953 // Make sure the DIV is higher than the shim
954 this.div.style.zIndex = Popup.minZIndex++;
956 CSS.setStyle(this.div,'display','block');
957 CSS.setStyle(this.div,'visibility','visible');
960 // Show the popup but make it modal
961 // --------------------------------------------------------------------
962 Popup.prototype.showModal = function(options) {
963 this.show(options,true);
966 // Apply user styles to the DIV
967 // --------------------------------------------------------------------
968 Popup.prototype.applyStyle = function() {
969 if (this.div!=null && this.style!=null && typeof(this.style)=="object") {
970 for (var i in this.style) {
971 this.div.style[i] = this.style[i];
977 // --------------------------------------------------------------------
978 Popup.prototype.hide = function() {
979 // If this was a temp object creating on-the-fly, then remove objects from the DOM so
980 // The document doesn't get littered with extra objects
981 if (this.destroyDivOnHide) {
982 DOM.removeNode(this.div);
984 delete Popup.objects[this.id];
986 else if (this.div!=null) {
987 CSS.setStyle(this.div,'display','none');
990 if (this.destroyObjectsOnHide) {
991 DOM.removeNode(this.iframe);
992 DOM.removeNode(this.screen);
993 DOM.removeNode(this.screenIframeShim);
996 if (this.iframe!=null) {
997 this.iframe.style.display = "none";
999 if (this.screen!=null) {
1000 this.screen.style.display = "none";
1002 if (this.screenIframeShim!=null) {
1003 this.screenIframeShim.style.display = "none";
1008 // Util funcs for position
1009 // --------------------------------------------------------------------
1010 Popup.prototype.setTop = function(top) {
1011 this.div.style.top = top+"px";
1013 Popup.prototype.setLeft = function(left) {
1014 this.div.style.left = left+"px";
1016 Popup.prototype.getTop = function() {
1017 return parseInt(CSS.getStyle(this.div,"top"),10);
1019 Popup.prototype.getLeft = function() {
1020 return parseInt(CSS.getStyle(this.div,"left"),10);
1023 // All the logic to position the popup based on various criteria
1024 // --------------------------------------------------------------------
1025 Popup.prototype.setPosition = function() {
1026 if (this.position!=null) {
1027 var m = this.position.match(/^(\S+)\s+(\S+)/);
1028 if (m!=null && m.length==3) {
1032 var ref = this.reference;
1033 if (ref==null) { ref = Screen.getBody(); }
1034 var p = Position.get(ref);
1036 var refLeft = p.left;
1037 var refWidth = DOM.getOuterWidth(ref);
1038 var refHeight = DOM.getOuterHeight(ref);
1040 var width = DOM.getOuterWidth(this.div);
1041 var height = DOM.getOuterHeight(this.div);
1043 var scrollLeft = Screen.getScrollLeft();
1044 var scrollTop = Screen.getScrollTop();
1046 // Set vertical position relative to reference object
1047 if (v=="above") { this.setTop(refTop-height+this.offsetTop); }
1048 else if (v=="top") { this.setTop(refTop+this.offsetTop); }
1049 else if (v=="center") { this.setTop(refTop+(refHeight/2)-(height/2)+this.offsetTop); }
1050 else if (v=="bottom") { this.setTop(refTop+refHeight-height+this.offsetTop); }
1051 else if (v=="below") { this.setTop(refTop+refHeight+this.offsetTop); }
1053 // Set horizontal position relative to reference object
1054 if (h=="adjacent-left") { this.setLeft(refLeft-width+this.offsetLeft); }
1055 else if (h=="left") { this.setLeft(refLeft+this.offsetLeft); }
1056 else if (h=="center") { this.setLeft(refLeft+(refWidth/2)-(width/2)+this.offsetLeft); }
1057 else if (h=="right") { this.setLeft(refLeft+refWidth-width+this.offsetLeft); }
1058 else if (h=="adjacent-right") { this.setLeft(refLeft+refWidth+this.offsetLeft); }
1061 else if (this.top==null && this.left==null) {
1065 if (this.top==null) { this.top=0; }
1066 if (this.left==null) { this.left=0; }
1067 this.div.style.top = this.top+this.offsetTop+"px";
1068 this.div.style.left = this.left+this.offsetLeft+"px";
1071 // Re-position to make sure it stays on the screen
1072 if (this.constrainToScreen) {
1077 // Append an object to the body
1078 // --------------------------------------------------------------------
1079 Popup.prototype.appendToBody = function(o) {
1080 var body = Screen.getBody();
1081 if (body && body.appendChild) {
1082 body.appendChild(o);
1086 // Create a new DIV object to be used for a popup
1087 // --------------------------------------------------------------------
1088 Popup.prototype.createDiv = function() {
1089 if (document.createElement) {
1090 var d = document.createElement("DIV");
1091 d.style.position="absolute";
1092 d.style.display="block";
1093 d.style.visibility="hidden";
1094 this.appendToBody(d);
1097 alert("ERROR: Couldn't create DIV element in Popup.prototype.createDiv()");
1101 // Create a new IFRAME object to be used behind the popup
1102 // --------------------------------------------------------------------
1103 Popup.prototype.createIframe = function() {
1104 if (document.createElement) {
1105 var i= document.createElement("IFRAME");
1106 i.style.position="absolute";
1107 i.style.display="block";
1108 i.style.visibility="hidden";
1109 i.style.background="none";
1110 this.appendToBody(i);
1114 alert("ERROR: Couldn't create IFRAME object in Popup.prototype.createIframe()");
1118 // Add an IFRAME shim for the DIV
1119 // --------------------------------------------------------------------
1120 Popup.prototype.addIframeShim = function() {
1121 if (this.iframe==null) {
1122 this.iframe = this.createIframe();
1124 this.iframe.className = Popup.iframeClass;
1125 CSS.setStyle(this.iframe,'top',this.getTop()+"px");
1126 CSS.setStyle(this.iframe,'left',this.getLeft()+"px");
1127 CSS.setStyle(this.iframe,'width',DOM.getOuterWidth(this.div) + "px");
1128 CSS.setStyle(this.iframe,'height',DOM.getOuterHeight(this.div) + "px");
1129 CSS.setStyle(this.iframe,'zIndex',Popup.minZIndex++);
1130 CSS.setStyle(this.iframe,'opacity',0);
1131 CSS.setStyle(this.iframe,'visibility','visible');
1132 CSS.setStyle(this.iframe,'display','block');
1135 // Create a "screen" to make a popup modal
1136 // --------------------------------------------------------------------
1137 Popup.prototype.addScreen = function() {
1138 if (this.screen==null) {
1139 this.screen = this.createDiv();
1140 this.screen.style.top="0px";
1141 this.screen.style.left="0px";
1142 this.screen.style.backgroundColor = this.screenColor;
1143 this.screen.className=Popup.screenClass;;
1144 CSS.setStyle(this.screen,"opacity",this.screenOpacity);
1145 this.screen.onclick = function(e) { Event.cancelBubble(Event.resolve(e)); }
1147 if (this.screenIframeShim==null) {
1148 this.screenIframeShim = this.createIframe();
1149 this.screenIframeShim.style.top="0px";
1150 this.screenIframeShim.style.left="0px";
1151 this.screenIframeShim.className=Popup.screenIframeClass;
1152 CSS.setStyle(this.screenIframeShim,"opacity",0);
1154 this.screen.style.width = Screen.getDocumentWidth()+"px";
1155 this.screen.style.height = Screen.getDocumentHeight()+"px";
1156 this.screenIframeShim.style.width = Screen.getDocumentWidth()+"px";
1157 this.screenIframeShim.style.height = Screen.getDocumentHeight()+"px";
1158 this.screenIframeShim.style.zIndex = Popup.minZIndex++;
1159 this.screenIframeShim.style.visibility="visible";
1160 this.screenIframeShim.style.display="block";
1161 this.screen.style.zIndex = Popup.minZIndex++;
1162 this.screen.style.visibility="visible";
1163 this.screen.style.display="block";
1166 // Re-position the DIV so it stays on the screen
1167 // --------------------------------------------------------------------
1168 Popup.prototype.fitToScreen = function() {
1169 var width = DOM.getOuterWidth(this.div);
1170 var height = DOM.getOuterHeight(this.div);
1171 var top = this.getTop();
1172 var left = this.getLeft();
1174 var clientWidth = Screen.getViewportWidth();
1175 var clientHeight = Screen.getViewportHeight();
1177 var scrollLeft = Screen.getScrollLeft();
1178 var scrollTop = Screen.getScrollTop();
1180 if (top-scrollTop+height>clientHeight) {
1181 top = top - ((top+height) - (scrollTop+clientHeight));
1182 this.div.style.top = top + "px";
1184 if (left-scrollLeft+width>clientWidth) {
1185 left = left - ((left+width) - (scrollLeft+clientWidth));
1186 this.div.style.left = left + "px";
1188 if (top<scrollTop) {
1189 this.div.style.top=scrollTop+"px";
1191 if (left<scrollLeft) {
1192 this.div.style.left=scrollLeft+"px";
1196 // Center the DIV object
1197 // --------------------------------------------------------------------
1198 Popup.prototype.center = function() {
1199 var left = DOM.getOuterWidth(this.div);
1200 var top = DOM.getOuterHeight(this.div);
1201 if (isNaN(left)) { left=0; }
1202 if (isNaN(top)) { top=0; }
1203 var clientW = Screen.getViewportWidth();
1204 var clientH = Screen.getViewportHeight();
1205 if (clientW!=null && clientH!=null) {
1206 top = (clientH-top)/2;
1207 left = (clientW-left)/2;
1209 top += Screen.getScrollTop();
1210 left += Screen.getScrollLeft();
1212 this.div.style.top = top+this.offsetTop+"px";
1213 this.div.style.left = left+this.offsetLeft+"px";