MediaWiki:Cluetip.js

Aus Offene Naturführer
Wechseln zu: Navigation, Suche

Hinweis - Leere nach dem Speichern den Browser-Cache, um die Änderungen sehen zu können: Mozilla/Firefox/Safari: Shift gedrückt halten und auf Aktualisieren klicken oder alternativ entweder Strg-F5 oder Strg-R (Befehlstaste-R bei Macintosh) drücken; Konqueror: Auf Aktualisieren klicken oder F5 drücken; Opera: Cache unter Extras → Internetspuren löschen…; Internet Explorer: Strg-F5 drücken oder Strg gedrückt halten und dabei Aktualisieren anklicken.

//////////////////////////////////////////////////
// Cluetip Code from http://plugins.learningjquery.com/cluetip/
// Version 1.0.6.x (modified for Off.Naturführer)
// Dual licensed under the MIT and GPL licenses (compatible with license here):
// http://www.opensource.org/licenses/mit-license.php
// http://www.gnu.org/licenses/gpl.html
// Maintained by Karl Swedberg, additional credits on site above and here in version 2010-06-05T11:33
(function($) {
	$.cluetip = {version: '1.0.6'};
	var $cluetip, $cluetipInner, $cluetipOuter, $cluetipTitle, $cluetipArrows, $cluetipWait, $dropShadow, imgCount,
		insertionElement = 'body';
	$.fn.cluetip = function(js, options) {
		if (typeof js == 'object') {
			options = js;
			js = null;
		}
		if (js == 'destroy') {
			return this.removeData('thisInfo').unbind('.cluetip');
		}
		return this.each(function(index) {
			var link=this, $this=$(this);

			// support metadata plugin (v1.0 and 2.0)
			var opts = $.extend(true, {}, $.fn.cluetip.defaults, options || {}, $.metadata ? $this.metadata() : $.meta ? $this.data() : {});

			// start out with no contents (for ajax activation)
			var cluetipContents = false;
			var cluezIndex = +opts.cluezIndex;
			$this.data('thisInfo', {title: link.title, zIndex: cluezIndex});
			var isActive = false, closeOnDelay = 0;

			// create the cluetip divs
			if (!$('#cluetip').length) {
				$(['<div id="cluetip">',
					'<div id="cluetip-outer">',
						'<h3 id="cluetip-title"></h3>',
						'<div id="cluetip-inner"></div>',
					'</div>',
					'<div id="cluetip-extra"></div>',
					'<div id="cluetip-arrows" class="cluetip-arrows"></div>',
				'</div>'].join(''))
				.appendTo(insertionElement).hide();

				$cluetip = $('#cluetip').css({position: 'absolute'});
				$cluetipOuter = $('#cluetip-outer').css({position: 'relative', zIndex: cluezIndex});
				$cluetipInner = $('#cluetip-inner');
				$cluetipTitle = $('#cluetip-title');
				$cluetipArrows = $('#cluetip-arrows');
				$cluetipWait = $('<div id="cluetip-waitimage"></div>')
					.css({position: 'absolute'}).insertBefore($cluetip).hide();
			}
			var dropShadowSteps = (opts.dropShadow) ? +opts.dropShadowSteps : 0;
			if (!$dropShadow) {
				$dropShadow = $([]);
				for (var i=0; i < dropShadowSteps; i++) {
					$dropShadow = $dropShadow.add($('<div></div>').css({zIndex: cluezIndex-1, opacity:0.1, top: 1+i, left: 1+i}));
				}
				$dropShadow.css({position: 'absolute', backgroundColor: '#000'})
				.prependTo($cluetip);
			}
			var tipAttribute = $this.attr(opts.attribute);
			if (!tipAttribute && !opts.splitTitle && !js) {
				return true;
			}
			// if hideLocal is set to true, on DOM ready hide the local content that will be displayed in the clueTip
			if (opts.local && opts.localPrefix) {tipAttribute = opts.localPrefix + tipAttribute;}
			if (opts.local && opts.hideLocal) { $(tipAttribute + ':first').hide(); }
			var tOffset = parseInt(opts.topOffset, 10), lOffset = parseInt(opts.leftOffset, 10);
			// vertical measurement variables
			var tipHeight, wHeight,
					sTop, linkTop, posY, tipY, mouseY, baseline,
					defHeight = isNaN(parseInt(opts.height, 10)) ? 'auto' : (/\D/g).test(opts.height) ? opts.height : opts.height + 'px';
			// horizontal measurement variables
			var tipInnerWidth = parseInt(opts.width, 10) || 275,
				tipWidth = tipInnerWidth + (parseInt($cluetip.css('paddingLeft'),10)||0) + (parseInt($cluetip.css('paddingRight'),10)||0) + dropShadowSteps,
				linkWidth = this.offsetWidth,
				linkLeft, posX, mouseX, winWidth;

			// parse the title
			var tipParts;
			var tipTitle = (opts.attribute != 'title') ? $this.attr(opts.titleAttribute) : '';
			if (opts.splitTitle) {
				if (tipTitle === undefined) {tipTitle = '';}
				tipParts = tipTitle.split(opts.splitTitle);
				tipTitle = tipParts.shift();
			}
			if (opts.escapeTitle) {
				tipTitle = tipTitle.replace(/&/g,'&amp;').replace(/>/g,'&gt;').replace(/</g,'&lt;');
			}

			function returnFalse() { return false; }

/***************************************
* ACTIVATION
****************************************/

//activate clueTip
		var activate = function(event) {
			var pY;
			if (!opts.onActivate($this)) {
				return false;
			}
			isActive = true;
			$cluetip.removeClass().css({width: tipInnerWidth});
			if (tipAttribute == $this.attr('href')) {
				$this.css('cursor', opts.cursor);
			}
			if (opts.hoverClass) {
				$this.addClass(opts.hoverClass);
			}
			linkTop = posY = $this.offset().top;
			linkLeft = $this.offset().left;
			mouseX = event.pageX;
			mouseY = event.pageY;
			if (link.tagName.toLowerCase() != 'area') {
				sTop = $(document).scrollTop();
				winWidth = $(window).width();
			}
// position clueTip horizontally
			if (opts.positionBy == 'fixed') {
				posX = linkWidth + linkLeft + lOffset;
				$cluetip.css({left: posX});
			} else {
				posX = (linkWidth > linkLeft && linkLeft > tipWidth) || linkLeft + linkWidth + tipWidth + lOffset > winWidth ? linkLeft - tipWidth - lOffset : linkWidth + linkLeft + lOffset;
				if (link.tagName.toLowerCase() == 'area' || opts.positionBy == 'mouse' || linkWidth + tipWidth > winWidth) { // position by mouse
					if (mouseX + 20 + tipWidth > winWidth) {
						$cluetip.addClass(' cluetip-jtip');
						posX = (mouseX - tipWidth - lOffset) >= 0 ? mouseX - tipWidth - lOffset - parseInt($cluetip.css('marginLeft'),10) + parseInt($cluetipInner.css('marginRight'),10) :	mouseX - (tipWidth/2);
					} else {
						posX = mouseX + lOffset;
					}
				}
				pY = posX < 0 ? event.pageY + tOffset : event.pageY;
				$cluetip.css({
					left: (posX > 0 && opts.positionBy != 'bottomTop') ? posX : (mouseX + (tipWidth/2) > winWidth) ? winWidth/2 - tipWidth/2 : Math.max(mouseX - (tipWidth/2),0),
					zIndex: $this.data('thisInfo').zIndex
				});
				$cluetipArrows.css({zIndex: $this.data('thisInfo').zIndex+1});
			}
			wHeight = $(window).height();

/***************************************
* load a string from cluetip method's first argument
***************************************/
			if (js) {
				if (typeof js == 'function') {
					js = js.call(link);
				}
				$cluetipInner.html(js);
				cluetipShow(pY);
			}
/***************************************
* load the title attribute only (or user-selected attribute).
* clueTip title is the string before the first delimiter
* subsequent delimiters place clueTip body text on separate lines
***************************************/

			else if (tipParts) {
				var tpl = tipParts.length;
				$cluetipInner.html(tpl ? tipParts[0] : '');
				if (tpl > 1) {
					for (var i=1; i < tpl; i++){
						$cluetipInner.append('<div class="split-body">' + tipParts[i] + '</div>');
					}
				}
				cluetipShow(pY);
			}
/***************************************
* load external file via ajax
***************************************/

			else if (!opts.local && tipAttribute.indexOf('#') !== 0) {
				if (/\.(jpe?g|tiff?|gif|png)$/i.test(tipAttribute)) {
					$cluetipInner.html('<img src="' + tipAttribute + '" alt="' + tipTitle + '" />');
					cluetipShow(pY);
				} else if (cluetipContents && opts.ajaxCache) {
					$cluetipInner.html(cluetipContents);
					cluetipShow(pY);
				} else {
					var optionBeforeSend = opts.ajaxSettings.beforeSend,
							optionError = opts.ajaxSettings.error,
							optionSuccess = opts.ajaxSettings.success,
							optionComplete = opts.ajaxSettings.complete;
					var ajaxSettings = {
						cache: false, // force requested page not to be cached by browser
						url: tipAttribute,
						beforeSend: function(xhr) {
							if (optionBeforeSend) {optionBeforeSend.call(link, xhr, $cluetip, $cluetipInner);}
							$cluetipOuter.children().empty();
							$cluetipWait.css({top: mouseY+20, left: mouseX+20, zIndex: $this.data('thisInfo').zIndex-1}).show();
						},
						error: function(xhr, textStatus) {
							if (isActive) {
								if (optionError) {
									optionError.call(link, xhr, textStatus, $cluetip, $cluetipInner);
								} else {
									$cluetipInner.html('<i>sorry, the contents could not be loaded</i>');
								}
							}
						},
						success: function(data, textStatus) {
							cluetipContents = opts.ajaxProcess.call(link, data);
							if (isActive) {
								if (optionSuccess) {optionSuccess.call(link, data, textStatus, $cluetip, $cluetipInner);}
								$cluetipInner.html(cluetipContents);
							}
						},
						complete: function(xhr, textStatus) {
							if (optionComplete) {optionComplete.call(link, xhr, textStatus, $cluetip, $cluetipInner);}
							imgCount = $('#cluetip-inner img').length;
							if (imgCount && !$.browser.opera) {
								$('#cluetip-inner img').bind('load error', function() {
									imgCount--;
									if (imgCount<1) {
										$cluetipWait.hide();
										if (isActive) { cluetipShow(pY); }
									}
								});
							} else {
								$cluetipWait.hide();
								if (isActive) { cluetipShow(pY); }
							}
						}
					};
					var ajaxMergedSettings = $.extend(true, {}, opts.ajaxSettings, ajaxSettings);
					$.ajax(ajaxMergedSettings);
				}

/***************************************
* load an element from the same page
***************************************/
			} else if (opts.local) {

				var $localContent = $(tipAttribute + (/#\S+$/.test(tipAttribute) ? '' : ':eq(' + index + ')')).clone(true).show();
				$cluetipInner.html($localContent);
				cluetipShow(pY);
			}
		};

// get dimensions and options for cluetip and prepare it to be shown
		var cluetipShow = function(bpY) {
			$cluetip.addClass('cluetip-jtip');
			if (opts.truncate) {
				var $truncloaded = $cluetipInner.text().slice(0,opts.truncate) + '...';
				$cluetipInner.html($truncloaded);
			}
			if (opts.showTitle) {
				$cluetipTitle.show().html(tipTitle ? tipTitle : '&nbsp;');
			} else {
				$cluetipTitle.hide();
			}
			// INSERTED CODE: get href (= real wiki page link) and add as link in title ("(New Window)"). Cluetip now on link itself!
			// Not found how to get access in onShow() to "this"; thus inserted here.
			$cluetipTitle.prepend("<a href='"+ $this.attr("href") + "' target='_blank' title='"+ $j.resource('toolTipNewWindow') +"' >" + $j.resource('newWindow') + "</a>").show();
			if (opts.sticky) { // Close text modified directly
				var $closeLink = $j('<div id="cluetip-close"/>').append(buttonClose(function() {cluetipClose();return false;}));
				if(opts.closePosition == 'bottom') {
					$closeLink.appendTo($cluetipInner);
				} else if(opts.closePosition == 'title'){
					$closeLink.prependTo($cluetipTitle);
				} else {
					$closeLink.prependTo($cluetipInner);
				}
				// ### SHOULD BE HANDLED ABOVE ##### $closeLink.bind('click.cluetip', function() {cluetipClose();return false;});
				if (opts.mouseOutClose) {
					$cluetip.bind('mouseleave.cluetip', function() {cluetipClose();});
				} else {
					$cluetip.unbind('mouseleave.cluetip');
				}
			}
// now that content is loaded, finish the positioning
			var direction = '';
			$cluetipOuter.css({zIndex: $this.data('thisInfo').zIndex, overflow: defHeight == 'auto' ? 'visible' : 'auto', height: defHeight});
			tipHeight = defHeight == 'auto' ? Math.max($cluetip.outerHeight(),$cluetip.height()) : parseInt(defHeight,10);
			tipY = posY;
			baseline = sTop + wHeight;
			if (opts.positionBy == 'fixed') {
				tipY = posY - opts.dropShadowSteps + tOffset;
			} else if ( (posX < mouseX && Math.max(posX, 0) + tipWidth > mouseX) || opts.positionBy == 'bottomTop') {
				if (posY + tipHeight + tOffset > baseline && mouseY - sTop > tipHeight + tOffset) {
					tipY = mouseY - tipHeight - tOffset;
					direction = 'top';
				} else {
					tipY = mouseY + tOffset;
					direction = 'bottom';
				}
			} else if ( posY + tipHeight + tOffset > baseline ) {
				tipY = (tipHeight >= wHeight) ? sTop : baseline - tipHeight - tOffset;
			} else if ($this.css('display') == 'block' || link.tagName.toLowerCase() == 'area' || opts.positionBy == "mouse") {
				tipY = bpY - tOffset;
			} else {
				tipY = posY - opts.dropShadowSteps;
			}
			if (direction == '') {
				direction = (posX < linkLeft) ? 'left' : 'right';
			}
			$cluetip.css({top: tipY + 'px'}).removeClass().addClass('clue-' + direction + '-jtip').addClass(' cluetip-jtip');
			if (opts.arrows) { // set up arrow positioning to align with element
				var bgY = (posY - tipY - opts.dropShadowSteps);
				$cluetipArrows.css({top: (/(left|right)/.test(direction) && posX >=0 && bgY > 0) ? bgY + 'px' : /(left|right)/.test(direction) ? 0 : ''}).show();
			} else {
				$cluetipArrows.hide();
			}

// (first hide, then) ***SHOW THE CLUETIP***
			$dropShadow.hide();
			$cluetip.hide()[opts.fx.open](opts.fx.openSpeed || 0);
			if (opts.dropShadow) { $dropShadow.css({height: tipHeight, width: tipInnerWidth, zIndex: $this.data('thisInfo').zIndex-1}).show(); }
			if ($.fn.bgiframe) { $cluetip.bgiframe(); }
			// trigger the optional onShow function
			opts.onShow.call(link, $cluetip, $cluetipInner);
		};

/**************
* INACTIVATION
***************/
		var inactivate = function(event) {
			isActive = false;
			$cluetipWait.hide();
			if (!opts.sticky || (/click|toggle/).test(opts.activation) ) {
				cluetipClose();
				clearTimeout(closeOnDelay);
			}
			if (opts.hoverClass) {
				$this.removeClass(opts.hoverClass);
			}
		};
// close cluetip and reset some things
		var cluetipClose = function() {
			$cluetipOuter
			.parent().hide().removeClass();
			opts.onHide.call(link, $cluetip, $cluetipInner);
			$this.removeClass('cluetip-clicked');
			if (tipTitle) {
				$this.attr(opts.titleAttribute, tipTitle);
			}
			$this.css('cursor','');
			if (opts.arrows) {
				$cluetipArrows.css({top: ''});
			}
		};
		$(document).bind('hideCluetip', function(e) {
			cluetipClose();
		});
/***************************************
	 =BIND EVENTS
-------------------------------------- */
	// activate by click
			if ( (/click|toggle/).test(opts.activation) ) {
				$this.bind('click.cluetip', function(event) {
					if ($cluetip.is(':hidden') || !$this.is('.cluetip-clicked')) {
						activate(event);
						$('.cluetip-clicked').removeClass('cluetip-clicked');
						$this.addClass('cluetip-clicked');
					} else {
						inactivate(event);
					}
					this.blur();
					return false;
				});
	// activate by focus; inactivate by blur
			} else if (opts.activation == 'focus') {
				$this.bind('focus.cluetip', function(event) {
					activate(event);
				});
				$this.bind('blur.cluetip', function(event) {
					inactivate(event);
				});
	// activate by hover
			} else {
				// clicking is returned false if clickThrough option is set to false
				$this[opts.clickThrough ? 'unbind' : 'bind']('click', returnFalse);
				if ($.fn.hoverIntent && opts.hoverIntent) {
					$this.hoverIntent({
						sensitivity: opts.hoverIntent.sensitivity,
						interval: opts.hoverIntent.interval,
						over: function(event) {
							activate(event);
						},
						timeout: opts.hoverIntent.timeout,
						out: function(event) {inactivate(event); $this.unbind('mousemove.cluetip');}
					});
				} else {
					$this.bind('mouseenter.cluetip', function(event) {
						activate(event);
					})
					.bind('mouseleave.cluetip', function(event) {
						inactivate(event);
						$this.unbind('mousemove.cluetip');
					});
				}
				$this.bind('mouseover.cluetip', function(event) {
					$this.attr('title','');
				}).bind('mouseleave.cluetip', function(event) {
					$this.attr('title', $this.data('thisInfo').title);
				});
			}
		});
	};

/*
 * Options for clueTip
 * Each can be explicitly overridden by changing its value
 * $.fn.cluetip.defaults.width = 200;
 * Each can also be overridden by passing an options map to the cluetip method
 * $('a.example').cluetip({width: 200});
 * would change the default width to 200 for clueTips invoked by a link with class of "example"
 */

	$.fn.cluetip.defaults = {	// set up default options
		width:						400,			// The width of the clueTip
		height:					 'auto',	 // The height of the clueTip
		cluezIndex:			 97,			 // Sets the z-index style property of the clueTip
		positionBy:			 'auto',	 // Sets the type of positioning: 'auto', 'mouse','bottomTop', 'fixed'
		topOffset:				24,			 // Number of px to offset clueTip from top of invoking element
		leftOffset:			 12,			 // Number of px to offset clueTip from left of invoking element
		local:						false,		// Whether to use content from the same page for the clueTip's body
		localPrefix:			null,		 // string to be prepended to the tip attribute if local is true
		hideLocal:				true,		 // If local is true, this determines whether local content to be shown in clueTip should be hidden at its original location
		attribute:				'resource', // the attribute to be used for fetching the clueTip's body content -- rel is sanitized by wiki!!!
		titleAttribute:	 'title',	// the attribute to be used for fetching the clueTip's title
		splitTitle:			 '',			 // A char to split the title attribute into title and divs within clueTip body. Example: |
		escapeTitle:			false,		// whether to html escape the title attribute
		showTitle:				true,		 // show title bar of the clueTip, even if title attribute not set
		hoverClass:			 '',			 // class applied to the invoking element onmouseover and removed onmouseout
		cursor:					 'help',
		arrows:					 false,		// if true, displays arrow on appropriate side of clueTip
		dropShadow:			 true,		 // set to false if you don't want the drop-shadow effect on the clueTip
		dropShadowSteps:	6,				// adjusts the size of the drop shadow
		sticky:					 false,		// keep visible until manually closed
		mouseOutClose:		false,		// close when clueTip is moused out
		activation:			 'hover',	// set to 'click' to force user to click to show clueTip
																// set to 'focus' to show on focus of a form element and hide on blur
		clickThrough:		 false,		// if true, and activation is not 'click', then clicking on link will take user to the link's href,
																// even if href and tipAttribute are equal
		closePosition:		'top',		// location of close text for sticky cluetips; can be 'top' or 'bottom' or 'title'
		closeText:				'X',			// text (or HTML) to to be clicked to close sticky clueTips
		truncate:				 0,				// number of characters to truncate clueTip's contents. if 0, no truncation occurs

		// effect and speed for opening clueTips
		fx: {
				open:			 'show', // can be 'show' or 'slideDown' or 'fadeIn'
				openSpeed:	''
		},

		// settings for hoverIntent
		hoverIntent: {
				sensitivity:	4,
				interval:		 300,
				timeout:			0
		},

		// short-circuit function to run just before clueTip is shown.
		onActivate:	function(e) {return true;},
		// function to run just after clueTip is shown.
		onShow:			function(ct, ci){},
		// function to run just after clueTip is hidden.
		onHide:			function(ct, ci){},
		// whether to cache results of ajax request to avoid unnecessary hits to server
		ajaxCache:	 true,
		// process data retrieved via xhr before it's displayed
		ajaxProcess: function(data) {
									data = data.replace(/<(script|style|title)[^<]+<\/(script|style|title)>/gm, '').replace(/<(link|meta)[^>]+>/g,'');
									return data;
								},

		// can pass in standard $.ajax() parameters. Callback functions, such as beforeSend,
		// will be queued first within the default callbacks.
		// The only exception is error, which overrides the default
		ajaxSettings: {
		// error: function(ct, ci) { /* override default error callback */ }
		// beforeSend: function(ct, ci) { /* called first within default beforeSend callback }
		dataType: 'html'
		}
	};
})($j);
Quelle: Offene Naturführer, Das Wiki zu Bestimmungsfragen: MediaWiki:Cluetip.js. Abgerufen am 23. Dezember 2024, 10:45 von https://offene-naturfuehrer.de/web/MediaWiki:Cluetip.js