META-INF.resources.jquery.position.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of richfaces-core-impl Show documentation
Show all versions of richfaces-core-impl Show documentation
The RichFaces Core Implementation.
/**
* @fileOverview jQuery setPosition Plugin to place elements on the page
* @author Pavel Yaschenko, 05.2010
* @version 0.5
*/
// draft examples of usage
// jQuery('#tooltip').setPosition('#aaa',{from:'bottom-left', to:'auto-auto'});
// jQuery('#bbb').bind("click",function(e){jQuery('#tooltip').setPosition(e);});
// TODO: clear code
// TODO: optimization
// jQuery(target).setPosition(source,[params])
// source:
// jQuery selector
// object {id:}
// object {left:,top:,width:,height} // all properties are optimal
// jQuery object
// dom element
// event
//
// params:
// type: string // position type
// collision: string // not implemented
// offset: array [x,y] // implemented only for noPositionType
// from: string // place target relative of source
// to: string // direction for target
/**
* @name jQuery
* @namespace jQuery
* */
(function($) {
/**
* Place DOM element relative to another element or using position parameters. Elements with style.display='none' also supported.
*
* @example jQuery('#tooltip').setPosition('#myDiv',{from:'LB', to:'AA'});
* @example jQuery('#myClickDiv').bind("click",function(e){jQuery('#tooltip').setPosition(e);});
*
* @function
* @name jQuery#setPosition
*
* @param {object} source - object that provides information about new position.
* accepts:
*
* - jQuery selector or object
* - object with id:
{id:'myDiv'}
* - object with region settings:
{left:0, top:0, width:100, height:100}
* - DOM Element
* - Event object
*
*
* @param {object} params - position parameters:
* -
* @param {string} [params.type] - position type that defines positioning and auto positioning rules ["TOOLTIP","DROPDOWN"]
-
* @param {string} [params.collision] - not implemented yet
-
* @param {array} [params.offset] - provides array(2) with x and y for manually position definition
* affects only if "type", "from" and "to" not defined -
* @param {string} [params.from] - place target relative of source // draft definition
-
* @param {string} [params.to] - direction for target // draft definition
*
*
* @return {jQuery} jQuery wrapped DOM elements
* */
$.fn.setPosition = function(source, params) {
var stype = typeof source;
if (stype == "object" || stype == "string") {
var rect = {};
if (stype == "string" || source.nodeType || source instanceof jQuery || typeof source.length!="undefined") {
rect = getElementRect(source);
} else if (source.type) {
rect = getPointerRect(source);
} else if (source.id) {
rect = getElementRect(document.getElementById(source.id));
} else {
rect = source;
}
var params = params || {};
var def = params.type || params.from || params.to ? $.PositionTypes[params.type || defaultType] : {noPositionType:true};
var options = $.extend({}, defaults, def, params);
if (!options.noPositionType) {
if (options.from.length>2) {
options.from = positionDefinition[options.from.toLowerCase()];
}
if (options.to.length>2) {
options.to = positionDefinition[options.to.toLowerCase()];
}
}
return this.each(function() {
element = $(this);
//alert(rect.left+" "+rect.top+" "+rect.width+" "+rect.height);
position(rect, element, options);
});
}
return this;
};
var defaultType = "TOOLTIP";
var defaults = {
collision: "",
offset: [0,0]
};
var re = /^(left|right)-(top|buttom|auto)$/i;
// TODO: make it private
var positionDefinition = {
'top-left':'LT',
'top-right':'RT',
'bottom-left':'LB',
'bottom-right':'RB',
'top-auto':'AT',
'bottom-auto':'AB',
'auto-left':'LA',
'auto-right':'RA',
'auto-auto':'AA'
};
$.PositionTypes = {
// horisontal constants: L-left, R-right, C-center, A-auto
// vertical constants: T-top, B-bottom, M-middle, A-auto
// for auto: list of joinPoint-Direction pairs
TOOLTIP: {from:"AA", to:"AA", auto:["RTRT", "RBRT", "LTRT", "RTLT", "LTLT", "LBLT", "RTRB", "RBRB", "LBRB", "RBLB"]},
DROPDOWN:{from:"AA", to:"AA", auto:["LBRB", "LTRT", "RBLB", "RTLT"]},
DDMENUGROUP:{from:"AA", to:"AA", auto:["RTRB", "RBRT", "LTLB", "LBLT"]}
};
/**
* Add or replace position type rules for auto positioning.
* Does not fully determinated with parameters yet, only draft version.
*
* @function
* @name jQuery.addPositionType
* @param {string} type - name of position rules
* @param {object} option - options of position rules
* */
$.addPositionType = function (type, options) {
// TODO: change [options] to [from, to, auto]
/*var obj = {};
if (match=from.match(re))!=null ) {
obj.from = [ match[1]=='right' ? 'R' : 'L', match[2]=='bottom' ? 'B' : 'T'];
}
if (match=to.match(re))!=null ) {
obj.to = [ match[1]=='right' ? 'R' : match[1]=='left' ? 'L' : 'A', match[2]=='bottom' ? 'B' : match[2]=='top' ? 'T' : 'A'];
}*/
$.PositionTypes[type] = options;
}
function getPointerRect (event) {
var e = $.event.fix(event);
return {width: 0, height: 0, left: e.pageX, top: e.pageY};
};
function getElementRect (element) {
var jqe = $(element);
var offset = jqe.offset();
var rect = {width: jqe.outerWidth(), height: jqe.outerHeight(), left: Math.floor(offset.left), top: Math.floor(offset.top)};
if (jqe.length>1) {
var width, height, offset;
var e;
for (var i=1;i rect.width) rect.width = width - d;
} else {
rect.width += d;
}
var d = rect.top - offset.top;
if (d<0) {
if (height-d > rect.height) rect.height = height -d;
} else {
rect.height += d;
}
if (offset.left < rect.left) rect.left = offset.left;
if (offset.top < rect.top) rect.top = offset.top;
}
}
return rect;
};
function checkCollision (elementRect, windowRect) {
// return 0 if elementRect in windowRect without collision
if (elementRect.left >= windowRect.left &&
elementRect.top >= windowRect.top &&
elementRect.right <= windowRect.right &&
elementRect.bottom <= windowRect.bottom)
return 0;
// return collision squire
var rect = {left: (elementRect.left>windowRect.left ? elementRect.left : windowRect.left),
top: (elementRect.top>windowRect.top ? elementRect.top : windowRect.top)};
rect.right = elementRect.right=0 && oy>=0 && theBest.squares)) {
ox=theBest.x; oy=theBest.y
}
}
return {left:ox, top:oy};
}
function position (rect, element, options) {
var width = element.width();
var height = element.height();
rect.width = rect.width || 0;
rect.height = rect.height || 0;
var left = parseInt(element.css('left'),10);
if (isNaN(left) || left==0) {
left = 0;
element.css('left', '0px');
}
if (isNaN(rect.left)) rect.left = left;
var top = parseInt(element.css('top'),10);
if (isNaN(top) || top==0) {
top = 0;
element.css('top', '0px');
}
if (isNaN(rect.top)) rect.top = top;
var pos = {};
if (options.noPositionType) {
pos.left = rect.left + rect.width + options.offset[0];
pos.top = rect.top + options.offset[1];
} else {
var jqw = $(window);
var winRect = {left:jqw.scrollLeft(), top:jqw.scrollTop()};
winRect.right = winRect.left + jqw.width();
winRect.bottom = winRect.top + jqw.height();
pos = calculatePosition(rect, options.offset, winRect, {width:width, height:height}, options);
}
// jQuery does not support to get offset for hidden elements
var hideElement=false;
var eVisibility;
var e;
if (element.css("display")=="none") {
hideElement=true;
e = element.get(0);
eVisibility = e.style.visibility;
e.style.visibility = 'hidden';
e.style.display = 'block';
}
var elementOffset = element.offset();
if (hideElement) {
e.style.visibility = eVisibility;
e.style.display = 'none';
}
pos.left += left - Math.floor(elementOffset.left);
pos.top += top - Math.floor(elementOffset.top);
if (left!=pos.left) {
element.css('left', (pos.left + 'px'));
}
if (top!=pos.top) {
element.css('top', (pos.top + 'px'));
}
};
})(jQuery);