/* * popup.js * * dependencies: prototype.js, effects.js, lowpro.js * * -------------------------------------------------------------------------- * * Allows you to open up a URL inside of a Facebook-style window. To use * simply assign the class "popup" to a link that contains an href to the * HTML snippet that you would like to load up inside a window: * * Window * * You can also "popup" a specific div by referencing it by ID: * * Popup * * * You will need to install the following hook: * * Event.addBehavior({'a.popup': Popup.TriggerBehavior()}); * * -------------------------------------------------------------------------- * * Copyright (c) 2008, John W. Long * Portions copyright (c) 2008, Five Points Solutions, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * */ var Popup = { BorderThickness: 8, BorderImage: '/images/popup_border_background.png', BorderTopLeftImage: '/images/popup_border_top_left.png', BorderTopRightImage: '/images/popup_border_top_right.png', BorderBottomLeftImage: '/images/popup_border_bottom_left.png', BorderBottomRightImage: '/images/popup_border_bottom_right.png' }; Popup.borderImages = function() { return $A([ Popup.BorderImage, Popup.BorderTopLeftImage, Popup.BorderTopRightImage, Popup.BorderBottomLeftImage, Popup.BorderBottomRightImage ]); } Popup.preloadImages = function() { if (!Popup.imagesPreloaded) { Popup.borderImages().each(function(src) { var image = new Image(); image.src = src; }); Popup.preloadedImages = true; } } Popup.TriggerBehavior = Behavior.create({ initialize: function() { var matches = this.element.href.match(/\#(.+)$/); if (matches) { this.window = new Popup.Window($(matches[1])); } else { this.window = new Popup.AjaxWindow(this.element.href); } }, onclick: function(event) { this.popup(); event.stop(); }, popup: function() { this.window.show(); } }); Popup.AbstractWindow = Class.create({ initialize: function() { Popup.preloadImages(); this.buildWindow(); }, buildWindow: function() { this.element = $div({'class': 'popup_window', style: 'display: none; padding: 0 ' + Popup.BorderThickness + 'px; position: absolute'}); this.top = $div({style: 'background: url(' + Popup.BorderImage + '); height: ' + Popup.BorderThickness + 'px'}); this.element.insert(this.top); var outer = $div({style: 'background: url(' + Popup.BorderImage + '); margin: 0px -' + Popup.BorderThickness + 'px; padding: 0px ' + Popup.BorderThickness + 'px; position: relative'}); this.element.insert(outer); this.bottom = $div({style: 'background: url(' + Popup.BorderImage + '); height: ' + Popup.BorderThickness + 'px'}); this.element.insert(this.bottom); var topLeft = $div({style: 'background: url(' + Popup.BorderTopLeftImage + '); height: ' + Popup.BorderThickness + 'px; width: ' + Popup.BorderThickness + 'px; position: absolute; left: 0; top: -' + Popup.BorderThickness + 'px'}); outer.insert(topLeft); var topRight = $div({style: 'background: url(' + Popup.BorderTopRightImage + '); height: ' + Popup.BorderThickness + 'px; width: ' + Popup.BorderThickness + 'px; position: absolute; right: 0; top: -' + Popup.BorderThickness + 'px'}); outer.insert(topRight); var bottomLeft = $div({style: 'background: url(' + Popup.BorderBottomLeftImage + '); height: ' + Popup.BorderThickness + 'px; width: ' + Popup.BorderThickness + 'px; position: absolute; left: 0; bottom: -' + Popup.BorderThickness + 'px'}); outer.insert(bottomLeft); var bottomRight = $div({style: 'background: url(' + Popup.BorderBottomRightImage + '); height: ' + Popup.BorderThickness + 'px; width: ' + Popup.BorderThickness + 'px; position: absolute; right: 0; bottom: -' + Popup.BorderThickness + 'px'}); outer.insert(bottomRight); this.content = $div({style: 'background-color: white'}); outer.insert(this.content); var body = $$('body').first(); body.insert(this.element); }, show: function() { this.beforeShow(); this.element.show(); this.afterShow(); }, hide: function() { this.element.hide(); }, toggle: function() { if (this.element.visible()) { this.hide(); } else { this.show(); } }, focus: function() { var form = this.element.down('form'); if (form) { var elements = form.getElements().reject(function(e) { return e.type == 'hidden' }); var element = elements[0] || form.down('button'); if (element) element.focus(); } }, beforeShow: function() { if (Prototype.Browser.IE) { // IE fixes var width = this.element.getWidth() - (Popup.BorderThickness * 2); this.top.setStyle("width:" + width + "px"); this.bottom.setStyle("width:" + width + "px"); } this.centerWindowInView(); }, afterShow: function() { this.focus(); }, centerWindowInView: function() { var offsets = document.viewport.getScrollOffsets(); this.element.setStyle({ left: parseInt(offsets.left + (document.viewport.getWidth() - this.element.getWidth()) / 2) + 'px', top: parseInt(offsets.top + (document.viewport.getHeight() - this.element.getHeight()) / 2.2) + 'px' }); } }); Popup.Window = Class.create(Popup.AbstractWindow, { initialize: function($super, element) { $super(); element.remove(); this.content.update(element); element.show(); } }); Popup.AjaxWindow = Class.create(Popup.AbstractWindow, { initialize: function($super, url, options) { $super(); options = Object.extend({reload: true}, options); this.url = url; this.reload = options.reload; }, show: function($super) { if (!this.loaded || this.reload) { new Ajax.Updater(this.content, this.url, {asynchronous: false, method: "get", evalScripts: true, onComplete: $super}); this.loaded = true; } else { $super(); } } }); // Element extensions Element.addMethods({ closePopup: function(element) { $(element).up('div.popup_window').hide(); } });