This commit is contained in:
gorhill 2014-11-07 10:07:26 -05:00
parent 20d790e30d
commit 2ebe5dc13a
4 changed files with 286 additions and 80 deletions

View file

@ -323,7 +323,7 @@ var updateWidgets = function() {
/******************************************************************************/
var onListCheckboxChanged = function() {
var href = uDom(this).parent().find('a').first().attr('href');
var href = uDom(this).parent().descendants('a').first().attr('href');
if ( typeof href !== 'string' ) {
return;
}
@ -349,13 +349,13 @@ var onListLinkClicked = function(ev) {
var onPurgeClicked = function() {
var button = uDom(this);
var li = button.parent();
var href = li.find('a').first().attr('href');
var href = li.descendants('a').first().attr('href');
if ( !href ) {
return;
}
messaging.tell({ what: 'purgeCache', path: href });
button.remove();
if ( li.find('input').first().prop('checked') ) {
if ( li.descendants('input').first().prop('checked') ) {
cacheWasPurged = true;
updateWidgets();
}
@ -377,16 +377,16 @@ var reloadAll = function(update) {
// Reload blacklists
var switches = [];
var lis = uDom('#lists .listDetails');
var i = lis.length();
var i = lis.length;
var path;
while ( i-- ) {
path = lis
.subset(i)
.find('a')
.subset(i, 1)
.descendants('a')
.attr('href');
switches.push({
location: path,
off: lis.subset(i).find('input').prop('checked') === false
off: lis.subset(i, 1).descendants('input').prop('checked') === false
});
}
messaging.tell({

View file

@ -28,7 +28,7 @@ uDom.onLoad(function() {
uDom('.whatisthis').on('click', function() {
uDom(this)
.parent()
.find('.whatisthis-expandable')
.descendants('.whatisthis-expandable')
.toggleClass('whatisthis-expanded');
});
});

View file

@ -22,19 +22,19 @@
// Helper to deal with the i18n'ing of HTML files.
uDom.onLoad(function() {
uDom('[data-i18n]').forEach(function() {
this.innerHTML = chrome.i18n.getMessage(this.getAttribute('data-i18n'));
uDom('[data-i18n]').forEach(function(elem) {
elem.html(chrome.i18n.getMessage(elem.attr('data-i18n')));
});
uDom('[title]').forEach(function() {
var title = chrome.i18n.getMessage(this.getAttribute('title'));
uDom('[title]').forEach(function(elem) {
var title = chrome.i18n.getMessage(elem.attr('title'));
if ( title ) {
this.setAttribute('title', title);
elem.attr('title', title);
}
});
uDom('[data-i18n-tip]').forEach(function() {
this.setAttribute(
uDom('[data-i18n-tip]').forEach(function(elem) {
elem.attr(
'data-tip',
chrome.i18n.getMessage(this.getAttribute('data-i18n-tip')).replace(/<br>/g, '')
chrome.i18n.getMessage(elem.attr('data-i18n-tip')).replace(/<br>/g, '')
);
});
});

View file

@ -38,6 +38,18 @@ var DOMList = function() {
/******************************************************************************/
Object.defineProperty(
DOMList.prototype,
'length',
{
get: function() {
return this.nodes.length;
}
}
);
/******************************************************************************/
var DOMListFactory = function(selector, context) {
var r = new DOMList();
if ( typeof selector === 'string' ) {
@ -100,8 +112,8 @@ var addListToList = function(list, other) {
var addSelectorToList = function(list, selector, context) {
var p = context || document;
var r = p.querySelectorAll(selector);
var i = r.length;
while ( i-- ) {
var n = r.length;
for ( var i = 0; i < n; i++ ) {
list.nodes.push(r[i]);
}
return list;
@ -114,6 +126,8 @@ var pTagOfChildTag = {
'option': 'select'
};
// TODO: documentFragment
var addHTMLToList = function(list, html) {
var matches = html.match(/^<([a-z]+)/);
if ( !matches || matches.length !== 2 ) {
@ -134,15 +148,99 @@ var addHTMLToList = function(list, html) {
/******************************************************************************/
var isChildOf = function(child, parent) {
return child !== null && parent !== null && child.parentNode === parent;
};
/******************************************************************************/
var isDescendantOf = function(descendant, ancestor) {
while ( descendant.parentNode !== null ) {
if ( descendant.parentNode === ancestor ) {
return true;
}
descendant = descendant.parentNode;
}
return false;
};
/******************************************************************************/
var nodeInNodeList = function(node, nodeList) {
var i = nodeList.length;
while ( i-- ) {
if ( nodeList[i] === node ) {
return true;
}
}
return false;
};
/******************************************************************************/
var doesMatchSelector = function(node, selector) {
if ( !node ) {
return false;
}
if ( node.nodeType !== 1 ) {
return false;
}
if ( selector === undefined ) {
return true;
}
var parentNode = node.parentNode;
if ( !parentNode || !parentNode.setAttribute ) {
return false;
}
var doesMatch = false;
parentNode.setAttribute('uDom-32kXc6xEZA7o73AMB8vLbLct1RZOkeoO', '');
var grandpaNode = parentNode.parentNode || document;
var nl = grandpaNode.querySelectorAll('[uDom-32kXc6xEZA7o73AMB8vLbLct1RZOkeoO] > ' + selector);
var i = nl.length;
while ( doesMatch === false && i-- ) {
doesMatch = nl[i] === node;
}
parentNode.removeAttribute('uDom-32kXc6xEZA7o73AMB8vLbLct1RZOkeoO');
return doesMatch;
};
/******************************************************************************/
DOMList.prototype.length = function() {
return this.nodes.length;
};
/******************************************************************************/
DOMList.prototype.nodeAt = function(i) {
return this.nodes[i];
};
DOMList.prototype.at = function(i) {
return addNodeToList(new DOMList(), this.nodes[i]);
};
/******************************************************************************/
DOMList.prototype.toArray = function() {
return this.nodes.slice();
};
/******************************************************************************/
DOMList.prototype.forEach = function(fn) {
var n = this.nodes.length;
for ( var i = 0; i < n; i++ ) {
fn(this.at(i), i);
}
return this;
};
/******************************************************************************/
DOMList.prototype.subset = function(i, l) {
var r = new DOMList();
var n = l !== undefined ? l : 1;
var n = l !== undefined ? l : this.nodes.length;
var j = Math.min(i + n, this.nodes.length);
if ( i < j ) {
r.nodes = this.nodes.slice(i, j);
@ -153,13 +251,30 @@ DOMList.prototype.subset = function(i, l) {
/******************************************************************************/
DOMList.prototype.first = function() {
return this.subset(0);
return this.subset(0, 1);
};
/******************************************************************************/
DOMList.prototype.node = function(i) {
return this.nodes[i];
DOMList.prototype.next = function(selector) {
var r = new DOMList();
var n = this.nodes.length;
var node;
for ( var i = 0; i < n; i++ ) {
node = this.nodes[i];
while ( node.nextSibling !== null ) {
node = node.nextSibling;
if ( node.nodeType !== 1 ) {
continue;
}
if ( doesMatchSelector(node, selector) === false ) {
continue;
}
addNodeToList(r, node);
break;
}
}
return r;
};
/******************************************************************************/
@ -174,7 +289,54 @@ DOMList.prototype.parent = function() {
/******************************************************************************/
DOMList.prototype.find = function(selector) {
DOMList.prototype.filter = function(filter) {
var r = new DOMList();
var filterFunc;
if ( typeof filter === 'string' ) {
filterFunc = function() {
return doesMatchSelector(this, filter);
};
} else if ( typeof filter === 'function' ) {
filterFunc = filter;
} else {
filterFunc = function(){
return true;
};
}
var n = this.nodes.length;
var node;
for ( var i = 0; i < n; i++ ) {
node = this.nodes[i];
if ( filterFunc.apply(node) ) {
addNodeToList(r, node);
}
}
return r;
};
/******************************************************************************/
// TODO: Avoid possible duplicates
DOMList.prototype.ancestors = function(selector) {
var r = new DOMList();
var n = this.nodes.length;
var node;
for ( var i = 0; i < n; i++ ) {
node = this.nodes[i].parentNode;
while ( node ) {
if ( doesMatchSelector(node, selector) ) {
addNodeToList(r, node);
}
node = node.parentNode;
}
}
return r;
};
/******************************************************************************/
DOMList.prototype.descendants = function(selector) {
var r = new DOMList();
var n = this.nodes.length;
var nl;
@ -187,28 +349,36 @@ DOMList.prototype.find = function(selector) {
/******************************************************************************/
DOMList.prototype.forEach = function(callback) {
DOMList.prototype.contents = function() {
var r = new DOMList();
var cnodes, cn, ci;
var n = this.nodes.length;
for ( var i = 0; i < n; i++ ) {
callback.bind(this.nodes[i]).call();
cnodes = this.nodes[i].childNodes;
cn = cnodes.length;
for ( ci = 0; ci < cn; ci++ ) {
addNodeToList(r, cnodes.item(ci));
}
}
return this;
return r;
};
/******************************************************************************/
DOMList.prototype.remove = function() {
var n = this.nodes.length;
var c, p;
for ( var i = 0; i < n; i++ ) {
c = this.nodes[i];
if ( p = c.parentNode ) {
p.removeChild(c);
var cn, p;
var i = this.nodes.length;
while ( i-- ) {
cn = this.nodes[i];
if ( p = cn.parentNode ) {
p.removeChild(cn);
}
}
return this;
};
DOMList.prototype.detach = DOMList.prototype.remove;
/******************************************************************************/
DOMList.prototype.empty = function() {
@ -254,12 +424,10 @@ DOMList.prototype.prepend = function(selector, context) {
/******************************************************************************/
DOMList.prototype.appendTo = function(selector, context) {
var p = DOMListFactory(selector, context);
if ( p.length ) {
var n = this.nodes.length;
for ( var i = 0; i < n; i++ ) {
p.nodes[0].appendChild(this.nodes[i]);
}
var p = selector instanceof DOMListFactory ? selector : DOMListFactory(selector, context);
var n = p.length;
for ( var i = 0; i < n; i++ ) {
p.nodes[0].appendChild(this.nodes[i]);
}
return this;
};
@ -284,6 +452,28 @@ DOMList.prototype.insertAfter = function(selector, context) {
/******************************************************************************/
DOMList.prototype.insertBefore = function(selector, context) {
if ( this.nodes.length === 0 ) {
return this;
}
var referenceNodes = DOMListFactory(selector, context);
if ( referenceNodes.nodes.length === 0 ) {
return this;
}
var referenceNode = referenceNodes.nodes[0];
var parentNode = referenceNode.parentNode;
if ( !parentNode ) {
return this;
}
var n = this.nodes.length;
for ( var i = 0; i < n; i++ ) {
parentNode.insertBefore(this.nodes[i], referenceNode);
}
return this;
};
/******************************************************************************/
DOMList.prototype.clone = function(notDeep) {
var r = new DOMList();
var n = this.nodes.length;
@ -324,7 +514,7 @@ DOMList.prototype.attr = function(attr, value) {
DOMList.prototype.prop = function(prop, value) {
var i = this.nodes.length;
if ( value === undefined ) {
return i ? this.nodes[0][prop] : undefined;
return i !== 0 ? this.nodes[0][prop] : undefined;
}
while ( i-- ) {
this.nodes[i][prop] = value;
@ -379,13 +569,33 @@ DOMList.prototype.text = function(text) {
/******************************************************************************/
DOMList.prototype.hasClassName = function(className) {
var toggleClass = function(node, className, targetState) {
var tokenList = node.classList;
if ( tokenList instanceof DOMTokenList === false ) {
return;
}
var currentState = tokenList.contains(className);
var newState = targetState;
if ( newState === undefined ) {
newState = !currentState;
}
if ( newState === currentState ) {
return;
}
tokenList.toggle(className, newState)
};
/******************************************************************************/
DOMList.prototype.hasClass = function(className) {
if ( !this.nodes.length ) {
return false;
}
var re = new RegExp('(^| )' + className + '( |$)');
return re.test(this.nodes[0].className);
var tokenList = this.nodes[0].classList;
return tokenList instanceof DOMTokenList &&
tokenList.contains(className);
};
DOMList.prototype.hasClassName = DOMList.prototype.hasClass;
DOMList.prototype.addClass = function(className) {
return this.toggleClass(className, true);
@ -402,49 +612,46 @@ DOMList.prototype.removeClass = function(className) {
return this;
};
/******************************************************************************/
DOMList.prototype.toggleClass = function(className, targetState) {
var re = new RegExp('(^| )' + className + '( |$)');
var n = this.nodes.length;
var node, currentState, newState, newClassName;
for ( var i = 0; i < n; i++ ) {
node = this.nodes[i];
currentState = re.test(node.className);
newState = targetState;
if ( newState === undefined ) {
newState = !currentState;
}
if ( newState === currentState ) {
continue;
}
newClassName = node.className;
if ( newState ) {
newClassName += ' ' + className;
} else {
newClassName = newClassName.replace(re, ' ');
}
node.className = newClassName.trim();
if ( className.indexOf(' ') !== -1 ) {
return this.toggleClasses(className, true);
}
var i = this.nodes.length;
while ( i-- ) {
toggleClass(this.nodes[i], className, targetState);
}
return this;
};
/******************************************************************************/
var makeEventHandler = function(context, selector, callback) {
DOMList.prototype.toggleClasses = function(classNames, targetState) {
var tokens = classNames.split(/\s+/);
var i = this.nodes.length;
var node, j;
while ( i-- ) {
node = this.nodes[i];
j = tokens.length;
while ( j-- ) {
toggleClass(node, tokens[j], targetState);
}
}
return this;
};
/******************************************************************************/
var makeEventHandler = function(selector, callback) {
return function(event) {
var candidates = context.querySelectorAll(selector);
if ( !candidates.length ) {
var dispatcher = event.currentTarget;
if ( !dispatcher || typeof dispatcher.querySelectorAll !== 'function' ) {
return;
}
var node = event.target;
var i;
while ( node && node !== context ) {
i = candidates.length;
while ( i-- ) {
if ( candidates[i] === node ) {
return callback.call(node, event);
}
}
node = node.parentNode;
var receiver = event.target;
if ( nodeInNodeList(receiver, dispatcher.querySelectorAll(selector)) ) {
callback.call(receiver, event);
}
};
};
@ -453,14 +660,13 @@ DOMList.prototype.on = function(etype, selector, callback) {
if ( typeof selector === 'function' ) {
callback = selector;
selector = undefined;
} else {
callback = makeEventHandler(selector, callback);
}
var i = this.nodes.length;
while ( i-- ) {
if ( selector !== undefined ) {
this.nodes[i].addEventListener(etype, makeEventHandler(this.nodes[i], selector, callback), true);
} else {
this.nodes[i].addEventListener(etype, callback);
}
this.nodes[i].addEventListener(etype, callback, selector !== undefined);
}
return this;
};