复选框上的JavaScript会克隆此div,未选中时将其删除

时间:2018-12-13 04:04:55

标签: javascript jquery html css local-storage

选中该复选框后,克隆正确的div并显示在示例中:<div id="favorite"></div>取消选中该复选框时,删除克隆,并附带localStorage。有人可以帮我解决这个问题吗?

function onClickAvGamesCheckBox() {
  var arr = $('.AvGamesCheckBox').map(function() {
    return this.checked;
  }).get();
  localStorage.setItem("checked", JSON.stringify(arr));
}

$(document).ready(function() {
  var arr = JSON.parse(localStorage.getItem('checked')) || [];
  arr.forEach(function(checked, i) {
    $('.AvGamesCheckBox').eq(i).prop('checked', checked);
  });
  $(".AvGamesCheckBox").click(onClickAvGamesCheckBox);
});

//* Clone script
$(".avclone :checkbox").change(function() {
  var name = $(this).closest("div").attr("name");
  if (this.checked)
    $(".columns[name=" + name + "]").clone().appendTo("#favorite");
  else
    $("#favorite .columns[name=" + name + "]").remove();
});
* {
  box-sizing: border-box;
  padding: 5px;
}

.AvGamesContainer {
  display: block;
  position: relative;
  padding-left: 35px;
  margin-bottom: 12px;
  cursor: pointer;
  font-size: 22px;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

.AvGamesContainer input {
  position: absolute;
  opacity: 0;
  display: none;
  visibility: hidden;
  cursor: pointer;
  height: 0;
  width: 0;
}

.AvGamesCheckmark {
  position: absolute;
  top: 26px;
  right: 0;
  height: 25px;
  width: 25px;
  padding: 3px !important;
  background-color: #fff;
  background-image: url("https://i.ibb.co/Yyp3QTL/addstar.png");
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
  -webkit-border-top-right-radius: 5px;
  -webkit-border-bottom-left-radius: 8px;
  -moz-border-radius-topright: 5px;
  -moz-border-radius-bottomleft: 8px;
  border-top-right-radius: 5px;
  border-bottom-left-radius: 8px;
  z-index: 5;
}

.AvGamesContainer input:checked~.AvGamesCheckmark {
  background-color: #fff;
  color: yellow !important;
  background-image: url("https://i.ibb.co/0J7XxyK/favstar.png");
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
}

.AvGamesContainer:hover input~.AvGamesCheckmark {
  background-color: #fff;
}

.AvGamesCheckmark:after {
  content: "";
  position: absolute;
  display: none;
}

.AvGamesContainer input:checked~.AvGamesCheckmark:after {
  display: none;
}

.AvGamesContainer .AvGamesCheckmark:after {
  display: none;
}

img {
  width: 100%;
  height: auto;
  background: #fff;
  border-radius: 10px;
  -webkit-box-shadow: 0px 1px 5px 2px rgba(0, 0, 0, 0.75);
  -moz-box-shadow: 0px 1px 5px 2px rgba(0, 0, 0, 0.75);
  box-shadow: 0px 1px 5px 2px rgba(0, 0, 0, 0.75);
  transition: all 0.5s ease-in-out 0s;
  z-index: 4;
}

img:hover {
  -webkit-box-shadow: 0px 1px 5px 2px rgba(0, 0, 0, 0.75);
  -moz-box-shadow: 0px 1px 5px 2px rgba(0, 0, 0, 0.75);
  box-shadow: 0px 1px 5px 2px rgba(0, 0, 0, 0.75);
  -webkit-filter: saturate(150%);
}

.column {
  float: left;
  width: 50%;
  padding: 5px;
  height: auto;
}

.columns {
  position: relative;
  border-radius: 10px;
  text-align: center;
  width: 99%;
  margin: 0 auto;
  padding: 5px;
}

.row:after {
  content: "";
  display: table;
  clear: both;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div class="avclone">
  <div class="column">
    <div class="columns">
      <label class="AvGamesContainer">
  <input type="checkbox" name="AvGamesContainer" class="AvGamesCheckBox">
  <span class="AvGamesCheckmark"></span>
  </label>
      <a href="https://games.softgames.com/games/aquablitz-2/gamesites/7665/" data-path><img src="https://d1bjj4kazoovdg.cloudfront.net/assets/games/aquablitz-2/teaser.jpg?p=pub-15088-15357" title="Aqua Blitz 2"></a>
    </div>
  </div>

  <div class="column">
    <div class="columns">
      <label class="AvGamesContainer">
  <input type="checkbox" name="AvGamesContainer" class="AvGamesCheckBox">
  <span class="AvGamesCheckmark"></span>
  </label>
      <a href="https://games.softgames.com/games/daily-sudoku/gamesites/7665/" data-path><img src="https://d1bjj4kazoovdg.cloudfront.net/assets/games/daily-sudoku/teaser.jpg?p=pub-15088-15357" title="Daily Sudoku"></a>
    </div>
  </div>

</div>
<div id="favorite"></div>

选中该复选框后,克隆正确的div并显示在示例中:<div id="favorite"></div>取消选中该复选框时,删除克隆,并附带localStorage。有人可以帮我解决这个问题吗?

3 个答案:

答案 0 :(得分:6)

您有一个点击处理程序,因此我们将其连接起来以进行存储(由于沙箱而无法在此处使用),我们还可以使用数据并以此进行过滤,并向每个columns容器添加索引用来过滤克隆的项目,这样我们就可以定位它们并删除,无论先添加哪一个。

这是一个带有自定义事件和稍微复杂一些的存储示例的小提琴: https://jsfiddle.net/MarkSchultheiss/5Luyn18j/47/只是为了避免在SO上使用沙箱而做的事情。

原文:

//borrow some code from https://stackoverflow.com/a/15651670/125981
(function($) {
  $.fn.filterByData = function(prop, val) {
    return this.filter(
      function() {
        return $(this).data(prop) == val;
      }
    );
  }
})(window.jQuery);

function onClickAvGamesCheckBox(event) {
  var arr = $('.AvGamesCheckBox').map(function() {
    return this.checked;
  }).get();
  // localStorage.setItem("checked", JSON.stringify(arr));
}

$(function() {
  //add some data
  $('.AvGamesCheckBox').each(function(index, element) {
    $(this).closest('.column').data("checkindex", index);
  });
  // replace [] with the commented out for real stuff
  var arr = []; //JSON.parse(localStorage.getItem('checked')) || [];
  arr.forEach(function(checked, i) {
    $('.AvGamesCheckBox').eq(i).prop('checked', checked);
  });
  $(".AvGamesCheckBox").trigger("change");
});

//* Clone script
$(".avclone").on('change', '.AvGamesCheckBox', function() {
  var checkContainer = $(this).closest('.column');
  var checkIndex = checkContainer.data("checkindex");
  var matcher = $("#favorite").find(".column").filterByData("checkindex", checkIndex);
  if (this.checked && !matcher.length)
    checkContainer.clone(true).appendTo("#favorite");
  else
    matcher.remove();
}).on('click', '.AvGamesCheckBox', onClickAvGamesCheckBox);
* {
  box-sizing: border-box;
  padding: 5px;
}

.AvGamesContainer {
  display: block;
  position: relative;
  padding-left: 35px;
  margin-bottom: 12px;
  cursor: pointer;
  font-size: 22px;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

.AvGamesContainer input {
  position: absolute;
  opacity: 0;
  display: none;
  visibility: hidden;
  cursor: pointer;
  height: 0;
  width: 0;
}

.AvGamesCheckmark {
  position: absolute;
  top: 26px;
  right: 0;
  height: 25px;
  width: 25px;
  padding: 3px !important;
  background-color: #fff;
  background-image: url("https://i.ibb.co/Yyp3QTL/addstar.png");
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
  -webkit-border-top-right-radius: 5px;
  -webkit-border-bottom-left-radius: 8px;
  -moz-border-radius-topright: 5px;
  -moz-border-radius-bottomleft: 8px;
  border-top-right-radius: 5px;
  border-bottom-left-radius: 8px;
  z-index: 5;
}

.AvGamesContainer input:checked~.AvGamesCheckmark {
  background-color: #fff;
  color: yellow !important;
  background-image: url("https://i.ibb.co/0J7XxyK/favstar.png");
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
}

.AvGamesContainer:hover input~.AvGamesCheckmark {
  background-color: #fff;
}

.AvGamesCheckmark:after {
  content: "";
  position: absolute;
  display: none;
}

.AvGamesContainer input:checked~.AvGamesCheckmark:after {
  display: none;
}

.AvGamesContainer .AvGamesCheckmark:after {
  display: none;
}

img {
  width: 100%;
  height: auto;
  background: #fff;
  border-radius: 10px;
  -webkit-box-shadow: 0px 1px 5px 2px rgba(0, 0, 0, 0.75);
  -moz-box-shadow: 0px 1px 5px 2px rgba(0, 0, 0, 0.75);
  box-shadow: 0px 1px 5px 2px rgba(0, 0, 0, 0.75);
  transition: all 0.5s ease-in-out 0s;
  z-index: 4;
}

img:hover {
  -webkit-box-shadow: 0px 1px 5px 2px rgba(0, 0, 0, 0.75);
  -moz-box-shadow: 0px 1px 5px 2px rgba(0, 0, 0, 0.75);
  box-shadow: 0px 1px 5px 2px rgba(0, 0, 0, 0.75);
  -webkit-filter: saturate(150%);
}

.column {
  float: left;
  width: 50%;
  padding: 5px;
  height: auto;
}

.columns {
  position: relative;
  border-radius: 10px;
  text-align: center;
  width: 99%;
  margin: 0 auto;
  padding: 5px;
}

.row:after {
  content: "";
  display: table;
  clear: both;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div class="avclone">
  <div class="column">
    <div class="columns">
      <label class="AvGamesContainer">
  <input type="checkbox" name="AvGamesContainer" class="AvGamesCheckBox">
  <span class="AvGamesCheckmark"></span>
  </label>
      <a href="https://games.softgames.com/games/aquablitz-2/gamesites/7665/" data-path><img src="https://d1bjj4kazoovdg.cloudfront.net/assets/games/aquablitz-2/teaser.jpg?p=pub-15088-15357" title="Aqua Blitz 2"></a>
    </div>
  </div>
  <div class="column">
    <div class="columns">
      <label class="AvGamesContainer">
  <input type="checkbox" name="AvGamesContainer" class="AvGamesCheckBox">
  <span class="AvGamesCheckmark"></span>
  </label>
      <a href="https://games.softgames.com/games/daily-sudoku/gamesites/7665/" data-path><img src="https://d1bjj4kazoovdg.cloudfront.net/assets/games/daily-sudoku/teaser.jpg?p=pub-15088-15357" title="Daily Sudoku"></a>
    </div>
  </div>
</div>
<div id="favorite" ></div>

单击克隆后的添加: 编辑:添加了自定义事件并评论了如何修改以供实际使用

//borrow some code from https://stackoverflow.com/a/15651670/125981
(function($) {
  $.fn.filterByData = function(prop, val) {
    return this.filter(
      function() {
        return $(this).data(prop) == val;
      }
    );
  }
})(window.jQuery);

function onClickAvGamesCheckBox(event) {
  var arr = $(".avclone").find('.AvGamesCheckBox').map(function() {
    return this.checked;
  }).get();
  //EDIT: un-comment for real use
  // localStorage.setItem("checked", JSON.stringify(arr));
}

$(function() {
  //add some data
  var checks = $(".avclone").find('.AvGamesCheckBox');
  checks.each(function(index, element) {
    $(this).closest('.column').data("checkindex", index);
  });
  //EDIT replace []; with commented out code for real use
  var arr = []; //JSON.parse(localStorage.getItem('checked')) || [];
  arr.forEach(function(checked, i) {
    checks.eq(i).prop('checked', checked);
  });
  //checks.trigger("change");
});

//* Clone script
$(".avclone, #favorite").on('change', '.AvGamesCheckBox', function() {
  var checkContainer = $(this).closest('.column');
  var checkIndex = checkContainer.data("checkindex");
  var matcher = $("#favorite").find(".column").filterByData("checkindex", checkIndex);
  if (this.checked && !matcher.length) {
    checkContainer.clone(true).appendTo("#favorite");
  } else {
    $(".avclone").find('.AvGamesCheckBox')
         .eq(checkIndex).trigger('clickcustom');
    matcher.remove();
  }
});
$(".avclone").on('click clickcustom', '.AvGamesCheckBox', onClickAvGamesCheckBox);
* {
  box-sizing: border-box;
  padding: 5px;
}

.AvGamesContainer {
  display: block;
  position: relative;
  padding-left: 35px;
  margin-bottom: 12px;
  cursor: pointer;
  font-size: 22px;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

.AvGamesContainer input {
  position: absolute;
  opacity: 0;
  display: none;
  visibility: hidden;
  cursor: pointer;
  height: 0;
  width: 0;
}

.AvGamesCheckmark {
  position: absolute;
  top: 26px;
  right: 0;
  height: 25px;
  width: 25px;
  padding: 3px !important;
  background-color: #fff;
  background-image: url("https://i.ibb.co/Yyp3QTL/addstar.png");
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
  -webkit-border-top-right-radius: 5px;
  -webkit-border-bottom-left-radius: 8px;
  -moz-border-radius-topright: 5px;
  -moz-border-radius-bottomleft: 8px;
  border-top-right-radius: 5px;
  border-bottom-left-radius: 8px;
  z-index: 5;
}

.AvGamesContainer input:checked~.AvGamesCheckmark {
  background-color: #fff;
  color: yellow !important;
  background-image: url("https://i.ibb.co/0J7XxyK/favstar.png");
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
}

.AvGamesContainer:hover input~.AvGamesCheckmark {
  background-color: #fff;
}

.AvGamesCheckmark:after {
  content: "";
  position: absolute;
  display: none;
}

.AvGamesContainer input:checked~.AvGamesCheckmark:after {
  display: none;
}

.AvGamesContainer .AvGamesCheckmark:after {
  display: none;
}

img {
  width: 100%;
  height: auto;
  background: #fff;
  border-radius: 10px;
  -webkit-box-shadow: 0px 1px 5px 2px rgba(0, 0, 0, 0.75);
  -moz-box-shadow: 0px 1px 5px 2px rgba(0, 0, 0, 0.75);
  box-shadow: 0px 1px 5px 2px rgba(0, 0, 0, 0.75);
  transition: all 0.5s ease-in-out 0s;
  z-index: 4;
}

img:hover {
  -webkit-box-shadow: 0px 1px 5px 2px rgba(0, 0, 0, 0.75);
  -moz-box-shadow: 0px 1px 5px 2px rgba(0, 0, 0, 0.75);
  box-shadow: 0px 1px 5px 2px rgba(0, 0, 0, 0.75);
  -webkit-filter: saturate(150%);
}

.column {
  float: left;
  width: 50%;
  padding: 5px;
  height: auto;
}

.columns {
  position: relative;
  border-radius: 10px;
  text-align: center;
  width: 99%;
  margin: 0 auto;
  padding: 5px;
}

.row:after {
  content: "";
  display: table;
  clear: both;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div class="avclone">
  <div class="column">
    <div class="columns">
      <label class="AvGamesContainer">
  <input type="checkbox" name="AvGamesContainer" class="AvGamesCheckBox">
  <span class="AvGamesCheckmark"></span>
  </label>
      <a href="https://games.softgames.com/games/aquablitz-2/gamesites/7665/" data-path><img src="https://d1bjj4kazoovdg.cloudfront.net/assets/games/aquablitz-2/teaser.jpg?p=pub-15088-15357" title="Aqua Blitz 2"></a>
    </div>
  </div>
  <div class="column">
    <div class="columns">
      <label class="AvGamesContainer">
  <input type="checkbox" name="AvGamesContainer" class="AvGamesCheckBox">
  <span class="AvGamesCheckmark"></span>
  </label>
      <a href="https://games.softgames.com/games/daily-sudoku/gamesites/7665/" data-path><img src="https://d1bjj4kazoovdg.cloudfront.net/assets/games/daily-sudoku/teaser.jpg?p=pub-15088-15357" title="Daily Sudoku"></a>
    </div>
  </div>
</div>
<div id="favorite"></div>

答案 1 :(得分:2)

这应该为您工作。注意:避免使用驼峰类或ID。同样依靠元素索引,我也不希望使用某种标识符来跟踪元素关系。

JS:

function onClickAvGamesCheckBox() {
    var arr = $('.AvGamesCheckBox').map(function() {
    return this.checked;
  }).get();
  localStorage.setItem("checked", JSON.stringify(arr));
}

$(document).ready(function() {
    var arr = JSON.parse(localStorage.getItem('checked')) || [];
  arr.forEach(function(checked, i) {

  $('.AvGamesCheckBox').eq(i).prop('checked', checked).trigger("change");
  });
  $(".AvGamesCheckBox").click(onClickAvGamesCheckBox);
});

//* Clone script
$(document).on("change", ".avclone [type='checkbox']", function(e){ 
var column = $(e.target).closest(".column"),
    eq = column.index();
if ($(e.target).prop("checked"))
    column.clone().attr("data-eq", eq).appendTo("#favorite");
else
    $("#favorite .column[data-eq='"+eq+"']").remove();
});

CSS:

* {
  box-sizing: border-box;
  padding: 5px;
}
.AvGamesContainer {
  display: block;
  position: relative;
  padding-left: 35px;
  margin-bottom: 12px;
  cursor: pointer;
  font-size: 22px;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}
.AvGamesContainer input {
  position: absolute;
  opacity: 0;
  display: none;
  visibility: hidden;
  cursor: pointer;
  height: 0;
  width: 0;
}
.AvGamesCheckmark {
  position: absolute;
  top: 26px;
  right: 0;
  height: 25px;
  width: 25px;
  padding: 3px !important;
  background-color: #fff;
  background-image: url("https://i.ibb.co/Yyp3QTL/addstar.png");
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
-webkit-border-top-right-radius: 5px;
-webkit-border-bottom-left-radius: 8px;
-moz-border-radius-topright: 5px;
-moz-border-radius-bottomleft: 8px;
border-top-right-radius: 5px;
border-bottom-left-radius: 8px;
  z-index: 5;
}
.AvGamesContainer input:checked ~ .AvGamesCheckmark {
  background-color: #fff;
  color: yellow !important;
  background-image: url("https://i.ibb.co/0J7XxyK/favstar.png");
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
}
.AvGamesContainer:hover input ~ .AvGamesCheckmark {
  background-color: #fff;
}
.AvGamesCheckmark:after {
  content: "";
  position: absolute;
  display: none;
}
.AvGamesContainer input:checked ~ .AvGamesCheckmark:after {
  display: none;
}
.AvGamesContainer .AvGamesCheckmark:after {
  display: none;
}
img {
  width: 100%;
  height: auto;
  background: #fff;
  border-radius: 10px;
  -webkit-box-shadow: 0px 1px 5px 2px rgba(0,0,0,0.75);
  -moz-box-shadow: 0px 1px 5px 2px rgba(0,0,0,0.75);
  box-shadow: 0px 1px 5px 2px rgba(0,0,0,0.75);
  transition: all 0.5s ease-in-out 0s;
  z-index: 4;
}
img:hover {
  -webkit-box-shadow: 0px 1px 5px 2px rgba(0,0,0,0.75);
  -moz-box-shadow: 0px 1px 5px 2px rgba(0,0,0,0.75);
  box-shadow: 0px 1px 5px 2px rgba(0,0,0,0.75);
  -webkit-filter: saturate(150%);
}
.column {
  float: left;
  width: 50%;
  padding: 5px;
  height: auto;
}
.columns {
  position: relative;
  border-radius: 10px;
  text-align: center;
  width: 99%;
  margin: 0 auto;
  padding: 5px;
}
.row:after {
  content: "";
  display: table;
  clear: both;
}

#favorite .column .AvGamesCheckmark {
  display: none!important
}

HTML:

<div class="avclone"> 
<div class="column">
  <div class="columns">
  <label class="AvGamesContainer">
  <input type="checkbox" name="AvGamesContainer" class="AvGamesCheckBox">
  <span class="AvGamesCheckmark"></span>
  </label> 
<a href="https://games.softgames.com/games/aquablitz-2/gamesites/7665/" data-path><img src="https://d1bjj4kazoovdg.cloudfront.net/assets/games/aquablitz-2/teaser.jpg?p=pub-15088-15357" title="Aqua Blitz 2"></a>
</div>
</div>

<div class="column">
  <div class="columns">
  <label class="AvGamesContainer">
  <input type="checkbox" name="AvGamesContainer1" class="AvGamesCheckBox">
  <span class="AvGamesCheckmark"></span>
  </label>
<a href="https://games.softgames.com/games/daily-sudoku/gamesites/7665/" data-path><img src="https://d1bjj4kazoovdg.cloudfront.net/assets/games/daily-sudoku/teaser.jpg?p=pub-15088-15357" title="Daily Sudoku"></a>
  </div>
</div> 

</div>

<div id="favorite"></div>

答案 2 :(得分:2)

@Leo,因为您问过如何在React中做到这一点。 演示https://react-krwy1w.stackblitz.io/

代码https://stackblitz.com/edit/react-krwy1w?file=index.js

import React, { Component } from 'react';
import { render } from 'react-dom';
import './style.css';

const GAME_IMAGES = [
  {
    title: "some title 01",
    href: "https://games.softgames.com/games/aquablitz-2/gamesites/7665/",
    img: "https://d1bjj4kazoovdg.cloudfront.net/assets/games/aquablitz-2/teaser.jpg?p=pub-15088-15357"
  },
  {
    title: "some title 02",
    href: "https://games.softgames.com/games/aquablitz-2/gamesites/7665/",
    img: "https://d1bjj4kazoovdg.cloudfront.net/assets/games/daily-sudoku/teaser.jpg?p=pub-15088-15357"
  },
  {
    title: "some title 03",
    href: "https://games.softgames.com/games/aquablitz-2/gamesites/7665/",
    img: "https://d1bjj4kazoovdg.cloudfront.net/assets/games/aquablitz-2/teaser.jpg?p=pub-15088-15357"
  },
];


const GameCard = ({title, href, img, onChange}) => {
  return (
    <div className="column">
      <div className="columns">
        <label className="AvGamesContainer">
          <input type="checkbox" name="AvGamesContainer" className="AvGamesCheckBox" onChange={(e) => onChange(e.target.checked, {title, href, img})}/>
          <span className ="AvGamesCheckmark"></span>
        </label>
          <a href={href}>
            <img src={img} title={title}/>
          </a>
      </div>
    </div>
  );
};

class App extends Component {
  constructor() {
    super();
    this.state = {
      display: null
    }
  }

  handleChange(isChecked, obj) {
    this.setState({
        display: isChecked ? obj : null
      });
  }

  render() {
    return (
      <div>
        {
          this.state.display !== null ?
            <div id="favorite">
          {<GameCard {...this.state.display} />}
        </div> : null
        }

        <p>
          Start editing to see some magic happen :)
        </p>
        {
          GAME_IMAGES.map(prop => <GameCard {...prop} onChange={this.handleChange.bind(this)} />)
        }
      </div>
    );
  }
}

render(<App />, document.getElementById('root'));