1

I have created a basic to-do list. I want to add the option to color code, similar to Google Keep (this is an exercise). I have tried simply putting one HTML select in, as you can see in my jsfiddle but this changes the background of that entire section.

<p display="none">
  <section class="main" style="display: block;" >
    <div data-bind="visible:todos().length>0">
      <input id="toggle-all" type="checkbox" data-bind="checked:markAll"/>
      <label for="toggle-all">Mark all as complete</label>
      <br /><br />
      <select id="colorOptions" id="toggle-all"></select>
    </div>
    <ul id="mycell" class="todo-list" data-bind="template:{ name:'item-template',foreach: todos}">
    </ul>
  </section>
</p>

Question: How do I add an option to individually color code the to-do items?

DBS
  • 9,110
  • 4
  • 35
  • 53
user12390879
  • 25
  • 11

2 Answers2

1

Ok, I did it using the templates. First I added the selection for the colors inside the template in the li, so that every entry has a selection. Then I added an id for every selection (which is the order variable, the first <select> has the id="0" the second has the id="1" and so on) in order to differentiate them and to make each of them have different functions onchange. I also made the addColorsOptions function which adds the options on every selection when it is created using its unique id.

$(function(){
    var Todo = function(id, title, done, order,callback) {
        var self = this;
        self.id = ko.observable(id);
        self.title = ko.observable(title);
        self.done = ko.observable(done);
        self.order = order;
        self.updateCallback = ko.computed(function(){
            callback(self);
            return true;
        });        
    }
    
    var viewModel = function(){
        var self = this;
        self.todos =  ko.observableArray([]);
        self.inputTitle = ko.observable("");
        self.doneTodos = ko.observable(0);
        self.markAll = ko.observable(false);

        self.addOne = function() {
           var order = self.todos().length;
           var t = new Todo(order, self.inputTitle(),false,order,self.countUpdate);
           self.todos.push(t);           
           self.addColorsOptions(order);
        };
        
        self.createOnEnter = function(item,event){
            if (event.keyCode == 13 && self.inputTitle()){
                self.addOne();
                self.inputTitle("");
            }else{
                return true;
            };           
        }
        
        self.toggleEditMode = function(item,event){
            $(event.target).closest('li').toggleClass('editing');
        }
        
        self.editOnEnter = function(item,event){
            if (event.keyCode == 13 && item.title){
                item.updateCallback();
                self.toggleEditMode(item,event);
            }else{
                return true;
            };           
        }

        self.markAll.subscribe(function(newValue){
            ko.utils.arrayForEach(self.todos(), function(item) {
                return item.done(newValue);
            });        
        });

        self.countUpdate = function(item){
            var doneArray = ko.utils.arrayFilter(self.todos(), function(it) {
                return it.done();
            });
            self.doneTodos(doneArray.length);
            return true;
        };
        
        self.countDoneText = function(bool){
            var cntAll = self.todos().length;
            var cnt  = (bool ? self.doneTodos() : cntAll - self.doneTodos());
            var text = "<span class='count'>" + cnt.toString() + "</span>";
            text += (bool ? " completed" : " remaining");
            text += (self.doneTodos() > 1 ? " items" : " item");
            return text;
        }
        
        self.clear = function(){
            self.todos.remove(function(item){ return item.done(); });
        }
        
        
        self.addColorsOptions = function(id){
            
            var colors = [{
        display: "light yellow",
        value: "ffffcc"        
    }, {
        display: "light blue",
        value: "ccffff"
    }, {
        display: "light green",
        value: "ccffcc"
    }, {
        display: "gray",
        value: "cccccc"
    }, {
        display: "white",
        value: "ffffff"
    }];
    
    var options = ['<option value="">Select color</option>'];
    
    for(var i = 0; i < colors.length; i++){
       options.push('<option value="');
       options.push(colors[i].value);
       options.push('">');
       options.push(colors[i].display);
       options.push('</option>');       
    }
    
    $("#" + id).html(options.join('')).change(function(){
        var val = $(this).val();
        if(val){
        $("#" + id).closest('li').css('backgroundColor', '#' + val);
        }
    });
            
            
        }
        
        
     };
    
    ko.applyBindings(new viewModel()); 

})
body {
 font-size: 14px;
  background-color: #3c6dc5;
 color: #333333;
 width: 520px;
 margin: 0 auto;
}

#todoapp {
  background-color: #3c6dc4;
 padding: 20px;
 margin-bottom: 40px;
}

#todoapp h1 {
 font-size: 36px;
 text-align: center;
  color:white;
}

#todoapp input[type="text"] {
 width: 466px;
 font-size: 24px;
 line-height: 1.4em;
 padding: 6px;
  color:#000033;
}

.main {
 display: none;
}

.todo-list {
 margin: 10px 0;
 padding: 0;
 list-style: none;
  color: #E0E0EF;
}


.todo-list li {
 padding: 18px 20px 18px 0;
 position: relative;
 font-size: 24px;
 border-bottom: 1px solid #cccccc;
}

.todo-list li:last-child {
 border-bottom: none;
}

.todo-list li .edit {
    display: none;
}
.todo-list li.editing {
 border-bottom: 1px solid #778899;
}

.todo-list li.editing .view {
 display: none;
}
.todo-list li.editing .edit {
 display: block;
 width: 444px;
 padding: 13px 15px 14px 20px;
 margin: 0;
}

.todo-list li.done label {
    color: #777777;
    text-decoration: line-through;
}


.todo-list .destroy {
 position: absolute;
 right: 5px;
 top: 20px;
 display: none;
 cursor: pointer;
 width: 20px;
 height: 20px;
}

#todoapp footer {
 display: none;
 margin: 0 -20px -20px -20px;
 overflow: hidden;
 color: #555555;
 background: #f4fce8;
 border-top: 1px solid #ededed;
 padding: 0 20px;
 line-height: 37px;
}

.todo-count {
    float:left;    
}

.todo-count .count{
    font-weight:bold;    
}

#clear-completed {
 float: right;
 line-height: 20px;
 text-decoration: none;
 background: rgba(0, 0, 0, 0.1);
 color: #555555;
 font-size: 11px;
 margin-top: 8px;
 margin-bottom: 8px;
 padding: 0 10px 1px;
 cursor: pointer;
}
label{color:white;}
<script src="http://knockoutjs.com/downloads/knockout-2.3.0.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="todoapp">
    <header>
      <h1>Fun To Do!</h1>
      <input id="new-todo" type="text" placeholder="Finish Homework..." data-bind="value:inputTitle,event: { keyup: createOnEnter}"/>
    </header>

    <section class="main" style="display: block;" >
   
      <div data-bind="visible:todos().length>0">
      
      <input id="toggle-all" type="checkbox" data-bind="checked:markAll"/>
          <label for="toggle-all">Mark all as complete</label> <br /><br />
      </div>
      <ul id="mycell" class="todo-list" data-bind="template:{ name:'item-template',foreach: todos}">
      </ul>
    </section>
    
    <footer style="display: block;">
      <div data-bind="visible:todos().length>0">
        <div class="todo-count"><b data-bind="text:todos().length"></b> items left</div>
        <!-- ko if: doneTodos() > 0 -->
          <a id="clear-completed" data-bind="click:clear">
              Clear <span data-bind="html:countDoneText(true)"></span>.
          </a>
        <!-- /ko -->
        <br style="clear:both"/>
      </div>
    </footer>
</div>
          
<script type="text/template" id="item-template">
    <li data-bind="event:{ dblclick :$root.toggleEditMode},css : {done:done() }">
        <div class="view" >
          <input class="toggle" type="checkbox" data-bind="checked:done"/>
          <label data-bind="text:title"></label>
          <a class="destroy"></a>
        </div>
        <input class="edit" type="text" data-bind="value:title,event: { keyup: $root.editOnEnter}" />
        <select data-bind="attr: {'id': id}"></select>
    </li>
</script>

You can also see the JSFiddle here.

For any question feel free to comment. I hope this was helpful :)

EDIT

See this JSFiddle for the <input type="color"> addition.

Mr Lister
  • 45,515
  • 15
  • 108
  • 150
Thanasis1101
  • 1,614
  • 4
  • 17
  • 28
1

I tested your fiddle code. There is some unwanted code (that i did not find) that fade out your div databind="..... So to remove this problem you can add this at the end of jquery codes before last }); to see some thing like this:

   $('div').show(); //adding code
});

Now the select works and you can see the changes in page inspector, But you can not see that here because your ul is empty. To see the result change that ul with an static data ul like this:

<ul id="mycell" class="todo-list">
   <li>first</li>
   <li>second</li>
</ul>
Farzin Kanzi
  • 3,380
  • 2
  • 21
  • 23