- , , ( ).
- , TreeWalker ( node IE) . . , .
window.fixedElementsTool = {
data: {
error: false,
method: typeof document.createTreeWalker == 'function' && typeof NodeFilter !== 'undefined' ? 'TreeWalker' : 'NodeTraversal',
viewport: { width: -1, height: -1 },
fixedElements: []
},
walker: null,
reject_tags: ['script','param'],
skip_tags: ['noscript', 'option'],
acceptNode: function(node){
var self = window.fixedElementsTool;
if (self.reject_tags.indexOf(node.tagName.toLowerCase()) > -1){
return self.data.method == 'TreeWalker' ? NodeFilter.FILTER_REJECT : false;
}
else if (self.skip_tags.indexOf(node.tagName.toLowerCase()) > -1){
return self.data.method == 'TreeWalker' ? NodeFilter.FILTER_SKIP : false;
}
else {
return self.data.method == 'TreeWalker' ? NodeFilter.FILTER_ACCEPT : true;
}
},
getStyle: function (el,styleProp){
try{
if (window.getComputedStyle){
return document.defaultView.getComputedStyle(el,null).getPropertyValue(styleProp);
}
else if (el.currentStyle){
return el.currentStyle[styleProp];
}
else {
return '';
}
}
catch(e){
return 'failed';
}
},
init: function(){
this.addPolyfills();
this.data.fixedElements = [];
try{
if (this.data.method == 'TreeWalker'){
this.walker = document.createTreeWalker( document.body, NodeFilter.SHOW_ELEMENT, this.acceptNode, false);
this.traverse();
}
else {
this.traverseIE(document.body);
}
this.data.viewport = this.getViewport();
}
catch(e){
this.data.error = e;
}
finally{
if (this.data.error){
}
}
},
toggle: function(toggle, type){
if (this.data.fixedElements.length == 0){ this.init(); }
switch(type){
case 'all':
for (var i=0; i < this.data.fixedElements.length; i++){
var item = this.data.fixedElements[i];
item.node.style.display = toggle == 'hide' ? 'none' : item.originalDisplay;
};
break;
case 'top':
for (var i=0; i < this.data.fixedElements.length; i++){
var item = this.data.fixedElements[i];
if (item.rect.top <= 5){
item.node.style.display = toggle == 'hide' ? 'none' : item.originalDisplay;
}
};
break;
case 'bottom':
for (var i=0; i < this.data.fixedElements.length; i++){
var item = this.data.fixedElements[i],
offsetBottom = this.data.viewport.height - item.rect.bottom;
if (offsetBottom <= 5){
item.node.style.display = toggle == 'hide' ? 'none' : item.originalDisplay;
}
};
break;
}
},
traverse: function(){
var position = this.getStyle(this.walker.currentNode,'position');
if (position == 'fixed'){
this.data.fixedElements.push({
node: this.walker.currentNode,
rect: this.walker.currentNode.getBoundingClientRect(),
originalDisplay: this.getStyle(this.walker.currentNode,'display') || ''
});
}
if (this.walker.firstChild()){
this.traverse();
}
if (this.walker.nextSibling()){
this.traverse();
}
else{
this.walker.parentNode();
return;
}
},
traverseIE: function(node){
if (node == null){ return; }
if (node.nodeType === 1 && this.acceptNode(node)){
var position = this.getStyle(node,'position');
if (position == 'fixed'){
this.data.fixedElements.push({
node: node,
rect: node.getBoundingClientRect(),
originalDisplay: this.getStyle(node,'display') || ''
});
}
}
if (node.firstChild && this.acceptNode(node)){
this.traverseIE(node.firstChild);
}
if (node.nextSibling){
this.traverseIE(node.nextSibling);
}
},
getViewport: function(){
var viewport = { width: -1, height: -1 };
if (window.document.documentElement != undefined && window.document.documentElement != null){
viewport.width = window.document.documentElement.clientWidth;
viewport.height = window.document.documentElement.clientHeight;
}
else if (window.document.body != undefined && window.document.body != null){
viewport.width = window.document.body.clientWidth;
viewport.height = window.document.body.clientHeight;
}
return viewport;
},
addPolyfills: function(){
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (searchElement, fromIndex) {
if ( this === undefined || this === null ) {
throw new TypeError( '"this" is null or not defined' );
}
var length = this.length >>> 0;
fromIndex = +fromIndex || 0;
if (Math.abs(fromIndex) === Infinity) {
fromIndex = 0;
}
if (fromIndex < 0) {
fromIndex += length;
if (fromIndex < 0) {
fromIndex = 0;
}
}
for (;fromIndex < length; fromIndex++) {
if (this[fromIndex] === searchElement) {
return fromIndex;
}
}
return -1;
};
}
}
};
fixedElementsTool.init();