bridgy-fed/static/fragmention.js

99 wiersze
3.1 KiB
JavaScript

// detect native/existing fragmention support
if (!('fragmention' in window.location)) (function () {
// populate fragmention
location.fragmention = location.fragmention || '';
// return first element in scope containing case-sensitive text
function getElementsByText(scope, text) {
// iterate descendants of scope
for (var all = scope.childNodes, index = 0, element, list = []; (element = all[index]); ++index) {
// conditionally return element containing visible, whitespace-insensitive, case-sensitive text (a match)
if (element.nodeType === 1 && (element.innerText || element.textContent || '').replace(/\s+/g, ' ').indexOf(text) !== -1) {
list = list.concat(getElementsByText(element, text));
}
}
// return scope (no match)
return list.length ? list : scope;
}
function getAnchorableElementByName(fragment) {
var elements = document.getElementsByName(fragment), index = -1;
while (elements[++index] && !/^A(REA)?$/.test(elements[index].nodeName)) {}
return elements[index];
}
// on dom ready or hash change
function onHashChange() {
// do nothing if the dom is not ready
if (!/e/.test(document.readyState)) return;
// set location fragmention as uri-decoded text (from href, as hash may be decoded)
var
id = location.href.match(/#((?:#|%23)?)(.+)/) || [0,'',''],
node = document.getElementById(id[1]+id[2]) || getAnchorableElementByName(id[1]+id[2]),
match = decodeURIComponent(id[2].replace(/\+/g, ' ')).split(' ');
location.fragmention = match[0];
location.fragmentionIndex = parseFloat(match[1]) || 0;
// conditionally remove stashed element fragmention attribute
if (element) {
element.removeAttribute('fragmention');
// DEPRECATED: trigger style in IE8
if (element.runtimeStyle) {
element.runtimeStyle.windows = element.runtimeStyle.windows;
}
}
// if fragmention exists
if (!node && location.fragmention) {
var
// get all elements containing text (or document)
elements = getElementsByText(document, location.fragmention),
// get total number of elements
length = elements.length,
// get index of element
modulus = length && location.fragmentionIndex % length,
index = length && modulus >= 0 ? modulus : length + modulus;
// get element
element = length && elements[index];
// if element found
if (element) {
// scroll to element
element.scrollIntoView();
// set fragmention attribute
element.setAttribute('fragmention', '');
// DEPRECATED: trigger style in IE8
if (element.runtimeStyle) {
element.runtimeStyle.windows = element.runtimeStyle.windows;
}
}
// otherwise clear stashed element
else {
element = null;
}
}
}
var
// DEPRECATED: configure listeners
defaultListener = 'addEventListener',
addEventListener = defaultListener in window ? [defaultListener, ''] : ['attachEvent', 'on'],
// set stashed element
element;
// add listeners
window[addEventListener[0]](addEventListener[1] + 'hashchange', onHashChange);
document[addEventListener[0]](addEventListener[1] + 'readystatechange', onHashChange);
onHashChange();
})();