문제

I would like to implement a check list by list item (li). I use data-checked attribute to keep the checking state. I set the icon color with css selector ('true' = black and 'false' = white color).

It work fine when the page display, all tasks show the white icon as their default data-checked value is 'false'. But when I click the list items, the data-checked value is modified to 'false', but the color does not change to black.

I have checked the value by alert them. They are properly.

What am I doing wrong?

Thank you.

HTML:

<ul>
  <li data-id='1' data-checked='false' onclick='toggle_task(this);'>
    <i class='fs fa-check'></i>
    <span>Task A</span>
  </li>
  <li data-id='2' data-checked='false' onclick='toggle_task(this);'>
    <i class='fs fa-check'></i>
    <span>Task B</span>
  </li>
</ul>
<button onclick='show_checked();'>Done</button>

CSS:

ul li[data-checked='true'] i:first-child {
  color: #000000;
}
ul li[data-checked='false'] i:first-child {
  color: #eeeeee;
}

Javascript:

function toggle_task(sender) {
  if ($(sender).data('checked').toString == 'true') {
    $(sender).data('checked','false');
  } else {
    $(sender).data('checked','true');
  }
}
function show_checked() {
  $(li).each(function() {
    var text = $(this).data('id').toString() + ': ' + $(this).data('checked').toString();
    alert($(this).data('checked'));
  });
}
도움이 되었습니까?

해결책

I think you have become confused between the HTML data-* attributes (which you are using as part of your CSS selector) and the jQuery data method which stores arbitrary JavaScript objects associated with the element but outside of the DOM. The confusion probably comes from this-

.data( key ) Returns: Object Description:

Return the value at the named data store for the first element in the jQuery collection, as set by data(name, value) or by an HTML5 data-* attribute.

The method allows you to read data from HTML 5 data-* attributes if there is no value with that key in the jQuery collection, but not to set it.

What you want to do is use the jQuery attr method like this-

function toggle_task(sender) {
  if ($(sender).attr('data-checked') === 'true') {
    $(sender).attr('data-checked','false');
  } else {
    $(sender).attr('data-checked','true');
  }
}

function show_checked() {
  $('li').each(function() {
    var text = $(this).attr('id') + ': ' + $(this).attr('data-checked');
    alert($(this).attr('data-checked')); //Consider using console.log rather than alert here
  }); //Fixed your jQuery selector - required quotes for li element - is not a JavaScript variable
}

As a bonus the attr method returns a string and not an object - so you can dispense with the toString calls.

I'm not entirely sure what you want to do visually, but if you want to have a coloured block need to the element indicating if it is checked or not (in which case the <i> element is not the most semantically appropriate) you also need to update your CSS-

/* These need to be background-color, not color */

ul li[data-checked='true'] i:first-child {
  background-color: #000000;
}
ul li[data-checked='false'] i:first-child {
  background-color: #eeeeee;
}

/* Also need to add these styles to actually see the empty elements */

.fa-check {
    display: inline-block;
    height: 0.5em;
    width: 0.5em;
}

I have created JSFiddles of your original code and the updated code which is worked as I think you want it to.

Please, please, please consider using unobtrusive event handlers with jQuery using the jQuery on method rather than having inline "onclick" attributes. This keeps your JavaScript logic separate from your HTML content, see http://en.wikipedia.org/wiki/Unobtrusive_JavaScript.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top