Remove JQuery
Closed this issue · 1 comments
ChristopherBull commented
The included JQuery is outdated. Rather than upgrading it, I want to remove it and replace its usage with modern native JS equivalents.
This will reduce extension size, give minor performance improvements (e.g., load times; not that this was an issue before), and reduce reliance on dependencies.
Remove JQuery from:
- Background
- Content Script (scripts injected into web pages)
- Options page
Geompse commented
Would this help ? I just wrote it from scratch, feel free of using it.
-
In contentScript.js and options.js, replace
$
byCL$
, remove jQuery, and add on the first lineimport { CL$ } from './CL.js';
. -
Create a new file CL.js
export default class CL
{
static parseHTML(html)
{
let tmp = document.createElement('cl-tmp');
tmp.innerHTML = html;
return new CL(tmp.childNodes);
}
static contains(host,element)
{
if(!element.parentNode)
return false;
if(element.parentNode === host)
return true;
return CL.contains(host,element.parentNode);
}
static onecallback(callback,event)
{
if(callback.done)
return;
callback.done = true;
callback.call(this,event);
}
static datacallback(callback,data,event)
{
if(data !== undefined)
event.data = data;
callback.call(this,event);
}
constructor(selector,context)
{
if(selector.constructor === this.constructor)
{
this.selector = selector.selector;
this.context = selector.context;
this.elements = selector.elements;
}
else if(typeof(selector) == 'function')
{
selector();
this.context = undefined;
this.elements = [];
}
else if(typeof(selector) == 'string')
{
this.selector = selector;
this.context = context;
this.elements = Array.from((context?(typeof(context)=='string'?document.querySelector(context):context):document).querySelectorAll(selector));
}
else
{
if(selector.constructor === NodeList)
selector = Array.from(selector);
this.selector = undefined;
this.context = undefined;
this.elements = selector?(selector.constructor===Array?selector:[selector]):[];
}
this.dataStore = {};
for(let pos=0; pos<this.elements.length; pos++)
this[pos] = this.elements[pos];
}
children()
{
let childNodes = [];
this.elements.forEach(element=>element.childNodes.forEach(childNode=>childNodes.push(childNode)));
return new CL(childNodes);
}
first()
{
return new CL(this.elements[0]);
}
next()
{
return new CL(this.elements[0].nextElementSibling);
}
last()
{
return new CL(this.elements[this.elements.length-1]);
}
one(eventName,selector,data,callback)
{
if(callback === undefined)
{
if(typeof(selector) == 'string')
{
callback = data;
data = undefined;
}
else
{
callback = data;
data = selector;
selector = undefined;
}
}
if(callback === undefined)
{
callback = data;
data = undefined;
}
this.on(eventName,selector,data,CL.onecallback.bind(this,callback));
}
on(eventName,selector,data,callback)
{
if(callback === undefined)
{
if(typeof(selector) == 'string')
{
callback = data;
data = undefined;
}
else
{
callback = data;
data = selector;
selector = undefined;
}
}
if(callback === undefined)
{
callback = data;
data = undefined;
}
if(selector)
this.elements.forEach(element=>element.querySelectorAll(selector).forEach(child=>child.addEventListener(eventName,CL.datacallback.bind(child,callback,data),false)));
else
this.elements.forEach(element=>element.addEventListener(eventName,CL.datacallback.bind(element,callback,data),false));
return this;
}
unbind(eventName,callback)
{
this.elements.forEach(element=>element.removeEventListener(eventName,callback.bind(element),false));
}
click(data,callback)
{
return this.on('click',data,callback);
}
mousemove(data,callback)
{
return this.on('mousemove',data,callback);
}
change()
{
console.warn('WIP trigger onchange');
return this;
}
data(propertyName,propertyValue)
{
if(propertyValue === undefined)
return this.dataStore[propertyName];
this.dataStore[propertyName] = propertyValue;
return this;
}
attr(propertyName,propertyValue)
{
if(propertyValue === undefined)
return this.elements[0].getAttribute(propertyName);
this.elements.forEach(element=>element.setAttribute(propertyName,propertyValue));
return this;
}
prop(propertyName,propertyValue)
{
if(propertyValue === undefined)
return this.elements[0][propertyName];
this.elements.forEach(element=>element[propertyName]=propertyValue);
return this;
}
val()
{
return this.elements[0].value;
}
height()
{
if(this.elements[0].innerHeight)
return this.elements[0].innerHeight;
let hidden = this.elements[0].style.display !== 'block';
if(hidden)
this.elements[0].style.display = 'block';
let connected = this.elements[0].parentNode;
if(!connected)
document.body.appendChild(this.elements[0]);
let height = this.elements[0].offsetHeight;
if(!connected)
document.body.removeChild(this.elements[0]);
if(hidden)
this.elements[0].style.display = 'none';
return height;
}
width()
{
if(this.elements[0].innerWidth)
return this.elements[0].innerWidth;
let hidden = this.elements[0].style.display !== 'block';
if(hidden)
this.elements[0].style.display = 'block';
let connected = this.elements[0].parentNode;
if(!connected)
document.body.appendChild(this.elements[0]);
let width = this.elements[0].offsetWidth;
if(!connected)
document.body.removeChild(this.elements[0]);
if(hidden)
this.elements[0].style.display = 'none';
return width;
}
text(textContent)
{
this.elements[0].textContent = textContent;
return this;
}
html(innerHTML)
{
this.elements[0].innerHTML = innerHTML;
return this;
}
append(element)
{
if(element.constructor === CL)
element.elements.forEach(child=>this.elements[0].appendChild(child));
else
this.elements[0].appendChild(element);
return this;
}
css(propertyName,propertyValue)
{
if(typeof(propertyName) === 'string')
{
if(propertyValue === undefined)
return this.elements[0].style[propertyName];
this.elements.forEach(element=>element.style[propertyName]=propertyValue);
return this;
}
for(let tmppropertyName in propertyName)
this.css(tmppropertyName,propertyName[tmppropertyName]);
return this;
}
show()
{
return this.css('display','block');
}
hide()
{
return this.css('display','none');
}
delay()
{
console.warn('WIP delay');
return this;
}
fadeIn(duration)
{
if(!duration)
duration = 500;
clearTimeout(this.fadeintimeout1);
clearTimeout(this.fadeouttimeout1);
clearTimeout(this.fadeouttimeout2);
this.css('transition','none');
this.css('opacity',0);
this.show();
this.css('transition','opacity '+(duration/1000)+'s');
this.fadeintimeout1 = setTimeout((function(){
this.css('opacity',1);
}).bind(this),200);
return this;
return this;
}
fadeOut(duration)
{
if(!duration)
duration = 500;
clearTimeout(this.fadeintimeout1);
clearTimeout(this.fadeouttimeout1);
clearTimeout(this.fadeouttimeout2);
this.css('transition','none');
this.css('opacity',1);
this.show();
this.css('transition','opacity '+(duration/1000)+'s');
this.fadeouttimeout1 = setTimeout((function(){
this.css('opacity',0);
this.fadeouttimeout2 = setTimeout(this.hide.bind(this),duration);
}).bind(this),200);
return this;
}
focusout()
{
console.warn('WIP focus out');
return this;
}
finish()
{
console.warn('WIP finish');
return this;
}
stop()
{
console.warn('WIP stop');
return this;
}
tabs()
{
new CLTabUI(this.selector);
return this;
}
accordion(options)
{
new CLAccordionUI(this.selector);
return this;
}
}
export const CL$ = (selector,context)=>new CL(selector,context);
CL$.parseHTML = CL.parseHTML;
CL$.contains = CL.contains;
class CLTabUI
{
static
{
let css = [];
css.push('cltabui-css{display:none;}');
css.push('[cltabui-host]{}');
css.push('[cltabui-host] ul{list-style-type:none;display:flex;}');
css.push('[cltabui-handle]{cursor:pointer;padding:0.5em 1em;margin:1px 0.2em 0 0;}');
css.push('[cltabui-handle] a{text-decoration:none;color:inherit;}');
css.push('[cltabui-handle="active"]{background:#007fff;border:1px solid #003eff;color:#ffffff;}');
css.push('[cltabui-handle="inactive"]{background:#f6f6f6;border:1px solid #c5c5c5;color:#333333;}');
css.push('[cltabui-content]{}');
css.push('[cltabui-content="active"]{display:block;}');
css.push('[cltabui-content="inactive"]{display:none;}');
let style = document.createElement('cltabui-css');
style.innerHTML = '<style type="text/css">'+"\n"+css.join("\n")+"\n"+'</style>';
document.body.appendChild(style);
}
constructor(selector)
{
let host = document.querySelector(selector);
host.setAttribute('cltabui-host','');
let handles = document.querySelectorAll(selector+'>ul>li');
let contents = [];
for(let pos=0; pos<handles.length; pos++)
{
let handle = handles[pos];
let link = handle.querySelector('a[href^="#"]');
let content = document.querySelector(selector+'>'+link.getAttribute('href'));
handle.setAttribute('cltabui-handle',pos==0?'active':'inactive');
content.setAttribute('cltabui-content',pos==0?'active':'inactive');
handle.onclick = this.onclick.bind(this,handle,content);
contents.push(content);
}
this.handles = handles;
this.contents = contents;
}
onclick(currenthandle,currentcontent,event)
{
event.stopPropagation();
event.preventDefault();
let handles = this.handles;
let contents = this.contents;
for(let pos=0; pos<handles.length; pos++)
{
let handle = handles[pos];
let content = contents[pos];
handle.setAttribute('cltabui-handle',handle===currenthandle?'active':'inactive');
content.setAttribute('cltabui-content',content===currentcontent?'active':'inactive');
}
}
}
class CLAccordionUI
{
static
{
let css = [];
css.push('claccordionui-css{display:none;}');
css.push('[claccordionui-host]{}');
css.push('[claccordionui-handle]{cursor:pointer;padding:0.5em 0.5em 0.5em 0.7em;margin:2px 0 0 0;}');
css.push('[claccordionui-handle="active"]{background:#007fff;border:1px solid #003eff;color:#ffffff;}');
css.push('[claccordionui-handle="active"]:before{content:\'v\';}');
css.push('[claccordionui-handle="inactive"]{background:#ededed;border:1px solid #cccccc;color:#2b2b2b;}');
css.push('[claccordionui-handle="inactive"]:before{content:\'>\';}');
css.push('[claccordionui-content]{padding:1em 2.2em;background:#ffffff;border:1px solid #dddddd;border-top:0;color:#333333;}');
css.push('[claccordionui-content="active"]{display:block;}');
css.push('[claccordionui-content="inactive"]{display:none;}');
let style = document.createElement('claccordionui-css');
style.innerHTML = '<style type="text/css">'+"\n"+css.join("\n")+"\n"+'</style>';
document.body.appendChild(style);
}
constructor(selector)
{
let host = document.querySelector(selector);
host.setAttribute('claccordionui-host','');
let handles = document.querySelectorAll(selector+'>h3');
let contents = document.querySelectorAll(selector+'>div');
for(let pos=0; pos<handles.length; pos++)
{
let handle = handles[pos];
let content = contents[pos];
handle.setAttribute('claccordionui-handle','inactive');
content.setAttribute('claccordionui-content','inactive');
handle.onclick = this.onclick.bind(this,handle,content);
}
}
onclick(currenthandle,currentcontent,event)
{
event.stopPropagation();
event.preventDefault();
currenthandle.setAttribute('claccordionui-handle',currenthandle.getAttribute('claccordionui-handle')=='inactive'?'active':'inactive');
currentcontent.setAttribute('claccordionui-content',currentcontent.getAttribute('claccordionui-content')=='inactive'?'active':'inactive');
}
}