Reputation: 115
In input of function is an object who has this structure:
{
tag: 'a', //type of html object
content: "blabal", //inner content
attr: {
href: "vk.com",
id: 'someId'
},
events: {
click: 'alert(this.href)',
focus: 'this.className="active"'
},
style: {
width:"100px"
}
}
It describes an HTML element. It has to return an HTML element with specified properties. How to parse it? I have something like this:
elemen={
tag:'a',
content:"blabal",
attr:{
href:"vk.com",
id:'someId'
},
events:{
click:'alert(this.href)',
focus:'this.className="active"'
},
style:{
width:"100px"
}
};
console.log(elemen.tag);
var node = document.createElement(elemen.tag);
node.innerHTML= elemen.content;
for(var prop in elemen.events){
var fun =new Function(elemen.events[prop]);
console.log(fun);
node.bind(prop, fun);
// divv.bind(prop, fun);
}
Upvotes: 8
Views: 33266
Reputation: 92501
Use the following function:
const objectToHTML = function(obj) {
const element = document.createElement(obj.tag)
element.innerHTML = obj.content
for (const name in obj.attr) {
const value = obj.attr[name]
element.setAttribute(name, value)
}
for (const name in obj.events) {
const listener = new Function(obj.events[name]).bind(element)
element.addEventListener(name, listener)
}
for (const property in obj.style) {
const value = obj.style[property]
element.style[property] = value
}
return element
}
To create an event listener from string, you have to convert it to function using the Function
constructor, bind context to it using Function.prototype.bind()
(otherwise the function would be executed with window
as context), and finally, use element.addEventListener()
.
The rest is rather obvious.
You can use this function like that:
const element = objectToHTML({
tag: 'a',
content: "blabal",
attr: {
href: "vk.com",
id: 'someId'
},
events: {
click: 'alert(this.href)',
focus: 'this.className="active"'
},
style: {
width: "100px"
}
})
document.body.appendChild(element)
See demo:
const objectToHTML = function(obj) {
const element = document.createElement(obj.tag)
element.innerHTML = obj.content
for (const name in obj.attr) {
const value = obj.attr[name]
element.setAttribute(name, value)
}
for (const name in obj.events) {
const listener = new Function(obj.events[name]).bind(element)
element.addEventListener(name, listener)
}
for (const property in obj.style) {
const value = obj.style[property]
element.style[property] = value
}
return element
}
const element = objectToHTML({
tag: 'a',
content: "blabal",
attr: {
href: "vk.com",
id: 'someId'
},
events: {
click: 'alert(this.href)',
focus: 'this.className="active"'
},
style: {
width: "100px"
}
})
document.body.appendChild(element)
Upvotes: 0
Reputation: 493
I recommend this form, is more adaptable.
window.onload = function() {
function init_() {
function action__(type, element, convert, a) {
if (type == "function") {
if (convert.create[a] != null) {
try {
var new_ = convert.create[a](element[a]);
} catch (rrr) {
rrr = (rrr.toString());
if (rrr.indexOf('2 arguments') != -1 && Object.keys(element[a]).length != 0) {
for (v in element[a]) {
convert.create[v] = element[a][v];
var new_ = convert.create;
}
};
}
convert['create'] = new_;
}
};
if (type == "object") {
for (f in element[a]) {
convert.create[a][f] = element[a][f];
}
}
if (type == "string" && a != "events") {
convert.create[a] = (element[a]);
} else if (type == "string" && a == "events") {
for (ev in element[a]) {
var type = convert.detectType(convert.create, ev);
if (type == "function") {
convert.create.addEventListener(ev, new Function(element[a][ev]));
}
};
};
return convert.create;
};
function createElement(elements) {
var finished = [];
if (typeof elements.tagName == "undefined" && !elements.length) {
elements = [elements];
}
for (r = 0; r < elements.length; r++) {
var element = elements[r];
if (element) {
var convert = {
create: document,
detectType: function(element, attribute) {
var type = "string";
if (typeof element[attribute] != "undefined") {
type = typeof element[attribute];
};
return type;
},
add: function(new_) {
if (new_ && new_ != "undefined") {
this.create = new_;
}
}
};
for (a in element) {
var type = convert.detectType(convert.create, a);
var returner = action__(type, element, convert, a);
convert.add(returner);
}
finished.push(convert.create);
};
}
return (finished);
};
var minifi_function = init_.toString();
var elements = [{
createElement: 'a',
innerHTML: "blabal",
setAttribute: {
href: "vk.com",
id: 'someId',
style: "height:200px;"
},
events: {
click: 'alert(this.href)',
focus: 'this.className="active"'
},
style: {
width: "100px"
}
}, {
createElement: 'div',
innerHTML: "see my content",
setAttribute: {
['data-link']: "vk.com",
id: 'someId2',
style: "height:200px;background:red;"
},
events: {
click: 'prompt("Copy",' + minifi_function + ')',
focus: 'this.className="activediv"'
},
style: {
width: "100px"
}
}];
var elementos = createElement(elements);
console.log(elementos);
for (p = 0; p < elementos.length; p++) {
document.body.appendChild(elementos[p]);
}
}
init_();
}
Upvotes: -1
Reputation: 50291
Using only javascript
var _createElem = document.createElement(""+_elem.tag+"");
_createElem.innerHTML = _elem.content;
//set attributes
for(var keys in _elem.attr){
_createElem.setAttribute(''+keys+'',_elem.attr[keys])
}
//set style
for(var keys in _elem.style){
_createElem.setAttribute(''+keys+'',_elem.style[keys])
}
//set events
for(var keys in _elem.events){
_createElem.setAttribute('on'+keys,_elem.events[keys])
}
document.getElementById("demoDiv").appendChild(_createElem)
Note: The elem has got both onclick
& href
, you may need to return true/false
as per your requirement
Upvotes: 4
Reputation: 36609
Use addEventListener
to register events on Element
and .bind(thisArg)
to have specified argument as this-context
var elemen = {
tag: 'a',
content: "blabal",
attr: {
href: "vk.com",
id: 'someId'
},
events: {
click: 'alert(this.href)',
focus: 'this.className="active"'
}
};
var node = document.createElement(elemen.tag);
node.innerHTML = elemen.content;
for (var attr in elemen.attr) {
node.setAttribute(attr, elemen.attr[attr]);
}
for (var prop in elemen.events) {
node.addEventListener(prop, new Function(elemen.events[prop]).bind(node));
}
document.body.appendChild(node);
.active {
color: red;
}
Upvotes: 7