jQuery .each not iterating through li - javascript

Have a bunch of li's that are essentially true or false questions. Problem is that it is working for the first li but not the next, next, next etc
jquery code is:
<script>
jQuery(document).ready(function() {
//Run the each iteration
jQuery('#question').each(function(i){
// Hide the initial values
jQuery('#true').hide();
jQuery('#false').hide();
var answer = '<?php echo the_sub_field( 'true_or_false' ); ?>';
console.log(answer);
jQuery("#button").click(function($){
$.preventDefault();
if( answer == 'True' ) {
jQuery('#false').hide();
jQuery('#true').show();
}
});
jQuery("#button2").click(function($){
$.preventDefault();
if( answer == 'True' ) {
jQuery('#true').hide();
jQuery('#false').show();
}
});
});
});
</script>
html code is:
<li id="question">
<div id="statement">
<?php the_sub_field( 'question' ); ?>?
</div>
<div id="true">
<?php the_sub_field( 'true_answer' ); ?>
</div>
<div id="false">
<?php the_sub_field( 'false_answer' ); ?>
</div>
true
false
</li>
I'm getting the right values to check against inside the console - however the each doesn't seem to be doing it for "each".
Thanks in advance :)
Here's the raw output:
<ul>
<li id="question">
<div id="question">
George likes to sing?
</div>
<div id="true">
You are correct, even when it's out of tune </div>
<div id="false">
Sadly we wish it was false, but it's true </div>
true
false
</li>
<script>
jQuery(document).ready(function() {
//Run the each iteration
jQuery('#question').each(function(i){
// Hide the initial values
jQuery('#true').hide();
jQuery('#false').hide();
var answer = 'True';
console.log(answer);
jQuery("#button").click(function($){
$.preventDefault();
if( answer == 'True' ) {
jQuery('#false').hide();
jQuery('#true').show();
}
});
jQuery("#button2").click(function($){
$.preventDefault();
if( answer == 'True' ) {
jQuery('#true').hide();
jQuery('#false').show();
}
});
});
});
</script>
<li id="question">
<div id="question">
Aj likes to say the word "WoWoWoWomp"??
</div>
<div id="true">
You are right, almost twenty times a day </div>
<div id="false">
Unfortunately you were wowowo wrong :) </div>
true
false
</li>
<script>
jQuery(document).ready(function() {
//Run the each iteration
jQuery('#question').each(function(i){
// Hide the initial values
jQuery('#true').hide();
jQuery('#false').hide();
var answer = 'False';
console.log(answer);
jQuery("#button").click(function($){
$.preventDefault();
if( answer == 'True' ) {
jQuery('#false').hide();
jQuery('#true').show();
}
});
jQuery("#button2").click(function($){
$.preventDefault();
if( answer == 'True' ) {
jQuery('#true').hide();
jQuery('#false').show();
}
});
});
});
</script>
</ul>

I am assuming this <li> is the pattern for all.
Given this: id is only allowed to be used one time ... either:
Change the id for each type (i.e. id="Question1", id="Question2"), or
Use classes (i.e. class="Question") which will allow for selecting multiple elements at one time.
While I referenced id="Question" above, this pattern should remain true. An id must be unique; this applies for: question, statement, true, false, button, button2, and any other id's you have listed.

You do not need to iterate. Replacing the id with class and rewriting the jquery shortens the code greatly. Here is the HTML output -
<ul>
<li>
<div class="question">George likes to sing?</div>
<div class="true">You are correct, even when it's out of tune</div>
<div class="false">Sadly we wish it was false, but it's true</div> true
false
</li>
<li>
<div class="question">Aj likes to say the word "WoWoWoWomp"??</div>
<div class="true">You are right, almost twenty times a day</div>
<div class="false">Unfortunately you were wowowo wrong :)</div> true
false
</li>
</ul>
Given that you can use this jQuery, which only needs to appear one time, not multiple times as you have done above. One set of functions handles all of the questions / answers. -
jQuery(document).ready(function () {
// hide the answers
jQuery('.true, .false').hide();
// show answer based on click
jQuery('.button').click(function (e) {
e.preventDefault();
jQuery(this).closest('li').find('.true').show();
jQuery(this).closest('li').find('.false').hide();
});
jQuery('.button2').click(function (e) {
e.preventDefault();
jQuery(this).closest('li').find('.false').show();
jQuery(this).closest('li').find('.true').hide();
});
});
You're also running an unnecessary test to see if a variable is set because the variable, being set as it is, is always set, so this has been removed from the code.
Here is a working example.

It's always best to use a class for iterating through items. Id should only be used once (for accessing a unique element). See the following example.
Jquery Code.
$('div#questions ul li.answer').each(function() {
console.log($(this).text());
});
Html.
<div id="questions">
<ul>
<li class="answer">True</li>
<li class="answer">True</li>
<li class="answer">False</li>
<li class="answer">False</li>
<li class="answer">True</li>
</ul>
</div>

Related

is there a way to update a div with new content only using ajax

This is the div that i am updating
but i want to add a active class to the (li) item
every time the div refreshes the active class goes away
so i don`t want to refresh all the data in the (ul) but
only add (li) if there is a new data in the database,
with out refreshing the previous (li) items
<div id="contacts">
<ul id="rooms" class="rooms">
<!-- This is where the data get inserted -->
<!-- the ajax call and this -->
<li class='contact' data-val='<?php echo $room['id']; ?>'>
<div class='wrap'>
<div class='meta'>
<p class='name'><?php echo $room['sender']; ?></p>
<p class='preview'><?php echo $room['senderemail']; ?></p>
</div>
</div>
</li>
</ul>
</div>
this is my ajax call
$(document).ready(function() {
var interval = setInterval(function(){
$.ajax({
url: 'rooms.php',
success: function(data){
$('#rooms').html(data);
}
});
}, 1000);
});
in the room php
$rooms = get_rooms();
foreach($rooms as $room){
?>
<li class='contact' data-val='<?php echo $room['id']; ?>'>
<div class='wrap'>
<div class='meta'>
<p class='name'><?php echo $room['sender']; ?></p>
<p class='preview'><?php echo $room['senderemail']; ?></p>
</div>
</div>
</li>
<?php
}
the get_rooms() function
function get_rooms() {
$sql = "SELECT id, sender, senderemail FROM chatroom ";
$result = mysqli_query($GLOBALS['dbh'], $sql);
$rooms = array();
while($room = mysqli_fetch_assoc($result)){
$rooms[] = array('id'=>$room['id'], 'sender'=>$room['sender'],
'senderemail'=>$room['senderemail']);
}
return $rooms;
}
You Just need to push new data to the div as below just replace your line with:
$('#rooms').append(data);
this will add new <li> in your existing <div> after the last <li>
jquery append()
To get the id of the last <li>
var lastId = $( "#rooms li" ).last().attr('id');
Once you get the last id then pass it in your ajax call.
If I understand you correctly, your problem is that you lose the active class (which you clicked on the li container) when there is new data.
This has to do with the fact that you exchange all of the content.
There are now three options. Either
You give the rooms.php the id of the currently active li-container
and this script sets the active class for the affected container.
You transfer all the chatrooms (ids) already shown to rooms.php and only
load the new ones (this means effort later with sorting).
You save the active li class and re set it after content changed (this is the fastest)
f.e: in your Ajax succes functions:
let id=0;
let active_li = $('li.active');
if (active_li.length>0) id=active_li.data('val');
$('#rooms').html(data);
if (id!=0) $('li[data-val="'+id+'"]').addClass ('active');
A few other thoughts:
Note the interval of 1000ms. Possible it makes Problems if the request lasts longer than 1000ms. This may still work well in your tests, but maybe not anymore if there are a hundred or 1000 users in your application.
Doesn't it make sense to tell the server when you click the active room and save it in a session so that the server knows which room is active in the client?
You need to simply update your JS code like:
$(document).ready(function() {
var active_list = '';
var interval = setInterval(function(){
$.ajax({
url: 'rooms.php',
beforeSend: function(){
active_list = $('#rooms').find('li.contact.active').attr('data-val');
}
success: function(data){
$('#rooms').html(data);
$(data).find('li[data-val="' + active_list +'"]').addClass('active');
}
});
}, 1000);
});
This should solve your problem and Let me know if you still face any issue.

AngularJs filter not updating view

The view in my html is not getting filtered on selecting any li element.
But when I console the filter functions the output generated is correct.Also how to clear the filter so it is reusable again.I'm getting a blank page on clicking open or close select elements.Can anyone help me with this.
I have used two filters in a controller inside the functions like this-
indexController Functions-
this.UserTickets = ()=> {
//code to get the tickets
}
this.openTickets = () => {
index.filteredTickets = $filter('filter')(index.tickets, { status: "open" } );
console.log(index.filteredTickets);
};
//filter closed tickets
this.closeTickets = () => {
index.filteredTickets = $filter('filter')(index.tickets, { status: "close" } );
console.log(index.filteredTickets);
};
this.clearFilter = () => {
//clear the filter
};
HTML-
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
<li><a ng-click="indexCtrl.clearfilter()">None</a></li>
<li><a ng-click="indexCtrl.openTickets()">Open</a></li>
<li><a ng-click="indexCtrl.closeTickets()">Close</a></li>
</ul>
<div ng-repeat="ticket in indexCtrl.tickets | filter:tickets |filter:indexCtrl.filteredTickets">
<div class="ticket-no">
<h4>Ticket No:<span>{{ticket}}</span></h4>
</div>
<div class="ticket-title">
<a ng-href="/ticketView/{{ticket.ticketid}}"><h3>{{ticket.title}}</h3></a>
</div>
<div class="ticket-info">
<p class="pull-left">{{ticket.username}} On {{ticket.created | date:"MMM d, y h:mm a"}}</p>
<p class="pull-right">Status:<span>{{ticket.status}}</span></p>
</div>
<hr class="hr">
</div>
You are mixing both angular filter options. I would recommend the javascript filters, index.filteredTickets=$filter('filter')(index.tickets,{status:"open"}); rather than the html template syntax, ng-repeat="ticket in indexCtrl.tickets | filter:tickets...". The key difference between these methods is how often they are run. The html template syntax filters are run on every digest cycle, the javascript filters are only run when the method is called, in your case, on each button click. For small apps or when the lists are small, this difference won't be noticeable, but if your app grows in size, the constant filtering on each digest cycle can cause page lag.
The filters in the controller are my preferred way of handling this, so I will show you how to clean up your code for these to work. You are almost there, just a few small changes are needed.
In your html, you can remove the inline filters in the ng-repeat, these aren't needed, and change the array to be your filter list, index.filteredTickets.
.html
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
<li><a ng-click="indexCtrl.clearfilter()">None</a></li>
<li><a ng-click="indexCtrl.openTickets()">Open</a></li>
<li><a ng-click="indexCtrl.closeTickets()">Close</a></li>
</ul>
<div ng-repeat="ticket in indexCtrl.filteredTickets">
<div class="ticket-no">
<h4>Ticket No:<span>{{ticket}}</span></h4>
</div>
<div class="ticket-title">
<a ng-href="/ticketView/{{ticket.ticketid}}"><h3>{{ticket.title}}</h3></a>
</div>
<div class="ticket-info">
<p class="pull-left">{{ticket.username}} On {{ticket.created | date:"MMM d, y h:mm a"}}</p>
<p class="pull-right">Status:<span>{{ticket.status}}</span></p>
</div>
<hr class="hr">
</div>
For the javascript, you need to make sure the filteredTickets are accessible in the html. I'm not sure if index == this, if not, you may need to attach the filtered tickets to the scope. The one other change needed is to set the filteredTickets to your original list if the none button is pressed. You will also want to call clearFilter after you load the list, otherwise index.filteredList will be undefined/null.
.js
this.UserTickets = () => {
//code to get the tickets
....
//after getting list, call clear filter
this.clearFilter();
}
this.openTickets = () => {
index.filteredTickets = $filter('filter')(index.tickets, { status: "open" } );
console.log(index.filteredTickets);
};
//filter closed tickets
this.closeTickets = () => {
index.filteredTickets = $filter('filter')(index.tickets, { status: "close" } );
console.log(index.filteredTickets);
};
this.clearFilter = () => {
//clear the filter
index.filteredTickets = index.tickets;
};

Matching multiple keywords using contains() in jQuery

Currently matching a specific keyword using contains(). How can i expand this to include multiple keywords?
have tried using the || (or) operator, but no joy.
<!-- Product names include Apple iPad, Acer Iconia, Lenovo Thinkpad -->
<h1 id="pbtitle">Apple iPad 3</h1>
<div class="install_option" style="display:none;">
<div style="box-sizing:border-box; float:left;">
<a href="https://www.exmaple.com/acc" target="_blank">
<h3 style="font-weight:bold;">Would you like to view accessories?</h3>
</a>
</div>
</div>
$(".install_option").each(function() {
if($("h1#pbtitle:contains:contains('Acer' || 'Lenovo' || Apple )").length>0){
$('.install_option').css('display','block');
}
});
Use JavaScript function indexOf()
Working example jsfiddle
var options = ['Acer','Lenovo','Apple']; // options that you want to look for
var text = $("#pbtitle").text(); // string where you want to look in
options.forEach( function( element ) {
if ( text.indexOf( element ) != -1 ) { // if its NOT -1 (-1 = not found)
alert( 'found' ); // then we found it .. do your magic
}
})
Do this way
if($("h1#pbtitle:contains('Acer'),h1#pbtitle:contains('Lenovo'),h1#pbtitle:contains('Apple')").length>0)
Risking being a bit out of the question scope, I guess the product list is dynamic in same kind.
In that case it will be better to add a property to the product tag like:
<h1 id="pbtitle" has_install_option="true">Apple iPad 3</h1>
var condition = $('h1#pbtitle').attr('has_install_option') == 'true';
and checking that condition in your loop.
[think of the day you will have an Apple product with install_option or an Appleseed product...]
p.s in this example it's better to place the condition out side of the loop as the condition is static in relation to the looped elements

Pass value of list view to ajax

I have a list that is being created dynamically. Part of code that creates a list is:
<ul>
<?
foreach ($folders as $folder)
{
$folder = str_replace("{imap.gmail.com:993/imap/ssl}", "", $folder);
$folder2 = str_replace("[Gmail]/", "", $folder);
?>
<li>
<a><div id="box"><? echo $folder2; ?> </div></a>
</li>
<?}
</ul>
<div id="maillist"></div>
o/p of $folder
GMAIL/All Mail
GMAIL/Drafts
GMAIL/Important
o/p of $folder2
All Mail
Drafts
Important
what i want is that when a user clicks on All Mail, value corresponding to it (in this case: GMAIL/All Mail) should get pass to another script through ajax. The same process should follow for the other values in list also
ajax code
<script>
$(document).ready(function(){
$('#box').change(function(){
var boxid = $('#box').val();
console.log($('#box'))
if(boxid != 0)
{
$.ajax({
type:'post',
url:'a_fetchmaillist.php',
data:{id:boxid},
cache:false,
success: function(returndata){
$('#maillist').html(returndata);
console.log(returndata)
}
});
}
})
})
</script>
Can anyone tell if its possible to do what i want and if yes then how will it be done
First of all do not assign the same id multiple times, instead, set a class (eg box).
Then assign a data attribute for the specific folder ( eg. box-allMails ) and select that attribute on change:
foreach ($folders as $folder)
{
$folder = str_replace("{imap.gmail.com:993/imap/ssl}", "", $folder);
$folder2 = str_replace("[Gmail]/", "", $folder);
?>
<li>
<div class="box" data-folder="<? echo $folder2 ?>"><? echo $folder2; ?></div>
</li>
<?}
Then on change:
$(document).on('click', '.box', function() {
var folder = $(this).attr('data-folder');
// ajax call..
});
UPDATE
Important: You have to listen to 'click' event instead of 'change' because you click on a div, not on an input (I've changed the code).
Event delegation: Take note at the code:
$(document).on('click', '.dynamic-element', function() { .. })
instead of:
$('.element').on('click', function() { .. });
The second will not work because you are creating the elements dynamically.
Clickable: You do not have to insert an anchor tag to make the list item clickable unless you want to redirect to another page. In your case, you can style the .box div in order to get a cursor-pointer like this:
CSS
.box { cursor:pointer }
jQuery will take care of the rest (Check the example)
$(document).on('click', '.box', function() {
var folder = $(this).attr('data-folder');
alert('You clicked on: ' + folder);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul>
<li><div class="box" data-folder="folderOne">Folder One</div></li>
<li><div class="box" data-folder="folderTwo">Folder Two</div></li>
<li><div class="box" data-folder="folderThree">Folder Three</div></li>
<li><div class="box" data-folder="folderFour">Folder Four</div></li>
</ul>

Using Javascript to update a <li></li> from some data send from PHP?

I have some Jquery tabs with Names on them.
(Ie: |Apple|Orange|Pear| )
I would like to update these titles to say something like
|Apple(2)|Orange|Pear(4)|
or something else based on the data returned by a php page ( say, numbers.php )
So,
Jquery requests numbers.php
numbers.php returns
Apple:2
Pear:4
How can I have JS, then use that data to dynamically update the Jquery tab "titles" with the data returned?
Then, if I re run the function, it would ask for numbers.php again and once again, update the tab titles based on what php returns?
Also, the names could change.. So next time it runs, Apples may not exist, but Pear may read 5 ..
In this instance, apple should be renamed "Apple"
Any help would be most excellent.
( hope ive made this clear? )
[ UPDATE ]
I have tried the below answer, but no luck.
The LI appears like this in the console:
<li id="tab-tabtestuser" class="ui-state-default ui-corner-top ui-tabs-active ui-state-active" role="tab" tabindex="0" aria-controls="newtab-tabtestuser" aria-labelledby="ui-id-5" aria-selected="true">tabtestuser <span class="count"></span><span class="ui-icon ui-icon-close" role="presentation">Remove Tab</span></li>
If you return the data from numbers.php in a meaningful format such as JSON, you can then process the data and update the tabs in Javascript much more easily. Here is a basic example of what you want to do, you will probably want to improve upon it.
numbers.php
{
apple: 5,
orange: 3,
pear: 2
}
Javascript:
$.getJSON( "numbers.php", function( data ) {
$.each( data, function( key, val ) {
$('#tab-' + key).find('span.count').text(val);
if (val == 0) {
$('#tab-' + key).hide();
};
});
});
HTML:
<div id="tabs">
<ul>
<li id="tab-apple">Apple <span class="count"></span></li>
<li id="tab-orange">Orange <span class="count"></span></li>
<li id="tab-pear">Pear <span class="count"></span></li>
</ul>
<div id="tabs-apple"></div>
<div id="tabs-orange"></div>
<div id="tabs-pear"></div>
</div>

Categories

Resources