|
1 /** |
|
2 * Copyright (c)2005-2009 Matt Kruse (javascripttoolbox.com) |
|
3 * |
|
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/ |
|
8 * |
|
9 * Please do not link to the .js files on javascripttoolbox.com from |
|
10 * your site. Copy the files locally to your server instead. |
|
11 * |
|
12 */ |
|
13 /* ******************************************************************* */ |
|
14 /* UTIL FUNCTIONS */ |
|
15 /* ******************************************************************* */ |
|
16 var Util = {'$VERSION':1.06}; |
|
17 |
|
18 // Util functions - these are GLOBAL so they |
|
19 // look like built-in functions. |
|
20 |
|
21 // Determine if an object is an array |
|
22 function isArray(o) { |
|
23 return (o!=null && typeof(o)=="object" && typeof(o.length)=="number" && (o.length==0 || defined(o[0]))); |
|
24 }; |
|
25 |
|
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)); |
|
29 }; |
|
30 |
|
31 // Determine if a reference is defined |
|
32 function defined(o) { |
|
33 return (typeof(o)!="undefined"); |
|
34 }; |
|
35 |
|
36 // Iterate over an array, object, or list of items and run code against each item |
|
37 // Similar functionality to Perl's map() function |
|
38 function map(func) { |
|
39 var i,j,o; |
|
40 var results = []; |
|
41 if (typeof(func)=="string") { |
|
42 func = new Function('$_',func); |
|
43 } |
|
44 for (i=1; i<arguments.length; i++) { |
|
45 o = arguments[i]; |
|
46 if (isArray(o)) { |
|
47 for (j=0; j<o.length; j++) { |
|
48 results[results.length] = func(o[j]); |
|
49 } |
|
50 } |
|
51 else if (isObject(o)) { |
|
52 for (j in o) { |
|
53 results[results.length] = func(o[j]); |
|
54 } |
|
55 } |
|
56 else { |
|
57 results[results.length] = func(o); |
|
58 } |
|
59 } |
|
60 return results; |
|
61 }; |
|
62 |
|
63 // Set default values in an object if they are undefined |
|
64 function setDefaultValues(o,values) { |
|
65 if (!defined(o) || o==null) { |
|
66 o = {}; |
|
67 } |
|
68 if (!defined(values) || values==null) { |
|
69 return o; |
|
70 } |
|
71 for (var val in values) { |
|
72 if (!defined(o[val])) { |
|
73 o[val] = values[val]; |
|
74 } |
|
75 } |
|
76 return o; |
|
77 }; |
|
78 |
|
79 /* ******************************************************************* */ |
|
80 /* DEFAULT OBJECT PROTOTYPE ENHANCEMENTS */ |
|
81 /* ******************************************************************* */ |
|
82 // These functions add useful functionality to built-in objects |
|
83 Array.prototype.contains = function(o) { |
|
84 var i,l; |
|
85 if (!(l = this.length)) { return false; } |
|
86 for (i=0; i<l; i++) { |
|
87 if (o==this[i]) { |
|
88 return true; |
|
89 } |
|
90 } |
|
91 }; |
|
92 |
|
93 /* ******************************************************************* */ |
|
94 /* DOM FUNCTIONS */ |
|
95 /* ******************************************************************* */ |
|
96 var DOM = (function() { |
|
97 var dom = {}; |
|
98 |
|
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)) { |
|
106 return o; |
|
107 } |
|
108 } |
|
109 } |
|
110 else { |
|
111 tagNames = tagNames.toUpperCase(); |
|
112 while (o=o.parentNode) { |
|
113 if (o.nodeName && tagNames==o.nodeName) { |
|
114 return o; |
|
115 } |
|
116 } |
|
117 } |
|
118 return null; |
|
119 }; |
|
120 |
|
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 |
|
125 for (var i in o) { |
|
126 if (typeof(o[i])=="function") { |
|
127 o[i] = null; |
|
128 } |
|
129 } |
|
130 o.parentNode.removeChild(o); |
|
131 return true; |
|
132 } |
|
133 return false; |
|
134 }; |
|
135 |
|
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; |
|
140 } |
|
141 return null; |
|
142 }; |
|
143 |
|
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; |
|
148 } |
|
149 return null; |
|
150 }; |
|
151 |
|
152 // Resolve an item, an array of items, or an object of items |
|
153 dom.resolve = function() { |
|
154 var results = new Array(); |
|
155 var i,j,o; |
|
156 for (var i=0; i<arguments.length; i++) { |
|
157 var o = arguments[i]; |
|
158 if (o==null) { |
|
159 if (arguments.length==1) { |
|
160 return null; |
|
161 } |
|
162 results[results.length] = null; |
|
163 } |
|
164 else if (typeof(o)=='string') { |
|
165 if (document.getElementById) { |
|
166 o = document.getElementById(o); |
|
167 } |
|
168 else if (document.all) { |
|
169 o = document.all[o]; |
|
170 } |
|
171 if (arguments.length==1) { |
|
172 return o; |
|
173 } |
|
174 results[results.length] = o; |
|
175 } |
|
176 else if (isArray(o)) { |
|
177 for (j=0; j<o.length; j++) { |
|
178 results[results.length] = o[j]; |
|
179 } |
|
180 } |
|
181 else if (isObject(o)) { |
|
182 for (j in o) { |
|
183 results[results.length] = o[j]; |
|
184 } |
|
185 } |
|
186 else if (arguments.length==1) { |
|
187 return o; |
|
188 } |
|
189 else { |
|
190 results[results.length] = o; |
|
191 } |
|
192 } |
|
193 return results; |
|
194 }; |
|
195 dom.$ = dom.resolve; |
|
196 |
|
197 return dom; |
|
198 })(); |
|
199 |
|
200 /* ******************************************************************* */ |
|
201 /* CSS FUNCTIONS */ |
|
202 /* ******************************************************************* */ |
|
203 var CSS = (function(){ |
|
204 var css = {}; |
|
205 |
|
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]; |
|
212 var hex = ""; |
|
213 var digits = "0123456789abcdef"; |
|
214 while(rgb!=0) { |
|
215 hex = digits.charAt(rgb&0xf)+hex; |
|
216 rgb>>>=4; |
|
217 } |
|
218 while(hex.length<6) { hex='0'+hex; } |
|
219 return "#" + hex; |
|
220 }; |
|
221 |
|
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; } |
|
226 var str = ""; |
|
227 var c = null; |
|
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(); |
|
232 } |
|
233 return str; |
|
234 }; |
|
235 |
|
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") { |
|
241 return re.test(obj); |
|
242 } |
|
243 else if (typeof(obj)=="object" && obj.className) { |
|
244 return re.test(obj.className); |
|
245 } |
|
246 return false; |
|
247 }; |
|
248 |
|
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; |
|
254 return true; |
|
255 } |
|
256 if (css.hasClass(obj,className)) { return true; } |
|
257 obj.className = obj.className + " " + className; |
|
258 return true; |
|
259 }; |
|
260 |
|
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,' '); |
|
267 return true; |
|
268 }; |
|
269 |
|
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); |
|
275 return true; |
|
276 }; |
|
277 |
|
278 // Get the currently-applied style of an object |
|
279 css.getStyle = function(o, property) { |
|
280 if (o==null) { return null; } |
|
281 var val = 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"); |
|
286 if (val==null) { |
|
287 val = css.getStyle(o,"styleFloat"); |
|
288 } |
|
289 } |
|
290 else if (o.currentStyle && defined(o.currentStyle[camelProperty])) { |
|
291 val = o.currentStyle[camelProperty]; |
|
292 } |
|
293 else if (window.getComputedStyle) { |
|
294 val = window.getComputedStyle(o,null).getPropertyValue(property); |
|
295 } |
|
296 else if (o.style && defined(o.style[camelProperty])) { |
|
297 val = o.style[camelProperty]; |
|
298 } |
|
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); |
|
303 } |
|
304 // Lowercase all #hex values |
|
305 if (/^#/.test(val)) { |
|
306 val = val.toLowerCase(); |
|
307 } |
|
308 return val; |
|
309 }; |
|
310 css.get = css.getStyle; |
|
311 |
|
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; |
|
318 } |
|
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 + ")"; |
|
325 } |
|
326 } |
|
327 else { |
|
328 o.style[css.hyphen2camel(property)] = value; |
|
329 } |
|
330 return true; |
|
331 }; |
|
332 css.set = css.setStyle; |
|
333 |
|
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!="") { |
|
338 return o.id; |
|
339 } |
|
340 var id = null; |
|
341 while (id==null || document.getElementById(id)!=null) { |
|
342 id = "ID_"+(css.uniqueIdNumber++); |
|
343 } |
|
344 if (defined(o) && o!=null && (!defined(o.id)||o.id=="")) { |
|
345 o.id = id; |
|
346 } |
|
347 return id; |
|
348 }; |
|
349 |
|
350 return css; |
|
351 })(); |
|
352 |
|
353 /* ******************************************************************* */ |
|
354 /* EVENT FUNCTIONS */ |
|
355 /* ******************************************************************* */ |
|
356 |
|
357 var Event = (function(){ |
|
358 var ev = {}; |
|
359 |
|
360 // Resolve an event using IE's window.event if necessary |
|
361 // -------------------------------------------------------------------- |
|
362 ev.resolve = function(e) { |
|
363 if (!defined(e) && defined(window.event)) { |
|
364 e = window.event; |
|
365 } |
|
366 return e; |
|
367 }; |
|
368 |
|
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 ); |
|
376 return true; |
|
377 } |
|
378 else if (obj.attachEvent) { |
|
379 obj.attachEvent( "on"+type, fn ); |
|
380 return true; |
|
381 } |
|
382 return false; |
|
383 }; |
|
384 |
|
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) { |
|
390 e = ev.resolve(e); |
|
391 if (defined(e.pageX)) { |
|
392 return e.pageX; |
|
393 } |
|
394 if (defined(e.clientX)) { |
|
395 return e.clientX+Screen.getScrollLeft(); |
|
396 } |
|
397 return null; |
|
398 }; |
|
399 ev.getMouseY = function(e) { |
|
400 e = ev.resolve(e); |
|
401 if (defined(e.pageY)) { |
|
402 return e.pageY; |
|
403 } |
|
404 if (defined(e.clientY)) { |
|
405 return e.clientY+Screen.getScrollTop(); |
|
406 } |
|
407 return null; |
|
408 }; |
|
409 |
|
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) { |
|
414 e = ev.resolve(e); |
|
415 if (typeof(e.stopPropagation)=="function") { e.stopPropagation(); } |
|
416 if (defined(e.cancelBubble)) { e.cancelBubble = true; } |
|
417 }; |
|
418 ev.stopPropagation = ev.cancelBubble; |
|
419 |
|
420 // Prevent the default handling of the event to occur |
|
421 // -------------------------------------------------------------------- |
|
422 ev.preventDefault = function(e) { |
|
423 e = ev.resolve(e); |
|
424 if (typeof(e.preventDefault)=="function") { e.preventDefault(); } |
|
425 if (defined(e.returnValue)) { e.returnValue = false; } |
|
426 }; |
|
427 |
|
428 return ev; |
|
429 })(); |
|
430 |
|
431 /* ******************************************************************* */ |
|
432 /* SCREEN FUNCTIONS */ |
|
433 /* ******************************************************************* */ |
|
434 var Screen = (function() { |
|
435 var screen = {}; |
|
436 |
|
437 // Get a reference to the body |
|
438 // -------------------------------------------------------------------- |
|
439 screen.getBody = function() { |
|
440 if (document.body) { |
|
441 return document.body; |
|
442 } |
|
443 if (document.getElementsByTagName) { |
|
444 var bodies = document.getElementsByTagName("BODY"); |
|
445 if (bodies!=null && bodies.length>0) { |
|
446 return bodies[0]; |
|
447 } |
|
448 } |
|
449 return null; |
|
450 }; |
|
451 |
|
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; |
|
457 } |
|
458 if (document.body && defined(document.body.scrollTop)) { |
|
459 return document.body.scrollTop; |
|
460 } |
|
461 return null; |
|
462 }; |
|
463 |
|
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; |
|
469 } |
|
470 if (document.body && defined(document.body.scrollLeft)) { |
|
471 return document.body.scrollLeft; |
|
472 } |
|
473 return null; |
|
474 }; |
|
475 |
|
476 // Util function to default a bad number to 0 |
|
477 // -------------------------------------------------------------------- |
|
478 screen.zero = function(n) { |
|
479 return (!defined(n) || isNaN(n))?0:n; |
|
480 }; |
|
481 |
|
482 // Get the width of the entire document |
|
483 // -------------------------------------------------------------------- |
|
484 screen.getDocumentWidth = function() { |
|
485 var width = 0; |
|
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); |
|
491 } |
|
492 else { |
|
493 width = Math.max(body.clientWidth, body.scrollWidth); |
|
494 } |
|
495 if (isNaN(width) || width==0) { |
|
496 width = screen.zero(self.innerWidth); |
|
497 } |
|
498 return width; |
|
499 }; |
|
500 |
|
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)); |
|
510 } |
|
511 return Math.max(body.scrollHeight, body.clientHeight, screen.zero(self.innerHeight)); |
|
512 }; |
|
513 |
|
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; |
|
519 } |
|
520 else if (document.compatMode && document.body) { |
|
521 return document.body.clientWidth; |
|
522 } |
|
523 return screen.zero(self.innerWidth); |
|
524 }; |
|
525 |
|
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; |
|
531 } |
|
532 else if (document.compatMode && !window.opera && document.body) { |
|
533 return document.body.clientHeight; |
|
534 } |
|
535 return screen.zero(self.innerHeight); |
|
536 }; |
|
537 |
|
538 return screen; |
|
539 })();var Sort = (function(){ |
|
540 var sort = {}; |
|
541 sort.AlphaNumeric = function(a,b) { |
|
542 if (a==b) { return 0; } |
|
543 if (a<b) { return -1; } |
|
544 return 1; |
|
545 }; |
|
546 |
|
547 sort.Default = sort.AlphaNumeric; |
|
548 |
|
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; } |
|
554 } |
|
555 else { |
|
556 val = 0; |
|
557 } |
|
558 } |
|
559 return val; |
|
560 }; |
|
561 |
|
562 sort.Numeric = function(a,b) { |
|
563 return sort.NumericConversion(a)-sort.NumericConversion(b); |
|
564 }; |
|
565 |
|
566 sort.IgnoreCaseConversion = function(val) { |
|
567 if (val==null) { val=""; } |
|
568 return (""+val).toLowerCase(); |
|
569 }; |
|
570 |
|
571 sort.IgnoreCase = function(a,b) { |
|
572 return sort.AlphaNumeric(sort.IgnoreCaseConversion(a),sort.IgnoreCaseConversion(b)); |
|
573 }; |
|
574 |
|
575 sort.CurrencyConversion = function(val) { |
|
576 if (typeof(val)=="string") { |
|
577 val = val.replace(/^[^\d\.]/,''); |
|
578 } |
|
579 return sort.NumericConversion(val); |
|
580 }; |
|
581 |
|
582 sort.Currency = function(a,b) { |
|
583 return sort.Numeric(sort.CurrencyConversion(a),sort.CurrencyConversion(b)); |
|
584 }; |
|
585 |
|
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) { |
|
591 yr = +yr; |
|
592 if (yr<50) { yr += 2000; } |
|
593 else if (yr<100) { yr += 1900; } |
|
594 return yr; |
|
595 }; |
|
596 var ret; |
|
597 // YYYY-MM-DD |
|
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]); |
|
600 } |
|
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]); |
|
604 } |
|
605 return 99999999; // So non-parsed dates will be last, not first |
|
606 }; |
|
607 return getdate(val); |
|
608 }; |
|
609 |
|
610 sort.Date = function(a,b) { |
|
611 return sort.Numeric(sort.DateConversion(a),sort.DateConversion(b)); |
|
612 }; |
|
613 |
|
614 return sort; |
|
615 })(); |
|
616 |
|
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); |
|
623 } |
|
624 else if (document.all && document.all[s]!=null) { |
|
625 return document.all[s]; |
|
626 } |
|
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] |
|
631 } |
|
632 } |
|
633 } |
|
634 } |
|
635 |
|
636 var pos = {}; |
|
637 pos.$VERSION = 1.0; |
|
638 |
|
639 // Set the position of an object |
|
640 // ============================= |
|
641 pos.set = function(o,left,top) { |
|
642 if (typeof(o)=="string") { |
|
643 o = resolveObject(o); |
|
644 } |
|
645 if (o==null || !o.style) { |
|
646 return false; |
|
647 } |
|
648 |
|
649 // If the second parameter is an object, it is assumed to be the result of getPosition() |
|
650 if (typeof(left)=="object") { |
|
651 var pos = left; |
|
652 left = pos.left; |
|
653 top = pos.top; |
|
654 } |
|
655 |
|
656 o.style.left = left + "px"; |
|
657 o.style.top = top + "px"; |
|
658 return true; |
|
659 }; |
|
660 |
|
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); |
|
668 } |
|
669 |
|
670 if (o==null) { |
|
671 return null; |
|
672 } |
|
673 |
|
674 var left = 0; |
|
675 var top = 0; |
|
676 var width = 0; |
|
677 var height = 0; |
|
678 var parentNode = null; |
|
679 var offsetParent = null; |
|
680 |
|
681 |
|
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) { |
|
686 el = el.parentNode; |
|
687 if (el.offsetParent==null) { |
|
688 } |
|
689 else { |
|
690 var considerScroll = true; |
|
691 /* |
|
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. |
|
696 */ |
|
697 if (fixBrowserQuirks && window.opera) { |
|
698 if (el==originalObject.parentNode || el.nodeName=="TR") { |
|
699 considerScroll = false; |
|
700 } |
|
701 } |
|
702 if (considerScroll) { |
|
703 if (el.scrollTop && el.scrollTop>0) { |
|
704 top -= el.scrollTop; |
|
705 } |
|
706 if (el.scrollLeft && el.scrollLeft>0) { |
|
707 left -= el.scrollLeft; |
|
708 } |
|
709 } |
|
710 } |
|
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; |
|
716 } |
|
717 top += o.offsetTop; |
|
718 if (el.clientTop && el.nodeName!="TABLE") { |
|
719 top += el.clientTop; |
|
720 } |
|
721 o = el; |
|
722 if (o.offsetParent==null) { |
|
723 if (o.offsetLeft) { |
|
724 left += o.offsetLeft; |
|
725 } |
|
726 if (o.offsetTop) { |
|
727 top += o.offsetTop; |
|
728 } |
|
729 } |
|
730 offsetParent = o.offsetParent; |
|
731 } |
|
732 } |
|
733 |
|
734 |
|
735 if (originalObject.offsetWidth) { |
|
736 width = originalObject.offsetWidth; |
|
737 } |
|
738 if (originalObject.offsetHeight) { |
|
739 height = originalObject.offsetHeight; |
|
740 } |
|
741 |
|
742 return {'left':left, 'top':top, 'width':width, 'height':height |
|
743 }; |
|
744 }; |
|
745 |
|
746 // Retrieve the position of an object's center point |
|
747 // ================================================= |
|
748 pos.getCenter = function(o) { |
|
749 var c = this.get(o); |
|
750 if (c==null) { return null; } |
|
751 c.left = c.left + (c.width/2); |
|
752 c.top = c.top + (c.height/2); |
|
753 return c; |
|
754 }; |
|
755 |
|
756 return pos; |
|
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; |
|
767 } |
|
768 if (defined(this.div) && this.div!=null && defined(this.div.id)) { |
|
769 Popup.objectsById[this.div.id] = this.div.id; |
|
770 } |
|
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]; |
|
775 } |
|
776 } |
|
777 return this; |
|
778 }; |
|
779 |
|
780 // CLASS PROPERTIES |
|
781 // -------------------------------------------------------------------- |
|
782 // Index of popup objects, to maintain a global reference if necessary |
|
783 Popup.maxIndex = 0; |
|
784 Popup.objects = {}; |
|
785 Popup.objectsById = {}; |
|
786 |
|
787 // The z-index value that popups will start at |
|
788 Popup.minZIndex = 101; |
|
789 |
|
790 // Class names to assign to other objects |
|
791 Popup.screenClass = "PopupScreen"; |
|
792 Popup.iframeClass = "PopupIframe"; |
|
793 Popup.screenIframeClass = "PopupScreenIframe"; |
|
794 |
|
795 // CLASS METHODS |
|
796 // -------------------------------------------------------------------- |
|
797 |
|
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) { |
|
803 p.hide(); |
|
804 } |
|
805 } |
|
806 }; |
|
807 // Catch global events as a trigger to hide auto-hide popups |
|
808 Event.add(document, "mouseup", Popup.hideAll, false); |
|
809 |
|
810 // A simple class method to show a popup without creating an instance |
|
811 Popup.show = function(divObject, referenceObject, position, options, modal) { |
|
812 var popup; |
|
813 if (defined(divObject)) { |
|
814 popup = new Popup(divObject); |
|
815 } |
|
816 else { |
|
817 popup = new Popup(); |
|
818 popup.destroyDivOnHide = true; |
|
819 } |
|
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]; |
|
825 } |
|
826 } |
|
827 if (typeof(modal)=="boolean") { |
|
828 popup.modal = modal; |
|
829 } |
|
830 popup.destroyObjectsOnHide = true; |
|
831 popup.show(); |
|
832 return popup; |
|
833 }; |
|
834 |
|
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); |
|
838 }; |
|
839 |
|
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]; |
|
844 } |
|
845 return null; |
|
846 }; |
|
847 |
|
848 // A method to hide a popup based on a div id |
|
849 Popup.hide = function(divId) { |
|
850 var popup = Popup.get(divId); |
|
851 if (popup!=null) { |
|
852 popup.hide(); |
|
853 } |
|
854 }; |
|
855 |
|
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"; |
|
880 |
|
881 // INSTANCE METHODS |
|
882 // -------------------------------------------------------------------- |
|
883 |
|
884 // Show the popup |
|
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]; |
|
891 } |
|
892 } |
|
893 this.div = DOM.resolve(this.div); |
|
894 CSS.setStyle(this.div,'position','absolute'); |
|
895 |
|
896 // If there is no div pre-defined to use, create one |
|
897 if (this.div==null) { |
|
898 this.div = this.createDiv(); |
|
899 } |
|
900 if (this.content!=null) { |
|
901 this.div.innerHTML = this.content; |
|
902 this.content = null; |
|
903 } |
|
904 if (this.className!=null) { |
|
905 this.div.className = this.className; |
|
906 } |
|
907 if (this.style!=null) { |
|
908 this.applyStyle(); |
|
909 } |
|
910 if (this.width!=null) { |
|
911 this.div.style.width = this.width+"px"; |
|
912 this.div.style.overflowX="auto"; |
|
913 } |
|
914 if (this.height!=null) { |
|
915 this.div.style.height = this.height+"px"; |
|
916 this.div.style.overflowY="auto"; |
|
917 } |
|
918 |
|
919 // Do the actual display - this is a separate method so display transitions can be implemented |
|
920 this.transition(); |
|
921 |
|
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)); |
|
925 }; |
|
926 this.div.onmouseup = this.div.onclick; |
|
927 |
|
928 // Focus to the DIV if possible |
|
929 if (this.modal && this.div.focus) { |
|
930 this.div.focus(); |
|
931 } |
|
932 }; |
|
933 |
|
934 // Show the popup but make it modal |
|
935 // -------------------------------------------------------------------- |
|
936 Popup.prototype.transition = function() { |
|
937 if (this.modal) { |
|
938 this.addScreen(); |
|
939 } |
|
940 |
|
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'); |
|
944 |
|
945 // Position the popup |
|
946 this.setPosition(); |
|
947 |
|
948 // Add the shim if necessary |
|
949 if (this.useIframeShim) { |
|
950 this.addIframeShim(); |
|
951 } |
|
952 |
|
953 // Make sure the DIV is higher than the shim |
|
954 this.div.style.zIndex = Popup.minZIndex++; |
|
955 |
|
956 CSS.setStyle(this.div,'display','block'); |
|
957 CSS.setStyle(this.div,'visibility','visible'); |
|
958 }; |
|
959 |
|
960 // Show the popup but make it modal |
|
961 // -------------------------------------------------------------------- |
|
962 Popup.prototype.showModal = function(options) { |
|
963 this.show(options,true); |
|
964 }; |
|
965 |
|
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]; |
|
972 } |
|
973 } |
|
974 }; |
|
975 |
|
976 // Hide the popup |
|
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); |
|
983 this.div = null; |
|
984 delete Popup.objects[this.id]; |
|
985 } |
|
986 else if (this.div!=null) { |
|
987 CSS.setStyle(this.div,'display','none'); |
|
988 } |
|
989 |
|
990 if (this.destroyObjectsOnHide) { |
|
991 DOM.removeNode(this.iframe); |
|
992 DOM.removeNode(this.screen); |
|
993 DOM.removeNode(this.screenIframeShim); |
|
994 } |
|
995 else { |
|
996 if (this.iframe!=null) { |
|
997 this.iframe.style.display = "none"; |
|
998 } |
|
999 if (this.screen!=null) { |
|
1000 this.screen.style.display = "none"; |
|
1001 } |
|
1002 if (this.screenIframeShim!=null) { |
|
1003 this.screenIframeShim.style.display = "none"; |
|
1004 } |
|
1005 } |
|
1006 }; |
|
1007 |
|
1008 // Util funcs for position |
|
1009 // -------------------------------------------------------------------- |
|
1010 Popup.prototype.setTop = function(top) { |
|
1011 this.div.style.top = top+"px"; |
|
1012 }; |
|
1013 Popup.prototype.setLeft = function(left) { |
|
1014 this.div.style.left = left+"px"; |
|
1015 }; |
|
1016 Popup.prototype.getTop = function() { |
|
1017 return parseInt(CSS.getStyle(this.div,"top"),10); |
|
1018 }; |
|
1019 Popup.prototype.getLeft = function() { |
|
1020 return parseInt(CSS.getStyle(this.div,"left"),10); |
|
1021 }; |
|
1022 |
|
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) { |
|
1029 var v = m[1]; |
|
1030 var h = m[2]; |
|
1031 |
|
1032 var ref = this.reference; |
|
1033 if (ref==null) { ref = Screen.getBody(); } |
|
1034 var p = Position.get(ref); |
|
1035 var refTop = p.top; |
|
1036 var refLeft = p.left; |
|
1037 var refWidth = DOM.getOuterWidth(ref); |
|
1038 var refHeight = DOM.getOuterHeight(ref); |
|
1039 |
|
1040 var width = DOM.getOuterWidth(this.div); |
|
1041 var height = DOM.getOuterHeight(this.div); |
|
1042 |
|
1043 var scrollLeft = Screen.getScrollLeft(); |
|
1044 var scrollTop = Screen.getScrollTop(); |
|
1045 |
|
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); } |
|
1052 |
|
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); } |
|
1059 } |
|
1060 } |
|
1061 else if (this.top==null && this.left==null) { |
|
1062 this.center(); |
|
1063 } |
|
1064 else { |
|
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"; |
|
1069 } |
|
1070 |
|
1071 // Re-position to make sure it stays on the screen |
|
1072 if (this.constrainToScreen) { |
|
1073 this.fitToScreen(); |
|
1074 } |
|
1075 }; |
|
1076 |
|
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); |
|
1083 } |
|
1084 }; |
|
1085 |
|
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); |
|
1095 return d; |
|
1096 } |
|
1097 alert("ERROR: Couldn't create DIV element in Popup.prototype.createDiv()"); |
|
1098 return null; |
|
1099 }; |
|
1100 |
|
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); |
|
1111 return i; |
|
1112 } |
|
1113 else { |
|
1114 alert("ERROR: Couldn't create IFRAME object in Popup.prototype.createIframe()"); |
|
1115 } |
|
1116 }; |
|
1117 |
|
1118 // Add an IFRAME shim for the DIV |
|
1119 // -------------------------------------------------------------------- |
|
1120 Popup.prototype.addIframeShim = function() { |
|
1121 if (this.iframe==null) { |
|
1122 this.iframe = this.createIframe(); |
|
1123 } |
|
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'); |
|
1133 }; |
|
1134 |
|
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)); } |
|
1146 } |
|
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); |
|
1153 } |
|
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"; |
|
1164 }; |
|
1165 |
|
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(); |
|
1173 |
|
1174 var clientWidth = Screen.getViewportWidth(); |
|
1175 var clientHeight = Screen.getViewportHeight(); |
|
1176 |
|
1177 var scrollLeft = Screen.getScrollLeft(); |
|
1178 var scrollTop = Screen.getScrollTop(); |
|
1179 |
|
1180 if (top-scrollTop+height>clientHeight) { |
|
1181 top = top - ((top+height) - (scrollTop+clientHeight)); |
|
1182 this.div.style.top = top + "px"; |
|
1183 } |
|
1184 if (left-scrollLeft+width>clientWidth) { |
|
1185 left = left - ((left+width) - (scrollLeft+clientWidth)); |
|
1186 this.div.style.left = left + "px"; |
|
1187 } |
|
1188 if (top<scrollTop) { |
|
1189 this.div.style.top=scrollTop+"px"; |
|
1190 } |
|
1191 if (left<scrollLeft) { |
|
1192 this.div.style.left=scrollLeft+"px"; |
|
1193 } |
|
1194 }; |
|
1195 |
|
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; |
|
1208 } |
|
1209 top += Screen.getScrollTop(); |
|
1210 left += Screen.getScrollLeft(); |
|
1211 |
|
1212 this.div.style.top = top+this.offsetTop+"px"; |
|
1213 this.div.style.left = left+this.offsetLeft+"px"; |
|
1214 }; |
|
1215 |