1/**
2 * iBox 2.2 (Build 1612)
3 * For more info & download: http://www.ibegin.com/labs/ibox/
4 * Created as a part of the iBegin Labs Project - http://www.ibegin.com/labs/
5 * For licensing please see readme.html (MIT Open Source License)
6*/
7var iBox = function() {
8	var _pub = {
9		// label for the close link
10		close_label: 'Close',
11
12		// show iframed content in the parent window
13		// this *does not* work with #containers
14		inherit_frames: false,
15
16		// how fast to fade in the overlay/ibox (this is each step in ms)
17		fade_in_speed: 300,
18		fade_out_speed: 300,
19
20		// our attribute identifier for our iBox elements
21		attribute_name: 'rel',
22
23		// tags to hide when we show our box
24		tags_to_hide: ['select', 'embed', 'object'],
25
26		// default width of the box (when displaying html only)
27		// height is calculated automatically
28		default_width: 450,
29
30		// public version number
31		version_number: '2.2',
32		// internal build number
33		build_number: '1612',
34
35		// browser checks
36		is_opera: navigator.userAgent.indexOf('Opera/9') != -1,
37		is_ie: navigator.userAgent.indexOf("MSIE ") != -1,
38		is_ie6: false /*@cc_on || @_jscript_version < 5.7 @*/,
39		is_firefox: navigator.appName == "Netscape" && navigator.userAgent.indexOf("Gecko") != -1 && navigator.userAgent.indexOf("Netscape") == -1,
40		is_mac: navigator.userAgent.indexOf('Macintosh') != -1,
41
42		// url for including images/external files
43		base_url: '',
44
45		/**
46		 * Updates the base_url variable.
47		 * @param {String} path Relative or absolute path to this file.
48		 */
49		setPath: function(path) {
50			_pub.base_url = path;
51		},
52
53		/**
54		 * Checks a container for specified tags containing rel="ibox"
55		 * @param {Object} container
56		 * @param {String} tag_name
57		 */
58		checkTags: function(container, tag_name) {
59			if (!container) var container = document.body;
60			if (!tag_name) var tag_name = 'a';
61			var els = container.getElementsByTagName(tag_name);
62			for (var i=0; i<els.length; i++) {
63				if (els[i].getAttribute(_pub.attribute_name)) {
64					var t = els[i].getAttribute(_pub.attribute_name);
65					if ((t.indexOf("ibox") != -1) || t.toLowerCase() == "ibox") { // check if this element is an iBox element
66						els[i].onclick = _pub.handleTag;
67					}
68				}
69			}
70		},
71
72		/**
73		 * Binds arguments to a callback function
74		 */
75		bind: function(fn) {
76				var args = [];
77				for (var n=1; n<arguments.length; n++) args.push(arguments[n]);
78				return function(e) { return fn.apply(this, [e].concat(args)); };
79		},
80
81		/**
82		 * Sets the content of the ibox
83		 * @param {String} content HTML content
84		 * @param {Object} params
85		 */
86		html: function(content, params) {
87			if (content === undefined) return els.content;
88			if (params === undefined) var params = {};
89			if (!active.is_loaded) return;
90			_pub.clear();
91
92			_pub.updateObject(els.wrapper.style, {display: 'block', visibility: 'hidden', left: 0, top: 0, height: '', width: ''});
93
94			if (typeof(content) == 'string') els.content.innerHTML = content;
95			else els.content.appendChild(content);
96
97			var pagesize = _pub.getPageSize();
98
99			if (params.can_resize === undefined) params.can_resize = true;
100			if (params.fade_in === undefined) params.use_fade = true;
101
102			if (params.fullscreen) {
103				params.width = '100%';
104				params.height = '100%';
105			}
106
107			// reset offsets
108			offset.container = [els.wrapper.offsetLeft*2, els.wrapper.offsetTop*2];
109			offset.wrapper = [els.wrapper.offsetWidth-els.content.offsetWidth, els.wrapper.offsetHeight-els.content.offsetHeight];
110
111			// TODO: remove the +4 when issue is solved with calculations
112			offset.wrapper[1] += 4;
113
114			if (params.width) var width = params.width;
115			else var width = _pub.default_width;
116
117			if (params.height) var height = params.height;
118			else {
119				els.content.style.height = '100%';
120				var height = els.content.offsetHeight + 12;
121				els.content.style.height = '';
122			}
123			active.dimensions = [width, height];
124			active.params = params;
125			_pub.reposition();
126
127			// XXX: Fix for inline containers which had elements that were hidden
128			for (var i=0; i<_pub.tags_to_hide.length; i++) {
129				showTags(_pub.tags_to_hide[i], els.content);
130			}
131
132			els.wrapper.style.visibility = 'visible';
133		},
134
135		/**
136		 * Empties the content of the iBox (also hides the loading indicator)
137		 */
138		clear: function() {
139			els.loading.style.display = "none";
140			while (els.content.firstChild) els.content.removeChild(els.content.firstChild);
141		},
142
143		/**
144		 * Loads text into the ibox
145		 * @param {String} text
146		 * @param {String} title
147		 * @param {Object} params
148		 */
149		show: function(text, title, params) {
150			showInit(title, params, function() {
151				_pub.html(text, active.params);
152			});
153		},
154		/**
155		 * Loads a url into the ibox
156		 * @param {String} url
157		 * @param {String} title
158		 * @param {Object} params
159		 */
160		showURL: function(url, title, params) {
161			showInit(title, params, function() {
162				for (var i=0; i<_pub.plugins.list.length; i++) {
163					var plugin = _pub.plugins.list[i];
164					if (plugin.match(url)) {
165						active.plugin = plugin;
166						plugin.render(url, active.params);
167						break;
168					}
169				}
170			});
171		},
172
173		/**
174		 * Hides the iBox
175		 */
176		hide: function() {
177			if (active.plugin) {
178				// call the plugins unload method
179				if (active.plugin.unload) active.plugin.unload();
180			}
181			active = {}
182			_pub.clear();
183			// restore elements that were hidden
184			for (var i=0; i<_pub.tags_to_hide.length; i++) showTags(_pub.tags_to_hide[i]);
185
186			els.loading.style.display = 'none';
187			els.wrapper.style.display = 'none';
188			_pub.fade(els.overlay, _pub.getOpacity(null, els.overlay), 0, _pub.fade_out_speed, function() { els.overlay.style.display = 'none';});
189			_pub.fireEvent('hide');
190		},
191
192		/**
193		 * Repositions the iBox wrapper based on the params set originally.
194		 */
195		reposition: function() {
196			if (!active.is_loaded) return;
197
198			// center loading box
199			if (els.loading.style.display != 'none') _pub.center(els.loading);
200
201			// update ibox width/height/position
202			if (active.dimensions) {
203				var pagesize = _pub.getPageSize();
204
205				var width = active.dimensions[0];
206				var height = active.dimensions[1];
207
208				if (height.toString().indexOf('%') != -1) {
209					els.wrapper.style.height = (Math.max(document.documentElement.clientHeight, document.body.clientHeight, pagesize.height) - offset.container[0])*(parseInt(height)/100) + 'px';
210				}
211				else if (height) {
212					els.content.style.height = height + 'px';
213					// TODO: if we dont set wrapper height, it doesnt restrict the height and the box is fine
214					// so offset.wrapper[1] must not be correct
215					els.wrapper.style.height = els.content.offsetHeight + offset.wrapper[1] + 'px';
216				}
217				else {
218					els.wrapper.style.height = els.content.offsetHeight + offset.wrapper[1] + 'px';
219				}
220				var container_offset = (els.content.offsetHeight - els.content.firstChild.offsetHeight);
221				if (width.toString().indexOf('%') != -1) {
222					els.wrapper.style.width = (Math.max(document.documentElement.clientWidth, document.body.clientWidth, pagesize.width) - offset.container[1])*(parseInt(width)/100) + 'px';
223					var container_offset = 0;
224				}
225				else {
226					els.content.style.width = width + 'px';
227					els.wrapper.style.width = els.content.offsetWidth + offset.wrapper[0] + 'px';
228				}
229
230				_pub.updateObject(els.content.style, {width: '', height: ''});
231
232				var width = parseInt(els.wrapper.style.width);
233				var height = parseInt(els.wrapper.style.height);
234
235				// if we can resize this, make sure it fits in our page bounds
236				if (active.params.can_resize) {
237					var x = pagesize.width;
238					var y = pagesize.height;
239
240					x -= offset.container[0];
241					y -= offset.container[1];
242					if (width > x) {
243						if (active.params.constrain) height = height * (x/width);
244						width = x;
245					}
246					if (height > y) {
247						if (active.params.constrain) width = width * (y/height);
248						height = y;
249					}
250					_pub.updateObject(els.wrapper.style, {width: width + 'px', height: height + 'px'});
251				}
252
253				//els.content.style.width = width - offset.wrapper[0] + 'px';
254				// TODO: this isn't adjusting to the right height for containers that are smaller than the page height
255				// resize the wrappers height based on the content boxes height
256				// this needs to be height - ibox_content[margin+padding+border]
257				els.content.style.height = height - offset.wrapper[1] + 'px';
258				if (active.dimensions != ['100%', '100%']) _pub.center(els.wrapper);
259			}
260
261			// fix overlay width/height (cant use css fixed on ie6 or fx or any
262			// browser really due to issues)
263			els.overlay.style.height = Math.max(document.body.clientHeight, document.documentElement.clientHeight) + 'px';
264		},
265
266		updateObject: function(obj, params) {
267			for (var i in params) obj[i] = params[i];
268		},
269
270		/**
271		 * Centers an object
272		 * @param {Object} obj
273		 */
274		center: function(obj) {
275			var pageSize = _pub.getPageSize();
276			var scrollPos = _pub.getScrollPos();
277			var emSize = _pub.getElementSize(obj);
278			var x = Math.round((pageSize.width - emSize.width) / 2 + scrollPos.scrollX);
279			var y = Math.round((pageSize.height - emSize.height) / 2 + scrollPos.scrollY);
280			if (obj.offsetLeft) x -= obj.offsetLeft;
281			if (obj.offsetTop) y -= obj.offsetTop;
282			if (obj.style.left) x += parseInt(obj.style.left);
283			if (obj.style.top) y += parseInt(obj.style.top);
284			// this nearly centers it due to scrollbars
285			x -= 10;
286			_pub.updateObject(obj.style, {top: y + 'px', left: x + 'px'});
287		},
288
289		getStyle: function(obj, styleProp) {
290			if (obj.currentStyle)
291				return obj.currentStyle[styleProp];
292			else if (window.getComputedStyle)
293				return document.defaultView.getComputedStyle(obj,null).getPropertyValue(styleProp);
294		},
295
296		/**
297		 * Gets the scroll positions
298		 */
299		getScrollPos: function() {
300			var docElem = document.documentElement;
301			return {
302				scrollX: document.body.scrollLeft || window.pageXOffset || (docElem && docElem.scrollLeft),
303				scrollY: document.body.scrollTop || window.pageYOffset || (docElem && docElem.scrollTop)
304			};
305		},
306
307		/**
308		 * Gets the page constraints
309		 */
310		getPageSize: function() {
311			return {
312				width: window.innerWidth || (document.documentElement && document.documentElement.clientWidth) || document.body.clientWidth,
313				height: window.innerHeight || (document.documentElement && document.documentElement.clientHeight) || document.body.clientHeight
314			};
315		},
316
317		/**
318		 * Gets an objects offsets
319		 * @param {Object} obj
320		 */
321		getElementSize: function(obj) {
322			return {
323				width: obj.offsetWidth || obj.style.pixelWidth,
324				height: obj.offsetHeight || obj.style.pixelHeight
325			};
326		},
327
328		fade: function(obj, start, end, speed, callback) {
329			if (start === undefined || !(start >= 0) || !(start <= 100)) var start = 0;
330			if (end === undefined || !(end >= 0) || !(end <= 100)) var end = 100;
331			if (speed === undefined) var speed = 0;
332
333			if (obj.fader) clearInterval(obj.fader);
334
335			if (!speed) {
336				_pub.setOpacity(null, obj, end);
337				if (callback) callback();
338			}
339
340			var opacity_difference = end - start;
341			var time_total = speed; // time is speed (jQuery compat)
342			var step_size = 25; // step size in ms
343			var steps = time_total / step_size; // total number of steps
344			var increment = Math.ceil(opacity_difference / steps); // how much to incr per step
345
346			obj.fader = setInterval(_pub.bind(function(e, obj, increment, end, callback) {
347				var opacity = _pub.getOpacity(e, obj) + increment;
348				_pub.setOpacity(e, obj, opacity);
349				if ((increment < 0 && opacity <= end) || (increment > 0 && opacity >= end)) {
350					_pub.setOpacity(e, obj, end);
351					clearInterval(obj.fader);
352					if (callback) callback();
353				}
354			}, obj, increment, end, callback), step_size);
355		},
356
357		/**
358		 * Sets the opacity of an element
359		 * @param {Object} obj
360		 * @param {Integer} value
361		 */
362		setOpacity: function(e, obj, value) {
363			value = Math.round(value);
364			obj.style.opacity = value/100;
365			obj.style.filter = 'alpha(opacity=' + value + ')';
366		},
367
368		/**
369		 * Gets the opacity of an element
370		 * @param {Object} obj
371		 * @return {Integer} value
372		 */
373		getOpacity: function(e, obj) {
374			return _pub.getStyle(obj, 'opacity')*100;
375		},
376
377		/**
378		 * Creates a new XMLHttpRequest object based on browser
379		 */
380		createXMLHttpRequest: function() {
381			var http;
382			if (window.XMLHttpRequest) { // Mozilla, Safari,...
383				http = new XMLHttpRequest();
384				if (http.overrideMimeType) {
385					// set type accordingly to anticipated content type
386					http.overrideMimeType('text/html');
387				}
388			}
389			else if (window.ActiveXObject) { // IE
390				try {
391					http = new ActiveXObject("Msxml2.XMLHTTP");
392				} catch (e) {
393					try {
394						http = new ActiveXObject("Microsoft.XMLHTTP");
395					} catch (e) {}
396				}
397			}
398			if (!http) {
399				alert('Cannot create XMLHTTP instance');
400				return false;
401			}
402			return http;
403		},
404
405		addEvent: function(obj, evType, fn) {
406			if (obj.addEventListener) {
407				obj.addEventListener(evType, fn, false);
408				return true;
409			}
410			else if (obj.attachEvent) {
411				var r = obj.attachEvent("on"+evType, fn);
412				return r;
413			}
414			else {
415				return false;
416			}
417		},
418
419		addEventListener: function(name, callback) {
420			if (!events[name]) events[name] = new Array();
421			events[name].push(callback);
422		},
423
424		/**
425		 * Causes all event listeners attached to `name` event to
426		 * execute.
427		 * @param {String} name Event name
428		 */
429		fireEvent: function(name) {
430				if (events[name] && events[name].length) {
431					for (var i=0; i<events[name].length; i++) {
432						var args = [];
433						for (var n=1; n<arguments.length; n++) args.push(arguments[n]);
434						// Events returning false stop propagation
435						if (events[name][i](args) === false) break;
436					}
437				}
438		},
439
440		/**
441		 * Parses the arguments in the rel attribute
442		 * @param {String} query
443		 */
444		parseQuery: function(query) {
445			 var params = new Object();
446			 if (!query) return params;
447			 var pairs = query.split(/[;&]/);
448			 var end_token;
449			 for (var i=0; i<pairs.length; i++) {
450					var keyval = pairs[i].split('=');
451					if (!keyval || keyval.length != 2) continue;
452					var key = unescape(keyval[0]);
453					var val = unescape(keyval[1]);
454					val = val.replace(/\+/g, ' ');
455					if (val[0] == '"') var token = '"';
456					else if (val[0] == "'") var token = "'";
457					else var token = null;
458					if (token) {
459						if (val[val.length-1] != token) {
460							do {
461								i += 1;
462								val += '&'+pairs[i];
463							}
464							while ((end_token = pairs[i][pairs[i].length-1]) != token)
465						}
466						val = val.substr(1, val.length-2);
467					}
468					if (val == 'true') val = true;
469					else if (val == 'false') val = false;
470					else if (val == 'null') val = null;
471					params[key] = val;
472			 }
473			 return params;
474		},
475		/**
476		 * Handles the onclick event for iBox anchors.
477		 * @param {Event} e
478		 */
479		handleTag: function(e) {
480			var t = this.getAttribute('rel');
481			var params = _pub.parseQuery(t.substr(5,999));
482			if (params.target) var url = params.target;
483			else if (this.target && !params.ignore_target) var url = this.target;
484			else var url = this.href;
485			var title = this.title;
486			if (_pub.inherit_frames && window.parent) window.parent.iBox.showURL(url, title, params);
487			else _pub.showURL(url, title, params);
488			return false;
489		},
490
491		plugins: {
492			list: new Array(),
493			register: function(func, last) {
494				if (last === undefined) var last = false;
495				if (!last) {
496					_pub.plugins.list = [func].concat(_pub.plugins.list);
497				}
498				else {
499					_pub.plugins.list.push(func);
500				}
501			}
502		}
503	};
504
505	// private methods and variables
506	var active = {};
507
508	// events
509	var events = {};
510
511	// some containers
512	// we store these in memory instead of finding them each time
513	var els = {};
514
515	var offset = {};
516
517	/**
518	 * Creates the iBox container and appends it to an element
519	 * @param {HTMLObject} elem Container to attach to
520	 * @return {HTMLObject} iBox element
521	 */
522	var create = function(elem) {
523		pagesize = _pub.getPageSize();
524
525		// TODO: why isnt this using DOM tools
526		// a trick on just creating an ibox wrapper then doing an innerHTML on our root ibox element
527		els.container = document.createElement('div');
528		els.container.id = 'ibox';
529
530		els.overlay = document.createElement('div');
531		els.overlay.style.display = 'none';
532		_pub.setOpacity(null, els.overlay, 0);
533		// firefox mac has issues with opacity and flash
534		if (!_pub.is_firefox) els.overlay.style.background = '#000000';
535		else els.overlay.style.backgroundImage = "url('" + _pub.base_url + "images/bg.png')";
536		els.overlay.id = 'ibox_overlay';
537		params = {position: 'absolute', top: 0, left: 0, width: '100%'};
538		_pub.updateObject(els.overlay.style, params);
539		els.overlay.onclick = _pub.hide;
540		els.container.appendChild(els.overlay);
541
542		els.loading = document.createElement('div');
543		els.loading.id = 'ibox_loading';
544		els.loading.innerHTML = 'Loading...';
545		els.loading.style.display = 'none';
546		els.loading.onclick = _pub.hide
547		els.container.appendChild(els.loading);
548
549		els.wrapper = document.createElement('div')
550		els.wrapper.id = 'ibox_wrapper';
551		_pub.updateObject(els.wrapper.style, {position: 'absolute', top: 0, left: 0, display: 'none'});
552
553		els.content = document.createElement('div');
554		els.content.id = 'ibox_content';
555		_pub.updateObject(els.content.style, {overflow: 'auto'})
556		els.wrapper.appendChild(els.content);
557
558		var child = document.createElement('div');
559		child.id = 'ibox_footer_wrapper';
560
561		var child2 = document.createElement('a');
562		child2.innerHTML = _pub.close_label;
563		child2.href = 'javascript:void(0)';
564		child2.onclick = _pub.hide;
565		child.appendChild(child2);
566
567		els.footer = document.createElement('div');
568		els.footer.id = 'ibox_footer';
569		els.footer.innerHTML = '&nbsp;';
570		child.appendChild(els.footer);
571		els.wrapper.appendChild(child);
572
573		els.container.appendChild(els.wrapper);
574
575		elem.appendChild(els.container);
576
577		_pub.updateObject(els.wrapper.style, {right: '', bottom: ''});
578
579		return els.container;
580	};
581
582	/**
583	 * Hides tags within the container
584	 * @param {String} tag The name of the tag (e.g. 'a')
585	 * @param {HTMLObject} container The container to restore tags within (defaults to document)
586	 */
587	var hideTags = function(tag, container) {
588		if (container === undefined) var container = document.body;
589		var list = container.getElementsByTagName(tag);
590		for (var i=0; i<list.length; i++) {
591			if (_pub.getStyle(list[i], 'visibility') != 'hidden' && list[i].style.display != 'none') {
592				list[i].style.visibility = 'hidden';
593				list[i].wasHidden = true;
594			}
595		}
596	};
597
598	/**
599	 * Shows all previously hidden tags in a container.
600	 * @param {String} tag The name of the tag (e.g. 'a')
601	 * @param {HTMLObject} container The container to restore tags within (defaults to document)
602	 */
603	var showTags = function(tag, container) {
604		if (container === undefined) var container = document.body;
605		var list = container.getElementsByTagName(tag);
606		for (var i=0; i<list.length; i++) {
607			if (list[i].wasHidden) {
608				list[i].style.visibility = 'visible';
609				list[i].wasHidden = null;
610			}
611		}
612	};
613
614	var showInit = function(title, params, callback) {
615		if (!_initialized) initialize();
616		if (params === undefined) var params = {};
617		if (active.plugin) _pub.hide();
618
619		active.is_loaded = true;
620		active.params = params;
621
622		els.loading.style.display = "block";
623
624		_pub.center(els.loading);
625		_pub.reposition();
626
627		// hide tags
628		for (var i=0; i<_pub.tags_to_hide.length; i++) {
629			hideTags(_pub.tags_to_hide[i]);
630		}
631
632		// set title here
633		els.footer.innerHTML = title || "&nbsp;";
634
635		// setup background
636		els.overlay.style.display = "block";
637
638		if (!_pub.is_firefox) var amount = 70;
639		else var amount = 100;
640		_pub.fade(els.overlay, _pub.getOpacity(null, els.overlay), amount, _pub.fade_in_speed, callback);
641
642		_pub.fireEvent('show');
643	};
644
645	var drawCSS = function() {
646		// Core CSS (positioning/etc)
647		var core_styles = "#ibox {z-index:1000000;text-align:left;} #ibox_overlay {z-index:1000000;} #ibox_loading {position:absolute;z-index:1000001;} #ibox_wrapper {margin:30px;position:absolute;top:0;left:0;z-index:1000001;} #ibox_content {z-index:1000002;margin:27px 5px 5px 5px;padding:2px;} #ibox_content object {display:block;} #ibox_content .ibox_image {width:100%;height:100%;margin:0;padding:0;border:0;display:block;} #ibox_footer_wrapper a {float:right;display:block;outline:0;margin:0;padding:0;} #ibox_footer_wrapper {text-align:left;position:absolute;top:5px;right:5px;left:5px;white-space:nowrap;overflow:hidden;}";
648
649		// Default style/theme/skin/whatever
650		var default_skin = "#ibox_footer_wrapper {font-weight:bold;height:20px;line-height:20px;} #ibox_footer_wrapper a {text-decoration:none;background:#888;border:1px solid #666;line-height:16px;padding:0 5px;color:#333;font-weight:bold;font-family:Verdana, Arial, Helvetica, sans-serif;font-size:10px;} #ibox_footer_wrapper a:hover {background-color:#bbb;color:#111;} #ibox_footer_wrapper {font-size:12px;font-family:Verdana, Arial, Helvetica, sans-serif;color:#111;} #ibox_wrapper {border:1px solid #ccc;} #ibox_wrapper {background-color:#999;}#ibox_content {background-color:#eee;border:1px solid #666;} #ibox_loading {padding:50px; background:#000;color:#fff;font-size:16px;font-weight:bold;}";
651
652		var head = document.getElementsByTagName("head")[0];
653
654		// tricky hack for IE
655		// because IE doesn't like when you insert stuff the proper way
656		// and we cant use relative paths to include this as an external
657		// stylesheet
658		var htmDiv = document.createElement('div');
659
660		htmDiv.innerHTML = '<p>x</p><style type="text/css">'+default_skin+'</style>';
661		head.insertBefore(htmDiv.childNodes[1], head.firstChild);
662
663		htmDiv.innerHTML = '<p>x</p><style type="text/css">'+core_styles+'</style>';
664		head.insertBefore(htmDiv.childNodes[1], head.firstChild);
665	};
666
667	var _initialized = false;
668	var initialize = function() {
669		// make sure we haven't already done this
670		if (_initialized) return;
671		_initialized = true;
672		// elements here start the look up from the start non <a> tags
673		drawCSS();
674		var els = document.getElementsByTagName('script');
675		var src;
676		for (var i=0, el=null; (el = els[i]); i++) {
677			if (!(src = el.getAttribute('src'))) continue;
678			src = src.split('?')[0];
679			if (src.substr(src.length-8) == '/ibox.js') {
680				_pub.setPath(src.substr(0, src.length-7));
681				break;
682			}
683		}
684		create(document.body);
685		_pub.checkTags(document.body, 'a');
686		_pub.http = _pub.createXMLHttpRequest();
687		_pub.fireEvent('load');
688	};
689
690	_pub.addEvent(window, 'keypress', function(e){ if (e.keyCode == (window.event ? 27 : e.DOM_VK_ESCAPE)) { iBox.hide(); }});
691	_pub.addEvent(window, 'resize', _pub.reposition);
692	_pub.addEvent(window, 'load', initialize);
693	_pub.addEvent(window, 'scroll', _pub.reposition);
694
695	// DEFAULT PLUGINS
696
697	/**
698	 * Handles embedded containers in the page based on url of #container.
699	 * This _ONLY_ works with hidden containers.
700	 */
701	var iBoxPlugin_Container = function() {
702		var was_error = false;
703		var original_wrapper = null;
704		return {
705			/**
706			 * Matches the url and returns true if it fits this plugin.
707			 */
708			match: function(url) {
709				return url.indexOf('#') != -1;
710			},
711			/**
712			 * Called when this plugin is unloaded.
713			 */
714			unload: function() {
715				if (was_error) return;
716				var elemSrc = _pub.html().firstChild;
717				if (elemSrc) {
718					elemSrc.style.display = 'none';
719					original_wrapper.appendChild(elemSrc);
720				}
721			},
722			/**
723			 * Handles the output
724			 * @param {iBox} ibox
725			 * @param {String} url
726			 * @return {iBoxContent} an instance or subclass of iBoxContent
727			 */
728			render: function(url, params) {
729				was_error = false;
730				var elemSrcId = url.substr(url.indexOf("#") + 1);
731				var elemSrc = document.getElementById(elemSrcId);
732				// If the element doesnt exist, break the switch
733				if (!elemSrc) {
734					was_error = true;
735					_pub.html(document.createTextNode('There was an error loading the document.'), params);
736				}
737				else {
738					original_wrapper = elemSrc.parentNode;
739					elemSrc.style.display = 'block';
740					_pub.html(elemSrc, params);
741				}
742			}
743		}
744	}();
745	_pub.plugins.register(iBoxPlugin_Container, true);
746
747	/**
748	 * Handles images
749	 */
750	var iBoxPlugin_Image = function() {
751		// Image types (for auto detection of image display)
752		var image_types = /\.jpg|\.jpeg|\.png|\.gif/gi;
753
754		return {
755			match: function(url) {
756				return url.match(image_types);
757			},
758
759			render: function(url, params) {
760				var img = document.createElement('img');
761				img.onclick = _pub.hide;
762				img.className = 'ibox_image'
763				img.style.cursor = 'pointer';
764				img.onload = function() {
765					_pub.html(img, {width: this.width, height: this.height, constrain: true})
766				}
767				img.onerror = function() {
768					_pub.html(document.createTextNode('There was an error loading the document.'), params);
769				}
770				img.src = url;
771			}
772		}
773	}();
774	_pub.plugins.register(iBoxPlugin_Image);
775
776	var iBoxPlugin_YouTube = function() {
777		var youtube_url = /(?:http:\/\/)?(?:www\d*\.)?(youtube\.(?:[a-z]+))\/(?:v\/|(?:watch(?:\.php)?)?\?(?:.+&)?v=)([^&]+).*/;
778		return {
779			match: function(url) {
780				return url.match(youtube_url);
781			},
782
783			render: function(url, params) {
784				var _match = url.match(youtube_url);
785				var domain = _match[1];
786				var id = _match[2];
787				params.width = 425;
788				params.height = 355;
789				params.constrain = true;
790				var html = '<span><object width="100%" height="100%" style="overflow: hidden; display: block;"><param name="movie" value="http://www.' + domain + '/v/' + id + '"/><param name="wmode" value="transparent"/><embed src="http://www.' + domain + '/v/' + id + '" type="application/x-shockwave-flash" wmode="transparent" width="100%" height="100%"></embed></object></span>';
791				_pub.html(html, params);
792			}
793		}
794	}();
795	_pub.plugins.register(iBoxPlugin_YouTube);
796
797	var iBoxPlugin_Document = function() {
798		return {
799			match: function(url) {
800				return true;
801			},
802
803			render: function(url, params) {
804				_pub.http.open('get', url, true);
805
806				_pub.http.onreadystatechange = function() {
807					if (_pub.http.readyState == 4) {
808						// XXX: why does status return 0?
809						if (_pub.http.status == 200 || _pub.http.status == 0) {
810							_pub.html(_pub.http.responseText, params);
811						}
812						else {
813							_pub.html(document.createTextNode('There was an error loading the document.'), params);
814						}
815					}
816				}
817				_pub.http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
818				try {
819					_pub.http.send(null);
820				}
821				catch (ex) {
822					_pub.html(document.createTextNode('There was an error loading the document.'), params);
823				}
824			}
825		};
826	}();
827	_pub.plugins.register(iBoxPlugin_Document, true);
828
829	return _pub;
830}();