2012-06-20 21:16:41 +00:00
|
|
|
/*\
|
2012-07-14 14:57:36 +00:00
|
|
|
title: $:/core/modules/utils/dom.js
|
2012-06-20 21:16:41 +00:00
|
|
|
type: application/javascript
|
|
|
|
module-type: utils
|
|
|
|
|
|
|
|
Various static DOM-related utility functions.
|
|
|
|
|
|
|
|
\*/
|
|
|
|
(function(){
|
|
|
|
|
|
|
|
/*jslint node: true, browser: true */
|
|
|
|
/*global $tw: false */
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
/*
|
|
|
|
Determines whether element 'a' contains element 'b'
|
|
|
|
Code thanks to John Resig, http://ejohn.org/blog/comparing-document-position/
|
|
|
|
*/
|
|
|
|
exports.domContains = function(a,b) {
|
|
|
|
return a.contains ?
|
|
|
|
a != b && a.contains(b) :
|
|
|
|
!!(a.compareDocumentPosition(b) & 16);
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.hasClass = function(el,className) {
|
|
|
|
return el.className.split(" ").indexOf(className) !== -1;
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.addClass = function(el,className) {
|
|
|
|
var c = el.className.split(" ");
|
|
|
|
if(c.indexOf(className) === -1) {
|
|
|
|
c.push(className);
|
|
|
|
}
|
|
|
|
el.className = c.join(" ");
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.removeClass = function(el,className) {
|
|
|
|
var c = el.className.split(" "),
|
|
|
|
p = c.indexOf(className);
|
|
|
|
if(p !== -1) {
|
|
|
|
c.splice(p,1);
|
|
|
|
el.className = c.join(" ");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.toggleClass = function(el,className,status) {
|
|
|
|
if(status === undefined) {
|
|
|
|
status = !exports.hasClass(el,className);
|
|
|
|
}
|
|
|
|
if(status) {
|
|
|
|
exports.addClass(el,className);
|
|
|
|
} else {
|
|
|
|
exports.removeClass(el,className);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.applyStyleSheet = function(id,css) {
|
|
|
|
var el = document.getElementById(id);
|
|
|
|
if(document.createStyleSheet) { // Older versions of IE
|
|
|
|
if(el) {
|
|
|
|
el.parentNode.removeChild(el);
|
|
|
|
}
|
|
|
|
document.getElementsByTagName("head")[0].insertAdjacentHTML("beforeEnd",
|
|
|
|
' <style id="' + id + '" type="text/css">' + css + '</style>'); // fails without
|
|
|
|
} else { // Modern browsers
|
|
|
|
if(el) {
|
|
|
|
el.replaceChild(document.createTextNode(css), el.firstChild);
|
|
|
|
} else {
|
|
|
|
el = document.createElement("style");
|
|
|
|
el.type = "text/css";
|
|
|
|
el.id = id;
|
|
|
|
el.appendChild(document.createTextNode(css));
|
|
|
|
document.getElementsByTagName("head")[0].appendChild(el);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-06-20 21:20:48 +00:00
|
|
|
/*
|
2012-07-07 16:14:50 +00:00
|
|
|
Get the scroll position of the viewport
|
|
|
|
Returns:
|
|
|
|
{
|
|
|
|
x: horizontal scroll position in pixels,
|
|
|
|
y: vertical scroll position in pixels
|
|
|
|
}
|
2012-06-20 21:20:48 +00:00
|
|
|
*/
|
2012-07-07 16:14:50 +00:00
|
|
|
exports.getScrollPosition = function() {
|
|
|
|
if("scrollX" in window) {
|
|
|
|
return {x: window.scrollX, y: window.scrollY};
|
|
|
|
} else {
|
|
|
|
return {x: document.documentElement.scrollLeft, y: document.documentElement.scrollTop};
|
2012-06-20 21:20:48 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-10-26 21:12:40 +00:00
|
|
|
/*
|
|
|
|
Gets the bounding rectangle of an element in absolute page coordinates
|
|
|
|
*/
|
|
|
|
exports.getBoundingPageRect = function(element) {
|
|
|
|
var scrollPos = $tw.utils.getScrollPosition(),
|
|
|
|
clientRect = element.getBoundingClientRect();
|
|
|
|
return {
|
|
|
|
left: clientRect.left + scrollPos.x,
|
|
|
|
width: clientRect.width,
|
|
|
|
right: clientRect.right + scrollPos.x,
|
|
|
|
top: clientRect.top + scrollPos.y,
|
|
|
|
height: clientRect.height,
|
|
|
|
bottom: clientRect.bottom + scrollPos.y
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2012-07-13 12:02:34 +00:00
|
|
|
/*
|
|
|
|
Saves a named password in the browser
|
|
|
|
*/
|
|
|
|
exports.savePassword = function(name,password) {
|
|
|
|
localStorage.setItem("tw5-password-" + name,password);
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
Retrieve a named password from the browser
|
|
|
|
*/
|
|
|
|
exports.getPassword = function(name) {
|
|
|
|
return localStorage.getItem("tw5-password-" + name);
|
|
|
|
};
|
|
|
|
|
2012-08-02 21:32:34 +00:00
|
|
|
/*
|
|
|
|
Force layout of a dom node and its descendents
|
|
|
|
*/
|
|
|
|
exports.forceLayout = function(element) {
|
|
|
|
var dummy = element.offsetWidth;
|
|
|
|
};
|
|
|
|
|
2012-10-15 16:18:32 +00:00
|
|
|
/*
|
|
|
|
Pulse an element for debugging purposes
|
|
|
|
*/
|
|
|
|
exports.pulseElement = function(element) {
|
|
|
|
// Event handler to remove the class at the end
|
|
|
|
element.addEventListener($tw.browser.animationEnd,function handler(event) {
|
|
|
|
element.removeEventListener($tw.browser.animationEnd,handler,false);
|
|
|
|
$tw.utils.removeClass(element,"pulse");
|
|
|
|
},false);
|
|
|
|
// Apply the pulse class
|
|
|
|
$tw.utils.removeClass(element,"pulse");
|
|
|
|
element.offsetWidth;
|
|
|
|
$tw.utils.addClass(element,"pulse");
|
|
|
|
};
|
|
|
|
|
2012-06-20 21:16:41 +00:00
|
|
|
})();
|