jQuery .size() function doesn´t work with a variable - javascript

At many points in my code I need to know how many .page classes are used.
To know this I use $(".page").size()
I want to save this information into a variable.
So I wrote this:
var vari = {
*more variables*
totalPageCount : $(".page").size()
};
The Problem is that vari.totalPageCount always gives 0 back.
With console.log() I get this:
console.log($(".page").size()); // Return 8
console.log(vari.totalPageCount); // Return 0
Edit:
Here is a example how i use it.
JS:
var vari = {
currentPage : 0,
pageAnimations : 0,
animationList : ".fade-in, .fade-out",
totalPageCount : $(".page").size(),
};
var footer = {
html : function(){
var html;
var date = this.date();
for(var i=0; i<vari.totalPageCount; i++){
html = '<span class="pageNumber" id="pageNumber">Folie:'+i+' • '+vari.custom["companyName"]+' • '+date+'</span>';
$("#normalPage"+i).append(html);
}
return;
}
};
HTML:
<body class="presWrapper">
<div class="pageWrapper">
<div class="page startPage" id="startPage">
<h2 class="mainTitle">Lorem</h2>
<h4 class="subTitle">Ipsum</h4>
</div>
</div>
<div class="pageWrapper">
<div class="page normalPage" id="normalPage1">
<div class="content">
<p class="fade-in">HELLO WORLD</p>
</div>
</div>
</div>
<div class="pageWrapper">
<div class="page endPage" id="endPage">
<div class="content">
<p class="fade-out">HELLO SATURN</p>
<p class="fade-out">HELLO WORLD</p>
<p class="fade-in">HELLO WORLD</p>
<p>pTag</p>
</div>
</div>
</div>
</body>
Any suggestions to solve this problem?

vari.totalPageCount Gets evaluated only when it is declared.
As a result it will only have the value of $(".page").size() when it is first run.
Unless you are waiting on document ready the children of .page have not yet been added and it has length 0.
When you later call the console and execute the selector again - you get the true count in the console message - but the stored value has already been calculated as 0 within vari.
length() and size() are equivalent functions in jquery but size has been deprecated so length is the appropriate function to call. But in either case - its likely you are just evaluating the length too early when the vari object is constructed for it to have a meaningful value.
Does the following give you the wrong value for the property:
$(document).ready(function () {
var vari = {totalPageCount: $('.page').length};
console.log(vari.totalPageCount);
});
Relevant documentation

The .size() method is deprecated as of jQuery 1.8.
Use length property instead:
var vari = {
*more variables*
totalPageCount : $(".page").length;
};
Also, make sure you are using this code at the bottom of the script or inside a document ready handler. You won't get accurate information if you try to get it before DOM has been fully setup.

This will increment count for every element with having the page class
var count = 0;
$('.page').each(function() {
count++;
});
var vari = {
totalPageCount: count
};
Working jsFiddle

Related

Combine $ and _ to pluck by data values?

I have a list of jquery elements with a data attribute.
Now I want to get a list of these data attributes.
As the data-attribute is some kind of an object property, I thought this might work with underscores pluck method.
Is this even possible?
See this short example:
var divs = $("div");
// now do something
// expected result: [1, 2, 3]
<script src="https://cdnjs.com/libraries/underscore.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div data-foo="1">a</div>
<div data-foo="2">b</div>
<div data-foo="3">c</div>
<div>x</div>
Solution
Based on #romeo-sierra this is the way I wrote it down (as I already have jquery objects). Underscores pluck is superfluous
var foos = $("div").map(function() {
return $(this).data("foo");
}).toArray();
console.log(foos);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div data-foo="1">a</div>
<div data-foo="2">b</div>
<div data-foo="3">c</div>
<div>x</div>
Vanilla JS can accomplish this just fine, no jQuery nor any other library needed:
const foos = [...document.querySelectorAll('[data-foo]')]
.map(elm => elm.dataset.foo);
console.log(foos);
<div data-foo="1">a</div>
<div data-foo="2">b</div>
<div data-foo="3">c</div>
<div>x</div>
ES5 version:
var foos = Array.prototype.map.call(document.querySelectorAll('[data-foo]'), function(elm) {
return elm.dataset.foo;
});
console.log(foos);
<div data-foo="1">a</div>
<div data-foo="2">b</div>
<div data-foo="3">c</div>
<div>x</div>
How about the following, that uses pure jQuery? (since you already are using it)
var arr = [];
$('div[data-foo]').each(function(){
arr.push($(this).data("foo")); // should return the value
});
console.log(arr);
Check this fiddle out.
You definitely have to lookup for a specific data attribute.
You can't just drain the whole page for elements data attribute and obtain a complete list like that.
But if you know what you look for...
See below
var attribute = "foormidable";
$("*").each(function(){
var match = $(this).attr("data-"+attribute);
if(typeof(match)!="undefined"){
console.log(match);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div data-foorm="1">a</div>
<div data-foormidable="2">b</div>
<div data-foolahlayouuu="3">c</div>
<div>x</div>
OR using .data()
var attribute = "foormidable";
$("*").each(function(){
var match = $(this).data(attribute);
if(typeof(match)!="undefined"){
console.log(match);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div data-foorm="1">a</div>
<div data-foormidable="2">b</div>
<div data-foolahlayouuu="3">c</div>
<div>x</div>
That last one will get the value of THE OBJECT... Be it dynamic via JS code.
That is real different from the on load markup attribute value.
;)

jQuery Not Rearranging Elements on my Django Page

I'm trying to add 2 sort options to a web page. Currently, when I click the respective links (.alpha and .finish), I see an animation on the screen and can tell that the names are moving, but then the output remains the same. Below is the jQuery script I'm working with off of this JSFiddle that I found in a google search.
var $divs = $('div.col-xs-3');
$('.alpha').on('click', function () {
var alphabeticallyOrderedDivs = $divs.sort(function (a, b) {
return $(a).attr('data-name') > $(b).attr('data-name');
});
$('.people').html(alphabeticallyOrderedDivs);
});
$('.finish').on('click', function () {
var numericallyOrderedDivs = $divs.sort(function (a, b) {
return $(a).attr('id') < $(b).attr('id');
});
$('.people').html(numericallyOrderedDivs);
});
I am using Django to display the page and currently have an order_by to correctly order each div alphabetically. Is this affecting it?
Three things:
jQuery doesn't officially have a sort function, so don't rely on it.
The sort function it does have (unofficially) it gets from Array.prototype. We'll use that one directly. The way that sort function's callback works, it's expected to return a number, not a boolean: A negative number if the first argument should appear before the second, 0 if they're equal for sorting purposes, and greater than zero if the second should appear before the first.
Officially, html doesn't accept either a jQuery object or an array (just strings and functions), so let's use empty().append(...) instead:
So to fix the code in your question, first we use get to get a true array from the jQuery set, and then we use localeCompare to correctly compare the names:
var $divs = $('div.col-xs-3');
$('.alpha').on('click', function () {
var alphabeticallyOrderedDivs = $divs.get().sort(function (a, b) {
// Note -----------------------------^^^^^^
return $(a).attr('data-name').localeCompare($(b).attr('data-name'));
// Note -------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
});
$('.people').empty().append(alphabeticallyOrderedDivs);
// Note -----^^^^^^^^^^^^^^
});
<input type="button" class="alpha" value="Alpha">
<div class="people">
<div class="col-xs-3" data-name="q">q</div>
<div class="col-xs-3" data-name="p">p</div>
<div class="col-xs-3" data-name="j">j</div>
<div class="col-xs-3" data-name="e">e</div>
<div class="col-xs-3" data-name="t">t</div>
<div class="col-xs-3" data-name="d">e</div>
<div class="col-xs-3" data-name="a">a</div>
<div class="col-xs-3" data-name="q">q</div>
<div class="col-xs-3" data-name="r">r</div>
<div class="col-xs-3" data-name="x">x</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

querySelectorAll is not a function

I'm trying to find all oferts in the var articleFirst, but the return message in the console says that "querySelectorAll" is not a function. Why I do get that error?
This is my HTML:
<article class="first">
<div class="feature parts">
<div class="oferts">
<div class="heart icons"></div>
<h1>Build with passion</h1>
</div>
</div>
</article>
This is my JavaScript:
var articleFirst = document.querySelectorAll("article.first");
var oferts = articleFirst.querySelectorAll(".oferts");
Error:
Uncaught TypeError: articleFirst.querySelectorAll is not a function
Try do do this:
var articleFirst = document.querySelectorAll("article.first");
console.log(articleFirst)
var oferts = articleFirst[0].querySelectorAll(".oferts");
console.log(oferts)
With console you can see what is happening.
Or just do this:
document.querySelectorAll("article.first .oferts");
querySelectorAll is a method found on Element and Document nodes in the DOM.
You are trying to call it on the return value of a call to querySelectorAll which returns a Node List (which is an array like object). You would need to loop over the Node List and call querySelector all on each node in it in turn.
Alternatively, just use a descendant combinator in your initial call to it.
var oferts = document.querySelectorAll("article.first .oferts");
You need to use document.querySelector instead of document.querySelectorAll because the next query depends on a single HTMLElement but document.querySelectorAll returns a NodeList.
document.addEventListener('DOMContentLoaded', TestCtrl);
function TestCtrl() {
var firstArticle = document.querySelector('article.first');
console.log('oferts', firstArticle.querySelectorAll('.oferts'));
}
<article class="first">
<div class="feature parts">
<div class="oferts">
<div class="heart icons"></div>
<h1>Build with passion</h1>
</div>
</div>
</article>
A little verbose but you could try qselectorAll('article') then turn that nodeList into an array and pick the first index.. so something like:
let articleList = querySelectorAll('article'); // makes a NodeList of all article tags on the webpage
let article = Array.from(articleList);
article[0];

Generate a list in javascript and add it to a div in html

I have a javascript function which gets some values from ajax. From javascript I add that values to a div whose display is by default none. In my function from ajax i also gets an array of values. My task is to make a list on html inside my div based on the array values.
Can anyone help me to do this..
Javascript function:
function showpopup(id)
{
var advid=id;
$.ajax
({
type:"post",
url:"ajax_getadv.php?function=getadv",
data:{id:advid},
cache:false,
success:function(data){
var values=data;
var myarray=values.split("/");
var name=myarray[0];
var email=myarray[1];
var country=myarray[2];
var web=myarray[3];
var advid=myarray[4];
var count=myarray[5];
var val=myarray[6]
var mytitle=val.split(",");
document.getElementById("advname").innerHTML = name;
document.getElementById("advid").innerHTML = advid;
document.getElementById("email1").innerHTML = email;
if(country!="")
{
document.getElementById("country").innerHTML = country;
}
else
{
document.getElementById("country").innerHTML = "Not Available";
}
if(web!="")
{
document.getElementById("website").innerHTML = web;
}
else
{
document.getElementById("website").innerHTML = "Not Available";
}
var generateHere = document.getElementById("newlist");
var mycount=mytitle.length;
alert(mycount);
for( var i = 0 ; i < mycount ; i++)
{
generateHere.innerHTML = '<div class="someclass"><ul><li>My Text</li></ul></div>';
}
}
});
document.getElementById('box-config-modal1').style.display='block';
}
Here mytitle is the array which i want to display as list. I've put a for loop to create a list in the div. I have to show mytitle rather than My text.
HTML div:
<!--SHOW MODAL 1-->
<div id="box-config-modal1" class="modal hide fade in" style="display: none;">
<div class="box" id="box-details">
<h4 class="box-header round-top">Details</h4>
<div class="box-container-toggle" style="padding-left:20px;padding-right:20px;">
<div class="box-content" >
<form name="popup" id="popup" >
<fieldset>
<button class="close" data-dismiss="modal"></button>
<h3>User Details</h3>
<div class="control-group">
<div class="controls"> <label class="control-label" for="typeahead" style="width:100px;float:left;" >Name </label><label id="advname" style="padding-left:150px;"></label></div>
</div>
<div class="control-group">
<div class="controls"><label class="control-label" for="typeahead" style="width:100px;float:left;" >ID </label><label id="advid" style="padding-left:150px;"></label></div>
</div>
<div class="control-group">
<div class="controls"><label class="control-label" for="typeahead" style="width:100px;float:left;">Email </label><label id="email1" style="padding-left:150px;"></label></div>
</div>
<div class="control-group">
<div class="controls"><label class="control-label" for="typeahead" style="width:100px;float:left;">Country </label><label id="country" style="padding-left:150px;"></label ></div>
</div>
<div class="control-group">
<div class="controls"><label class="control-label" for="typeahead" style="width:100px;float:left;">Website </label><label id="website" style="padding-left:150px;"></label ></div>
</div>
<div class="" id="newlist">
</div>
<div class="modal-footer">
Exit
</div>
</fieldset>
</form>
</div>
</div>
</div>
It is in this div i want to create a list. I've added a new div with id newlist
There are a couple of options becoming available in w3 drafts and standards these days and into the future.. webcomponents and shadowDOM specifically..
until those become widely adopted standards..
You can look to building DOM elements in Javascript HtmlDOMElement and than attach it to the document body in 1 assignment to the actual DOM.
function showpopup(id)
{
var advid=id,
options = {
type:"post",
url:"ajax_getadv.php?function=getadv",
data:{id:advid},
cache:false,
success: OnSuccess
};
$.ajax(options);
}
Helper Function
function createControlGroup(options) {
var options = options || {};
options.id = options.id || "ukn-"+Date.now();
options.for = options.for || options.id;
options.displayText = options.displayText || "NotSet";
options.displayValue = options.displayValue || "Unknown";
var cntrlGrpElm = document.createElement("div"),
cntrlElms = document.createElement("div"),
cntrlLabel1 = document.createElement("label"),
cntrlLabel2 = document.createElement("label");
var cntrlGrpElmClass=document.createAttribute("class"),
cntrlElmsClass=document.createAttribute("class"),
cntrlLabel1Class=document.createAttribute("class");
cntrlGrpElmClassAttr.nodeValue="control-group";
cntrlGrpElm.attributes.setNamedItem(cntrlGrpElmClassAttr);
cntrlElmsClass.nodeValue="controls";
cntrlElms.attributes.setNamedItem(cntrlElmsClass);
cntrlLabel1Class.nodeValue="control-label";
cntrlLabel1.attributes.setNamedItem(cntrlLabel1Class);
var cntrlLabel2Id=document.createAttribute("id");
cntrlLabel2Id.nodeValue=options.id;
cntrlLabel2.attributes.setNamedItem(cntrlLabel2Id);
var cntrlLabel1For=document.createAttribute("for");
cntrlLabel1For=options.for;
cntrlLabel1.attributes.setNamedItem(cntrlLabel1For);
var cntrlLabel1Text = document.createTextNode(options.displayText),
cntrlLabel2Text = document.createTextNode(options.displayValue);
cntrlLabel1.appendChild(cntrlLabel1Text);
cntrlLabel2.appendChild(cntrlLabel2Text);
cntrlElms.appendChild(cntrlLabel1);
cntrlElms.appendChild(cntrlLabel2);
cntrlGrpElm.appendChild(cntrlElms);
return cntrlGrpElm;
}
OnSuccess Callback Function
function OnSuccess(e) {
var values=e.responseText;
var myarray=values.split("/");
var name=myarray[0],
email=myarray[1],
country=myarray[2],
web=myarray[3],
advid=myarray[4],
count=myarray[5],
val=myarray[6];
var mytitle=val.split(",");
var title1=mytitle[0],
title2=mytitle[1],
title3=mytitle[2];
use the helper function to create and return the DOMElement, we're passing an ambiguous object here.
var cntrlGrpElms = document.createElement("fieldset");
var cntrlGrpElmsClass = document.createAttribute("class");
cntrlGrpElmsClass.nodeValue = "contrl-group-list";
cntrlGrpElms.attributes.setNamedItem(cntrlGrpElmsClass);
cntrlGrpElms.appendChild(createControlGroup({"id":"item-1","displayText":"Item 1", "displayValue":"Value of Item 1"}));
cntrlGrpElms.appendChild(createControlGroup({"id":"item-2","displayText":"Item 2", "displayValue":"Value of Item 2"}));
cntrlGrpElms.appendChild(createControlGroup({"id":"item-3","displayText":"Item 3", "displayValue":"Value of Item 3"}));
cntrlGrpElms.appendChild(createControlGroup({"id":"item-4","displayText":"Item 4", "displayValue":"Value of Item 4"}));
This is sample data.. You would, of course, use your data, and structure: I just mimicked the elements with the fieldset tag, excluding the button and div.modal-footer. CSS will pick up on the changes, so I didn't see any point in specifying the styles.
At this point, we tapper this function off by adding the DOMElement (and the children) in the document.body.
document.body.appendChild(cntrlGrpElms);
} /* End of - $.ajax - 'OnSuccess' Callback*/
This should really make the process clearer for you. But I don't know exactly how you intended to structure the list. The HTML structure you provided seems more like a control panel.
Also, I want to explicitly point out that your callback function (which you were defining anonymously in your code sample) was handling the eventArg improperly.. so I'm not sure if that was the underline issue you were having or not. If it was, you aside from the documentation, you should use the browser debugger to investigate these matters... F12 will usually invoke the developer console.. depending on the browser, you'll need to set breakpoints on the source (not html dom window.. the 'sources' or external files).. then you can invoke the 'showpopup(id)' function in the console.. it should pause at the breakpoint.. then you can either use the console to evaluate the 'e' eventArg within the scope of the function.. or you can add the 'e' object to the watch expressions' panel.. this is all standard debugger interfacing.. modern web browsers have sure given us developers a great tool to improve and explore the web with.
the event returned is a jqXHR (XmlHttpRequest).. the documentation on it is here
On a complete side note: It is likely that this jqXHR object will change (or at least these documents) in the near future (extended really)..
there are two newer prevalent dataTypes supported by XHR2 now, blob and arraybuffer.. 'bson' (Binary json) is, I think, considered a blob type, but it really has sort of a mixed medium, string and byte data.. so I'm not entirely sure about it.. I know Newtonsoft.json supports it with serialization on the .Net framework already.
You can find more information about XHR2 (which is XHR Level 1 now) and blob, arraybuffer support by googling it..
The Jan 2012 w3.org documentation is here. (when it was still level-2.. and stayed at for pretty darn long)
The newest release spec was in Jan 2014 w3.org: here
But XHR is a Living Standard, and a 'snapshot' of the most recent spec can be found here
To write inside an HTML tag, simply use innerHTML as shown below:
function divCall()
{
document.getElementById('myDiv').innerHTML += 'your newly added text';
}
//make sure your div id is myDiv

Get next textarea outside div without id

I need to get the next textarea, but I'm not being able with next or even find.
Sample code HTML:
<div>
<div class="guides_chapters_button" onclick="surroundtest('[center]', '[/center]');">Center</div>
<div class="guides_chapters_button" style="text-decoration: underline;" onclick="surround('[u]', '[/u]');">u</div>
</div>
<textarea class="guides_chapters_textarea" id="textareamatch" name="matchupm" rows="7" cols="25"></textarea>
JS:
window.surround = function surround(text2,text3){
$("#textareamatch").surroundSelectedText(text2, text3);
}
function surroundtest(text2,text3){
var c = $(this).parent().next('textarea');
c.surroundSelectedText(text2, text3);
}
JS FIDDLE: http://jsfiddle.net/qmpY8/1/
What I need working is surroundtest, the other is an example working but using the id. I would love to replace that one because Im usinc cloned objects.
The this statement in surroundtest applies to the window object and not the element. What you should do is to change the function definition as so:
function surroundtest(element, text2,text3){
var c = $(element).parent().next('textarea');
...
}
And the HTML accordingly:
<div class="guides_chapters_button" onclick="surroundtest(this, '[center]', '[/center]');">Center</div>
If this is the HTML you are going with, then .closest() can also be used to get the textarea element.Like below:
var c = $(element).parent().closest('textarea');

Categories