javascripts/right-tooltips-src.js in right-rails-0.4.4 vs javascripts/right-tooltips-src.js in right-rails-0.5.0
- old
+ new
@@ -1,130 +1,187 @@
/**
* The native tooltips feature for RightJS
*
* See http://rightjs.org/ui/tooltips for more details
*
- * Copyright (C) 2009 Nikolay V. Nemshilov aka St.
+ * Copyright (C) 2009-2010 Nikolay V. Nemshilov
*/
if (!RightJS) throw "Gimme RightJS!";
/**
* The native tooltips feature for RithJS
*
- *
- * Copyright (C) 2009 Nikolay V. Nemshilov aka St.
+ * Copyright (C) 2009-2010 Nikolay V. Nemshilov
*/
-
var Tooltip = new Class({
include: Options,
extend: {
Options: {
- checkTags: '*', // tags that should be checked on-load
- relName: 'tooltip',
- idSuffix: '-tooltip',
- fxName: 'fade',
- fxDuration: 400,
- delay: 400 // the appearance delay
+ cssRule: '[rel=tooltip]', // a css-marker of an element with a tooltip
+
+ fxName: 'fade', // the appearance effect name
+ fxDuration: 400, // the appearance effect duration
+ delay: 400, // the appearance delay
+
+ move: true, // if it should be moved with the mouse
+
+ idSuffix: '-tooltip' // ID prefix for tooltips with ID
},
current: null, // currently active tooltip reference
+ instances: [], // keeps the list of instances
- // scans the page for auto-discoverable tooltiped elements
- rescan: function(scope) {
- var key = Tooltip.Options.relName;
- ($(scope) || document).select(Tooltip.Options.checkTags+'[rel='+key+']').each(function(element) {
- var text = element.get('title') || element.get('alt');
- if (text) {
- var data = element.get('data-'+key+'-options');
- new Tooltip(element, eval('('+data+')'));
- }
- });
- }
+ // tries to find a tip closest to the event
+ find: function(event) {
+ var target = event.target, targets = [target].concat(target.parents()),
+ targets = targets.slice(0, targets.length - 2),
+ element = targets.first(function(node) {
+ return node._tooltip || node.match(Tooltip.Options.cssRule);
+ });
+
+ if (element) {
+ var uid = $uid(element);
+ return Tooltip.instances[uid] = Tooltip.instances[uid] || new Tooltip(element);
+ }
+ },
+
+ // DEPRECATED a dummy method for the old API backward compatibility
+ rescan: function(scope) { }
},
+ /**
+ * Constructor
+ *
+ * @param Element associated element
+ * @param Object options
+ */
initialize: function(element, options) {
- this.element = $E('div', {'class': 'right-tooltip'}).insertTo(document.body).hide();
- this.container = $E('div', {'class': 'right-tooltip-container'}).insertTo(this.element);
+ this.associate = element = $(element);
+ this.element = $E('div', {
+ 'class': 'right-tooltip',
+ 'html': '<div class="right-tooltip-arrow"></div>'+
+ '<div class="right-tooltip-container">'+
+ (element.get('title') || element.get('alt'))+
+ '</div>'
+ }).insertTo(document.body);
- this.setOptions(options).assignTo(element);
+ this.setOptions(options || eval('('+element.get('data-tooltips-options')+')'));
+
+ element.set({ title: '', alt: ''});
+
+ if (element.id)
+ this.element.id = element.id + this.options.idSuffix;
},
- setText: function(text) {
- this.container.update(text);
- return this;
- },
-
- getText: function() {
- return this.container.innerHTML;
- },
-
+ /**
+ * Hides the tooltip
+ *
+ * @return Tooltip this
+ */
hide: function() {
- Tooltip.current = null;
this.cancelTimer();
- this.element.hide(this.options.fxName, {duration: this.options.fxDuration});
+ this.element.hide(this.options.fxName, {
+ duration: this.options.fxDuration,
+ onFinish: function() {
+ if (Tooltip.current === this)
+ Tooltip.current = null;
+ }.bind(this)
+ });
return this;
},
- show: function() {
- Tooltip.current = this;
- this.element.show(this.options.fxName, {duration: this.options.fxDuration});
-
- return this;
+ /**
+ * Shows the tooltip with a dealy
+ *
+ * @param Boolean if true will show tooltip immediately
+ * @return Tooltip this
+ */
+ show: function(immediately) {
+ // hidding all the others
+ Tooltip.instances.each(function(tip) {
+ if (tip && tip !== this) tip.hide();
+ }, this);
+
+ // show the tooltip with a delay
+ this.timer = (function() {
+ this.element.stop().show(this.options.fxName, {duration: this.options.fxDuration});
+
+ Tooltip.current = this;
+ }).bind(this).delay(this.options.delay);
+
+ return Tooltip.current = this;
},
- showDelayed: function() {
- Tooltip.current = this;
- this.timer = this.show.bind(this).delay(this.options.delay);
- },
-
- cancelTimer: function() {
- if (this.timer) {
- this.timer.cancel();
- this.timer = null;
- }
- },
-
+ /**
+ * Moves the tooltip where the event happened
+ *
+ * @return Tooltip this
+ */
moveTo: function(event) {
this.element.style.left = event.pageX + 'px';
this.element.style.top = event.pageY + 'px';
return this;
},
- assignTo: function(element) {
- this.setText(element.get('title') || element.get('alt'));
-
- // removing the element native title and alt
- element.setAttribute('title', '');
- element.setAttribute('alt', '');
-
- element.on({
- mouseover: this.showDelayed.bind(this),
- mouseout: this.hide.bind(this)
- });
-
- if (element.id) this.element.id = element.id + this.options.idSuffix;
-
- this.associate = element;
-
- return this;
+// protected
+
+ // cancels a show timeout
+ cancelTimer: function() {
+ if (this.timer) {
+ this.timer.cancel();
+ this.timer = null;
+ }
}
});
/**
* The post load tooltips initialization script
*
- * Copyright (C) 2009 Nikolay V. Nemshilov aka St.
+ * Copyright (C) 2009-2010 Nikolay V. Nemshilov
*/
document.on({
- ready: function() { Tooltip.rescan(); },
+ /**
+ * Watches all the mouse-over events and reacts if one of the targets
+ * matches a tooltip
+ *
+ * @param Event event
+ */
+ mouseover: function(event) {
+ var prev_tip = Tooltip.current, this_tip = Tooltip.find(event);
+
+ if (this_tip) {
+ if (prev_tip && prev_tip !== this_tip) prev_tip.hide();
+ if (this_tip.element.hidden()) this_tip.show();
+
+ this_tip.moveTo(event);
+ }
+ },
+ /**
+ * Catches the mouseout events and hides tooltips when needed
+ *
+ * @param Event event
+ */
+ mouseout: function(event) {
+ var curr_tip = Tooltip.current, this_tip = Tooltip.find(event);
+
+ if (curr_tip && (!this_tip || this_tip === curr_tip))
+ curr_tip.hide();
+ },
+
+ /**
+ * Moves tooltips when active
+ *
+ * @param Event event
+ */
mousemove: function(event) {
- if (Tooltip.current) {
- Tooltip.current.moveTo(event);
+ var tip = Tooltip.current;
+ if (tip && tip.options.move) {
+ tip.moveTo(event);
}
}
});
-document.write("<style type=\"text/css\">div.right-tooltip{position:absolute;margin-top:16pt;margin-left:2pt;border:1px solid #DDD;background-color:#FFF8EE;color:#666;font-size:80%;cursor:default;border-radius:.4em;-moz-border-radius:.4em;-webkit-border-radius:.4em;box-shadow:.4em .4em .4em #AAA;-moz-box-shadow:.4em .4em .4em #AAA;-webkit-box-shadow:.4em .4em .4em #AAA}div.right-tooltip-container{margin:.6em;border-left:2px solid brown;padding-left:.5em}</style>");
+document.write("<style type=\"text/css\">div.right-tooltip{display:none;position:absolute;z-index:999999;font-size:90%;margin-top:16pt;margin-left:5pt;color:#FFF;text-shadow:0 0 .2em #000;border:.3em solid rgba(255,255,255,0.2);background-color:rgba(25,25,25,0.92);background-image:-webkit-gradient(linear,0% 0%,0% 100%,from(transparent),to(#000));*background-color:#000;*border:.3em solid #444;border-radius:.4em;-moz-border-radius:.4em;-webkit-border-radius:.4em;box-shadow:0 0 .4em #555;-moz-box-shadow:0 0 .4em #555;-webkit-box-shadow:0 0 .4em #555}div.right-tooltip-container{margin:.4em .6em}</style>");
\ No newline at end of file