I work on the simple ToDo list written on jQuery (and JS, of course).
I already created the static ToDo list with a possibility to add new items only by editing the code. It is logically that I am going to create a dynamic list now.
I've already tried some methods, like .load() code from external file, create .after(), but it all goes wrong for me.
What would you suggest me to do?
You may find all the source codes in strasbourgmeetings.org/ccc
I would be very grateful if you could help me solving this question.
Gloserio, yes, Add Item does not work now, because I of the problem I described.
ncubica, the problem is that at the moment I am not able to add new items to my list (only bu editing the code). Dynamic means that it would be possible to add/delete items. To do that I tried to use .after() method with the function inside it, that will copy the <li id="item1">List item here</li><li id="buttons1">Buttons here</li> (roughly speaking), but it puts all list items on the upper side and all buttons to the bottom.
This is a part of the JS code:
<script>
// Waiting for the document to load
$(document).ready(function() {
// Wanted to create a dynamic item list, that's why I used this variable. I thought it would
// generate unique IDs (there was 'id++' somewhere in the function I already deleted).
var id = 1;
// This is going to be used as an action for 'Add Item' button. (It is not a button, actually, it is just <span> with cursor: pointer. Using <a> causes page reload);
$('.add').click(function() {
$('#item'+id).after(function(i) { // '#item'+id should be something like this in the code: #item2, #item3, etc.
})
})
// 'Done' button
$('#done1').click(function() {
console.log('# "Done" button pressed');
$('#list1').css('background-color','#89f49a').css('border','1px solid #16bf31').css('text-decoration','line-through').css('color','#817f7f').css('font-weight','normal');
console.log('# Item doned successfully');
});
// 'Undone' button (is gonna be renamed to 'Reset');
$('#undone1').click(function() {
console.log('# "Undone" button pressed');
$('#list1').css('background-color','').css('border','').css('text-decoration','').css('color','').css('font-weight','normal');
});
// 'Working' button
$('#working1').click(function() {
$('#list1').css('background-color','#edc951').css('border','1px solid #dda119').css('font-weight','bold').css('color','#000').css('text-decoration','none');
});
// 'Cancel' button
$('#cancel1').click(function() {
$('#list1').css('background-color','#ff8c8c').css('border','1px solid #ea2c2c').css('font-weight','normal').css('text-decoration','line-through').css('color','#f00');
});
// 'Delete' button
$('#del1').click(function() {
$('div#dlist1').remove();
$('li#action1').remove();
});
});
</script>
And HTML part:
<div class="list">
<ul id="sortable">
<div class="list-item" id="item1"><div class="spacer1" id="spacer1"></div>
<div class="l-element" id="dlist1"><li id="list1" class="ui-widget ui-state-default">Create add feature</div>
<li id="action1" class="action"><input type="button" value="Done" class="done" id="done1"><input type="button" value="Undone" class="undone" id="undone1"><input type="button" value="Working" class="working" id="working1"><input type="button" value="Cancel" class="cancel" id="cancel1"><span id="del1" class="delete">Delete</span></li>
<div class="spacer"></div></div>
</ul>
<div>
As you can see, there is only 1 list item I wrote. IDs are static and can not be changed at the moment. All I need is to change IDs (ok, it will be var id = 1; id++) and to add the part of the code (inside <div class="list-item")
why don't you try jQuery's .clone() and attach it to the "Add Item" behaviour?
You can check it here.
I personally made one as well, and it works really simply, a checkbox, the text, followed by a delete button.
Works great, though I'm still working on a way to make it save it after you close the browser.
jQuery code:
function addListItem() {
var textToAdd = $('#new-text').val(); // The finish class is just for css styling
$('#list').append('<li class="item"><input type="checkbox" class="finish" />' + textToAdd + '<button class="delete">Delete</button></li>');
$('#new-text').val('');
}
function deleteItem() {
$(this).parent().remove();
}
$(document).ready(function() {
$('#add').on('click', addListItem);
$(document).on('click', '.delete', deleteItem);
});
HTML code:
<!DOCTYPE html>
<html>
<head>
<title>To Do List</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<h2>To Do List</h2>
<p>Project started on <strong>4-1-2015</strong>.</p>
<input type="text" id="new-text" /><button id="add">Add</button>
<ul id="list">
</ul>
<script src="jquery.js" type="text/javascript"></script>
<script src="script.js" type="text/javascript"></script>
</body>
</html>
Hope this helped :)
Related
At the moment, I am trying to make a search field for a project using javascript and for some reason my search code is not working. I attribute this to the complexity of the list items, to this point, what would be the proper Javascript code to search the H3 tags in the list below:
<ul class="results" list-style: none>
<li class="result">
<div class="container">
<div class='headline'>
<h3>a list item</h3>
</div>
</div>
</li>
<li class="result">
<div class="container">
<div class='headline'>
<h3>a list item 2</h3>
</div>
</div>
</li>
<li class="result">
<div class="container">
<div class='headline'>
<h3>a list item 3</h3>
</div>
</div>
</li>
</ul>
There must be better definition of: "I attribute this to the complexity of the list items, to this point, what would be the proper Javascript code to search the H3 tags in the list below:"
Most basic search:
document.querySelectorAll('h3'); // -> returning a nodelist with all the h3 elements in the dom
If you need to add more "complexity" then just change the selector in ('selector')
Otherwise please edit your question to be more precise what you want, like an example output.
UPDATE:
So if I understood correctly what you meant then a very very general example to just demonstrate what i guessing you mean
const getH3 = document.querySelectorAll('ul.results h3'); // here we get all the h3 inside the ul
// let us assume that in our "seach box" the term was '2' for example
const term = '2';
// what to do now? Since we got all our h3 already inside a const we can just go through all of them to check if the term is there, like for example with a forEach
// also creating here an array to push in all the matches
let matches = [];
getH3.forEach(h3 => {
if (h3.textContent.includes(term)) matches.push(h3); // here we push in if our search term was found inside the textContent of an h3 using the string method "includes"
// ofc you can also directly just push the found textContent or also both .-.
});
console.log(matches); // output: [h3]
console.log(matches[0].textContent); // output: a list item 2
UPDATE 2
so this should then answer general questions on this topic:
here the code with comments:
// for simplicity i will stick with the example from before with my 2 since its a pretty simple term :)
// so we doing the same things as before but with some modification
const getH3 = document.querySelectorAll('ul.results h3'); // keep in mind that this script should be executed
// after the dom loaded, otherwise getH3 will be [] empty
// getting our input field which i added to the html with the id
const search = document.getElementById('search'); // here the same with the loading
// so now we have several ways to make our "searching" for probably all ways we need some event
// this could be everytime we type something or when we click on a button etc.
// we will use the "input" or "change" event
// so adding the Eventlistener, could be achieved in two ways, i will use the addEventListener method
search.addEventListener('input', () => {
// everytime there is an input in the input element this function will be called
// since you dont need to work with the element, we dont need to save what we found, we will just make them the only ones left on the screen
// this can be achieved (in my opinion!) with giving or removing a class which makes them disappear or appear
// so we added a small css class with display:none
// now again we go through all h3
// so now it gets a bit weird since we used the h3, i will explain the other way underneath
getH3.forEach(h3 => {
if (h3.textContent.includes(search.value)) { // if the h3 should be displayed
h3.parentElement.parentElement.parentElement.classList.remove('invis') // dom traversing to the li element which holds the h3 to remove the class in case it was there
} else { // if the h3 shouldnt be displayed
h3.parentElement.parentElement.parentElement.classList.add('invis') // adding the class to the li so it disappear
}
});
/*
alternative we could also go through all the li or just use document.querySelector('ul.results>li')
to get all the li
like:
const getLi = document.querySelectorAll('ul.results>li');
getLi.forEach(li =>{
...
})
*/
})
in html added on top the ul:
<input id="search" type="text"> <!-- search box -->
And in css the class:
.invis {
display: none;
}
and here a example snippet you can run yourself to see how it works now:
const getH3 = document.querySelectorAll('ul.results h3');
const search = document.getElementById('search');
search.addEventListener('input', () => {
getH3.forEach(h3 => {
if (h3.textContent.includes(search.value)) h3.parentElement.parentElement.parentElement.classList.remove('invis');
else h3.parentElement.parentElement.parentElement.classList.add('invis');
});
})
.invis {
display: none;
}
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Searching</title>
</head>
<body>
<input id="search" type="text"> <!-- search box -->
<ul class="results" list-style: none>
<li class="result">
<div class="container">
<div class='headline'>
<h3>a list item</h3>
</div>
</div>
</li>
<li class="result">
<div class="container">
<div class='headline'>
<h3>a list item 2</h3>
</div>
</div>
</li>
<li class="result">
<div class="container">
<div class='headline'>
<h3>a list item 3</h3>
</div>
</div>
</li>
</ul>
</body>
</html>
The finished product is just supposed to have a checkbox next to each entry, and the option to edit or delete each item. I'm nowhere near that as I can't even get an item to post.
Here's are the files that I have: HTML, CSS, JS.
Also, I'm sorry for the formatting.I didn't paste the CSS as that's not an issue as far as I'm concerned.
HTML:
var list = document.getElementById('list'); //The unordered list.
var entry = document.createElement("li"); //Whatever this is. I'm assuming a command saved into a variable (?).
//var todolist = list.getElementsById('li');
// var btn = document.getElementById('ToDoButton');
//
// btn.addEventListener("click", function(){
// todolist.appendChild('li');
// });
/* Upon submission of the item in the text field, the string is stored in inputValue
and theText becomes a text node of inputValue, which is appended to the end of the variable
entry. This means that there should be a new item added to the unordered list with the information
found in the text field, but it doesn't show.
Also, as far as I know, this is only if the Add button is clicked, and not upon
pressing Enter while in the text box. */
function newElement() {
var inputValue = document.getElementById("textBox").value;
var theText = document.createTextNode(inputValue);
entry.appendChild(theText);
if (inputValue !== '') {
document.getElementById(list).appendChild(entry);
}
}
<!DOCTYPE html>
<html>
<head>
<title>To-Do List</title>
<link rel="stylesheet" href="todo.css">
</head>
<body>
<div class="toDoList">
<h4>To-Do List</h4>
<form target="_self">
<!-- This is so that the submitted information doesn't go anywhere but to the current page. -->
<input type="text" name="toDoList" placeholder="To-Do" id="textBox">
<input type="submit" value="Add" onclick="newElement()" id="ToDoButton">
<!-- newElement() is a JS function that will add the information in the search bar to the unordered list below. -->
</form>
</div>
<section id="main">
Tasks:
<ul id="list">
<!-- These are dummy values for the unordered list. The idea
is that the next item should be placed beneath them. -->
<li>test1</li>
<li>test2</li>
<li>test3</li>
</ul>
</section>
<script type="text/javascript" src="todo.js">
</script>
</body>
</html>
This is a short example of how to dynamically add elements on the page. User types in a to do item, then clicks the button. When they click the button, we get the value from the input box, create a new list item element, and then append it to the dom.
function addItem() {
var el = document.createElement('li')
var val = document.getElementById('item-val').value;
el.innerHTML = val;
document.getElementById('list').append(el);
}
<input id="item-val" type="text" />
<button onclick="addItem()">Add an item</button>
<ul id="list"></ul>
A few problems:
1) When you click the button, it submits the form. This causes your page to refresh, so any and all changes made by the JavaScript are lost, because you re-load the page from the server. Changing it to <button type="button" means it doesn't cause a postback any more. To be honest you probably don't actually need <form> here at all if you aren't going to send the data to the server.
2) Better to put your list and entry variables inside the function - globals are best avoided if you can, to reduce accidental scope issues. Also you need to create a new entry each time, not keep appending the same one.
3) document.getElementById(list).appendChild(entry) doesn't work because list is already an object representing an element - it's not a string containing an ID. so list.appendChild() is correct here - i.e. you can just call the appendChild() function on the existing object directly.
4) Optionally, you don't really need the separate textNode object - just set the innerText property of the list item instead.
5) Optionally again, but considered best practice: I declared an unobtrusive event handler (using addEventListener) rather than putting it inline inside the HTML. This is generally considered to make the code more maintainable and traceable, as all the script is held in one place, separate from the HTML.
Here's a fixed version:
document.querySelector("#ToDoButton").addEventListener("click", newElement);
/* Upon submission of the item in the text field, the string is stored in inputValue
and theText becomes a text node of inputValue, which is appended to the end of the variable
entry.*/
function newElement() {
var list = document.getElementById('list'); //The unordered list.
var entry = document.createElement("li"); //a new list item
var inputValue = document.getElementById("textBox").value;
if (inputValue !== '') {
entry.innerText = inputValue;
list.appendChild(entry);
}
}
<!DOCTYPE html>
<html>
<head>
<title>To-Do List</title>
<link rel="stylesheet" href="todo.css">
</head>
<body>
<div class="toDoList">
<h4>To-Do List</h4>
<form target="_self">
<input type="text" name="toDoList" placeholder="To-Do" id="textBox">
<button type="button" id="ToDoButton">Add</button>
</form>
</div>
<section id="main">
Tasks:
<ul id="list">
<!-- These are dummy values for the unordered list. The idea
is that the next item should be placed beneath them. -->
<li>test1</li>
<li>test2</li>
<li>test3</li>
</ul>
</section>
<script type="text/javascript" src="todo.js">
</script>
</body>
</html>
Your main issue is that you were using and <input type="submit"> when you were expecting the behavior of <input type="button"> with a click event listener:
document.querySelector('#ToDoButton').addEventListener('click', newElement);
function newElement() {
var inputValue = document.getElementById("textBox").value;
var theText = document.createTextNode(inputValue);
var liEl = document.createElement('li');
liEl.appendChild(theText);
if (inputValue !== '') {
document.getElementById('list').appendChild(liEl);
}
}
<head>
<title>To-Do List</title>
<link rel="stylesheet" href="todo.css">
</head>
<body>
<div class="toDoList">
<h4>To-Do List</h4>
<input type="text" name="toDoList" placeholder="To-Do" id="textBox">
<!--The input type needs to be "button, not "submit"-->
<input type="button" value="Add" id="ToDoButton">
</div>
<section id="main">
Tasks:
<ul id="list">
<li>test1</li>
<li>test2</li>
<li>test3</li>
</ul>
</section>
<script type="text/javascript" src="todo.js">
</script>
</body>
I have an mvc project where I have implemented two jQuery selectable plugin like below:
The <HTML> code,
<div class="product-page-options">
<div class="pull-left">
<label class="control-label" style="font-weight:bolder">Size:</label>
<ol class="ui-selectable" style="width:auto" id="selectable">
#{
var size = Model.AvailableSizes.Split(',');
foreach (var item in size)
{
<li class="ui-selectable">#item</li>
}
}
</ol>
</div>
<div class="pull-left">
<label class="control-label">Color:</label>
<ol class="ui-selectable" style="width:auto" id="selectable1">
#{
var color = Model.AvailableColors.Split(',');
foreach (var clr in color)
{
<li class="ui-selectable">#clr</li>
}
}
</ol>
</div>
</div>
The static script for selectable jQuery plugin.
<script type="text/javascript">
$(document).ready(function () {
$("#selectable").selectable({
selected: function (event, ui) {
$(ui.selected).siblings().removeClass("ui-selected");
$("#selectedsize").val($("li.ui-selected").html());
}
});
});
</script>
<script type="text/javascript">
$(document).ready(function () {
$("#selectable1").selectable({
selected: function (event, ci) {
$(ci.selected).siblings().removeClass("ui-selected");
$("#selectedsize").val($("li.ui-selected").html());
}
});
});
</script>
The first selectable jQuery plugin works perfectly while the second is not functioning properly. I mean I cannot select any item from the second selectable list and also the appearance is not same as the first one. The picture below shows clearly the problem.
Anything i can do about it? any help would be appreciated. Thanks in advance.
There's 2 issues at play here. Firstly, you will need to have styles set up specifically for both of the selectables (if you have based your code on the examples on the jQuery UI site. Secondly, upon selecting in the selector for the items, you will need to identify the path to the selected li element as a child of the relevant selectable.
$("#selectedcolor").val($("#selectable1>li.ui-selected").html());
The following plunker will show you it working :
Link To My Plunker
I have a simple application, where I'd like to toggle between showing and hiding elements in a fieldset using jQuery's .toggle effect. The trouble is, occasionally I have to double-click the button that enables the toggle, to get it to work.
Any ideas on what's going on?
HTML:
<!DOCTYPE html>
<html>
<head>
<script src="jquery-2.1.1.min.js"></script>
<script src="test.js"></script>
</head>
<body>
<div class="LeftFrame">
<div id="LeftTable"><strong>Left</div>
</div>
<div id="MainTable"><strong>Main
<div>
<br>
<form><fieldset><legend><button id="buttonShowFields">Add Info</button></legend>
<div id="InfoAddFields">
ID: <input type="text"><br>
Serial Number: <input type="text"><br>
Location: <select id="inputLocation">
<option>Location1</option>
<option>Location2</option></select><br>
Status: <select id="inputStatus">
<option>Complete</option>
<option>In Process</option></select><br>
</div>
</fieldset></form>
</div>
</div>
</body>
</html>
... and javascript (test.js ref in html above):
$(document).ready(function(){
// Show options to add workorder
// $("#WOAddFields").hide();
$("#buttonShowFields").click(function(){
$("#InfoAddFields").toggle();
});
});
Prevent the submit with event.preventDefault() when you click the button
http://jsfiddle.net/3NPPP/
$(document).ready(function(){
$("#buttonShowFields").click(function(e){
e.preventDefault();
$("#InfoAddFields").toggle();
});
});
I was having the same problem when using plain javaScript to toggle an element with the following function:
function toggle(element){
if (element.style.display !== "none")
element.style.display = "none";
else element.style.display = "block";
}
I noticed that when I added display:none to the CSS of the element I wanted to toggle, I needed to double click to first show the element. To fix this, I had to explicitly add style="display:none" to the HTML element tag.
instead of this...
<button id="buttonShowFields">Add Info</button>
use this...
<input type="button" id="buttonShowFields" value="Add Info" />
Please change event method to bind instead click.
$("#buttonShowFields").bind('click',function(){
$("#InfoAddFields").toggle();
});
I know there are a lot of free/paid quiz systems out there, but none are customizable enough, especially that I need it in RTL direction.
Anyway, I have made this simple script: fiddle
<!-- question 1 -->
<div id="01">hello there
<br />
<input id="01_correct_btn" type="button" onclick="getElementById('01_correct').style.display = 'block';
getElementById('01_continue').style.display = 'block'; this.style.display = 'none'; getElementById('01_wrong_a').style.display='none';getElementById('01_wrong_b').style.display='none'" />Hi
<br />
<input id="01_wrong_a" type="button" onclick="getElementById('01_wrong').style.display = 'block';
getElementById('01_continue').style.display = 'block'; this.style.display = 'none'; getElementById('01_correct_btn').style.display='none';
getElementById('01_wrong_b').style.display='none'" />bye
<br />
<input id="01_wrong_b" type="button" onclick="getElementById('01_wrong').style.display = 'block';
getElementById('01_continue').style.display = 'block'; this.style.display = 'none'; getElementById('01_correct_btn').style.display='none';
getElementById('01_wrong_a').style.display='none'" />thanks
<br />____________________
<div id="01_correct" style="display:none">yep, you're right...
<br />
</div>
<div id="01_wrong" style="display:none">You are so wrong
<br />
</div>
<input style="display:none" type="button" id="01_continue" onclick="getElementById('01').style.display = 'none';
getElementById('02').style.display = 'block'" value="continue" />
</div>
<!-- question 2 -->
<div id="02" style="display:none">question 2: Welcome to the real world</div>
1: How can I hide all wrong answers without having to add all their ids (getElementByClassName didn't work)
2: Instead of re-copying the script for each question, can this be done by JavaScript where in each new form:
a. a "correct_btn" displays a "correct_note" and hides all other buttons
b. "wrong_btn"s display a "wrong_note" and hides all other buttons
c. both "correct_btn" and "wrong_btn"s will display the continue button
d. "continue" button hides current div/form and displays next one
It would be much easier this way to create as much questions as possible.
Thank you very much.
I would suggest looking at the HTML class system. As you can assign one class to multiple items. Then just create a script instead of calling the onclick javascript event.
I know you requested javascript, but you tagged JQuery and as I feel a JQuery script would serve you better for what you are trying to do I suggested that. Doing this with Javascript could get very wordy and complicated.
HTML
<div id="Q1">Hello There<br/>
<div class = "Q1 correct choice"><input type="button"/>Hi</div>
<div class = "Q1 wrong choice"><input type="button"/>Bye</div>
<div class = "Q1 wrong choice"><input type="button"/>Thanks</div>
</div>
<div id="Q1_Correct" style="display: none;">You are correct</div>
<div id="Q1_Wrong" style="display: none;">You are wrong</div>
You can also set up a generic correct/wrong message to be displayed.
Now, using JQuery would probably be easiest... like in this fiddle : http://jsfiddle.net/p5YY4/1/ (its not perfect, but some styling should solve some click issues... but I think you can get the gist)
JQuery
$('.choice').on('click', function() {
var parent = $(this).parent().attr('id');
if($(this).hasClass('correct')){
$('.choice').hide();
var response = "#" + parent + "_Correct";
$(response).show();
}
if($(this).hasClass('wrong')){
$('.choice').hide();
var response = "#" + parent + "_Wrong";
$(response).show();
}
});
Let me know if you have any questions about this.
For making the script native to one document here is what you would need to set up to get it to work :
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.0.js"></script>
<script type="text/javascript">
$(document).ready(function(){
//The script I have already provided should go here
});
</script>
You can also create a separate document and call it lets say quizWorker.js
and then using the same layout as I just stated (in the js file I would also put the script in the $(document).ready function)
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.0.js"></script>
<script type="text/javascript" src="quizWorker.js"></script>