HTML Page search - javascript

I have a very long html file (20K+ lines) and I want to have a search that will find the search term and then scroll to the li class="page" data-name="XX". If more than one instance of the term is found we need a "next" result button.
Here is an excerpt from my HTML file I want to search:
<li class="page" data-name="11">
<div class="pageResizer" style="width:640px;height:960px;"> </div>
<div id="item690" class="pageItem" alt="Rectangle"> </div>
<div id="item728" class="pageItem" alt="Rectangle"> </div><button class="pageItem" alt="Home" id="item1426" data-id="1426" onclick="nav.to(5);"> </button><button class="pageItem" alt="prevBtn" id="item1423" data-id="1423" onclick="nav.back(this);"> </button><button class="pageItem" alt="nextBtn" id="item2550" data-id="2550" onclick="nav.next(this);"> </button><img src="assets/images/blank.gif" class="pageItem" alt="Rectangle" style="left:491px;top:11px;" data-src="assets/images/item_2757.png"/>
<div id="item2788" class="pageItem singleline" alt="Lafayette Chamber">
<p class="autoParaStyle1">Lafayette Chamber</p>
</div><button class="pageItem" alt="Share" id="item3136" data-id="3136"> </button>
<a href="javascript:nav.to(2);"><button class="pageItem" alt="Help" id="item2977" data-id="2977" onclick="nav.to(2);"> </button>
</a><img src="assets/images/blank.gif" class="pageItem" alt="Rectangle" style="left:1px;top:66px;" data-src="assets/images/item_4899.jpg"/><img src="assets/images/blank.gif" class="pageItem" alt="Rectangle" style="left:1px;top:707px;" data-src="assets/images/item_4901.jpg"/>
<div id="item4906" class="pageItem singleline" alt="lafayETTE ">
<p class="autoParaStyle13">lafayETTE<br />
</p>
</div>
<div id="item4937" class="pageItem singleline" alt="HISTORY">
<p class="autoParaStyle14">HISTORY</p>
</div>
<div id="item4982" class="pageItem" alt=" little more than a century ago, the first pioneers trickled into this region after a long journey across the Great P...">
<p class="Article-Body"> <span class="autoCharStyle5">little more than a century ago, the first pioneers trickled into this region after a long journey across the Great Plains. The gold rush attracted more and more adventurous fortune seekers who were closely followed by other settlers. The honeymoon of Lafayette and Mary E. Miller was spent crossing the plains and arriving in the Boulder region. In 1863, they started farming the Burlington (Longmont) area and soon moved south and settled in the present site of Lafayette. Lafayette Miller was an industrious man and besides farming, he operated the stage stop and ran several meat markets. His sudden death in 1878 left Mary Miller with six small children to raise. She did this and more…she raised a town!<br /></span> </p>
<p class="autoParaStyle8"><br /></p>
</div>
<div id="item27143" class="pageItem singleline" alt="A">
<p class="autoParaStyle15">A</p>
</div>
Here is the code I have so far:
<script>
function search() {
var name = document.getElementById("searchForm").elements["searchItem"].value;
var pattern = name.toLowerCase();
var targetId = "";
var divs = document.getElementsByClassName("page");
for (var i = 0; i < divs.length; i++) {
var para = divs[i].getElementsByTagName("p");
var index = para[0].innerText.toLowerCase().indexOf(pattern);
if (index != -1) {
targetId = divs[i].parentNode.id;
document.getElementById(targetId).scrollIntoView();
break;
}
}
}
</script>
<form id="searchForm" action="javascript:search();">
<div class="input-group">
<button id="go" type="button"
onclick="document.getElementById('searchForm').submit(); return false;">
Search</button>
<input type="text" id="searchItem" class="form-control" placeholder="Search" cols="50" rows="2">
</div>
</form>
Not sure what I need to do to my code to make this work and don't have a clue how to make a "next result" button.

I think this is what you are looking for:
HTML:
<body>
<form id="searchForm" action="javascript:search();" class="form">
<button id="nextButton" onclick="nextItem()" type="button" class="make-invisible">NEXT</button>
<div class="input-group">
<button id="go">Search</button>
<input type="text" id="searchItem" name="searchItem" class="form-control" placeholder="Search" cols="50" rows="2">
</div>
</form>
<ul>
<li class="page" data-name="foo">Has data-name = foo</li>
<li class="page" data-name="foo">Has data-name = foo</li>
...
</ul>
</body>
JavaScript:
var selectedItems;
var currentlySelectedItem;
var makeInvisibleClassName = "make-invisible";
var nextButton = document.querySelector("#nextButton");
function search() {
makeInvisible();
var searchPhrase = document.querySelector("#searchItem").value;
selectedItems = document.querySelectorAll(".page[data-name='" + searchPhrase + "']");
if (selectedItems.length === 0) {
return;
}
if (selectedItems.length > 1) {
makeVisible();
}
currentlySelectedItem = 0;
nextItem();
}
function nextItem() {
selectedItems[currentlySelectedItem].scrollIntoView();
currentlySelectedItem++;
if (currentlySelectedItem >= selectedItems.length) {
currentlySelectedItem = 0;
}
}
//////////
function makeInvisible() {
nextButton.classList.add(makeInvisibleClassName);
}
function makeVisible() {
nextButton.classList.remove(makeInvisibleClassName);
}
CSS:
.form {
position: fixed;
left: 0;
top: 0;
display: flex;
flex-direction: row;
justify-content: center;
width: 100%;
}
#nextButton {
margin-right: 10px;
}
.make-invisible {
display: none;
}
Here is the working Demo
Ok, let me explain what I did here.
When you have a form you don't actually need to this:
<button id="go" type="button" onclick="document.getElementById('searchForm').submit(); return false;">
Instead you can go very simple:
<button id="go">Search</button>
The default button type in a form is type="submit" which automatically triggers the event specified in the action attribute.
The next thing is the NEXT button. I hard-coded it and in order to show it and hide it, I will add or remove class make-invisible. Notice the button is invisible at the beginning. It also has a click event which will trigger nextItem()
<button id="nextButton" onclick="nextItem()" type="button" class="make-invisible">NEXT</button>
I also made 2 global variables: selectedItems, which will store the array of selected items and currentlySelectedItem that has the index of currently scrolled to item.
The search() function gets all elements that has the class name page and has attribute data-name with specified word. Then it checks if there is more then one result. If so, it makes the button visible.
The nextItem() function scrolls into selected element, and raises index by one. If the index value if bigger then there is matching elements, it will start a loop.

Related

how to return rating on a span element?

I am trying to make a interactive rating component. I have no clue how I can return the result on a span element after a rating is chosen.
When I enter the rating on buttons:
After I submit the rating:
There I want to return the result.
I was trying an if statement in the forEach function but didn't know how to return the result on the span element.
const allBtns = document.querySelectorAll('.btn');
allBtns.forEach(btn => {
btn.addEventListener('click', function onClick() {
btn.style.backgroundColor = 'orange';
})
});
function ShowAndHide() {
let y = document.querySelector('.ratingbox');
let x = document.querySelector('.thankyou');
if (x.style.display == 'none') {
y.style.display = 'none';
x.style.display = 'block';
} else {
x.style.display = 'none';
}
}
<div class="ratingbox">
<div class="backgroundstar">
<img src="images/icon-star.svg" alt="" class="star">
</div>
<div class="writing">
<h1>How did we do?</h1>
<p>Please let us know how we did with your support request. All feedback is appreciated to help us improve our offering! </p>
</div>
<div class="flexbox">
<ul>
<li><button class="btn"><p id="num">1</p></button></li>
<li><button class="btn"><p id="num">2</p></button></li>
<li><button class="btn"><p id="num">3</p></button></li>
<li><button class="btn"><p id="num">4</p></button></li>
<li><button class="btn"><p id="num">5</p></button></li>
</ul>
<button class="submit" onclick="ShowAndHide()">SUBMIT</button>
</div>
</div>
<div class="thankyou " style="display: none; ">
<div class="message ">
<img src="https://via.placeholder.com/50" alt=" " class="img ">
<div class="selected ">
<span id="rating "></span>
</div>
<div class="greeting ">
<h2>Thank you!</h2>
<p id="appreciate ">We appreciate you taking the thime to give a rating.<br> If you ever need more support, don't hesitate to <br> get in touch!
</p>
</div>
</div>
</div>
Use the right tool for the job.
Use radio buttons to manage your rating and style the labels how you'd like. Then use CSS to handle hiding and showing. Leave JavaScript to manipulating the DOM.
Keep in mind IDs need to be unique. Once they are no longer unique, they are no longer ids. Things like document.getElementById will break if ID is not unique.
/*Get out radio buttons based on the name attribue*/
const allBtns = document.querySelectorAll('[name=rating]');
/*Add the event listener*/
allBtns.forEach(btn => {
btn.addEventListener('click', function onClick() {
/*Update the text using the value of the radio button*/
document.querySelector("#rating").innerHTML = `Thanks for rating us ${this.value}!`;
})
});
function ShowAndHide() {
/*Toggle the hide class on the appropriate boxes*/
document.querySelector('.ratingbox').classList.toggle("hide");
document.querySelector('.thankyou').classList.toggle("hide");;
}
/*Hide the radion buttons*/
.flexbox input {display:none;}
/*Give some buttonish styling to the check boxes */
.flexbox label {
display:block;
border: 1px blue solid;
border-radius: 50%;
font-size: 1.2em;
font-weight:bold;
text-align:center;
line-height:30px;
height: 30px;
width:30px;
margin-bottom: 1em;
}
/*Change the styling of the checked label*/
/*Note the use of the adjacent sibling cominator + */
.flexbox :checked + label {
background-color: orange;
}
/*Generic class to handle showing and hiding*/
.hide {
display:none;
}
<div class="ratingbox">
<div class="backgroundstar">
<img src="images/icon-star.svg" alt="" class="star">
</div>
<div class="writing">
<h1>How did we do?</h1>
<p>Please let us know how we did with your support request. All feedback is appreciated to help us improve our offering! </p>
</div>
<div class="flexbox">
<ul>
<!-- Using radio buttons , that will be hidden with associated labels -->
<li><input type="radio" name="rating" id="rtr1" value="1"><label for="rtr1">1</label></li>
<li><input type="radio" name="rating" id="rtr2" value="2"><label for="rtr2">2</label></li>
<li><input type="radio" name="rating" id="rtr3" value="3"><label for="rtr3">3</label></li>
<li><input type="radio" name="rating" id="rtr4" value="4"><label for="rtr4">4</label></li>
<li><input type="radio" name="rating" id="rtr5" value="5"><label for="rtr5">5</label></li>
</ul>
<button class="submit" onclick="ShowAndHide()">SUBMIT</button>
</div>
</div>
<div class="thankyou hide">
<div class="message ">
<img src="https://via.placeholder.com/50" alt=" " class="img ">
<div class="selected ">
<span id="rating"></span>
</div>
<div class="greeting ">
<h2>Thank you!</h2>
<p id="appreciate ">We appreciate you taking the thime to give a rating.<br> If you ever need more support, don't hesitate to <br> get in touch!
</p>
</div>
</div>
</div>
There are multiple issues with your code. The main issue is you are using the same id, num, for multiple elements, which is invalid. Change those id's to class instead, like this:
<ul>
<li><button class="btn"><p class="num">1</p></button></li>
<li><button class="btn"><p class="num">2</p></button></li>
<li><button class="btn"><p class="num">3</p></button></li>
<li><button class="btn"><p class="num">4</p></button></li>
<li><button class="btn"><p class="num">5</p></button></li>
</ul>
After doing that, one way to acquire the most recently selected button is to find the nested .num within your button click eventListeners, such as var rating = parseInt(btn.querySelector(".num").textContent)
Here is how you might do that with minimal changes to your current code:
const allBtns = document.querySelectorAll('.btn');
var currentRating = null;
allBtns.forEach(btn => {
btn.addEventListener('click', function onClick() {
btn.style.backgroundColor = 'orange';
currentRating = parseInt(btn.querySelector(".num").textContent)
})
});
function ShowAndHide() {
if (currentRating){
alert(currentRating);
}
let y = document.querySelector('.ratingbox');
let x = document.querySelector('.thankyou');
if (x.style.display == 'none') {
y.style.display = 'none';
x.style.display = 'block';
} else {
x.style.display = 'none';
}
}
Here is a JsFiddle that does just this and alerts the selected rating:
https://jsfiddle.net/eg4Ly0nd/
Note: I would recommend using hidden checkbox inputs within each of the li buttons and adding to code your event listener to check the selected input associated with a button and uncheck the others. Then you don't need the global currentRating variable that is included in my solution; you can just find the input that is checked. I only wrote it this way to make minimal changes to the code you provided while still giving a solution.
Just an alternative solution, you can set the rating value for each button by Javascript only, and with minimal change to existing code.
This way, it is independent to any content in p. It also saves the trouble of reading the p tag, since you might need to replace it with something else according to design.
The below Javascript snippet can be used with your posted HTML without changes.
Full example (run it with the button below for demo):
const allBtns = document.querySelectorAll('.btn');
const resultSpan = document.querySelector(".selected span")
allBtns.forEach((btn, i) => {
btn.addEventListener('click', function onClick() {
btn.style.backgroundColor = 'orange';
// Customize the output text here
// It displays in Success screen
resultSpan.innerText = `You have rated ${i + 1}`;
})
});
function ShowAndHide() {
let y = document.querySelector('.ratingbox');
let x = document.querySelector('.thankyou');
if (x.style.display == 'none') {
y.style.display = 'none';
x.style.display = 'block';
} else {
x.style.display = 'none';
}
}
<div class="ratingbox">
<div class="backgroundstar">
<img src="images/icon-star.svg" alt="" class="star">
</div>
<div class="writing">
<h1>How did we do?</h1>
<p>Please let us know how we did with your support request. All feedback is appreciated to help us improve our offering! </p>
</div>
<div class="flexbox">
<ul>
<li><button class="btn"><p>1</p></button></li>
<li><button class="btn"><p>2</p></button></li>
<li><button class="btn"><p>3</p></button></li>
<li><button class="btn"><p>4</p></button></li>
<li><button class="btn"><p>5</p></button></li>
</ul>
<button class="submit" onclick="ShowAndHide()">SUBMIT</button>
</div>
</div>
<div class="thankyou " style="display: none; ">
<div class="message ">
<img src="https://via.placeholder.com/50" alt=" " class="img ">
<div class="selected ">
<span id="rating "></span>
</div>
<div class="greeting ">
<h2>Thank you!</h2>
<p id="appreciate ">We appreciate you taking the thime to give a rating.<br> If you ever need more support, don't hesitate to <br> get in touch!
</p>
</div>
</div>
</div>
But as other comments mentioned, it is recommended that you assign a different id for each p, or no id at all since no need to read these tags in code anyway.

How can I add elements in JS to certain divs

How do I put the created input into the other div in situation I presented below? If I introduce divs in js like this - '<div class="monday_input"><input type="button" class="remove_button" value="-" onclick="removeMon(this)" /></div>' removing the whole element is not working for some reason in this specific case. Answering the question. No I cannot create div in parent in html because input won't magically suit to created div . Please help me somehow, thank you!
HTML:
<div class="day">
<div class="day_info">
<p>Monday</p>
</div>
<div class="add">
<div class="button" onclick="add_monday()">
<i class="fas fa-plus" id="plus"></i>
</div>
</div>
<div style="clear:both"></div>
</div>
<div id="mon">
<div style="clear:both"></div>
</div>
JavaScript:
Function to adding:
function add_monday() {
if (monday_sub_count < 5) {
monday_sub_count++;
{
const mon = document.createElement('div');
mon.className = 'subcategory';
mon.innerHTML = '<textarea name="monday'+monday_id_count+'" placeholder="Type anything you want here" class="subcategory_text"></textarea><input type="button" class="remove_button" value="-" onclick="removeMon(this)" />';
monday_id_count++;
document.getElementById('mon').appendChild(mon);
}
}
}
Function to removing:
function removeMon(mon) {
document.getElementById('mon').removeChild(mon.parentNode);
monday_sub_count--;
monday_id_count--;
};
with your own HTML
function add_monday() {
var monday_sub_count = 0;
var a;
while (monday_sub_count < 5) {
a = '<div><textarea name="monday'+monday_id_count+'" placeholder="Type anything you want here" class="subcategory_text"></textarea><input type="button" class="remove_button" value="-" onclick="removeMon(this)" /></div>';
monday_sub_count++;
$('#mon').append(a);
}
}
Here is working, "proper" version of your code. I think your problem may come from over-complicating the removal process.
function add_monday()
{
let monday_count = 0;
// Use DocumentFragment for marginal optimizations
let fragment = new DocumentFragment();
while(monday_count < 5)
{
let monday = document.createElement('div');
monday.classList.add('subcategory');
let textarea = document.createElement('textarea');
textarea.classList.add('subcategory_text');
textarea.name = "monday_"+monday_count;
textarea.placeholder = "Type anything you want here";
let removeBtn = document.createElement('input');
removeBtn.type = "button";
removeBtn.classList.add('remove_button');
removeBtn.value = "-";
removeBtn.addEventListener('click', removeMon.bind(null, removeBtn));
monday.append(textarea, removeBtn);
fragment.appendChild(monday);
monday_count++;
}
document.getElementById('mon').appendChild(fragment);
}
function removeMon(button)
{
button.parentElement.remove();
}
I simplified your script a little and changed your name attributes: Instead of assigning individual names I simply gave all textareas the name monday[]. When posting this to a PHP page the values will be pushed into an array with the same name and in case you want to harvest the values with JavaScript, then this can be done easily too.
function add_monday(){
$("#mon").append('<div><textarea name="monday[]" placeholder="Type anything you want here"></textarea><input type="button" value="-"/></div>'.repeat(5))
}
$("#mon").on("click","input[type=button]",function(){$(this).parent(). remove()})
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<div class="day">
<div class="day_info">
<p>Monday</p>
</div>
<div class="add">
<div class="button" onclick="add_monday()">
<i class="fas fa-plus" id="plus">click here to add fields</i>
</div>
</div>
<div style="clear:both"></div>
</div>
<div id="mon">
<div style="clear:both"></div>
</div>
And here a non-jQuery version:
const ad=document.querySelector(".alldays");
ad.innerHTML=
"Mon,Tues,Wednes,Thurs,Fri,Satur,Sun".split(",").map(d=>`
<div class="day">
<div class="day_info"><p>${d}day</p></div>
<div class="add">
<div class="button">
<i class="fas fa-plus" id="plus">click here to add fields</i>
</div>
</div>
<div style="clear:both"></div>
</div>
<div id="${d.toLowerCase().substr(0,3)}">
<div style="clear:both"></div>
</div>`).join("");
function add2day(el,n){
const wd=el.closest(".day"),
d=wd.querySelector("p").textContent.toLowerCase(),
html=`<textarea name="${d.toLowerCase()}[]" placeholder="Type anything you want here"></textarea><input type="button" value="-"/>`;
while (n--) {
let div= document.createElement("div");
div.innerHTML=html;
wd.nextElementSibling.appendChild(div);
}
}
ad.addEventListener("click",function(ev){
const el=ev.target;
switch(el.tagName){
case "INPUT": // remove field
el.parentNode.remove(); break;
case "I": // add new fields
add2day(el,3); break;
}
})
<div class="alldays"></div>
I extended the second script to make it work for any day of the week.

Separate Show/Hide button javascript

I'm trying to have 2 separate buttons so that when the first button is clicked there's a div that shows underneath it and then when the other button is pressed, another div pops out replacing/hiding the first div that came out when the first button was clicked.
Html:
<!-- Pre-Determined Button -->
<span class="tooltip">
<button style="border-top-right-radius: 13px; border-bottom-left-radius: 13px;border-bottom-right-radius: 20px;border-top-left-radius: 20px;" id="predetermine" onclick="javascript:predetermine();">Pre-Determined</button>
</span>
<!-- Auction Button -->
<span class="tooltip">
<button style="border-top-right-radius: 20px; border-bottom-left-radius: 20px;border-bottom-right-radius: 13px;border-top-left-radius: 13px;" id="auction" onclick="javascript:auction(); ">Auction</button>
</span>
</div>
<br>
<!-- Username Entry -->
<div class="username-entry" id="predetermineclick" style="visibility:hidden">
<label> Enter Username: </label>
<input class= "joe" type="text" id="uName" name="UserName">
</div>
<!-- Create code button -->
<div class="create" id="auctionclick" style="visibility:hidden">
<button class="button">Create Link</button>
</div>
For my javascript, I just wrote 2 seperate functions, but as you can see on the images the "create link" button goes on the bottom of the username spot. I know there's a way to put these 2 functions together and make the code cleaner.
Java script:
function predetermine() {
if (document.getElementById('predetermine').onclick) {
document.getElementById('predetermineclick').style.visibility='visible';
document.getElementById('auctionclick').style.visibility='hidden';
}
function auction() {
if (document.getElementById('auction').onclick) {
document.getElementById('auctionclick').style.visibility='visible';
document.getElementById('predetermineclick').style.visibility='hidden';
}
Use display: none to completely remove an element from the page.
function predetermine() {
if (document.getElementById('predetermine').onclick) {
document.getElementById('predetermineclick').style.display = 'block';
document.getElementById('auctionclick').style.display = 'none';
}
}
function auction() {
if (document.getElementById('auction').onclick) {
document.getElementById('auctionclick').style.display = 'block';
document.getElementById('predetermineclick').style.display = 'none';
}
}
<!-- Pre-Determined Button -->
<span class="tooltip">
<button style="border-top-right-radius: 13px; border-bottom-left-radius: 13px;border-bottom-right-radius: 20px;border-top-left-radius: 20px;" id="predetermine" onclick="javascript:predetermine();">Pre-Determined</button>
</span>
<!-- Auction Button -->
<span class="tooltip">
<button style="border-top-right-radius: 20px; border-bottom-left-radius: 20px;border-bottom-right-radius: 13px;border-top-left-radius: 13px;" id="auction" onclick="javascript:auction(); ">Auction</button>
</span>
<br>
<!-- Username Entry -->
<div class="username-entry" id="predetermineclick" style="display: none">
<label> Enter Username: </label>
<input class="joe" type="text" id="uName" name="UserName">
</div>
<!-- Create code button -->
<div class="create" id="auctionclick" style="display: none">
<button class="button">Create Link</button>
</div>
You can get the id of the clicked button by passing it in the javascript function. Try the code snippet below.
HTML:
<div>
<!-- Pre-Determined Button -->
<span class="tooltip">
<button
style="border-top-right-radius: 13px; border-bottom-left-radius: 13px;border-bottom-right-radius: 20px;border-top-left-radius: 20px;" id="predetermine" onclick="toggleState(this.id);">Pre-Determined</button>
</span>
<!-- Auction Button -->
<span class="tooltip">
<button
style="border-top-right-radius: 20px; border-bottom-left-radius: 20px;border-bottom-right-radius: 13px;border-top-left-radius: 13px;" id="auction" onclick="toggleState(this.id); ">Auction</button>
</span>
</div>
<br>
<!-- Username Entry -->
<div class="username-entry" id="predetermineclick" style="visibility:hidden">
<label> Enter Username: </label>
<input class="joe" type="text" id="uName" name="UserName">
</div>
<!-- Create code button -->
<div class="create" id="auctionclick" style="visibility:hidden">
<button class="button">Create Link</button>
</div>
Javascript:
function toggleState(clickedButtonId) {
const predetermineClick = document.getElementById('predetermineclick');
const auctionClick = document.getElementById('auctionclick');
if(clickedButtonId === 'predetermine') {
predetermineClick.style.visibility='visible';
auctionClick.style.visibility='hidden';
} else {
auctionClick.style.visibility='visible';
predetermineClick.style.visibility='hidden';
}
}
Another way of doing this is to pass the element itself instead of its id.
To make this work, change toggleState(this.id); to toggleState(this); in both the places in the above HTML code.
Then get the id of the triggered element like we've done in the code below.
function toggleState(clickedButton) {
const clickedButtonId = clickedButton.id;
const predetermineStyle = document.getElementById('predetermineclick').style;
const auctionStyle = document.getElementById('auctionclick').style;
if(clickedButtonId === 'predetermine') {
predetermineStyle.visibility = 'visible';
auctionStyle.visibility = 'hidden';
} else {
auctionStyle.visibility = 'visible';
predetermineStyle.visibility = 'hidden';
}
}
Also, I noticed there was a <div> element missing in your HTML code, which I'm sure you'd definitely have in your code file, but to make this answer self-sufficient, I took the liberty of adding a <div> element at the beginning.
I'd have chosen to remove the element instead of toggling its visibility, but I see that #Janned has already addressed that in his answer, so I won't go into it.

Create and add a <li> element to an ordered list using javascript/jquery

I'm trying to create a To Do list, and when the user enters a new task, and clicks the button, the javascript should create a li element containing a span that holds the user's entry, then add that li element to the ol in my HTML.
My HTML looks like this:
<body>
<h1>To Do:</h1>
<section>
<input type="text" id="add_todo">
<span id="add_task_error"> </span>
<input type="button" id="add_task" value="Add task">
<div id="empty_message" class="open">
<h3>You have no tasks left to accomplish!</h3>
</div>
<div id="tasklist">
<ol class="list">
</ol>
</div>
</section>
</body>
This is the function that is not working:
var newSpan = $('<span>input</span>').addClass("task");
//wrap it in a <li> element
newSpan = (".task").wrap("<li></li>");
$(".list").append(newSpan);
I also tried it this way:
var new_task = $('<li>*</li>').addClass('task');
new_task.appendTo('ol.list');
new_task.setAttribute('id', 'new_task');
$("#new_task").text(input);
Both ways did not work- when I clicked the Add Task button (which is not the problem- I tested it), nothing happened on the screen...
What am I doing wrong???
Try this
$(document).ready(function(){
$('#add_task').click(function(){
var task = $('#add_todo').val();
var html = '<li><span>'+task+'</span></li>';
$('.list').append(html);
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>To Do:</h1>
<section>
<input type="text" id="add_todo">
<span id="add_task_error"> </span>
<input type="button" id="add_task" value="Add task">
<div id="empty_message" class="open">
<h3>You have no tasks left to accomplish!</h3>
</div>
<div id="tasklist">
<ol class="list">
</ol>
</div>
</section>
Create the element, set all the attributes and when, you are done, add it to the ol.
var new_task = $('<li></li>').addClass('task');
new_task.text($("#add_todo").val()); //this is the value of the input
new_task.attr('id', 'new_task'); //use attr instead of setAttribute
new_task.appendTo('ol.list');
FIDDLE
Hope this works for you
JS code:
$("#add_task").click(function(){
var value = $("#add_todo").val();
$(".list").append("<li class='task'><span>"+ value +"</span></li>")
});
Here is the working Plnkr
This should be your code.
Call addLI() on click of your button
<input type="button" id="add_task" value="Add task" onclick="addLI()">
function addLI() {
//check for empty value
if ($('#add_todo').val() == "") {
alert("Please Add Todo.");
return;
}
//generate html for li
var html = "<li class='task' id='new_task'><span>" + $('#add_todo').val() + "</li>";
//append li to order list
$(".list").append(html);
}
Also try to hide the div on which you are showing the message before adding any new task.
<div id="empty_message" class="open">
<h3>You have no tasks left to accomplish!</h3>
</div>
$('.open').hide(); on click event of add task

Expanding list of li's with hidden content

I currently have a similar setup to the following link:
http://jsfiddle.net/d33zC/5/
divs in question:
<ul>
<li>
Question
<div id="question" style="display:none; margin:0px;">
<input type="text" />
</div>
</li>
<li>
Question
<div id="question2" style="display:none; margin:0px;">
<input type="text" />
</div>
</li>
<li>
Question
<div id="question3" style="display:none; margin:0px;">
<input type="text" />
</div>
</li>
Note that these divs already have expanding hidden content in them.​
Now, lots of questions are being generated, I am at a point where I need to keep a restricted list that can expand with the rest of the divs when clicked or automatically (a la google images or twitter).
Is there any way I can limit the amount, and "expand" the list to show the rest of the list?
Thanks.
Updated fiddle with lots of changes, see comments for explanations. The main points are
Added classes everywhere
Added a "See More" <li> at the end
Looped over each <ul> (given class questions) then <li> (given class qn) to set it up
Used event listeners
It is all done in native JavaScript (no jQuery required). The main bit of the JavaScript is as follows
window.addEventListener('load',function load(){
var n_shown_at_start = 3,
n_more_displayed_on_click = 3;
var qs = document.querySelectorAll('.questions'),
qn, sm, i = qs.length, j;
while( --i >= 0 ){ // loop over all questions
sm = qs[i].querySelector('.see_more'); // get see more entry
qn = qs[i].querySelectorAll('.qn'); // get question <li>s
j = qn.length;
while( --j >= 0 ){
qn[j]
.querySelector('.qn_vis') // <a>
.addEventListener('click', function click(){ // make click display question
qn_toggle(this);
return false; // no action
}, true);
if(sm) // if there is a see more button, hide some questions
qn[j].style.display = (j < n_shown_at_start ? '' : 'none');
}
if(sm){ // if there is a see more button, set it up
sm.qs = qs[i];
sm.start = n_shown_at_start;
sm.lim = n_more_displayed_on_click;
sm.addEventListener('click', function click(){
var qn = this.qs.getElementsByClassName('qn'), q,
i = this.start, j = i + this.lim;
this.start = j + 1;
while(i < j && (q = qn[i++])){ // loop over questions
q.style.display = 'block';
}
if(!q || !qn[i]){ // if we reached the end
this.textContent = 'No More';
}
}, false);
}
}
}, false);
Does this solve your problem?
Wrap the excess ones in a hidden DIV and show it when the Show All button is clicked
http://jsfiddle.net/vAZFv/2/
HTML:
<ul>
<li>
Question
<div id="question" style="display:none; margin:0px;">
<input type="text" />
</div>
</li>
<li>
Question
<div id="question2" style="display:none; margin:0px;">
<input type="text" />
</div>
</li>
<li>
Question
<div id="question3" style="display:none; margin:0px;">
<input type="text" />
</div>
</li>
<div id="hiddenOnes">
<li>
Question11
<div id="question3" style="display:none; margin:0px;">
<input type="text" />
</div>
</li>
<li>
Question11
<div id="question3" style="display:none; margin:0px;">
<input type="text" />
</div>
</li>
<li>
Question11
<div id="question3" style="display:none; margin:0px;">
<input type="text" />
</div>
</li>
</div>
</ul>
<input type="button" id="showAllBtn" value="Show all">​
JS:
function toggle2(id, link) {
var e = document.getElementById(id);
if (e.style.display == '') {
e.style.display = 'none';
} else {
e.style.display = '';
}
}
$(function() {
$("#hiddenOnes").hide();
$("#showAllBtn").click(function() {
$("#hiddenOnes").show();
});
});​
Here is another solution which does everything you ask for.
JS FIDDLE:
http://jsfiddle.net/erRCy/
HTML:
<ul class="topnav">
<li>Question</li>
<li>Question</li>
<li>Question</li>
<li>Question11</li>
<li>Question11</li>
<li>Question11</li>
<li>Question11</li>
</ul>
<input type="button" id="showAllBtn" value="Show all">
CSS:
.visible{
display:block;
}
.invisible{
display:none;
}
JS:
<script>
// Make all LIs under the UL(with class=topnav) invisible
$("ul.topnav > li").addClass('invisible');
// when the button is clicked
$("#showAllBtn").click(function() {
var gITEMS_PER_SET = 2; // set the no of items you want to show per set
//get next set of LIs which are invisible and make them visible
$("ul.topnav > li.invisible").slice(0, gITEMS_PER_SET).removeClass('invisible').addClass('visible');
});
// simulate the button click to show the initial set when page loads
$("#showAllBtn").click();​
<script>
​
You could do something like this:
http://jsfiddle.net/vZnJb/3/
First, hide all li's by adding style="display:none;" like you already do for your div's. Then, after pressing a button or clicking a link, you iterate over all li's with document.getElementsByTagName("li");, removing this style for a certain amount of them.
Js code:
var shown = 1;
var expand_per = 1;
function expand() {
shown += expand_per;
var allLists = document.getElementsByTagName("li");
i = 0;
while (i < shown) {
if (allLists[i] === undefined) {
break;
}
if (allLists[i].style.display == 'none') {
allLists[i].style.display = '';
}
i++
}
}​
Edit: Of course, in a real life situation, you would fetch all questions from a database, as mentioned by Sajjan Sarkar.

Categories

Resources