summaryrefslogtreecommitdiffstats
path: root/abs/core/local-website/htdocs/linhes/js/prototip/prototip.js
diff options
context:
space:
mode:
Diffstat (limited to 'abs/core/local-website/htdocs/linhes/js/prototip/prototip.js')
-rw-r--r--abs/core/local-website/htdocs/linhes/js/prototip/prototip.js506
1 files changed, 506 insertions, 0 deletions
diff --git a/abs/core/local-website/htdocs/linhes/js/prototip/prototip.js b/abs/core/local-website/htdocs/linhes/js/prototip/prototip.js
new file mode 100644
index 0000000..f386a03
--- /dev/null
+++ b/abs/core/local-website/htdocs/linhes/js/prototip/prototip.js
@@ -0,0 +1,506 @@
+// Prototip 1.2.0_pre1 - 17-12-2007
+
+// Copyright (c) 2007 Nick Stakenburg (http://www.nickstakenburg.com)
+//
+// 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.
+
+// More information on this project:
+// http://www.nickstakenburg.com/projects/prototip/
+
+var Prototip = {
+ Version: '1.2.0_pre1',
+
+ REQUIRED_Prototype: '1.6.0',
+ REQUIRED_Scriptaculous: '1.8.0',
+
+ start: function() {
+ this.require('Prototype');
+ Tips.initialize();
+ Element.observe(window, 'unload', this.unload);
+ },
+
+ require: function(library) {
+ if ((typeof window[library] == 'undefined') ||
+ (this.convertVersionString(window[library].Version) < this.convertVersionString(this['REQUIRED_' + library])))
+ throw('Prototip requires ' + library + ' >= ' + this['REQUIRED_' + library]);
+ },
+
+ convertVersionString: function(versionString) {
+ var r = versionString.split('.');
+ return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
+ },
+
+ viewport: {
+ getDimensions: function() {
+ var dimensions = { };
+ var B = Prototype.Browser;
+ $w('width height').each(function(d) {
+ var D = d.capitalize();
+ dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] :
+ (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D];
+ });
+ return dimensions;
+ }
+ },
+
+ capture: function(func) {
+ if (!Prototype.Browser.IE) {
+ func = func.wrap(function(proceed, event) {
+ var rel = event.relatedTarget, cur = event.currentTarget;
+ if (rel && rel.nodeType == Node.TEXT_NODE) rel = rel.parentNode;
+ if (rel && rel != cur && rel.descendantOf && !(rel.descendantOf(cur)))
+ proceed(event);
+ });
+ }
+ return func;
+ },
+
+ unload: function() { Tips.removeAll(); }
+};
+
+var Tips = {
+ // Configuration
+ closeButtons: true,
+ zIndex: 1200,
+
+ tips : [],
+ visible : [],
+
+ initialize: function() {
+ this.zIndexTop = this.zIndex;
+ },
+
+ useEvent : (function(IE) { return {
+ 'mouseover': (IE ? 'mouseenter' : 'mouseover'),
+ 'mouseout': (IE ? 'mouseleave' : 'mouseout'),
+ 'mouseenter': (IE ? 'mouseenter' : 'mouseover'),
+ 'mouseleave': (IE ? 'mouseleave' : 'mouseout')
+ };})(Prototype.Browser.IE),
+
+ fixIE: (function(agent) {
+ var version = new RegExp('MSIE ([\\d.]+)').exec(agent);
+ return version ? (parseFloat(version[1]) <= 6) : false;
+ })(navigator.userAgent),
+
+ add: function(tip) {
+ this.tips.push(tip);
+ },
+
+ hasTip: function(element) {
+ if (this.tips.find(function(t){ return t.element == $(element); }))
+ return true;
+ return false;
+ },
+
+ showTip: function(element) {
+ var tip = this.tips.find(function(t){ return t.element == $(element); });
+ if (tip) {
+ tip.show();
+ tip.position();
+ }
+ },
+
+ hideTip: function(element) {
+ var tip = this.tips.find(function(t){ return t.element == $(element); });
+ if (tip)
+ tip.hide();
+ },
+
+ hideAll: function() {
+ this.tips.each(function(tip) { tip.hide(); }.bind(this));
+ },
+
+ remove: function(element) {
+ var tip = this.tips.find(function(t){ return t.element == $(element); });
+ if (tip) {
+ tip.deactivate();
+ if (tip.tooltip) {
+ tip.wrapper.remove();
+ if (Tips.fixIE) tip.iframeShim.remove();
+ }
+ this.tips = this.tips.without(tip);
+ }
+ },
+
+ removeAll: function() {
+ this.tips.each(function(tip) { this.remove(tip.element); }.bind(this));
+ },
+
+ raise: function(tip) {
+ if (tip.highest) return;
+ if (this.visible.length == 0) {
+ this.zIndexTop = this.zIndex;
+ for (var i=0;i<this.tips.length;i++) {
+ this.tips[i].wrapper.style.zIndex = this.zIndex;
+ }
+ }
+ tip.style.zIndex = this.zIndexTop++;
+ for (var i=0;i<this.tips.length;i++) { this.tips[i].wrapper.highest = false; };
+ tip.highest = true;
+ },
+
+ addVisibile: function(tip) {
+ this.removeVisible(tip);
+ this.visible.push(tip);
+ },
+
+ removeVisible: function(tip) {
+ this.visible = this.visible.without(tip);
+ }
+};
+Tips.initialize();
+
+var Tip = Class.create({
+ initialize: function(element, content) {
+ this.element = $(element);
+ Tips.remove(this.element);
+
+ this.content = content;
+
+ var isHooking = (arguments[2] && arguments[2].hook);
+ var isShowOnClick = (arguments[2] && arguments[2].showOn == 'click');
+
+ this.options = Object.extend({
+ className: 'default', // see css, this will lead to .prototip .default
+ closeButton: Tips.closeButtons, // true, false
+ delay: !isShowOnClick ? 0.2 : false, // seconds before tooltip appears
+ duration: 0.3, // duration of the effect
+ effect: false, // false, 'appear' or 'blind'
+ hideAfter: false, // second before hide after no hover/activity
+ hideOn: 'mouseleave', // or any other event, false
+ hook: false, // { element: topLeft|topRight|bottomLeft|bottomRight, tip: see element }
+ offset: isHooking ? {x:0, y:0} : {x:16, y:16},
+ fixed: isHooking ? true : false, // follow the mouse if false
+ showOn: 'mousemove',
+ target: this.element, // or another element
+ title: false,
+ viewport: isHooking ? false : true // keep within viewport if mouse is followed
+ }, arguments[2] || {});
+
+ this.target = $(this.options.target);
+
+ this.setup();
+
+ if (this.options.effect) {
+ Prototip.require('Scriptaculous');
+ this.queue = { position: 'end', limit: 1, scope: this.wrapper.identify() }
+ }
+
+ Tips.add(this);
+ this.activate();
+ },
+
+ setup: function() {
+ this.wrapper = new Element('div', { 'class' : 'prototip' }).setStyle({
+ display: 'none', zIndex: Tips.zIndex });
+ this.wrapper.identify();
+
+ if (Tips.fixIE) {
+ this.iframeShim = new Element('iframe', { 'class' : 'iframeShim', src: 'javascript:false;' }).setStyle({
+ display: 'none', zIndex: Tips.zIndex - 1 });
+ }
+
+ this.tip = new Element('div', { 'class' : 'content' }).insert(this.content);
+ this.tip.insert(new Element('div').setStyle({ clear: 'both' }));
+
+ if (this.options.closeButton || (this.options.hideOn.element && this.options.hideOn.element == 'closeButton'))
+ this.closeButton = new Element('a', { href: '#', 'class' : 'close' });
+ },
+
+ build: function() {
+ if (Tips.fixIE) document.body.appendChild(this.iframeShim).setOpacity(0);
+
+ // effects go smooth with extra wrapper
+ var wrapper = 'wrapper';
+ if (this.options.effect) {
+ this.effectWrapper = this.wrapper.appendChild(new Element('div', { 'class' : 'effectWrapper' }));
+ wrapper = 'effectWrapper';
+ }
+
+ this.tooltip = this[wrapper].appendChild(new Element('div', { 'class' : 'tooltip ' + this.options.className }));
+
+ if (this.options.title || this.options.closeButton) {
+ this.toolbar = this.tooltip.appendChild(new Element('div', { 'class' : 'toolbar' }));
+ this.title = this.toolbar.appendChild(new Element('div', { 'class' : 'title' }).update(this.options.title || ' '));
+ }
+
+ this.tooltip.insert(this.tip);
+ document.body.appendChild(this.wrapper);
+
+ // fixate elements for better positioning and effects
+ var fixate = (this.options.effect) ? [this.wrapper, this.effectWrapper]: [this.wrapper];
+ if (Tips.fixIE) fixate.push(this.iframeShim);
+
+ // fix width
+ var fixedWidth = this.wrapper.getWidth();
+ fixate.invoke('setStyle', { width: fixedWidth + 'px' });
+
+ // make toolbar width fixed
+ if(this.toolbar) {
+ this.wrapper.setStyle({ visibility : 'hidden' }).show();
+ this.toolbar.setStyle({ width: this.toolbar.getWidth() + 'px'});
+ this.wrapper.hide().setStyle({ visibility : 'visible' });
+ }
+
+ // add close button
+ if (this.closeButton)
+ this.title.insert({ top: this.closeButton }).insert(new Element('div').setStyle({ clear: 'both' }));
+
+ var fixedHeight = this.wrapper.getHeight();
+ fixate.invoke('setStyle', { width: fixedWidth + 'px', height: fixedHeight + 'px' });
+
+ this[this.options.effect ? wrapper : 'tooltip'].hide();
+ },
+
+ activate: function() {
+ this.eventShow = this.showDelayed.bindAsEventListener(this);
+ this.eventHide = this.hide.bindAsEventListener(this);
+
+ // if fixed use mouseover instead of mousemove for less event calls
+ if (this.options.fixed && this.options.showOn == 'mousemove') this.options.showOn = 'mouseover';
+
+ if(this.options.showOn == this.options.hideOn) {
+ this.eventToggle = this.toggle.bindAsEventListener(this);
+ this.element.observe(this.options.showOn, this.eventToggle);
+ }
+
+ var hideOptions = {
+ 'element': this.eventToggle ? [] : [this.element],
+ 'target': this.eventToggle ? [] : [this.target],
+ 'tip': this.eventToggle ? [] : [this.wrapper],
+ 'closeButton': [],
+ 'none': []
+ };
+ var el = this.options.hideOn.element;
+ this.hideElement = el || (!this.options.hideOn ? 'none' : 'element');
+ this.hideTargets = hideOptions[this.hideElement];
+ if (!this.hideTargets && el && Object.isString(el)) this.hideTargets = this.tip.select(el);
+
+ var realEvent = {'mouseenter': 'mouseover', 'mouseleave': 'mouseout'};
+ $w('show hide').each(function(e) {
+ var E = e.capitalize();
+ var event = (this.options[e + 'On'].event || this.options[e + 'On']);
+ this[e + 'Action'] = event;
+ if (['mouseenter', 'mouseleave', 'mouseover', 'mouseout'].include(event)) {
+ this[e + 'Action'] = (Tips.useEvent[event] || event);
+ this['event' + E] = Prototip.capture(this['event' + E]);
+ }
+ }.bind(this));
+
+ if (!this.eventToggle) this.element.observe(this.options.showOn, this.eventShow);
+ if (this.hideTargets) this.hideTargets.invoke('observe', this.hideAction, this.eventHide);
+
+ // add postion observer to moving showOn click tips
+ if (!this.options.fixed && this.options.showOn == 'click') {
+ this.eventPosition = this.position.bindAsEventListener(this);
+ this.element.observe('mousemove', this.eventPosition);
+ }
+
+ // close button
+ this.buttonEvent = this.hide.wrap(function(proceed, event) {
+ event.stop();
+ proceed(event);
+ }).bindAsEventListener(this);
+ if (this.closeButton) this.closeButton.observe('click', this.buttonEvent);
+
+ // delay timeout
+ if (this.options.showOn != 'click' && (this.hideElement != 'element')) {
+ this.eventCheckDelay = Prototip.capture(function() {
+ this.clearTimer('show');
+ }).bindAsEventListener(this);
+ this.element.observe(Tips.useEvent['mouseout'], this.eventCheckDelay);
+ }
+
+ // activity (hideAfter, raise)
+ var elements = [this.element, this.wrapper];
+ this.activityEnter = Prototip.capture(function() {
+ Tips.raise(this.wrapper);
+ this.cancelHideAfter();
+ }).bindAsEventListener(this);
+ this.activityLeave = Prototip.capture(this.hideAfter).bindAsEventListener(this);
+ elements.invoke('observe', Tips.useEvent['mouseover'], this.activityEnter);
+ elements.invoke('observe', Tips.useEvent['mouseout'], this.activityLeave);
+ },
+
+ deactivate: function() {
+ if(this.options.showOn == this.options.hideOn)
+ this.element.stopObserving(this.options.showOn, this.eventToggle);
+ else {
+ this.element.stopObserving(this.options.showOn, this.eventShow);
+ if (this.hideTargets) this.hideTargets.invoke('stopObserving');
+ }
+
+ if (this.eventPosition) this.element.stopObserving('mousemove', this.eventPosition);
+ if (this.closeButton) this.closeButton.stopObserving();
+ if (this.eventCheckDelay) this.element.stopObserving('mouseout', this.eventCheckDelay);
+ this.wrapper.stopObserving();
+ this.element.stopObserving(Tips.useEvent['mouseover'], this.activityEnter);
+ this.element.stopObserving(Tips.useEvent['mouseout'], this.activityLeave);
+ },
+
+ showDelayed: function(event) {
+ if (!this.tooltip) this.build();
+ this.position(event); // follow mouse
+ if (this.wrapper.visible()) return;
+
+ this.clearTimer('show');
+ this.showTimer = this.show.bind(this).delay(this.options.delay);
+ },
+
+ clearTimer: function(timer) {
+ if (this[timer + 'Timer']) clearTimeout(this[timer + 'Timer']);
+ },
+
+ show: function() {
+ if (!this.tooltip) this.build();
+ if (this.wrapper.visible() && this.options.effect != 'appear') return;
+
+ if (Tips.fixIE) this.iframeShim.show();
+ Tips.addVisibile(this.wrapper);
+ this.wrapper.show();
+ if (!this.options.effect) this.tooltip.show();
+ else {
+ if (this.activeEffect) Effect.Queues.get(this.queue.scope).remove(this.activeEffect);
+ this.activeEffect = Effect[Effect.PAIRS[this.options.effect][0]](this.effectWrapper,
+ { duration: this.options.duration, queue: this.queue});
+ }
+ },
+
+ hideAfter: function(event) {
+ if (!this.options.hideAfter) return;
+ this.cancelHideAfter();
+ this.hideAfterTimer = this.hide.bind(this).delay(this.options.hideAfter);
+ },
+
+ cancelHideAfter: function() {
+ if (this.options.hideAfter) this.clearTimer('hideAfter');
+ },
+
+ hide: function() {
+ this.clearTimer('show');
+ if(!this.wrapper.visible()) return;
+
+ if (!this.options.effect) {
+ if (Tips.fixIE) this.iframeShim.hide();
+ this.tooltip.hide();
+ this.wrapper.hide();
+ Tips.removeVisible(this.wrapper);
+ }
+ else {
+ if (this.activeEffect) Effect.Queues.get(this.queue.scope).remove(this.activeEffect);
+ this.activeEffect = Effect[Effect.PAIRS[this.options.effect][1]](this.effectWrapper,
+ { duration: this.options.duration, queue: this.queue, afterFinish: function() {
+ if (Tips.fixIE) this.iframeShim.hide();
+ this.wrapper.hide();
+ Tips.removeVisible(this.wrapper);
+ }.bind(this)});
+ }
+ },
+
+ toggle: function(event) {
+ if (this.wrapper && this.wrapper.visible()) this.hide(event);
+ else this.showDelayed(event);
+ },
+
+ position: function(event) {
+ Tips.raise(this.wrapper);
+
+ var offset = {left: this.options.offset.x, top: this.options.offset.y};
+ var targetPosition = Position.cumulativeOffset(this.target);
+ var tipd = this.wrapper.getDimensions();
+
+ if (event)
+ var pos = { left: (this.options.fixed) ? targetPosition[0] : Event.pointerX(event),
+ top: (this.options.fixed) ? targetPosition[1] : Event.pointerY(event) };
+ else
+ var pos = { left: targetPosition[0], top: targetPosition[1] };
+
+ // add offsets
+ pos.left += offset.left;
+ pos.top += offset.top;
+
+ if (this.options.hook) {
+ var dims = {target: this.target.getDimensions(), tip: tipd}
+ var hooks = {target: Position.cumulativeOffset(this.target), tip: Position.cumulativeOffset(this.target)}
+
+ for (var z in hooks) {
+ switch (this.options.hook[z]) {
+ case 'topRight':
+ hooks[z][0] += dims[z].width;
+ break;
+ case 'topMiddle':
+ hooks[z][0] += (dims[z].width / 2);
+ break;
+ case 'rightMiddle':
+ hooks[z][0] += dims[z].width;
+ hooks[z][1] += (dims[z].height / 2);
+ break;
+ case 'bottomLeft':
+ hooks[z][1] += dims[z].height;
+ break;
+ case 'bottomRight':
+ hooks[z][0] += dims[z].width;
+ hooks[z][1] += dims[z].height;
+ break;
+ case 'bottomMiddle':
+ hooks[z][0] += (dims[z].width / 2);
+ hooks[z][1] += dims[z].height;
+ break;
+ case 'leftMiddle':
+ hooks[z][1] += (dims[z].height / 2);
+ break;
+ }
+ }
+
+ // move based on hooks
+ pos.left += -1*(hooks.tip[0] - hooks.target[0]);
+ pos.top += -1*(hooks.tip[1] - hooks.target[1]);
+ }
+
+ // move tooltip when there is a different target or when we don't have a event to position to
+ if ((!this.options.fixed && this.element !== this.target) || !event) {
+ var elementPosition = Position.cumulativeOffset(this.element);
+ pos.left += -1*(elementPosition[0] - targetPosition[0]);
+ pos.top += -1*(elementPosition[1] - targetPosition[1]);
+ }
+
+ if (!this.options.fixed && this.options.viewport) {
+ var scroll = document.viewport.getScrollOffsets();
+ var viewport = Prototip.viewport.getDimensions();
+ var pair = {left: 'width', top: 'height'};
+
+ for(var z in pair) {
+ if ((pos[z] + tipd[pair[z]] - scroll[z]) > viewport[pair[z]])
+ pos[z] = pos[z] - tipd[pair[z]] - 2*offset[z];
+ }
+ }
+
+ // Ensure that the tooltip does not render off screen left edge
+ if ( pos.left < 0 ) {
+ pos.left = 0;
+ }
+
+ var setPos = { left: pos.left + 'px', top: pos.top + 'px' };
+ this.wrapper.setStyle(setPos);
+ if (Tips.fixIE) this.iframeShim.setStyle(setPos);
+ }
+});
+
+Prototip.start();