Adding element to page every X number of divs - javascript

I need to run this function every X number of posts and the page uses AJAX to load in new posts as you scroll down the page. I was hoping to use the function below using a for loop with the modulus operator but it doesn't seem to accomplish what i'm looking for. Any idea how to do this?
$(document).ready(function($) {
function adTileLoop(){
var adTile = "<div class='new-box' id='article-tile'></div>";
var adLoc = 11;
var p = $('#article-tile');
var tile = $('#article-tile:nth-child('+adLoc+')');
for(var i = 0; i <= p.length; i++){
if(i % adLoc == 0){
$(tile).after(adTile);
}
}
}
$('#content').live(adTileLoop);
}

First of all, you need to be careful to keep IDs unique. The fact that you have $("#article-tile") and you are trying to select more than one is a mistake. ID's must be unique.
Here's a better way to run over a bunch of divs with jQuery:
$("div").each(function() {
console.log($(this));
});
You can then improve the selector to select only nth-children as you do in your question:
$("div:nth-child(2)") for example will get every other div on the page.
To retrieve the information about your posts specifically, use a selector specific to each post, something like: $(".post:nth-child(2)").
As Ashirvad suggested in the comments, you can run this after a successful ajax call and you will be able to retrieve the updated information about your page.

Related

Get Unsorted list list items that are added dynamically in the Controller

I am working on a project (MVC) with Razor views.
I am trying to populate a list dynamically (trying with ul/li but the select/option would also be fine) with a click on a button. The user is filling in a field, clicks a "add" button and this adds it to a ul/li structure.
When I am looking at the inspect element, I can see my values being added, my issue is to store them into Session["..."] ... Or in a hidden field so that I can iterate on them in the Controller action.
I tried several JS/Jquery answers from the net but none of them seemed to work in my case.
Here is how I populate the ul/li structure:
function addPrice() {
var priceValue = $("#PriceValue").val() // this is the input that users fill in
var ul = document.getElementById("priceListBox");
var li = document.createElement("li");
li.setAttribute('class', "list-group-item list-group-item-action"); // set the class for design
li.setAttribute('id', priceValue); // set the id to be able to remove
li.appendChild(document.createTextNode(priceValue));
ul.appendChild(li);
}
Above correctly populates a ul with list items holding the value of the user input.
This is my hidden field attempt:
<input type="hidden" name="PriceValues" value="" runat="server"/>
This is my predefined ul:
<ul class="list-group col-md-3" id="priceListBox" name="priceListBox" runat="server"> </ul>
This is the latest attempt I tried to build up my array and access these values in the controller action:
function SetItemsToArray() {
//const listItems = document.querySelectorAll('li');
//for (let i = 0; i < listItems.length; i++) {
// alert(listItems[i].textContent);
//}
var listItems = document.getElementById('priceListBox').getElementsByTagName('li'), myArray = map(listItems, getText);
function map(arraylike, fn) {
var ret = [], i = -1, len = arraylike.length;
while (++i < len) ret[i] = fn(arraylike[i]);
return ret;
}
function gettext(node) {
if (node.nodetype === 3) return node.data;
var txt = '';
if (node = node.firstchild) do {
txt += gettext(node);
} while (node = node.nextsibling);
$('#PriceValues').val(txt); // Jquery attempt
document.getelementbyid("PriceValues").value = txt; // js attempt
}
}
I would like to know:
What is the best way of achieving this?
What is the quickest way of achieving this?
Why is the current attempt not working?
Thank you all for any response, if any question ask and I will do my best to reply correctly to it.
Kind regards.
Perhaps, I'm wrong but, your input hidden, has a "name" attribute, instead of id? So shouldn't you assign an id instead of a name?
So with everyones input and several attempts i have succeeded to get the values in my controller.
#joseatchang, you are totally right, good point! Thank you for pointing that out. #Andreas, you are correct as well, with alerts i can see that it stops running at the "var listItems ..." and then it doesn't run any further. I am not able to make it work neither, i changed the getElementById syntax as well but i can't get the function to work properly but i still want to know what is wrong so if you want to elaborate on that i would appreciate it greatly.
#Scott Rickman, i tried several approaches with .textContent and others but the following worked like a charm (thanks for the splitting tip as well ;)):
This worked by putting it where i add the list items dynamically:
document.getElementById("PriceValues").value += priceValue + ";";
and in my controller:
var a = Request.Form["PriceValues"];
Thank you all for helping me, i really appreciate it!
Have a good week, kind regards!

JQuery & Javascript: Intermittant mis-matching of clicked div and returned div?

Thanks for giving this a look. I'll start with a quick image. Clicking on any of the red-boxed search results seems to return the <div> for the item directly above it.
Here I clicked on 1613 CAROUSEL CIR, but the event returned the id/content for the item representing 1612..
Sometimes it's even weirder, for example, every item following 1420 might point back to 1420. So it's not always a conflict with a <div> and it's immediate neighbor, although that's usually the case.
I've been unable to find any definite pattern in this behavior. Sometimes it's just one or two items in the list; sometimes most of the list is affected, with "a good portion" of results pointing to one particular div.
There's only one true consistency--typically the first several items work as expected, and short lists will be 100% correct. But really long lists (50+) are not necessarily worse than semi-long lists (20+).. :/
The code building the search results iterates over JSON data retrieved by a JQuery $.ajax() call, and this is the relevant code building the visible search results:
if( result.d.length > 0 )
{
var i=0;
for(i; i<result.d.length; i++)
{
// ..there's a bunch of irrelevant code here to set the map bounds..
// ..then I build the HTML using JQuery like this
//
var date = new Date();
var divID = "searchItemDiv" + date.getTime().toString();
var $searchItemDiv = $( "<div id='" + divID + "' class='searchItemDiv'>"+result.d[i].Description+"</div>" );
$searchItemDiv.data('itemData', result.d[i]);
$searchItemDiv.bind('click', onSearchItemClick);
$( "#searchResults" ).append($searchItemDiv);
}
}
While I don't suspect the event handler is the issue, the relevant code there looks like this:
function onSearchItemClick(event)
{
if( event.target.id.toString() !== '' )
{
// I clicked 1613, but event returned DIV with text of "1612"??
//
var item = $('#'+event.target.id.toString()).data('itemData');
alert( event.target.id.toString()+"\n"+
$('#'+event.target.id.toString()).text() );
// ..more irrelevant stuff to show a popup of property data..
}
}
FireFox, Chrome, and IE all demonstrate the same behavior, so it's not browser-specific.
I'm relatively sure this is not the product of a race condition during the render phase, but I'm not comfortable-enough with JavaScript to know that for certain.
I'm pretty baffled by this. FWIW, I'm a former Flex & C# developer and relatively new to JavaScript/JQuery development, so there may be a gotcha related JavaScript contexts and/or JQuery that I'm stepping into.
I would say, instead of binding the click function within a for-loop, just select all of the searchItemDiv's after the for-loop binds the data to them, and register a click function on all of them at once. You don't need a separate line to define variable i, just do it in the for statement. I also wouldn't try to generate random IDs with new Dates, that just seems unnecessary. Registering all click functionality at once will also make your click handler much simpler:
if( result.d.length > 0 )
{
for(var i = 0; i<result.d.length; i++)
{
// ..there's a bunch of irrelevant code here to set the map bounds..
// ..then I build the HTML using JQuery like this
// select the i'th searchItemDiv
$searchItemDiv = $($('.searchItemDiv')[i])
// give it the data
$searchItemDiv.data('itemData', result.d[i]);
$( "#searchResults" ).append($searchItemDiv);
}
// then register all the click handlers at once, very simple
$('.searchItemDiv').bind('click', function() {
var item = $(this);
alert(item.text());
});
}
--EDIT--
also, do the searchItemDivs already exist or are you trying to create them?
if you're trying to create them, you might want this in the for-loop instead:
for(var i = 0; i<result.d.length; i++)
{
// ..there's a bunch of irrelevant code here to set the map bounds..
// ..then I build the HTML using JQuery like this
// create a searchItemDiv
$searchItemDiv = $('<div class="searchItemDiv"></div>')
// give it the data
$searchItemDiv.data('itemData', result.d[i]);
$( "#searchResults" ).append($searchItemDiv);
}
I'm guessing that is what you want to do.
I think your problem depends on your searchItemDiv id.
Using the date doesn't ensure ids are unique so when you retrieve the object by id it will return an element (probably the first) with the same id.
Make sure to assign unique id on your elements.

Need performance improvement

I am trying out CasperJS. I am trying to create a web scraper . I need to scrape all pages of site(s) and get data in less than 5 seconds(each page).
For this I will have to crawl through all similar pages. Go to appropriate content div and get data from there.
So If the site has say 1000 pages. I need to complete whole operation as quickly as possible. I can not control N/w latency, page size etc parameter. All I can control is parsing mechanism. So I want it to be as fast as possible. If there is even small improvement, then it will extrapolate as the number of URLs
I am trying to parse child elements and creating CSS paths.
I need to make sure parsing does not take long time.
I hear standard java-script is more efficient in terms of performance than JQuery.
Hence, I need inputs.
What will be the standard JS equivalent of following JQuery code, which performance efficient in terms of parsing.
function() {
var TAG_CSS_PATH = 'div#buttons ul li.tab';
var selectOptions = $(TAG_CSS_PATH);
var results = [],i=0;
selectOptions.each(function(index,value) {
index=index+1;
results.push(TAG_CSS_PATH+':nth-of-type('+index+')');
});
return results
}
If anybody can provide any other suggestions, I will appreciate it.
This should do it:
function() {
var TAG_CSS_PATH = 'div#buttons ul li.tab',
selectOptions = document.querySelectorAll(TAG_CSS_PATH),
results = [],
l = selectOptions.length + 1;
for(var i = 1; i < l; i++){
results.push(TAG_CSS_PATH+':nth-of-type('+i+')');
}
return results;
}
The jQuery part is the $selector, and the $each. These can be replaced as follows.
function() {
var TAG_CSS_PATH = '#buttons ul li.tab',
selectOptions = document.querySelectorAll(TAG_CSS_PATH),
results = [];
for( var i = 1, ln = selectOptions.length + 1; i < ln; i++ ) {
results.push(TAG_CSS_PATH+':nth-of-type('+ i +')');
}
return results;
}
Since you are storing selectors, it seems still really inefficient to me (usage of nth-of-type are expensive selectors). Selectors are read from right to left.
CSS/selector optimisation
Note,
the div#buttons seems redundant. If you use CSS properly, you will have only exactly one element that matches id='buttons'. Thus, with proper use of IDs, you should be able to remove the div in the selector.
Further, if all your .tabs are li, then you can remove the li, too. If all your li.tabs are inside ul, you can remove the ul too.

How to remove duplicate ids from within a div, but keeping the original

Disclaimer: I am fully aware that the id attribute is for unique IDs. In my case, when the ajax request takes longer than usual it can glitch, causing two same chat messages. I am also aware that there are similar questions out there like this, but I have been unable to find one that solves my issue.
This is what I want to do:
Are there any duplicate IDs inside the div chat_log?
What are they?
Delete all the duplicates
Making sure that the original one is still there.
I've tried using the following code:
$('[id]').each(function () {
var ids = $('[id=' + this.id + ']');
if (ids.length > 1 && ids[0] == this) {
$(ids[1]).remove();
}
});
But I'm not sure how I can adapt that method to my situation, nor am I sure if it would be possible.
How can you ensure that something is unique? Let's say you have a bunch of vegetables (cucumbers, turnips, pizzas etc.) You want to ensure colour uniqueness, making sure that any colour only appears once. How'd you do it?
What I'd do is make a list. I'd go through every vegetable, and inspect its colour. If the colour is already on the list, we'll remove that vegetable from the bunch. Otherwise, we leave it as-is and add its colour to our list.
Once that logic is understood, all we need is to convert it to code! What a fantastically trivial thing to do (on paper, of course.)
//assumes $elem is the element you're deleting duplicates in
//create the ids list we'll check against
var ids = {};
//go over each element
var children = $elem.children();
for ( var i = 0, len = children.length; i < len; i++ ) {
var id = children[ i ].id;
//was this id previously seen?
if ( ids.hasOwnProperty(id) ) {
$( children[i] ).remove();
}
//a brand new id was discovered!
else {
ids[ id ] = true;
}
}
//done!
This is the very simple, plain logic version. You can make much fancier ways with some weird sizzle selectors, but this should get you started.
Demo (without jquery): http://tinkerbin.com/qGJpPsAQ
Your code should work but it only removes the second element that has the same ID, try this:
$('[id]').each(function() {
var $ids = $('[id=' + this.id + ']');
if ($ids.length > 1) {
$ids.not(':first').remove();
}
});
http://jsfiddle.net/3WUwZ/

In jQuery, how to efficiently add lots of elements?

I currently have a sketch for a truthtable generator. While it works fine, it is rather slow. Each combination of boolean values I have added to a <table> using jQuery. For each value, a <td> element is created by jQuery and then added to the <table>. Moreover, I'm using jQuery UI for a nice looking buttonset instead of radio buttons.
In my posted code extract, table is an array containing each boolean combination. Perhaps my code is a little inscrutable but what it basically comes down to is that with 4 boolean variables (16 possibilities), 96 <td> elements are created with classes added and data attributes set. In the second part, three groups of three radio buttons are created and converted into a jQuery UI buttonset.
Using a timer I figured out that it takes approximately 0.4 seconds before everything is filled up. Not that big of a deal, but it is certainly noticeable and does not have a positive effect on the user as each time he enters a different boolean formula it takes half a second to load.
$table = $('#table');
$.each(table, function(k, v) {
$tr = $('<tr>').addClass('res').data('number', k);
$.each(v[0], function(k2, v2) {
$td = $('<td>').text(v2).addClass(v2 ? 'green notresult' : 'red notresult');
for(var i = 0; i < 4; i++) {
$td.data(i, i === k2);
}
$tr.append($td);
});
$tr.append($('<td>').addClass('spacing'));
$table.append(
$tr.append(
$('<td>').text(v[1]).addClass(v[1] ? 'green result' : 'red result')
)
);
});
// ... here is some code that's not slowing down
$radiobuttonsdiv = $('#radiobuttonsdiv');
for(var i = 0; i < 4; i++) {
var $radiobase = $('<input>').attr('type', 'radio')
.attr('name', 'a'+i)
.click(handleChange);
// .label() is a custom function of mine which adds a label to a radio button
var $radioboth = $radiobase.clone().val('both').label();
var $radiotrue = $radiobase.clone().val('true').label();
var $radiofalse = $radiobase.clone().val('false').label();
var $td1 = $('<td>').addClass('varname').html(i);
var $td2 = $('<td>').attr('id', i);
$td2.append($radioboth, $radiotrue, $radiofalse).buttonset();
var $tr = $('<tr>').append($td1, $td2);
$radiobuttonsdiv.append($tr);
}
My questions are:
How could table-filling using jQuery be optimized? Or is a table perhaps not the best solution in this scenario?
Is it perhaps possible to suspend drawing, since that might be slowing everything down?
Try to avoid using .append in a loop, especially if you're adding a lot of elements. This is always a performance killer.
A better option is to build up a string with the markup and do a single (or as few as possible) .append when your loop is finished.
I see that you're using .data, which makes things a bit more complicated, but another option is to use the metadata plugin to attach structured markup to existing tags.
To defer rendering, you could try creating a new table without adding it to the DOM like:
var myDisconnectedTable = $('<table></table>')
Then adding your rows to that table:
myDisconnectedTable.append(...)
Then append your table to the div you want it in:
$('#idOfMyDiv').append(myDisconnectedTable)
I don't know that it will help, but it's worth a shot.

Categories

Resources