Reputation: 19
const self = {
element: document.querySelector(selector),
html: () => self.element,
on: (event, callback) => {
self.element.addEventListener(event, callback);
},
style: {
alignContent: (property) => {
return (property === null) ? self.element.style.alignContent : self.element.style.alignContent = property;
}
}
}
I am trying to make it so I have quick access to all CSS style properties with jQuery like selectors it should work as: select('h1').style.alignContent('center')
, but the problem is that I would have to make a seperate function for each style property in order for this method to work, is there a way to solve this problem without duplicating a lot of code?
//Duplication example
color: (property) => {
return (property === null) ? self.element.style.color : self.element.style.color = property;
}
Upvotes: 0
Views: 90
Reputation: 8130
One way to do this is with a Proxy
(mdn):
let elemWrapper = selector => {
let element = document.querySelector(selector);
return {
element,
html: () => element,
on: (event, callback) => {
element.addEventListener(event, callback);
},
style: new Proxy({}, {
get: (obj, prop) => {
// The user called a function named "prop"
// We need to return a function that sets the style property named "prop"
return cssValue => element.style[prop] = cssValue;
}
})
};
};
let bodyElem = elemWrapper('body');
bodyElem.style.backgroundColor('cyan');
Here to prove the concept I've set the body
element's background colour using a dynamically named function.
The big downside to this approach is the poor performance of Proxies (an excellent read on Proxy performance is available here).
This means it may be quicker to simply compile a list of all css property names, and define a function for each (never using Proxies). The following code compiles all css property names, to serve as a starting point:
console.log(Object.keys(document.body.style));
Upvotes: 4
Reputation: 89149
You can use a Proxy
to intercept all attempts to get a property.
let selector = '#test';
const self = {
element: document.querySelector(selector),
html: () => self.element,
on: (event, callback) => {
self.element.addEventListener(event, callback);
},
style: new Proxy(Object.create(null), {
get(target, prop, receiver) {
if (self.element.style.hasOwnProperty(prop)) {
return val => {
if (val != null) {
self.element.style[prop] = val;
} else {
return self.element.style[prop];
}
}
}
throw Error("No such property exists: " + prop);
}
})
};
self.style.color('red')
console.log("Color:", self.style.color());
<div id="test">
This is a test
</div>
You can also wrap this into a general function like so:
const getEnhancedElement = arg => {
const element = /Element/.test(Object.prototype.toString.call(arg)) ? arg
: document.querySelector(arg);//accept a HTMLElement or a selector
return {
element,
html: () => element,
on: (event, callback) => {
element.addEventListener(event, callback);
},
style: new Proxy(Object.create(null), {
get(target, prop) {
if (element.style.hasOwnProperty(prop)) {
return val => {
if (val != null) {//set value
element.style[prop] = val;
} else {//get value
return element.style[prop];
}
}
}
throw Error("No such property exists: " + prop);
}
})
};
};
let test = getEnhancedElement("#test");
test.style.color('red')
console.log("Color:", test.style.color());
test.style.textAlign('center');
<div id="test">
This is a test
</div>
Upvotes: 1
Reputation: 1818
I would have something like this:
style: {
chnageStyle: (propertyName, propertyVal) => {
return (propertyName === null) ? self.element.style[propertyName] : self.element.style[propertyName] = propertyVal;
}
}
Then you can call this:
style.changeStyle('alignContent','center');
style.changeStyle('color','orange');
Upvotes: 0