mirror of
https://github.com/gorhill/uMatrix.git
synced 2024-09-29 08:41:11 +13:00
move-away-from-jquery work
This commit is contained in:
parent
7ac86a7138
commit
f676a745c3
3 changed files with 656 additions and 66 deletions
163
src/js/popup.js
163
src/js/popup.js
|
@ -496,19 +496,18 @@ function getCollapseState(domain) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleCollapseState(element) {
|
function toggleCollapseState(element) {
|
||||||
element = $(element);
|
var el = uDom(element);
|
||||||
if ( element.parents('#matHead.collapsible').length > 0 ) {
|
if ( el.ancestors('#matHead.collapsible').length() > 0 ) {
|
||||||
toggleMainCollapseState(element);
|
toggleMainCollapseState(el);
|
||||||
} else {
|
} else {
|
||||||
toggleSpecificCollapseState(element);
|
toggleSpecificCollapseState(el);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleMainCollapseState(element) {
|
function toggleMainCollapseState(element) {
|
||||||
var matHead = element.parents('#matHead.collapsible')
|
var matHead = element.ancestors('#matHead.collapsible').toggleClass('collapsed');
|
||||||
.toggleClass('collapsed');
|
var collapsed = matHead.hasClassName('collapsed');
|
||||||
var collapsed = matHead.hasClass('collapsed');
|
uDom('#matList .matSection.collapsible').toggleClass('collapsed', collapsed);
|
||||||
$('#matList .matSection.collapsible').toggleClass('collapsed', collapsed);
|
|
||||||
setUserSetting('popupCollapseDomains', collapsed);
|
setUserSetting('popupCollapseDomains', collapsed);
|
||||||
|
|
||||||
var specificCollapseStates = getUserSetting('popupCollapseSpecificDomains') || {};
|
var specificCollapseStates = getUserSetting('popupCollapseSpecificDomains') || {};
|
||||||
|
@ -527,10 +526,9 @@ function toggleMainCollapseState(element) {
|
||||||
function toggleSpecificCollapseState(element) {
|
function toggleSpecificCollapseState(element) {
|
||||||
// Remember collapse state forever, but only if it is different
|
// Remember collapse state forever, but only if it is different
|
||||||
// from main collapse switch.
|
// from main collapse switch.
|
||||||
var section = element.parents('.matSection.collapsible')
|
var section = element.ancestors('.matSection.collapsible').toggleClass('collapsed');
|
||||||
.toggleClass('collapsed');
|
|
||||||
var domain = section.prop('domain');
|
var domain = section.prop('domain');
|
||||||
var collapsed = section.hasClass('collapsed');
|
var collapsed = section.hasClassName('collapsed');
|
||||||
var mainCollapseState = getUserSetting('popupCollapseDomains');
|
var mainCollapseState = getUserSetting('popupCollapseDomains');
|
||||||
var specificCollapseStates = getUserSetting('popupCollapseSpecificDomains') || {};
|
var specificCollapseStates = getUserSetting('popupCollapseSpecificDomains') || {};
|
||||||
if ( collapsed !== mainCollapseState ) {
|
if ( collapsed !== mainCollapseState ) {
|
||||||
|
@ -759,58 +757,90 @@ var createMatrixRow = function() {
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
function renderMatrixHeaderRow() {
|
function renderMatrixHeaderRow() {
|
||||||
var matHead = $('#matHead.collapsible');
|
var matHead = uDom('#matHead.collapsible');
|
||||||
matHead.toggleClass('collapsed', getUserSetting('popupCollapseDomains'));
|
matHead.toggleClass('collapsed', getUserSetting('popupCollapseDomains'));
|
||||||
var cells = matHead.find('.matCell');
|
var cells = matHead.find('.matCell');
|
||||||
$(cells[0]).prop({reqType: '*', hostname: '*'}).addClass(getCellClass('*', '*'));
|
uDom(cells.node(0))
|
||||||
$(cells[1]).prop({reqType: 'cookie', hostname: '*'}).addClass(getCellClass('*', 'cookie'));
|
.prop('reqType', '*')
|
||||||
$(cells[2]).prop({reqType: 'css', hostname: '*'}).addClass(getCellClass('*', 'css'));
|
.prop('hostname', '*')
|
||||||
$(cells[3]).prop({reqType: 'image', hostname: '*'}).addClass(getCellClass('*', 'image'));
|
.addClass(getCellClass('*', '*'));
|
||||||
$(cells[4]).prop({reqType: 'plugin', hostname: '*'}).addClass(getCellClass('*', 'plugin'));
|
uDom(cells.node(1))
|
||||||
$(cells[5]).prop({reqType: 'script', hostname: '*'}).addClass(getCellClass('*', 'script'));
|
.prop('reqType', 'cookie')
|
||||||
$(cells[6]).prop({reqType: 'xhr', hostname: '*'}).addClass(getCellClass('*', 'xhr'));
|
.prop('hostname', '*')
|
||||||
$(cells[7]).prop({reqType: 'frame', hostname: '*'}).addClass(getCellClass('*', 'frame'));
|
.addClass(getCellClass('*', 'cookie'));
|
||||||
$(cells[8]).prop({reqType: 'other', hostname: '*'}).addClass(getCellClass('*', 'other'));
|
uDom(cells.node(2))
|
||||||
$('#matHead .matRow').css('display', '');
|
.prop('reqType', 'css')
|
||||||
|
.prop('hostname', '*')
|
||||||
|
.addClass(getCellClass('*', 'css'));
|
||||||
|
uDom(cells.node(3))
|
||||||
|
.prop('reqType', 'image')
|
||||||
|
.prop('hostname', '*')
|
||||||
|
.addClass(getCellClass('*', 'image'));
|
||||||
|
uDom(cells.node(4))
|
||||||
|
.prop('reqType', 'plugin')
|
||||||
|
.prop('hostname', '*')
|
||||||
|
.addClass(getCellClass('*', 'plugin'));
|
||||||
|
uDom(cells.node(5))
|
||||||
|
.prop('reqType', 'script')
|
||||||
|
.prop('hostname', '*')
|
||||||
|
.addClass(getCellClass('*', 'script'));
|
||||||
|
uDom(cells.node(6))
|
||||||
|
.prop('reqType', 'xhr')
|
||||||
|
.prop('hostname', '*')
|
||||||
|
.addClass(getCellClass('*', 'xhr'));
|
||||||
|
uDom(cells.node(7))
|
||||||
|
.prop('reqType', 'frame')
|
||||||
|
.prop('hostname', '*')
|
||||||
|
.addClass(getCellClass('*', 'frame'));
|
||||||
|
uDom(cells.node(8))
|
||||||
|
.prop('reqType', 'other')
|
||||||
|
.prop('hostname', '*')
|
||||||
|
.addClass(getCellClass('*', 'other'));
|
||||||
|
uDom('#matHead .matRow').css('display', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
function renderMatrixCellDomain(cell, domain) {
|
function renderMatrixCellDomain(cell, domain) {
|
||||||
var contents = $(cell)
|
var contents = uDom(cell)
|
||||||
.prop({reqType: '*', hostname: domain})
|
.prop('reqType', '*')
|
||||||
|
.prop('hostname', domain)
|
||||||
.addClass(getCellClass(domain, '*'))
|
.addClass(getCellClass(domain, '*'))
|
||||||
.contents();
|
.contents();
|
||||||
contents[0].textContent = '\u202A' + punycode.toUnicode(domain);
|
contents.node(0).textContent = '\u202A' + punycode.toUnicode(domain);
|
||||||
contents[1].textContent = ' ';
|
contents.node(1).textContent = ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderMatrixCellSubdomain(cell, domain, subomain) {
|
function renderMatrixCellSubdomain(cell, domain, subomain) {
|
||||||
var contents = $(cell)
|
var contents = uDom(cell)
|
||||||
.prop({reqType: '*', hostname: subomain})
|
.prop('reqType', '*')
|
||||||
|
.prop('hostname', subomain)
|
||||||
.addClass(getCellClass(subomain, '*'))
|
.addClass(getCellClass(subomain, '*'))
|
||||||
.contents();
|
.contents();
|
||||||
contents[0].textContent = '\u202A' + punycode.toUnicode(subomain.slice(0, subomain.lastIndexOf(domain)-1)) + '.';
|
contents.node(0).textContent = '\u202A' + punycode.toUnicode(subomain.slice(0, subomain.lastIndexOf(domain)-1)) + '.';
|
||||||
contents[1].textContent = punycode.toUnicode(domain);
|
contents.node(1).textContent = punycode.toUnicode(domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderMatrixMetaCellDomain(cell, domain) {
|
function renderMatrixMetaCellDomain(cell, domain) {
|
||||||
var contents = $(cell)
|
var contents = uDom(cell)
|
||||||
.prop({reqType: '*', hostname: domain})
|
.prop('reqType', '*')
|
||||||
|
.prop('hostname', domain)
|
||||||
.addClass(getCellClass(domain, '*'))
|
.addClass(getCellClass(domain, '*'))
|
||||||
.contents();
|
.contents();
|
||||||
contents[0].textContent = '\u202A\u2217.' + punycode.toUnicode(domain);
|
contents.node(0).textContent = '\u202A\u2217.' + punycode.toUnicode(domain);
|
||||||
contents[1].textContent = ' ';
|
contents.node(1).textContent = ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderMatrixCellType(cell, hostname, type, stats) {
|
function renderMatrixCellType(cell, hostname, type, stats) {
|
||||||
cell = $(cell);
|
var ce = uDom(cell)
|
||||||
cell.prop({reqType: type, hostname: hostname, count: stats.count})
|
.prop('reqType', type)
|
||||||
|
.prop('hostname', hostname)
|
||||||
|
.prop('count', stats.count)
|
||||||
.addClass(getCellClass(hostname, type));
|
.addClass(getCellClass(hostname, type));
|
||||||
if ( stats.count ) {
|
if ( stats.count ) {
|
||||||
cell.text(stats.count);
|
ce.text(stats.count);
|
||||||
} else {
|
} else {
|
||||||
cell.text('\u00A0');
|
ce.text('\u00A0');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -854,31 +884,31 @@ function makeMatrixMetaRowDomain(domain, stats) {
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
function renderMatrixMetaCellType(cell, count) {
|
function renderMatrixMetaCellType(cell, count) {
|
||||||
cell = $(cell);
|
var ce = uDom(cell);
|
||||||
cell.addClass('ri');
|
ce.addClass('ri');
|
||||||
if ( count ) {
|
if ( count ) {
|
||||||
cell.text(count);
|
ce.text(count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeMatrixMetaRow(stats) {
|
function makeMatrixMetaRow(stats) {
|
||||||
var typeStats = stats.types;
|
var typeStats = stats.types;
|
||||||
var matrixRow = createMatrixRow().addClass('ro');
|
var matrixRow = uDom(createMatrixRow()[0]).addClass('ro');
|
||||||
var cells = matrixRow.children('.matCell');
|
var cells = matrixRow.find('.matCell');
|
||||||
var contents = $(cells[0])
|
var contents = uDom(cells.node(0))
|
||||||
.addClass('matCell rd')
|
.addClass('matCell rd')
|
||||||
.contents();
|
.contents();
|
||||||
contents[0].textContent = ' ';
|
contents.node(0).textContent = ' ';
|
||||||
contents[1].textContent = '\u202A' + typeStats['*'].count + ' blacklisted hostname(s)';
|
contents.node(1).textContent = '\u202A' + typeStats['*'].count + ' blacklisted hostname(s)';
|
||||||
renderMatrixMetaCellType(cells[1], typeStats.cookie.count);
|
renderMatrixMetaCellType(cells.node(1), typeStats.cookie.count);
|
||||||
renderMatrixMetaCellType(cells[2], typeStats.css.count);
|
renderMatrixMetaCellType(cells.node(2), typeStats.css.count);
|
||||||
renderMatrixMetaCellType(cells[3], typeStats.image.count);
|
renderMatrixMetaCellType(cells.node(3), typeStats.image.count);
|
||||||
renderMatrixMetaCellType(cells[4], typeStats.plugin.count);
|
renderMatrixMetaCellType(cells.node(4), typeStats.plugin.count);
|
||||||
renderMatrixMetaCellType(cells[5], typeStats.script.count);
|
renderMatrixMetaCellType(cells.node(5), typeStats.script.count);
|
||||||
renderMatrixMetaCellType(cells[6], typeStats.xhr.count);
|
renderMatrixMetaCellType(cells.node(6), typeStats.xhr.count);
|
||||||
renderMatrixMetaCellType(cells[7], typeStats.frame.count);
|
renderMatrixMetaCellType(cells.node(7), typeStats.frame.count);
|
||||||
renderMatrixMetaCellType(cells[8], typeStats.other.count);
|
renderMatrixMetaCellType(cells.node(8), typeStats.other.count);
|
||||||
return matrixRow;
|
return $(matrixRow.node(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -1246,10 +1276,10 @@ function initScopeCell() {
|
||||||
|
|
||||||
function updateScopeCell() {
|
function updateScopeCell() {
|
||||||
var µm = µMatrix;
|
var µm = µMatrix;
|
||||||
$('body')
|
uDom('body')
|
||||||
.removeClass('tScopeGlobal tScopeLocal tScopeSite')
|
.removeClass('tScopeGlobal tScopeLocal tScopeSite')
|
||||||
.addClass(getClassFromTemporaryScopeKey(targetScope))
|
.addClass(getClassFromTemporaryScopeKey(targetScope))
|
||||||
$('#scopeCell').text(targetScope.replace('*', '\u2217'));
|
uDom('#scopeCell').text(targetScope.replace('*', '\u2217'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -1287,7 +1317,7 @@ function updatePersistButton() {
|
||||||
button.children('span.badge').text(ruleset.count > 0 ? ruleset.count : '');
|
button.children('span.badge').text(ruleset.count > 0 ? ruleset.count : '');
|
||||||
var disabled = ruleset.count === 0;
|
var disabled = ruleset.count === 0;
|
||||||
button.toggleClass('disabled', disabled);
|
button.toggleClass('disabled', disabled);
|
||||||
$('#buttonRevertScope').toggleClass('disabled', disabled);
|
uDom('#buttonRevertScope').toggleClass('disabled', disabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
function persistScope() {
|
function persistScope() {
|
||||||
|
@ -1357,7 +1387,7 @@ function mouseleaveMatrixCellHandler() {
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
function gotoExtensionURL() {
|
function gotoExtensionURL() {
|
||||||
var url = $(this).data('extensionUrl');
|
var url = this.getAttribute('data-extension-url');
|
||||||
if ( url ) {
|
if ( url ) {
|
||||||
messaging.tell({ what: 'gotoExtensionURL', url: url });
|
messaging.tell({ what: 'gotoExtensionURL', url: url });
|
||||||
}
|
}
|
||||||
|
@ -1366,7 +1396,7 @@ function gotoExtensionURL() {
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
function gotoExternalURL() {
|
function gotoExternalURL() {
|
||||||
var url = $(this).data('externalUrl');
|
var url = this.getAttribute('data-external-url');
|
||||||
if ( url ) {
|
if ( url ) {
|
||||||
messaging.tell({ what: 'gotoURL', url: url });
|
messaging.tell({ what: 'gotoURL', url: url });
|
||||||
}
|
}
|
||||||
|
@ -1379,7 +1409,7 @@ function dropDownMenuShow() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function dropDownMenuHide() {
|
function dropDownMenuHide() {
|
||||||
$('.dropdown-menu').removeClass('show');
|
uDom('.dropdown-menu').removeClass('show');
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -1417,8 +1447,8 @@ var bindToTab = function(tabs) {
|
||||||
$('#toolbarLeft').remove();
|
$('#toolbarLeft').remove();
|
||||||
|
|
||||||
// https://github.com/gorhill/httpswitchboard/issues/191
|
// https://github.com/gorhill/httpswitchboard/issues/191
|
||||||
$('#noNetTrafficPrompt').text(chrome.i18n.getMessage('matrixNoNetTrafficPrompt'));
|
uDom('#noNetTrafficPrompt').text(chrome.i18n.getMessage('matrixNoNetTrafficPrompt'));
|
||||||
$('#noNetTrafficPrompt').css('display', '');
|
uDom('#noNetTrafficPrompt').css('display', '');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1475,9 +1505,10 @@ $(function() {
|
||||||
$('body').on('click', '.dropdown-menu-capture', dropDownMenuHide);
|
$('body').on('click', '.dropdown-menu-capture', dropDownMenuHide);
|
||||||
|
|
||||||
$('#matList').on('click', '.g3Meta', function() {
|
$('#matList').on('click', '.g3Meta', function() {
|
||||||
var separator = $(this);
|
var collapsed = uDom(this)
|
||||||
separator.toggleClass('g3Collapsed');
|
.toggleClass('g3Collapsed')
|
||||||
setUserSetting('popupHideBlacklisted', separator.hasClass('g3Collapsed'));
|
.hasClass('g3Collapsed');
|
||||||
|
setUserSetting('popupHideBlacklisted', collapsed);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
558
src/js/udom.js
Normal file
558
src/js/udom.js
Normal file
|
@ -0,0 +1,558 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
µBlock - a Chromium browser extension to block requests.
|
||||||
|
Copyright (C) 2014 Raymond Hill
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||||
|
|
||||||
|
Home: https://github.com/gorhill/uBlock
|
||||||
|
*/
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
// It's just a silly, minimalist DOM framework: this allows me to not rely
|
||||||
|
// on jQuery. jQuery contains way too much stuff than I need, and as per
|
||||||
|
// Opera rules, I am not allowed to use a cut-down version of jQuery. So
|
||||||
|
// the code here does *only* what I need, and nothing more, and with a lot
|
||||||
|
// of assumption on passed parameters, etc. I grow it on a per-need-basis only.
|
||||||
|
|
||||||
|
var uDom = (function() {
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var DOMList = function() {
|
||||||
|
this.nodes = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var addNodeToList = function(list, node) {
|
||||||
|
if ( node ) {
|
||||||
|
list.nodes.push(node);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var DOMListFactory = function(selector, context) {
|
||||||
|
var r = new DOMList();
|
||||||
|
if ( typeof selector === 'string' ) {
|
||||||
|
selector = selector.trim();
|
||||||
|
if ( selector.charAt(0) === '<' ) {
|
||||||
|
return addHTMLToList(r, selector);
|
||||||
|
}
|
||||||
|
if ( selector !== '' ) {
|
||||||
|
return addSelectorToList(r, selector, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( selector instanceof Node ) {
|
||||||
|
return addNodeToList(r, selector);
|
||||||
|
}
|
||||||
|
if ( selector instanceof NodeList ) {
|
||||||
|
return addNodeListToList(r, selector);
|
||||||
|
}
|
||||||
|
if ( selector instanceof DOMList ) {
|
||||||
|
return addListToList(r, selector);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
DOMListFactory.onLoad = function(callback) {
|
||||||
|
window.addEventListener('load', callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var addNodeListToList = function(list, nodelist) {
|
||||||
|
if ( nodelist ) {
|
||||||
|
var n = nodelist.length;
|
||||||
|
for ( var i = 0; i < n; i++ ) {
|
||||||
|
list.nodes.push(nodelist[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var addListToList = function(list, other) {
|
||||||
|
list.nodes = list.nodes.concat(other.nodes);
|
||||||
|
return list;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var addSelectorToList = function(list, selector, context) {
|
||||||
|
var p = context || document;
|
||||||
|
var r = p.querySelectorAll(selector);
|
||||||
|
var i = r.length;
|
||||||
|
while ( i-- ) {
|
||||||
|
list.nodes.push(r[i]);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var pTagOfChildTag = {
|
||||||
|
'tr': 'table',
|
||||||
|
'option': 'select'
|
||||||
|
};
|
||||||
|
|
||||||
|
var addHTMLToList = function(list, html) {
|
||||||
|
var matches = html.match(/^<([a-z]+)/);
|
||||||
|
if ( !matches || matches.length !== 2 ) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
var cTag = matches[1];
|
||||||
|
var pTag = pTagOfChildTag[cTag] || 'div';
|
||||||
|
var p = document.createElement(pTag);
|
||||||
|
p.innerHTML = html;
|
||||||
|
// Find real parent
|
||||||
|
var c = p.querySelector(cTag);
|
||||||
|
p = c.parentNode;
|
||||||
|
while ( p.firstChild ) {
|
||||||
|
list.nodes.push(p.removeChild(p.firstChild));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var isDescendantOf = function(descendant, ancestor) {
|
||||||
|
while ( descendant.parentNode !== null ) {
|
||||||
|
if ( descendant.parentNode === ancestor ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
descendant = descendant.parentNode;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
DOMList.prototype.length = function() {
|
||||||
|
return this.nodes.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
DOMList.prototype.node = function(i) {
|
||||||
|
return this.nodes[i];
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
DOMList.prototype.subset = function(i, l) {
|
||||||
|
var r = new DOMList();
|
||||||
|
var n = l !== undefined ? l : 1;
|
||||||
|
var j = Math.min(i + n, this.nodes.length);
|
||||||
|
if ( i < j ) {
|
||||||
|
r.nodes = this.nodes.slice(i, j);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
DOMList.prototype.first = function() {
|
||||||
|
return this.subset(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
DOMList.prototype.parent = function() {
|
||||||
|
var r = new DOMList();
|
||||||
|
if ( this.nodes.length ) {
|
||||||
|
addNodeToList(r, this.nodes[0].parentNode);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
DOMList.prototype.ancestors = function(selector) {
|
||||||
|
var r = new DOMList();
|
||||||
|
if ( this.nodes.length === 0 ) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
var candidates = document.querySelectorAll(selector);
|
||||||
|
var i = candidates.length;
|
||||||
|
var j, candidate;
|
||||||
|
while ( i-- ) {
|
||||||
|
candidate = candidates[i];
|
||||||
|
j = this.nodes.length;
|
||||||
|
while ( j-- ) {
|
||||||
|
if ( isDescendantOf(this.nodes[j], candidate) ) {
|
||||||
|
addNodeToList(r, candidate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
DOMList.prototype.find = function(selector) {
|
||||||
|
var r = new DOMList();
|
||||||
|
var n = this.nodes.length;
|
||||||
|
var nl;
|
||||||
|
for ( var i = 0; i < n; i++ ) {
|
||||||
|
nl = this.nodes[i].querySelectorAll(selector);
|
||||||
|
addNodeListToList(r, nl);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
DOMList.prototype.contents = function() {
|
||||||
|
var r = new DOMList();
|
||||||
|
var cnodes, cn, ci;
|
||||||
|
var n = this.nodes.length;
|
||||||
|
for ( var i = 0; i < n; i++ ) {
|
||||||
|
cnodes = this.nodes[i].childNodes;
|
||||||
|
cn = cnodes.length;
|
||||||
|
for ( ci = 0; ci < cn; ci++ ) {
|
||||||
|
addNodeToList(r, cnodes.item(ci));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
DOMList.prototype.forEach = function(callback) {
|
||||||
|
var n = this.nodes.length;
|
||||||
|
for ( var i = 0; i < n; i++ ) {
|
||||||
|
callback.bind(this.nodes[i]).call();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
DOMList.prototype.empty = function() {
|
||||||
|
var node;
|
||||||
|
var i = this.nodes.length;
|
||||||
|
while ( i-- ) {
|
||||||
|
node = this.nodes[i];
|
||||||
|
while ( node.firstChild ) {
|
||||||
|
node.removeChild(node.firstChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
DOMList.prototype.append = function(selector, context) {
|
||||||
|
var p = this.nodes[0];
|
||||||
|
if ( p ) {
|
||||||
|
var c = DOMListFactory(selector, context);
|
||||||
|
var n = c.nodes.length;
|
||||||
|
for ( var i = 0; i < n; i++ ) {
|
||||||
|
p.appendChild(c.nodes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
DOMList.prototype.prepend = function(selector, context) {
|
||||||
|
var p = this.nodes[0];
|
||||||
|
if ( p ) {
|
||||||
|
var c = DOMListFactory(selector, context);
|
||||||
|
var i = c.nodes.length;
|
||||||
|
while ( i-- ) {
|
||||||
|
p.insertBefore(c.nodes[i], p.firstChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
DOMList.prototype.insertAfter = function(selector, context) {
|
||||||
|
if ( this.nodes.length === 0 ) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
var p = this.nodes[0].parentNode;
|
||||||
|
if ( !p ) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
var c = DOMListFactory(selector, context);
|
||||||
|
var n = c.nodes.length;
|
||||||
|
for ( var i = 0; i < n; i++ ) {
|
||||||
|
p.appendChild(c.nodes[i]);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
DOMList.prototype.clone = function(notDeep) {
|
||||||
|
var r = new DOMList();
|
||||||
|
var n = this.nodes.length;
|
||||||
|
for ( var i = 0; i < n; i++ ) {
|
||||||
|
addNodeToList(r, this.nodes[i].cloneNode(!notDeep));
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
DOMList.prototype.attr = function(attr, value) {
|
||||||
|
var i = this.nodes.length;
|
||||||
|
if ( value === undefined && typeof attr !== 'object' ) {
|
||||||
|
return i ? this.nodes[0].getAttribute(attr) : undefined;
|
||||||
|
}
|
||||||
|
if ( typeof attr === 'object' ) {
|
||||||
|
var attrNames = Object.keys(attr);
|
||||||
|
var node, j, attrName;
|
||||||
|
while ( i-- ) {
|
||||||
|
node = this.nodes[i];
|
||||||
|
j = attrNames.length;
|
||||||
|
while ( j-- ) {
|
||||||
|
attrName = attrNames[j];
|
||||||
|
node.setAttribute(attrName, attr[attrName]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while ( i-- ) {
|
||||||
|
this.nodes[i].setAttribute(attr, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
DOMList.prototype.prop = function(prop, value) {
|
||||||
|
var i = this.nodes.length;
|
||||||
|
if ( value === undefined ) {
|
||||||
|
return i ? this.nodes[0][prop] : undefined;
|
||||||
|
}
|
||||||
|
while ( i-- ) {
|
||||||
|
this.nodes[i][prop] = value;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
DOMList.prototype.css = function(prop, value) {
|
||||||
|
var i = this.nodes.length;
|
||||||
|
if ( value === undefined ) {
|
||||||
|
return i ? this.nodes[0].style[prop] : undefined;
|
||||||
|
}
|
||||||
|
while ( i-- ) {
|
||||||
|
this.nodes[i].style[prop] = value;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
DOMList.prototype.val = function(value) {
|
||||||
|
return this.prop('value', value);
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
DOMList.prototype.html = function(html) {
|
||||||
|
var i = this.nodes.length;
|
||||||
|
if ( html === undefined ) {
|
||||||
|
return i ? this.nodes[0].innerHTML : '';
|
||||||
|
}
|
||||||
|
while ( i-- ) {
|
||||||
|
this.nodes[i].innerHTML = html;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
DOMList.prototype.text = function(text) {
|
||||||
|
var i = this.nodes.length;
|
||||||
|
if ( text === undefined ) {
|
||||||
|
return i ? this.nodes[0].textContent : '';
|
||||||
|
}
|
||||||
|
while ( i-- ) {
|
||||||
|
this.nodes[i].textContent = text;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var toggleClass = function(node, className, targetState) {
|
||||||
|
var re = new RegExp('(^| )' + className + '( |$)');
|
||||||
|
var currentState = re.test(node.className);
|
||||||
|
var newState = targetState;
|
||||||
|
if ( newState === undefined ) {
|
||||||
|
newState = !currentState;
|
||||||
|
}
|
||||||
|
if ( newState === currentState ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var newClassName = node.className;
|
||||||
|
if ( newState ) {
|
||||||
|
newClassName += ' ' + className;
|
||||||
|
} else {
|
||||||
|
newClassName = newClassName.replace(re, ' ');
|
||||||
|
}
|
||||||
|
node.className = newClassName.trim();
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
DOMList.prototype.hasClassName = function(className) {
|
||||||
|
if ( !this.nodes.length ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var re = new RegExp('(^| )' + className + '( |$)');
|
||||||
|
return re.test(this.nodes[0].className);
|
||||||
|
};
|
||||||
|
|
||||||
|
DOMList.prototype.addClass = function(className) {
|
||||||
|
return this.toggleClass(className, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
DOMList.prototype.removeClass = function(className) {
|
||||||
|
if ( className !== undefined ) {
|
||||||
|
return this.toggleClass(className, false);
|
||||||
|
}
|
||||||
|
var i = this.nodes.length;
|
||||||
|
while ( i-- ) {
|
||||||
|
this.nodes[i].className = '';
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
DOMList.prototype.toggleClass = function(className, targetState) {
|
||||||
|
var classNames = className.split(/\s+/);
|
||||||
|
var i = this.nodes.length;
|
||||||
|
var node, j;
|
||||||
|
while ( i-- ) {
|
||||||
|
node = this.nodes[i];
|
||||||
|
j = classNames.length;
|
||||||
|
while ( j-- ) {
|
||||||
|
toggleClass(node, classNames[j], targetState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var makeEventHandler = function(context, selector, callback) {
|
||||||
|
return function(event) {
|
||||||
|
var candidates = context.querySelectorAll(selector);
|
||||||
|
if ( !candidates.length ) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
DOMList.prototype.on = function(etype, selector, callback) {
|
||||||
|
if ( typeof selector === 'function' ) {
|
||||||
|
callback = selector;
|
||||||
|
selector = undefined;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
// TODO: Won't work for delegated handlers. Need to figure
|
||||||
|
// what needs to be done.
|
||||||
|
|
||||||
|
DOMList.prototype.off = function(evtype, callback) {
|
||||||
|
var i = this.nodes.length;
|
||||||
|
while ( i-- ) {
|
||||||
|
this.nodes[i].removeEventListener(evtype, callback);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
DOMList.prototype.trigger = function(etype) {
|
||||||
|
var ev = new CustomEvent(etype);
|
||||||
|
var i = this.nodes.length;
|
||||||
|
while ( i-- ) {
|
||||||
|
this.nodes[i].dispatchEvent(ev);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
return DOMListFactory;
|
||||||
|
|
||||||
|
})();
|
|
@ -74,6 +74,7 @@
|
||||||
|
|
||||||
<script src="lib/jquery-2.min.js"></script>
|
<script src="lib/jquery-2.min.js"></script>
|
||||||
<script src="lib/punycode.min.js"></script>
|
<script src="lib/punycode.min.js"></script>
|
||||||
|
<script src="js/udom.js"></script>
|
||||||
<script src="js/i18n.js"></script>
|
<script src="js/i18n.js"></script>
|
||||||
<script src="js/messaging-client.js"></script>
|
<script src="js/messaging-client.js"></script>
|
||||||
<script src="js/popup.js"></script>
|
<script src="js/popup.js"></script>
|
||||||
|
|
Loading…
Reference in a new issue