1/** 2 * SqueezeBox - Expandable Lightbox 3 * 4 * Allows to open various content as modal, 5 * centered and animated box. 6 * 7 * Inspired by 8 * ... Lokesh Dhakar - The original Lightbox v2 9 * ... Cody Lindley - ThickBox 10 * 11 * @version 1.0rc1 12 * 13 * @license MIT-style license 14 * @author Harald Kirschner <mail [at] digitarald.de> 15 * @copyright Author 16 */ 17var SqueezeBox = { 18 19 presets: { 20 size: {x: 600, y: 450}, 21 sizeLoading: {x: 200, y: 150}, 22 marginInner: {x: 20, y: 20}, 23 marginImage: {x: 150, y: 200}, 24 handler: false, 25 adopt: null, 26 closeWithOverlay: true, 27 zIndex: 65555, 28 overlayOpacity: 0.7, 29 classWindow: '', 30 classOverlay: '', 31 disableFx: false, 32 onOpen: Class.empty, 33 onClose: Class.empty, 34 onUpdate: Class.empty, 35 onResize: Class.empty, 36 onMove: Class.empty, 37 onShow: Class.empty, 38 onHide: Class.empty, 39 fxOverlayDuration: 250, 40 fxResizeDuration: 750, 41 fxContentDuration: 250, 42 ajaxOptions: {}, 43 isNewDatabase: false 44 }, 45 46 initialize: function(options) { 47 if (this.options) return this; 48 this.presets = $merge(this.presets, options) 49 this.setOptions(this.presets); 50 this.build(); 51 this.listeners = { 52 window: this.reposition.bind(this, [null]), 53 close: this.close.bind(this), 54 key: this.onkeypress.bind(this)}; 55 this.isOpen = this.isLoading = false; 56 this.window.close = this.listeners.close; 57 return this; 58 }, 59 60 build: function() { 61 this.overlay = new Element('div', { 62 id: 'sbox-overlay', 63 styles: { 64 display: 'none', 65 zIndex: this.options.zIndex 66 } 67 }); 68 this.content = new Element('div', { 69 id: 'sbox-content' 70 }); 71 this.btnClose = new Element('a', { 72 id: 'sbox-btn-close', 73 href: '#' 74 }); 75 this.window = new Element('div', { 76 id: 'sbox-window', 77 styles: { 78 display: 'none', 79 zIndex: this.options.zIndex + 2 80 } 81 }).adopt(this.btnClose, this.content); 82 83 if (!window.ie6) { 84 this.overlay.setStyles({ 85 position: 'fixed', 86 top: 0, 87 left: 0 88 }); 89 this.window.setStyles({ 90 position: 'fixed', 91 top: '50%', 92 left: '50%' 93 }); 94 } else { 95 this.overlay.style.setExpression('marginTop', 'document.documentElement.scrollTop + "px"'); 96 this.window.style.setExpression('marginTop', '0 - parseInt(this.offsetHeight / 2) + document.documentElement.scrollTop + "px"'); 97 98 this.overlay.setStyles({ 99 position: 'absolute', 100 top: '0%', 101 left: '0%' 102 //,marginTop: "expression(document.documentElement.scrollTop + 'px')" 103 }); 104 105 this.window.setStyles({ 106 position: 'absolute', 107 top: '0%', 108 left: '0%' 109 //,marginTop: "(expression(0 - parseInt(this.offsetHeight / 2) + document.documentElement.scrollTop + 'px')" 110 }); 111 } 112 113 if( typeof $(document.body).adopt === 'function' ) 114 { 115 $(document.body).adopt(this.overlay, this.window); 116 } 117 118 this.fx = { 119 overlay: this.overlay.effect('opacity', { 120 duration: this.options.fxOverlayDuration, 121 wait: false}).set(0), 122 window: this.window.effects({ 123 duration: this.options.fxResizeDuration, 124 wait: false}), 125 content: this.content.effect('opacity', { 126 duration: this.options.fxContentDuration, 127 wait: false}).set(0) 128 }; 129 }, 130 131 addClick: function(el) { 132 return el.addEvent('click', function() { 133 if (this.fromElement(el)) return false; 134 }.bind(this)); 135 }, 136 137 fromElement: function(el, options) { 138 this.initialize(); 139 this.element = $(el); 140 if (this.element && this.element.rel) options = $merge(options || {}, Json.evaluate(this.element.rel)); 141 this.setOptions(this.presets, options); 142 this.assignOptions(); 143 this.url = (this.element ? (this.options.url || this.element.href) : el) || ''; 144 145 if (this.options.handler) { 146 var handler = this.options.handler; 147 return this.setContent(handler, this.parsers[handler].call(this, true)); 148 } 149 var res = false; 150 for (var key in this.parsers) { 151 if ((res = this.parsers[key].call(this))) return this.setContent(key, res); 152 } 153 return this; 154 }, 155 156 assignOptions: function() { 157 this.overlay.setProperty('class', this.options.classOverlay); 158 this.window.setProperty('class', this.options.classWindow); 159 }, 160 161 showDiv: function(divId, options) { 162 this.initialize(); 163 164 this.element = options.isNewDatabase ? divId : ($(divId) || false); 165 166 this.setOptions($merge(this.presets, options || {})); 167 168 if (this.element && this.options.parse) { 169 var obj = this.element.getProperty(this.options.parse); 170 if (obj && (obj = JSON.decode(obj, this.options.parseSecure))) this.setOptions(obj); 171 } 172 this.url = divId; 173 174 this.assignOptions(); 175 176 var handler = handler || this.options.handler; 177 if (handler) return this.setContent(handler, this.parsers[handler].call(this, true)); 178 var ret = false;
179 return this.parsers.some(function(parser, key) { 180 var content = parser.call(this); 181 if (content) { 182 ret = this.setContent(key, content); 183 return true; 184 } 185 return false; 186 }, this); 187 }, 188 189 close: function(e) { 190 if (e) new Event(e).stop(); 191 if (!this.isOpen) return this; 192 this.fx.overlay.start(0).chain(this.toggleOverlay.bind(this)); 193 this.window.setStyle('display', 'none'); 194 this.trashImage(); 195 this.toggleListeners(); 196 this.isOpen = null; 197 this.fireEvent('onClose', [this.content]).removeEvents(); 198 this.options = {}; 199 this.setOptions(this.presets).callChain(); 200 return this; 201 }, 202 203 onError: function() { 204 if (this.image) this.trashImage(); 205 this.setContent('Error during loading'); 206 }, 207 208 trashImage: function() { 209 if (this.image) this.image = this.image.onload = this.image.onerror = this.image.onabort = null; 210 }, 211 212 setContent: function(handler, content) { 213 this.content.setProperty('class', 'sbox-content-' + handler); 214 this.applyTimer = this.applyContent.delay(this.fx.overlay.options.duration, this, [this.handlers[handler].call(this, content)]); 215 if (this.overlay.opacity) return this; 216 this.toggleOverlay(true); 217 this.fx.overlay.start(this.options.overlayOpacity); 218 this.reposition(); 219 return this; 220 }, 221 222 applyContent: function(content, size) { 223 this.applyTimer = $clear(this.applyTimer); 224 this.hideContent(); 225 if (!content) this.toggleLoading(true); 226 else { 227 if (this.isLoading) this.toggleLoading(false); 228 this.fireEvent('onUpdate', [this.content], 20); 229 } 230 this.content.empty()[['string', 'array', false].contains($type(content)) ? 'setHTML' : 'adopt'](content || ''); 231 this.callChain(); 232 if (!this.isOpen) { 233 this.toggleListeners(true); 234 this.resize(size, true); 235 this.isOpen = true; 236 this.fireEvent('onOpen', [this.content]); 237 } else this.resize(size); 238 }, 239 240 resize: function(size, instantly) { 241 var sizes = window.getSize(); 242 this.size = $merge(this.isLoading ? this.options.sizeLoading : this.options.size, size); 243 var to = { 244 width: this.size.x, 245 height: this.size.y, 246 marginLeft: - this.size.x / 2, 247 marginTop: - this.size.y / 2 248 //left: (sizes.scroll.x + (sizes.size.x - this.size.x - this.options.marginInner.x) / 2).toInt(), 249 //top: (sizes.scroll.y + (sizes.size.y - this.size.y - this.options.marginInner.y) / 2).toInt() 250 }; 251 $clear(this.showTimer || null); 252 this.hideContent(); 253 if (!instantly) this.fx.window.start(to).chain(this.showContent.bind(this)); 254 else { 255 this.window.setStyles(to).setStyle('display', ''); 256 this.showTimer = this.showContent.delay(50, this); 257 } 258 this.reposition(sizes); 259 }, 260 261 toggleListeners: function(state) { 262 var task = state ? 'addEvent' : 'removeEvent'; 263 this.btnClose[task]('click', this.listeners.close); 264 if (this.options.closeWithOverlay) this.overlay[task]('click', this.listeners.close); 265 document[task]('keydown', this.listeners.key); 266 window[task]('resize', this.listeners.window); 267 window[task]('scroll', this.listeners.window); 268 }, 269 270 toggleLoading: function(state) { 271 this.isLoading = state; 272 this.window[state ? 'addClass' : 'removeClass']('sbox-loading'); 273 if (state) this.fireEvent('onLoading', [this.window]); 274 }, 275 276 toggleOverlay: function(state) { 277 this.overlay.setStyle('display', state ? '' : 'none'); 278 $(document.body)[state ? 'addClass' : 'removeClass']('body-overlayed'); 279 }, 280 281 showContent: function() { 282 if (this.content.opacity) this.fireEvent('onShow', [this.window]); 283 this.fx.content.start(1); 284 }, 285 286 hideContent: function() { 287 if (!this.content.opacity) this.fireEvent('onHide', [this.window]); 288 this.fx.content.stop().set(0); 289 }, 290 291 onkeypress: function(e) { 292 switch (e.key) { 293 case 'esc': 294 case 'x': 295 this.close(); 296 break; 297 } 298 }, 299 300 reposition: function(sizes) { 301 sizes = sizes || window.getSize(); 302 303 if( ! sizes.hasOwnProperty( "size" ) || ! sizes.size.hasOwnProperty( "x" ) || ! sizes.size.hasOwnProperty( "y" )){ 304 sizes = { 305 size : { 306 x : 0, 307 y : 0 308 } 309 } 310 } 311 312 if( sizes.size.x === void 0 || sizes.size.x === null){ 313 sizes.size.x = 0; 314 } 315 if( sizes.size.y === void 0 || sizes.size.y === null){ 316 sizes.size.y = 0; 317 } 318 319 this.overlay.setStyles({ 320 //'left': sizes.scroll.x, 'top': sizes.scroll.y, 321 width: sizes.size.x, 322 height: sizes.size.y 323 }); 324 /* 325 this.window.setStyles({ 326 left: (sizes.scroll.x + (sizes.size.x - this.window.offsetWidth) / 2).toInt(), 327 top: (sizes.scroll.y + (sizes.size.y - this.window.offsetHeight) / 2).toInt() 328 }); 329 */ 330 this.fireEvent('onMove', [this.overlay, this.window, sizes]); 331 }, 332 333 removeEvents: function(type){ 334 if (!this.$events) return this; 335 if (!type) this.$events = null; 336 else if (this.$events[type]) this.$events[type] = null; 337 return this; 338 }, 339 340 parsers: { 341 'image': function(preset) { 342 return (preset || this.url.test(/\.(jpg|jpeg|png|gif|bmp)$/i)) ? this.url : false;
343 }, 344 'adopt': function(preset) { 345 var aoption = $(this.options.adopt); 346 var ndbOption = this.options.isNewDatabase && aoption !== null && !$.trim(aoption.html()) ? true : false; 347 var hasOption = ndbOption ? false : $(this.options.adopt); 348 if (hasOption) return $(this.options.adopt); 349 if (preset || ($(this.element) && !this.element.parentNode)) return this.options.isNewDatabase ? this.element : $(this.element); 350 var bits = this.url.match(/#([\w-]+)$/); 351 return bits ? $(bits[1]) : false; 352 }, 353 'url': function(preset) { 354 return (preset || (this.url && !this.url.test(/^javascript:/i))) ? this.url: false; 355 }, 356 'iframe': function(preset) { 357 return (preset || this.url) ? this.url: false; 358 }, 359 'string': function(preset) { 360 return true; 361 } 362 }, 363 364 handlers: { 365 'image': function(url) { 366 this.image = new Image(); 367 var events = { 368 loaded: function() { 369 var win = {x: window.getWidth() - this.options.marginImage.x, y: window.getHeight() - this.options.marginImage.y}; 370 var size = {x: this.image.width, y: this.image.height}; 371 for (var i = 0; i < 2; i++) 372 if (size.x > win.x) { 373 size.y *= win.x / size.x; 374 size.x = win.x; 375 } else if (size.y > win.y) { 376 size.x *= win.y / size.y; 377 size.y = win.y; 378 } 379 size = {x: parseInt(size.x), y: parseInt(size.y)}; 380 if (window.webkit419) this.image = new Element('img', {'src': this.image.src}); 381 else $(this.image); 382 this.image.setProperties({ 383 'width': size.x, 384 'height': size.y}); 385 this.applyContent(this.image, size); 386 }.bind(this), 387 failed: this.onError.bind(this) 388 }; 389 (function() { 390 this.src = url; 391 }).delay(10, this.image); 392 this.image.onload = events.loaded; 393 this.image.onerror = this.image.onabort = events.failed; 394 }, 395 'adopt': function(el) { 396 var clone = el.clone(); 397 clone.style.display = ''; 398 return clone; 399 }, 400 'url': function(url) { 401 this.ajax = new Ajax(url, this.options.ajaxOptions); 402 this.ajax.addEvent('onSuccess', function(resp) { 403 this.applyContent(resp); 404 this.ajax = null; 405 }.bind(this)); 406 this.ajax.addEvent('onFailure', this.onError.bind(this)); 407 this.ajax.request.delay(10, this.ajax); 408 }, 409 'iframe': function(url) { 410 return new Element('iframe', { 411 'src': url, 412 'frameBorder': 0, 413 'width': this.options.size.x, 414 'height': this.options.size.y 415 }); 416 }, 417 'string': function(str) { 418 return str; 419 } 420 }, 421 422 extend: $extend 423}; 424 425SqueezeBox.extend(SqueezeBox, Events.prototype); 426SqueezeBox.extend(SqueezeBox, Options.prototype); 427SqueezeBox.extend(SqueezeBox, Chain.prototype);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.