如何使用JSON数据创建动态星级评分

3

我正在设计一个星级评分系统,用于评价任何餐厅。在用户界面上,所有的“属性”都是动态的,我通过JSON格式获取数据。

我有五个属性,每个属性都有5个星级评分选项。

我的数据如下:

    [
          {
            "ATTRIBUTEID": "FOODQUALITY",
            "ATTRIBUTENAME": "Quality Of Food",
            "POSITION": 1
          },
          {
            "ATTRIBUTEID": "CLEANLINESS",
            "ATTRIBUTENAME": "Cleanliness",
            "POSITION": 2
          },
          {
            "ATTRIBUTEID": "SERVICE",
            "ATTRIBUTENAME": "Service",
            "POSITION": 3
          },
          {
            "ATTRIBUTEID": "STAFFBEHAVE",
            "ATTRIBUTENAME": "Staf Behavior",
            "POSITION": 4
          },
          {
            "ATTRIBUTEID": "AMBIENCE",
            "ATTRIBUTENAME": "Ambience",
            "POSITION": 5
          }
        ];

我想要实现的目标是这样的:

Image

我已经完成的工作

@charset "ISO-8859-1";
div.stars {
  width: 300px;
  display: inline-block;
  margin-left: -35px;
}

.commonLable {
  margin-left: 55px;
  font-family: sans-serif;
  font-weight: bold;
  margin-bottom: 0;
}

input.star {
  display: none;
}

label.star {
  float: right;
  padding: 5px;
  font-size: 40px;
  color: grey;
  transition: all .2s;
  margin-top: -25px;
}

hr {
  margin: 0;
}

input.star:checked~label.star:before {
  content: '\2605';
  color: #ffd309;
  transition: all .25s;
}

input.star-5:checked~label.star:before {
  color: #ffe840;
  text-shadow: 0 0 20px #952;
}

input.star-1:checked~label.star:before {
  color: #f24800;
}

label.star:hover {
  transform: rotate(-15deg) scale(1.3);
  cursor: pointer;
}

label.star:before {
  content: '\2605';
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/js/bootstrap.min.js"></script>
<div class="stars">
  <form action="">

    <div class="form-row">
      <label class="commonLable"> Cleanliness</label>
      <div class="form-group col-lg-12">
        <input class="star star-5" id="star-5" type="radio" name="star" value="5" />
        <label class="star star-5" for="star-5"></label>
        <input class="star star-4" id="star-4" type="radio" name="star" value="4" />
        <label class="star star-4" for="star-4"></label>
        <input class="star star-3" id="star-3" type="radio" name="star" value="3" />
        <label class="star star-3" for="star-3"></label>
        <input class="star star-2" id="star-2" type="radio" name="star" value="2" />
        <label class="star star-2" for="star-2"></label>
        <input class="star star-1" id="star-1" type="radio" name="star" value="1" />
        <label class="star star-1" for="star-1"></label>
      </div>
    </div>
    <div class="form-row">
      <label class="commonLable"> Quality Of Food
</label>
      <div class="form-group col-lg-12">
        <input class="star star-5" id="star-5r" type="radio" name="starr" />
        <label class="star star-5" for="star-5r"></label>
        <input class="star star-4" id="star-4r" type="radio" name="starr" />
        <label class="star star-4" for="star-4r"></label>
        <input class="star star-3" id="star-3r" type="radio" name="starr" />
        <label class="star star-3" for="star-3r"></label>
        <input class="star star-2" id="star-2r" type="radio" name="starr" />
        <label class="star star-2" for="star-2r"></label>
        <input class="star star-1" id="star-1r" type="radio" name="starr" />
        <label class="star star-1" for="star-1r"></label>
      </div>
    </div>
  </form>
</div>
</form>
</div>

在表单的最后,会有一个“提交”按钮,点击该按钮会向服务器发送一个动作,以保存反馈。由于我缺乏方法,不知道它是如何工作的,应该怎么做。

编辑

我已经编辑了我的代码片段,其中有两个属性食物质量清洁度,但当我点击清洁度星星时,上面的星星也被填充成颜色了。我知道这是因为通用的CSS样式,但这是我的问题,所有属性都是动态的,请检查我上传的JSON数据和我正在尝试做的事情的图片。

编辑

这是动态代码,可以动态创建星级和标签。

$(document).ready(function() {
  var data = [{
      "ATTRIBUTEID": "FOODQUALITY",
      "ATTRIBUTENAME": "Quality Of Food",
      "POSITION": 1
    },
    {
      "ATTRIBUTEID": "CLEANLINESS",
      "ATTRIBUTENAME": "Cleanliness",
      "POSITION": 2
    },
    {
      "ATTRIBUTEID": "SERVICE",
      "ATTRIBUTENAME": "Service",
      "POSITION": 3
    },
    {
      "ATTRIBUTEID": "STAFFBEHAVE",
      "ATTRIBUTENAME": "Staf Behavior",
      "POSITION": 4
    },
    {
      "ATTRIBUTEID": "AMBIENCE",
      "ATTRIBUTENAME": "Ambience",
      "POSITION": 5
    }
  ];

  for (v = 0; v < data.length; v++) {

    var container = document.getElementById("container");

    var firstDiv = document.createElement('div');
    firstDiv.setAttribute("class", "form-row");

    var secondDiv = document.createElement('div');
    secondDiv.setAttribute("class", "commonLable");
    secondDiv.append(data[v].ATTRIBUTENAME);


    var thirdDiv = document.createElement('div');
    thirdDiv.setAttribute("class", "form-group col-lg-12");

    /// append stars 

    for (i = 1; i < data.length + 1; i++) {
      var incrementedVar = i + 1;
      var stars = document.createElement("input");
      var label = document.createElement("label");
      stars.setAttribute("type", "radio");
      stars.setAttribute("id", '"' + data[v].ATTRIBUTEID + i + '"');
      stars.setAttribute("name", '"' + data[v].ATTRIBUTEID + i + '"');
      stars.setAttribute("class", "star star-5");
      stars.setAttribute("value", i);
      label.setAttribute("class", "star star-5");
      label.setAttribute("for", '"' + data[v].ATTRIBUTEID + i + '"');
      thirdDiv.append(stars, label);

    }

    secondDiv.append(thirdDiv);
    firstDiv.append(secondDiv);
    container.appendChild(firstDiv);
  }
  $('input:radio').change(
    function() {

      alert($(this).val());
    });
});
@charset "ISO-8859-1";
div.stars {
  width: 300px;
  display: inline-block;
  margin-left: -35px;
}

.commonLable {
  margin-left: 55px;
  font-family: sans-serif;
  font-weight: bold;
  margin-bottom: 0;
}

input.star {
  display: none;
}

label.star {
  float: right;
  padding: 5px;
  font-size: 40px;
  color: grey;
  transition: all .2s;
  margin-top: -25px;
}

hr {
  margin: 0;
}

input.star:checked~label.star:before {
  content: '\2605';
  color: #ffd309;
  transition: all .25s;
}

input.star-5:checked~label.star:before {
  color: #ffe840;
  text-shadow: 0 0 20px #952;
}

input.star-1:checked~label.star:before {
  color: #f24800;
}

label.star:hover {
  transform: rotate(-15deg) scale(1.3);
  cursor: pointer;
}

label.star:before {
  content: '\2605';
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css">
<div class="stars">
  <form action="" id="container">

  </form>
</div>

在第二个片段中,我添加了动态代码,但它无法正确地获取css。
问题:如果我将星号标记为4并希望将其从4到2取消标记,则无法实现。 请检查使用HTML的静态代码的片段1,我想要那种功能。

你具体在问什么?你的代码似乎运行正常。你缺少的只是单选按钮上的“value”属性,这样当表单提交时它们才能发送任何值到服务器。 - Rory McCrossan
4个回答

1
这是如何创建动态星级评分的方法。

var data = [
  {
    "ATTRIBUTEID": "FOODQUALITY",
    "ATTRIBUTENAME": "Quality Of Food",
    "POSITION": 1
  },
  {
    "ATTRIBUTEID": "CLEANLINESS",
    "Quantity": "Cleanliness",
    "POSITION": 2
  },
  {
    "ATTRIBUTEID": "SERVICE",
    "Quantity": "Service",
    "POSITION": 3
  },
  {
    "ATTRIBUTEID": "STAFFBEHAVE",
    "Quantity": "Staf Behavior",
    "POSITION": 4
  },
  {
    "ATTRIBUTEID": "AMBIENCE",
    "Quantity": "Ambience",
    "POSITION": 5
  }
];

for (v=0;v<data.length - 1;v++){
  var container = document.getElementById("container");

  var firstDiv = document.createElement('div');
  firstDiv.setAttribute("class", "form-row");

  var secondDiv = document.createElement('div');
  secondDiv.setAttribute("class", "commonLable");
  secondDiv.append(data[v].ATTRIBUTEID);


  var thirdDiv = document.createElement('div');
  thirdDiv.setAttribute("class", "form-group col-lg-12");

  /// append stars 

  for (i=0;i<5;i++){
   var incrementedVar = i+1;
    var stars = document.createElement("input");
    var label = document.createElement("label");
    stars.setAttribute("type", "radio");
    stars.setAttribute("id", '"'+ data[v].ATTRIBUTEID + i +'"');
    stars.setAttribute("name", '"'+ data[v].ATTRIBUTEID + i +'"');
    stars.setAttribute("class", "star star-5");
    label.setAttribute("class", "star star-5");
    label.setAttribute("for", '"'+ data[v].ATTRIBUTEID + i +'"');
    thirdDiv.append(stars, label);

  }

  secondDiv.append(thirdDiv);
  firstDiv.append(secondDiv);
  container.appendChild(firstDiv);
}
div.stars {
  width: 300px;
  display: inline-block;
}

.commonLable {
  margin-left: 55px;
  font-family: sans-serif;
  font-weight: bold;
}

input.star {
  display: none;
} 

label.star {
  float: right;
  padding: 5px;
  font-size: 30px;
  color: grey;
  transition: all .2s;
}

input.star:checked~label.star:before {
  content: '\2605';
  color: #FD4;
  transition: all .25s;
}

input.star-5:checked~label.star:before {
  color: #FE7;
  text-shadow: 0 0 20px #952;
}

input.star-1:checked~label.star:before {
  color: #F62;
}

label.star:hover {
  transform: rotate(-15deg) scale(1.3);
  cursor: pointer;
}

label.star:before {
  content: '\2605';
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/js/bootstrap.min.js"></script>
<div class="stars">
  <form action="" id="container">
   
  </form>
</div>


嘿,这很酷,但我想让它变得动态化,因为你可以检查我的JSON数据,属性名称和ID都在那里。我无法预测会有多少属性,在这里只是举例说明我已经静态地完成了两个属性,即“食品质量”和“清洁度”,我想用JavaScript或jQuery动态地完成它。 - manish thakur
还有一件事情你可能没有注意到,当我给第一个属性打了几颗星星后,点击第二个属性“清洁度”时,第一个属性的星星会消失。 - manish thakur
我已经明白了你的意思,很快会与你分享代码。第二个问题是通过更改ID和名称来处理的。 - Abdulhaq Shah
@manishthakuri已更新答案,现在它完全是动态的。我希望你现在可以处理剩下的部分了。 - Abdulhaq Shah
嘿,但只有单选按钮显示出来,没有星星,它不接受CSS。 - manish thakur
显示剩余4条评论

1

你的第二个示例不起作用,因为每个form-group中的输入没有相同的name。将它们赋予相同的name将解决你的问题。

你的星星是float: right,所以你需要按降序附加星星,以使它们按预期工作,否则左侧的第一个星星将具有值5

我还简化了你的代码,使用元素属性代替setAttribute()方法:

var data = [
  {
    "ATTRIBUTEID": "FOODQUALITY",
    "ATTRIBUTENAME": "Quality Of Food",
    "POSITION": 1
  },
  {
    "ATTRIBUTEID": "CLEANLINESS",
    "ATTRIBUTENAME": "Cleanliness",
    "POSITION": 2
  },
  {
    "ATTRIBUTEID": "SERVICE",
    "ATTRIBUTENAME": "Service",
    "POSITION": 3
  },
  {
    "ATTRIBUTEID": "STAFFBEHAVE",
    "ATTRIBUTENAME": "Staf Behavior",
    "POSITION": 4
  },
  {
    "ATTRIBUTEID": "AMBIENCE",
    "ATTRIBUTENAME": "Ambience",
    "POSITION": 5
  }
];

for (i = 0; i < data.length; i++){
  var container = document.getElementById("container");

  var row = document.createElement('div');
  row.className = "form-row";

  var commonLabel = document.createElement('label');
  commonLabel.className = "commonLable";
  commonLabel.innerHTML = data[i].ATTRIBUTENAME;


  var form_group = document.createElement('div');
  form_group.className = "form-group col-lg-12";

  for (j = 5;j > 0; j--) {
    var star = document.createElement("input");
    var label = document.createElement("label");
    star.type = "radio";
    star.id = data[i].ATTRIBUTEID + j;
    star.name = data[i].ATTRIBUTEID;
    star.className = "star star-" + j;
    star.value = j;
    label.className = "star star-" + j;
    label.htmlFor = data[i].ATTRIBUTEID + j;
    form_group.append(star, label);
  }

  row.append(commonLabel, form_group);
  container.appendChild(row);
}

$('#submit').click(function(){
  var formData = $('#container').serialize();
  alert(formData);
});
div.stars {
  width: 300px;
  display: inline-block;
}

.commonLable {
  margin-left: 55px;
  font-family: sans-serif;
  font-weight: bold;
}

input.star {
  display: none;
} 

label.star {
  float: right;
  padding: 5px;
  font-size: 30px;
  color: grey;
  transition: all .2s;
}

input.star:checked~label.star:before {
  content: '\2605';
  color: #FD4;
  transition: all .25s;
}

input.star-5:checked~label.star:before {
  color: #FE7;
  text-shadow: 0 0 20px #952;
}

input.star-1:checked~label.star:before {
  color: #F62;
}

label.star:hover {
  transform: rotate(-15deg) scale(1.3);
  cursor: pointer;
}

label.star:before {
  content: '\2605';
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/js/bootstrap.min.js"></script>
<div class="stars">
  <form action="" id="container">
   
  </form>
  <button type="button" id="submit">Submit</button>
</div>


@manishthakur,我已经编辑了我的答案来解决你提到的问题。请检查。 - Cuong Le Ngoc
是的。您有什么疑问吗? - Cuong Le Ngoc
先生,根据我的问题,您已经帮助我找到了正确的方法,但我需要一些关于在后端保存数据的建议。 - manish thakur
你能提供更多关于你想要的细节吗? - Cuong Le Ngoc
让我们在聊天中继续这个讨论 - Cuong Le Ngoc

1

请查看下面的代码片段,我进行了一些更正,并添加了提交按钮以获取结果。

$(document).ready(function() {
  var data = [{
      "ATTRIBUTEID": "FOODQUALITY",
      "ATTRIBUTENAME": "Quality Of Food",
      "POSITION": 1
    },
    {
      "ATTRIBUTEID": "CLEANLINESS",
      "ATTRIBUTENAME": "Cleanliness",
      "POSITION": 2
    },
    {
      "ATTRIBUTEID": "SERVICE",
      "ATTRIBUTENAME": "Service",
      "POSITION": 3
    },
    {
      "ATTRIBUTEID": "STAFFBEHAVE",
      "ATTRIBUTENAME": "Staf Behavior",
      "POSITION": 4
    },
    {
      "ATTRIBUTEID": "AMBIENCE",
      "ATTRIBUTENAME": "Ambience",
      "POSITION": 5
    }
  ];

  for (v = 0; v < data.length; v++) {

    var container = document.getElementById("container");

    var firstDiv = document.createElement('div');
    firstDiv.setAttribute("class", "form-row");

    var secondDiv = document.createElement('div');
    secondDiv.setAttribute("class", "commonLable");
    secondDiv.append(data[v].ATTRIBUTENAME);


    var thirdDiv = document.createElement('div');
    thirdDiv.setAttribute("class", "form-group col-lg-12");

    /// append stars 

    for (i = 1; i < data.length + 1; i++) {
      var incrementedVar = i + 1;
      var stars = document.createElement("input");
      var label = document.createElement("label");
      stars.setAttribute("type", "radio");
      stars.setAttribute("required", "required");
      stars.setAttribute("id", data[v].ATTRIBUTEID + i ); // removed double quotes
      stars.setAttribute("name",  data[v].ATTRIBUTEID );  // removed incremental i, removed double quotes
      stars.setAttribute("class", "star star-5");
      stars.setAttribute("value", i);
      label.setAttribute("class", "star star-5");
      label.setAttribute("for",  data[v].ATTRIBUTEID + i);  // removed double quotes
      thirdDiv.append(stars, label);

    }

    secondDiv.append(thirdDiv);
    firstDiv.append(secondDiv);
    container.appendChild(firstDiv);
    
  }
  var btn = document.createElement("button");
    btn.type = 'submit'; 
    btn.value= 'submit';
    btn.innerHTML = 'Submit'; 
    btn.setAttribute("style", "margin-left:55px;");
    container.append(btn);
  $('input:radio').change(
    function() {
    });
  $('.buttonSubmit').click(function(){
    var formData = $('#container').serialize();
    alert(formData);
  });
});
@charset "ISO-8859-1";
div.stars {
  width: 300px;
  display: inline-block;
  margin-left: -35px;
}

.commonLable {
  margin-left: 55px;
  font-family: sans-serif;
  font-weight: bold;
  margin-bottom: 0;
}

input.star {
  display: none;
}

label.star {
  float: right;
  padding: 5px;
  font-size: 40px;
  color: grey;
  transition: all .2s;
  margin-top: -25px;
}

hr {
  margin: 0;
}

input.star:checked~label.star:before {
  content: '\2605';
  color: #ffd309;
  transition: all .25s;
}

input.star-5:checked~label.star:before {
  color: #ffe840;
  text-shadow: 0 0 20px #952;
}

input.star-1:checked~label.star:before {
  color: #f24800;
}

label.star:hover {
  transform: rotate(-15deg) scale(1.3);
  cursor: pointer;
}

label.star:before {
  content: '\2605';
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css">
<div class="stars">
  <form action="" id="container">

  </form>
  
</div>


0
如果我已经标记了星星并想要取消从4到2的标记,这是不会发生的...
您可以使用以下CSS规则来黄色标记星星:
input.star:checked~label.star:before {

这适用于所有已选中复选框后面的 label.star

现在要取消黄色... 您只需取消选中同级输入框即可... 我使用 .siblings(selector) 来匹配它们... 并使用 .each() 循环将 checked 属性更改为 false。

$(this).siblings("input").each(function() {
  $(this).prop("checked", false);
});

这里是一段代码片段:

$(document).ready(function() {
  var data = [{
      "ATTRIBUTEID": "FOODQUALITY",
      "ATTRIBUTENAME": "Quality Of Food",
      "POSITION": 1
    },
    {
      "ATTRIBUTEID": "CLEANLINESS",
      "ATTRIBUTENAME": "Cleanliness",
      "POSITION": 2
    },
    {
      "ATTRIBUTEID": "SERVICE",
      "ATTRIBUTENAME": "Service",
      "POSITION": 3
    },
    {
      "ATTRIBUTEID": "STAFFBEHAVE",
      "ATTRIBUTENAME": "Staf Behavior",
      "POSITION": 4
    },
    {
      "ATTRIBUTEID": "AMBIENCE",
      "ATTRIBUTENAME": "Ambience",
      "POSITION": 5
    }
  ];

  for (v = 0; v < data.length; v++) {

    var container = document.getElementById("container");

    var firstDiv = document.createElement('div');
    firstDiv.setAttribute("class", "form-row");

    var secondDiv = document.createElement('div');
    secondDiv.setAttribute("class", "commonLable");
    secondDiv.append(data[v].ATTRIBUTENAME);


    var thirdDiv = document.createElement('div');
    thirdDiv.setAttribute("class", "form-group col-lg-12");

    /// append stars 

    for (i = 1; i < data.length + 1; i++) {
      var incrementedVar = i + 1;
      var stars = document.createElement("input");
      var label = document.createElement("label");
      stars.setAttribute("type", "radio");
      stars.setAttribute("id", data[v].ATTRIBUTEID + i);
      stars.setAttribute("name", data[v].ATTRIBUTEID + i);
      stars.setAttribute("class", "star star-5");
      stars.setAttribute("value", i);
      label.setAttribute("class", "star star-5");
      label.setAttribute("for", data[v].ATTRIBUTEID + i);
      thirdDiv.append(stars, label);

    }

    secondDiv.append(thirdDiv);
    firstDiv.append(secondDiv);
    container.appendChild(firstDiv);
  }


  $('input:radio').on("change", function() {
console.log($(this).prop("checked"));
    // Uncheck all sibling inputs that are before $(this) (in DOM... But visually on the right).
    $(this).siblings("input").each(function() {
      $(this).prop("checked", false);
    });
  });

});
@charset "ISO-8859-1";
div.stars {
  width: 300px;
  display: inline-block;
  margin-left: -35px;
}

.commonLable {
  margin-left: 55px;
  font-family: sans-serif;
  font-weight: bold;
  margin-bottom: 0;
}

input.star {
  display: none;
}

label.star {
  float: right;
  padding: 5px;
  font-size: 40px;
  color: grey;
  transition: all .2s;
  margin-top: -25px;
}

hr {
  margin: 0;
}

input.star:checked~label.star:before {
  content: '\2605';
  color: #ffd309;
  transition: all .25s;
}

input.star-5:checked~label.star:before {
  color: #ffe840;
  text-shadow: 0 0 20px #952;
}

input.star-1:checked~label.star:before {
  color: #f24800;
}

label.star:hover {
  transform: rotate(-15deg) scale(1.3);
  cursor: pointer;
}

label.star:before {
  content: '\2605';
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css">
<div class="stars">
  <form action="" id="container">

  </form>
</div>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接