diff options
Diffstat (limited to 'slideshows/default/template/billboard.js')
-rw-r--r-- | slideshows/default/template/billboard.js | 564 |
1 files changed, 564 insertions, 0 deletions
diff --git a/slideshows/default/template/billboard.js b/slideshows/default/template/billboard.js new file mode 100644 index 0000000..d0da2ca --- /dev/null +++ b/slideshows/default/template/billboard.js @@ -0,0 +1,564 @@ +/** + * RightJS-UI Billboard v2.2.0 + * http://rightjs.org/ui/billboard + * + * Copyright (C) 2010-2011 Nikolay Nemshilov + */ +var Billboard = RightJS.Billboard = (function(RightJS) { +/** + * This module defines the basic widgets constructor + * it creates an abstract proxy with the common functionality + * which then we reuse and override in the actual widgets + * + * Copyright (C) 2010-2011 Nikolay Nemshilov + */ + +/** + * The widget units constructor + * + * @param String tag-name or Object methods + * @param Object methods + * @return Widget wrapper + */ +function Widget(tag_name, methods) { + if (!methods) { + methods = tag_name; + tag_name = 'DIV'; + } + + /** + * An Abstract Widget Unit + * + * Copyright (C) 2010 Nikolay Nemshilov + */ + var AbstractWidget = new RightJS.Class(RightJS.Element.Wrappers[tag_name] || RightJS.Element, { + /** + * The common constructor + * + * @param Object options + * @param String optional tag name + * @return void + */ + initialize: function(key, options) { + this.key = key; + var args = [{'class': 'rui-' + key}]; + + // those two have different constructors + if (!(this instanceof RightJS.Input || this instanceof RightJS.Form)) { + args.unshift(tag_name); + } + this.$super.apply(this, args); + + if (RightJS.isString(options)) { + options = RightJS.$(options); + } + + // if the options is another element then + // try to dynamically rewrap it with our widget + if (options instanceof RightJS.Element) { + this._ = options._; + if ('$listeners' in options) { + options.$listeners = options.$listeners; + } + options = {}; + } + this.setOptions(options, this); + + return (RightJS.Wrapper.Cache[RightJS.$uid(this._)] = this); + }, + + // protected + + /** + * Catches the options + * + * @param Object user-options + * @param Element element with contextual options + * @return void + */ + setOptions: function(options, element) { + if (element) { + options = RightJS.Object.merge(options, new Function("return "+( + element.get('data-'+ this.key) || '{}' + ))()); + } + + if (options) { + RightJS.Options.setOptions.call(this, RightJS.Object.merge(this.options, options)); + } + + return this; + } + }); + + /** + * Creating the actual widget class + * + */ + var Klass = new RightJS.Class(AbstractWidget, methods); + + // creating the widget related shortcuts + RightJS.Observer.createShortcuts(Klass.prototype, Klass.EVENTS || RightJS([])); + + return Klass; +} + + +/** + * Billboard initialization script + * + * Copyright (C) 2010 Nikolay Nemshilov + */ +var R = RightJS, + $ = RightJS.$, + $$ = RightJS.$$, + $w = RightJS.$w, + $E = RightJS.$E, + Fx = RightJS.Fx, + Class = RightJS.Class, + Object = RightJS.Object; + + + + +/** + * Billboards basic class + * + * Copyright (C) 2010-2011 Nikolay Nemshilov + */ +var Billboard = new Widget('UL', { + extend: { + version: '2.2.0', + + EVENTS: $w('change first last'), + + Options: { + fxName: 'stripe', // visual effect name + fxDuration: 'long', // visual effect duration + + autostart: true, // if it should automatically start rotate things + delay: 4000, // delay between item shows + loop: true, // loop after reaching the last one + + showButtons: true, // should it show the next/prev buttons or not + prevButton: 'native', // prev item button, 'native' or an ID of your own + nextButton: 'native', // next item button, 'native' or an ID of your own + + stripes: 10, // the number of stripes + + cssRule: '*.rui-billboard' + } + }, + + /** + * Basic constructor + * + * @param mixed an element reference + * @return void + */ + initialize: function(element) { + this.$super('billboard', element); + + // initializing the buttons + if (this.options.showButtons) { + this.prevButton = this.options.prevButton !== 'native' ? $(this.options.prevButton) : + $E('div', {'class': 'rui-billboard-button-prev', 'html': '‹'}).insertTo(this); + this.nextButton = this.options.nextButton !== 'native' ? $(this.options.nextButton) : + $E('div', {'class': 'rui-billboard-button-next', 'html': '›'}).insertTo(this); + + this.prevButton.onClick(R(function(event) { + event.stop(); this.showPrev(); + }).bind(this)); + this.nextButton.onClick(R(function(event) { + event.stop(); this.showNext(); + }).bind(this)); + } + + // catching the 'first'/'last' events + this.onChange(function(event) { + if (event.item === this.items().first()) { + this.fire('first'); + } else if (event.item === this.items().last()) { + this.fire('last'); + } + }); + + // stopping/starting the slideshow with mouse over/out events + this.on({ + mouseover: function() { + this.stop(); + }, + + mouseout: function(event) { + if (this.options.autostart && !event.find('.rui-billboard')) { + this.start(); + } + } + }); + + // autostart + if (this.options.autostart) { + this.start(); + } + }, + + /** + * Returns the list of items to swap + * + * @return Array swappable items + */ + items: function() { + return this.children().without(this.prevButton, this.nextButton); + }, + + /** + * Show next item on the list + * + * @return Billboard this + */ + showNext: function() { + var items = this.items(), index = items.indexOf(this.current()) + 1; + + if (index == items.length && this.options.loop) { + index = 0; + } + + return this.current(index); + }, + + /** + * Show prev item on the list + * + * @return Billboard this + */ + showPrev: function() { + var items = this.items(), index = items.indexOf(this.current()) - 1; + + if (index < 0 && this.options.loop) { + index = items.length - 1; + } + + return this.current(index); + }, + + /** + * Gets/sets the current item + * + * @param mixed integer index or a LI element reference + * @return Billboard this or current LI element + */ + current: function(index) { + var items = this.items(); + + if (arguments.length) { + if (index instanceof Element) { + index = items.indexOf(index); + } + + this.runFx(items[index]); + } else { + return items.length ? ( + items.first('hasClass', 'rui-billboard-current') || + items.first().addClass('rui-billboard-current') + ) : null; + } + + return this; + }, + + /** + * Starts the slide show + * + * @return Billboard this + */ + start: function() { + this.timer = R(this.showNext).bind(this).periodical(this.options.delay); + }, + + /** + * stops the slideshow + * + * @return Billboard this + */ + stop: function() { + if (this.timer) { + this.timer.stop(); + } + }, + + /** + * Wrapping the event trigger so it always sent the + * current element references + * + * @param String event name + * @param Object options + * @return Billboard this + */ + fire: function(name, options) { + return this.$super(name, Object.merge({ + index: this.items().indexOf(this.current()), + item: this.current() + }, options)); + }, + +// protected + + /** + * Runs the fx transition + * + * @param Element new LI element + * @return void + */ + runFx: function(item) { + if (item && !this._running) { + var Fx = Billboard.Fx[R(this.options.fxName || '').capitalize()]; + + if (Fx) { + new Fx(this).start(this.current(), item); + } else { + this.current().removeClass('rui-billboard-current'); + item.addClass('rui-billboard-current'); + } + } + } +}); + +/** + * Basic billboard visual effect + * + * Copyright (C) 2010 Nikolay Nemshilov + */ +Billboard.Fx = new Class(Fx, { + + /** + * basic constructor + * + * @param Billboard billboard + * @return void + */ + initialize: function(billboard) { + this.container = $E('div', {'class': 'rui-billboard-fx-container'}); + + this.$super(billboard, { + duration: billboard.options.fxDuration, + onStart: function() { + billboard._running = true; + billboard.insert(this.container); + }, + onFinish: function() { + this.container.remove(); + billboard._running = false; + billboard.fire('change'); + } + }); + }, + + /** + * Starts an fx on the given item + * + * @param {Element} old LI element + * @param {Element} new LI element + * @return void + */ + prepare: function(old_item, new_item) { + old_item.removeClass('rui-billboard-current'); + new_item.addClass('rui-billboard-current'); + + this.clone = old_item.clone(); + + this.container.update(this.clone); + } + +}); + +/** + * Fade visual effects class + * + * Copyright (C) 2010 Nikolay Nemshilov + */ +Billboard.Fx.Fade = new Class(Billboard.Fx, { + + /** + * Starts an fx on the given item + * + * @param {Element} old LI element + * @param {Element} new LI element + * @return void + */ + prepare: function(old_item, new_item) { + this.$super(old_item, new_item); + }, + + /** + * Rendering the effect + * + * @param Float delta value + * @return void + */ + render: function(delta) { + this.container.setStyle({opacity: 1 - delta}); + } + +}); + +/** + * The slide visual effects class + * + * Copyright (C) 2010 Nikolay Nemshilov + */ +Billboard.Fx.Slide = new Class(Billboard.Fx, { + + /** + * overloading the 'prepare' method to add some stuff + * to the container depending on which direction do we slide + * + * @param {Element} old LI element + * @param {Element} new LI element + * @return void + */ + prepare: function(old_item, new_item) { + this._width = this.element.current().size().x; + this._direction = old_item.nextSiblings().include(new_item) ? -1 : 1; + + this.$super(old_item, new_item); + + this.clone.setStyle({width: this._width + 'px'}); + }, + + /** + * Rendering the Fx + * + * @param Float delta + * @return void + */ + render: function(delta) { + this.clone._.style.left = this._direction * this._width * delta + 'px'; + } + +}); + +/** + * Stripe visual effects class + * + * Copyright (C) 2010-2011 Nikolay Nemshilov + */ +Billboard.Fx.Stripe = new Class(Billboard.Fx, { + + directions: ['down', 'up', 'left', 'right'], + + /** + * Breaking the original element onto sripes in here + * + * @param {Element} old LI element + * @param {Element} new LI element + * @return void + */ + prepare: function(old_item, new_item) { + this.$super(old_item, new_item); + + var length = this.element.options.stripes, + width = this.element.items()[0].size().x / length, + delay = 100, + direction = this.directions.shift(); + + this.directions.push(direction); + this.container.clean(); + + for (var i=0; i < length; i++) { + var stripe = $E('div', { + 'class': 'rui-billboard-stripe', + 'style': { + width: width + 1 + 'px', + left: i * width + 'px' + } + }).insert(old_item.clone().setStyle({ + width: width * length + 'px', + left: - i * width + 'px' + })); + + this.container.append(stripe); + var options = { + duration: this.options.duration + }; + + if (direction !== 'right' && i === (length - 1) || (direction === 'right' && i === 0)) { + options.onFinish = R(this.finish).bind(this, true); + } + + switch (direction) { + case 'up': + R(function(stripe, options) { + stripe.setHeight(stripe.size().y); + stripe.morph({height: '0px'}, options); + }).bind(this, stripe, options).delay(i * delay); + break; + + case 'down': + stripe.setStyle('top: auto; bottom: 0px'); + R(function(stripe, options) { + stripe.setHeight(stripe.size().y); + stripe.morph({height: '0px'}, options); + }).bind(this, stripe, options).delay(i * delay); + break; + + case 'left': + R(function(stripe, options) { + stripe.morph({width: '0px'}, options); + }).bind(this, stripe, options).delay(i * delay); + break; + + case 'right': + R(function(stripe, options) { + stripe.morph({width: '0px'}, options); + }).bind(this, stripe, options).delay((length - i -1) * delay); + break; + + default: + this.finish(true); + } + } + }, + + + /** + * Stubbing the finish method so it didn't finish prematurely + * + * @return Fx this + */ + finish: function(for_sure) { + if (for_sure) { + this.$super(); + } + return this; + } + +}); + +/** + * Document level hooks for billboards + * + * Copyright (C) 2010 Nikolay Nemshilov + */ +$(document).onReady(function() { + $$(Billboard.Options.cssRule).each(function(element) { + if (!(element instanceof Billboard)) { + element = new Billboard(element); + } + }); +}); + +var embed_style = document.createElement('style'), + embed_rules = document.createTextNode("*.rui-billboard, *.rui-billboard> *{margin:0;padding:0;list-style:none} *.rui-billboard{display:inline-block; *display:inline; *zoom:1;position:relative} *.rui-billboard> *{display:none;width:100%;height:100%} *.rui-billboard> *:first-child, *.rui-billboard> *.rui-billboard-current:first-child{display:block;position:relative} *.rui-billboard> *>img{margin:0;padding:0} *.rui-billboard-current{position:absolute;left:0;top:0;display:block;z-index:999} *.rui-billboard-button-prev, *.rui-billboard-button-next{position:absolute;z-index:99999;left:.25em;top:auto;bottom:.25em;display:block;width:.5em;height:auto;text-align:center;font-size:200%;font-family:Arial;font-weight:bold;padding:0em .5em .2em .5em;background:white;opacity:0;filter:alpha(opacity:0);cursor:pointer;border:.12em solid #888;border-radius:.2em;-moz-border-radius:.2em;-webkit-border-radius:.2em;user-select:none;-moz-user-select:none;-webkit-user-select:none;transition:opacity .3s ease-in-out;-o-transition:opacity .3s ease-in-out;-moz-transition:opacity .3s ease-in-out;-webkit-transition:opacity .3s ease-in-out} *.rui-billboard-button-next{left:auto;right:.25em;text-align:right} *.rui-billboard-button-prev:active{text-indent:-.1em} *.rui-billboard-button-next:active{text-indent:.2em} *.rui-billboard:hover *.rui-billboard-button-prev, *.rui-billboard:hover *.rui-billboard-button-next{opacity:0.4;filter:alpha(opacity:40)} *.rui-billboard:hover *.rui-billboard-button-prev:hover, *.rui-billboard:hover *.rui-billboard-button-next:hover{opacity:0.7;filter:alpha(opacity:70)}.rui-billboard-fx-container{position:absolute;left:0;top:0;display:block;z-index:9999;overflow:hidden}.rui-billboard-fx-container> *{position:absolute;left:0;top:0}.rui-billboard-stripe{overflow:hidden}.rui-billboard-stripe> *{position:relative}"); + +embed_style.type = 'text/css'; +document.getElementsByTagName('head')[0].appendChild(embed_style); + +if(embed_style.styleSheet) { + embed_style.styleSheet.cssText = embed_rules.nodeValue; +} else { + embed_style.appendChild(embed_rules); +} + + +return Billboard; +})(RightJS); |