我的递归函数坏了,我不知道为什么。我正试图用barebone javascript编写json到css的解析器,似乎无法将我的头围绕为什么我的函数不起作用。有人能帮我一下吗?
在css中,你会得到你正在寻址的特定元素的子元素,比如
#nav li{
some style here
}
试图在javascript中操作相同的东西,但它不起作用。到目前为止,我的代码对于简单的选择器工作得很好。
var json = {
"body" : {
"background": "#303030",
"color": "#FFFFFF",
"font-family": "Arial, Helvetica, sans-serif"
},
"#nav": {
"li": {
"display": "inline-block",
"list-styles": "none",
"margin-right": "10px",
"padding": "10px, 10px"
}
}
}
// How to use:
// json is an obj
// body is a selector
// background is a property belong to a selector
// #303030 is a value for the property
//apply css changes to document without writing any css
//by default the first values are
// selector = background
// parent = document
// object = json
function styleApply(selector, parent, object){
var element, onSelector, signal;
//checks the first character of the selector and grabs element from page depending on what type of element it is
switch(selector[0]){
case ".":
element= parent.getElementsByClassName(selector.substring(1));
newParent = element[0]; //checks to see what is in the first index of the obtained element
break;
case "#":
element= parent.getElementById(selector.substring(1));
newParent = element;
break;
default:
element= parent.getElementsByTagName(selector);
newParent = element[0];
break;
}
//only works if there is actually an element in the page corresponding with the selector
if(newParent != null){
//loops through all elements with the same selector or in the case of id just does one loop
for(var i=0; i<element.length; i++){
//loops through all properties in the selector
for (var property in object[selector]){
//grabs the associated value with the selector could be string or object
var value= object[selector][property];
//if it is a string it is a style, if it is an object, it is targeting the elements inside the current selector only
if(typeof(value) === "string"){
element[i].style.setProperty(property, value);
}else{
/*I am breaking my code right here*/
//reusing the same function, this time selector is equal to property for the case of nav, it is the element 'li'
//newParent is the element who is a parent of the current element (e.g 'nav' is parent of 'li')
//value is the new object that is replacing json,
styleApply(property, newParent, value); //since value is an object it did not pass the string test and now the new object is value
/*Problem ends here */
}
}
}
}
}
my code for looping over all the values in json
for (var selector in json){
styleApply(selector, document, json);
}
我只是碰巧看到json写一个干净的css比直接连接字符串和数字在一起。我没有将样式直接应用于每个元素,而是将它们放入<style>
元素中,这使得在页面的整个生命周期中更容易更改。它还能够定位伪元素,如:前面,我使用的。
总之,函数是这样的:
// convert json to css
function jsonToCss(obj) {
var x, finalStr=''
for (x in obj) {
var y, decStr=''
for (y in obj[x]) {
decStr+= y + ':' + obj[x][y] + ';'
}
finalStr+= x + '{' + decStr + '}'
}
return finalStr
}
由于该函数只递归两个级别(一个用于选择器,另一个用于声明),您的json需要修改如下:
var json = {
"body" : {
"background": "#303030",
"color": "#FFFFFF",
"font-family": "Arial, Helvetica, sans-serif"
},
"#nav li": {
"display": "inline-block",
"list-styles": "none",
"margin-right": "10px",
"padding": "10px, 10px"
}
}
将其输入到函数中,您将得到以下字符串:
body{background:#303030;color:#FFFFFF;font-family:Arial, Helvetica, sans-serif;}#nav li{display:inline-block;list-styles:none;margin-right:10px;padding:10px, 10px;}
,然后可以将其放入样式元素中。我还没有验证这个函数产生的字符串,看看它是否格式良好,但它在我这边工作得很好。
这是一段很短的代码,是关于把json解析成css的,我想试试
——selectors指的是你在json中编写的CSS选择器
——parent开始引用文档,就像javascript中的document对象模型一样
——object是传入
的json对象。如果我误用了术语,请再次纠正我
function styleApply(selector, parent, object){
var element, onSelector, signal;
switch(selector[0]){
case ".":
element= parent.getElementsByClassName(selector.substring(1));
break;
case "#":
element= [parent.getElementById(selector.substring(1))];
break;
default:
element= parent.getElementsByTagName(selector);
break;
}
if(element[0] != null){
for(var i=0; i<element.length; i++){
for (var property in object[selector]){
var value= object[selector][property];
if(typeof(value) === "string"){
element[i].style.setProperty(property, value);
}else{
styleApply(property, element[i], object[selector]);
}
}
}
}
}