Problems with pagination in JQuery - javascript

I need to be able to parse an XML file with JQuery, show 3 posts at the time and have pagination that links to the rest of the posts.
Below in the code, I am parsing a local XML file that I have downloaded from slashdot. The code displays the right amount of posts and creates the links to paginate but when you click the pagination links, they do not work for some reason. I am still a JQuery n00b so I have problems figuring out what is wrong. Seems like JQuery does not have a really good debugging tool?
p.s. You can download http://slashdot.org/slashdot.xml to your local so you can test the code if you want.
here is the code
<html>
<head>
<script type="text/javascript" src="jquery-1.6.4.js"></script>
<script type="text/javascript">
$(document).ready(function()
{
$.ajax({
type: "GET",
url: "slashdot.xml",
dataType: "xml",
success: parseXml
});
});
function parseXml(xml)
{
//find every story
var count = 0;
$(xml).find("story").each(function()
{
count++;
var title = $(this).find('title').text()
var url = $(this).find('url').text()
var fullLink = '<li>' + title + '</li>';
//document.write('' + title + '<br/>');
$("#content").append(fullLink);
});
var show_per_page = 3;
var number_of_items = count;
var number_of_pages = Math.ceil(number_of_items/show_per_page);
$('#current_page').val(0);
$('#show_per_page').val(show_per_page);
var navigation_html = '<a class="previous_link" href="javascript:previous();">Prev</a> ';
var current_link = 0;
while(number_of_pages > current_link){
navigation_html += '<a class="page_link" href="javascript:go_to_page(' + current_link +')" longdesc="' + current_link +'">'+ (current_link + 1) +'</a>';
current_link++;
}
navigation_html += '<a class="next_link" href="javascript:next();"> Next</a>';
$('#page_navigation').html(navigation_html);
$('#page_navigation .page_link:first').addClass('active_page');
$('#content').children().css('display', 'none');
$('#content').children().slice(0, show_per_page).css('display', 'block');
function previous(){
new_page = parseInt($('#current_page').val()) - 1;
//if there is an item before the current active link run the function
if($('.active_page').prev('.page_link').length==true){
go_to_page(new_page);
}
}
function next(){
new_page = parseInt($('#current_page').val()) + 1;
//if there is an item after the current active link run the function
if($('.active_page').next('.page_link').length==true){
go_to_page(new_page);
}
}
function go_to_page(page_num){
//get the number of items shown per page
var show_per_page = parseInt($('#show_per_page').val());
//get the element number where to start the slice from
start_from = page_num * show_per_page;
//get the element number where to end the slice
end_on = start_from + show_per_page;
//hide all children elements of content div, get specific items and show them
$('#content').children().css('display', 'none').slice(start_from, end_on).css('display', 'block');
/*get the page link that has longdesc attribute of the current page and add active_page class to it
and remove that class from previously active page link*/
$('.page_link[longdesc=' + page_num +']').addClass('active_page').siblings('.active_page').removeClass('active_page');
//update the current page input field
$('#current_page').val(page_num);
}
//$("#content").append('count:' + count);
}
</script>
</head>
<body>
<!-- we will add our HTML content here -->
<input type="hidden" id="current_page"></input>
<input type="hidden" id="show_per_page"></input>
<div id="content">
</div>
<div id="page_navigation"></div>
</body>
</html>

First, your html is invalid. Input tags are self-closing and li items need to be inside of a list ul or ol not a div element.
<input type="hidden" id="current_page" />
<input type="hidden" id="show_per_page" />
<ul id="content"></ul>
Second, your click events aren't getting handled because go_to_page, next and previous are not in the global scope. You should create those elements and attach click handlers.
$("<a href='#'>Prev</a>").click(previous).appendTo("#page_navigation");
while (number_of_pages > current_link) {
$("<a href='#' class='page_link'>").text(++current_link).click(go_to_page).appendTo("#page_navigation")
}
$("<a href='#'>Next</a>").click(next).appendTo("#page_navigation");
Another tip, restructure the prev and next functions to just click on the previous or next page number. That way, this in go_to_page always points to the paging link.
function previous(e) {
e.preventDefault(); //Don't follow the link
$(".active_page").prev(".page_link").click();
}
function next(e) {
e.preventDefault();
$(".active_page").next(".page_link").click();
}
function go_to_page(e) {
e.preventDefault();
//Get the zero-based index instead of using an attribute
var page_num = $(this).index(".page_link");
//get the number of items shown per page
var show_per_page = parseInt($('#show_per_page').val());
//get the element number where to start the slice from
start_from = page_num * show_per_page;
//get the element number where to end the slice
end_on = start_from + show_per_page;
//hide all children elements of content div, get specific items and show them
$('#content').children().hide().slice(start_from, end_on).show();
//Since this always points to the page link, use that instead of looking for it
$(this).addClass("active_page").siblings(".active_page").removeClass("active_page");
//update the current page input field. Don't need this anymore since we can use the .active_page class to identify it.
//$('#current_page').val(page_num);
}
JSFiddle with the AJAX part removed.

Related

Unable to get property 'nodeValue' of undefined or null reference in simple jQuery loop

I am inserting li values into a ul element on a form.
Just as testing, I am entering 2 values into the ul. Now, once the user clicks submit, I am checking if any of those li values are duplicates in another list... if not, then submit the values. But, I am working on a scenario where if the user enters a few duplicates and non-duplicates in the ul.. then I would want the non-duplicates to be taken away from the ul element once they are submitted, but keep the duplicates in the list so that the user can see the duplicates.
Here is my code:
console.log("Serial Length - " + $("#SerialUL li").length);
var serialUlLength = $("#SerialUL li").length;
// remove serial numbers that have been submitted from the list on the form.
for(i = 0; i < serialUlLength; i++){
var serialNumber = $("#SerialUL li:eq(" + i + ")").contents().get(0).nodeValue;
var isInSubmitArray = $.inArray(serialNumber, submitArray);
if(isInSubmitArray > -1){
console.log(serialNumber);
$("#SerialUL li:eq(" + i + ")").remove();
}
}
As I stated above, as of now, I am only entering 2 li values into the ul for simple testing. The list that I am comparing against has 0 values in it.. so there shouldn't be any duplicates at this point. The problem I am experiencing happens for the second li element. I am receiving this console error:
Unable to get property 'nodeValue' of undefined or null reference
I have debugged in the console, but I guess I am staring at this for too long. Can someone assist in explaining why I am getting this error?
Any help is appreciated.
UPDATE
The values I am entering as li are 10 and 11. Here is what I see in the console based off of the code above in my question:
UPDATE 2
Code to show li being appended to ul element
// Append TextBox Value to '<ul>' element for user to see once they click button
$("#SerialUL").append("<li class='bullet-serial'>" + serialTxtBoxValue + "<button type='button' class='remove-button'>x</button></li>");
How about this vastly simpler and easier to debug - assuming a leading serial number and something not a number after
var submitArray=[123,567];
$("#SerialUL li").each(function(_,li) {
var ser = parseInt(li.textContent.trim()); // add .replace(/[^0-9]/g,"") if needed
console.log(ser)
if (submitArray.indexOf(ser) !== -1) {
console.log("removing",ser)
li.remove();
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="SerialUL">
<li>123 <button>X</button></li>
<li>456 <button>X</button></li>
<li>123 <button>X</button></li>
<li>567 <button>X</button></li>
<li>789 <button>X</button></li>
</ul>
More complex version with some useful extras such as delegation
var submitArray = [];
$("#serialTxtBox").on("input", function(e) {
var val = this.value;
$("#err").toggle(val && submitArray.indexOf(val)!==-1);
if (String(val).length == 3 && submitArray.indexOf(val)==-1) {
submitArray.push(val);
$("#SerialUL").append("<li class='bullet-serial'>" + val + "<button type='button' class='remove-button'>x</button></li>");
$(this).val("");
}
if ($("#err").is(":visible")) $(this).val("");
})
$("#SerialUL").on("click",".remove-button", function(e) { // delegation
e.preventDefault();
$(this).closest("li").remove();
submitArray = [];
$("#SerialUL li").each(function(_, li) {
var ser = parseInt(li.textContent.trim()); // add .replace(/[^0-9]/g,"") if needed
submitArray.push(ser);
});
})
#err { color:red; display:none }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" id="serialTxtBox" /><span id="err">Already there</span>
<ul id="SerialUL">
</ul>
You are returning element node with .contenets().get(0). "nodeValue" always returns null on element node.
Try filtering for text nodes only on contents() function:
var serialNumber = $("#SerialUL li:eq(" + i + ")").contents().filter(function() {
return this.nodeType === 3;
}).get(0).nodeValue;
Or use .textContent instead .nodeValue:
var serialNumber = $("#SerialUL li:eq(" + i + ")").contents().get(0).textContent;

How to exclude a certain number of entries when calling upon a json feed

Here's a simple script that displays two latest posts under a certain label (in this example, the label "main"), in some section of a Blogger blog.
<script type="text/javascript">
function mainposts(json) {
var item="";
for (var i = 0; i < json.feed.entry.length; i++) {
var mainContent = json.feed.entry[i].content.$t;
item += '<div>' + mainContent + '</div>';
}
document.getElementById("HTML7").innerHTML = item;
}
</script>
<script src="http://www.MYBLOG.com/feeds/posts/default/-/main?max-results=2&alt=json-in-script&callback=mainposts"></script>
Note that HMTL7 is the id that has been automatically assigned by Blogger to my HTML/Javascript-widget, which constitutes a div element by itself.
I have intentionally skipped including any post title variable in the script, so I'm just displaying the posts' content - no more, no less.
What I'd like to do is have two of these scripts for two different sections of my blog, where the second one would omit the two latest posts under the "main" label (same for both scripts), since they are already displayed by means of the first script.
What would I have to add to the second script to achieve this?
Add the start-index query parameter in the script src and initialize it from 3 (as the 1st and 2nd post would already be shown via the first instance of the code in the other section. The new code will look like -
<script type="text/javascript">
function mainposts(json) {
var item="";
for (var i = 0; i < json.feed.entry.length; i++) {
var mainContent = json.feed.entry[i].content.$t;
item += '<div>' + mainContent + '</div>';
}
document.getElementById("HTML99").innerHTML = item;
}
</script>
<script src="http://www.MYBLOG.com/feeds/posts/default/-/main?start-index=3&max-results=2&alt=json-in-script&callback=mainposts"></script>
The exact ID of HTML widget will depend on your blog (mainly it will be different from HTML7)
Initialize for loop variable with 2 var i = 2; and maximum results 4 max-results=4
<script type="text/javascript">
function mainposts(json) {
var item="";
for (var i = 2; i < json.feed.entry.length; i++) {
var mainContent = json.feed.entry[i].content.$t;
item += '<div>' + mainContent + '</div>';
}
document.getElementById("HTML7").innerHTML = item;
}
</script>
<script src="http://www.MYBLOG.com/feeds/posts/default/-/main?max-results=4&alt=json-in-script&callback=mainposts"></script>

How to reload current page and remember toggled class

Im reading in a flickr api list, and dynamically outputting into an unordered list format using some standard javascript. I have added functionality which enables you to toggle 'selected' class to the list.
How can i add cookie to the code which helps remember which list items i have selected when refreshing the page?
http://codepen.io/coolkingkhan/pen/PZvPOB
only pure javascript please IE8+
****** Javascript code *******
(function () {
var tags = 'london',
label = 'Small 320',
script = document.createElement( 'script' );
script.src ='http://api.flickr.com/services/feeds/photos_public.gne?format=json&jsoncallback=cb&tags=' + tags + '&label=' + label;
document.head.appendChild(script);
})();
function cb(data) {
// output the flickr images from api into img element within an unordered list
var output='<ul>';
for (var i=0; i < 9; i++) {
var imgURL = data.items[i].media.m;
output+='<li class="flickrlistitem">' + '<img src=' + imgURL + '/>' + '</li>';
}
output+='</ul>';
document.getElementById('flickrfeed').innerHTML = output;
// add click event on all items with the classname flickrlistitem
var anchor = document.querySelectorAll('.flickrlistitem');
for (var i=0; i < anchor.length; i++){
anchor[i].addEventListener("click", function(){
this.classList.toggle('selected');
}, false);
}
}
****** HTML code *******
<div class="main-container">
<div id="flickrfeed">
</div>
</div>
There was a similar question to this one a few minutes ago:
location.reload(), Javascript,HTML
Basically when the page reloads they set a cookie to read it later.... This approach should work.

how do i capture which number <div> got clicked on inside my container <div> and store it in a variable

edit: my code is all held inside a $(document).ready(function() {} because of this, and because my html code is generated inside my javascript file on the fly, i am experiencing issues using .click() when applying the answer that was given to use
$('.movies_cell').click(function(){
var tmp = $(this).index();
});
original:
i have 20 div elements on a page with a class of .movies_cell that are all generated from an ajax file. All of the div's are created within container div called #movies.
any of the .movies_cell div's can be clicked to bring up a modal box, because i am going to place information from my json file in that modal depending on what gets clicked i need to know which div got clicked, for instance, if it was the 5th div i want to know that the 5th div was clicked and then store that number in a variable, if it was the 2nd, or 3rd i want that number to be stored in a variable and then clear when another .movies_cell div gets clicked.
how would i write a javascript or jquery script to accomplish this? :(
thanks!
$('#myMovies').click(function () {
$.getJSON('data/movies.json', function (allData) {
$.each(allData, function (i, field) {
$('#movies').append(function () {
var movies = '<div class="movies_cell">';
movies += '<div class="movies_image">';
movies += '<img src="img/movies/' + (field.image) + '" alt="' + (field.name) + ' Poster" style="width: 100%; height: 100%">';
movies += '</div>';
movies += '<div class="movies_detail">';
movies += '<h1>' + (field.name) + '</h1>';
movies += '<img src="img/rating/' + (field.myRating) + '.png" alt="movie rating" style="margin: auto;">';
movies += '</div>';
movies += '</div>';
counter++;
console.log(counter);
return movies;
});
});
});
});
Use event delegation.(https://api.jquery.com/on#direct-and-delegated-events) At the top
$('#movies').on( "click", ".movies_cell > div", function() {
var tmp = $(".movies_cell > div").index(this);
console.log(tmp);
});
then
$('#myMovies').click(function () {
//rest of code
Can you use .index() ? It is a zero-based index of the collection of items with, for example, class="movies_cell"
$('.movies_cell').click(function(){
var tmp = $(this).index();
});
jsFiddle Demo

How to set values in dynamically created text boxes

In my app I am creating some dynamic textboxes by clicking an add button. We can put some values and time also. Now my need is that when the page loads, I want a given number of textboxes to be created and populated by a set of values. I am able to create the text boxes onload but cannot set the values. Here I am giving a fiddle where I have created my functionality. How can I set some values dynamically? Here is the fiddle MYFIDDLE
And also I want timepicker function in those onload created boxes.
function getTextBoxAfterValiddation(val){
var str_array = ['jeet','chatterjee'];
var randomId = '\''+"#interviewName"+val+'\'';
var nameId = "interviewName"+val+"";
var allNames = str_array.replace(/((\[)|(\]))/g,"");
alert(randomId)
$(randomId).val(arr[val]);
return '<input class="txt1" name = "DynamicTextBox" type="text" id = "'+nameId+'"/>';
}
for(var i = 0; i < 4; i++){
var div = $("<div />");
div.html(getTextBoxAfterValiddation(i));
$("#TextBoxContainer").append(div);
}
When you dynamically generate each element increment a counter and use that value as the elements id. Then you can put html or values into each element using jquery. In the example below every time i click a button with id "addphys" i append a new div on. Later i can grab values from each div because i know the count and each new div id is phys1, phys2, phys3...
var numphys = 0;
$("#addphys").click(function(){
$("#test").append("<div class=\"addedphys\"><p id=\"phys"+ numphys + "\"><p><label>Physician Username:</label><input type=\"text\" class=\"inputbox\" id=\"physusername" + numphys + "\" name=\"pass\"></p><p><label>Physician Password:</label><input type=\"text\" class=\"inputbox\" id=\"physpassword" + numphys + "\" name=\"pass\"></p></p></div>");
numphys += 1;
});
Hope that helps.

Categories

Resources