Jquery Evolution from simple plain javascript - javascript

i have been using jquery for a while now but only thing i know about jquery is probably a dozen of functions that get my job done. but i want to understand how jquery evolved from simpl plain javascript i.e how
$("#xyz").val();
is converted to
document.getElementById('xyz').value;
i have searched for my answer on the web but most of the writers are happy to show how you can hook on to different DOM elements with jquery, selector details etc. but nothing can be found about how actually the transition was made. can anyone refer me to some tutorial where i can get my required material?
thanks

jQuery is not a compiler. jQuery does not get compiled into javascript.
.val is a method of an object. The jQuery object.
Specifically it is
function (value) {
if (!arguments.length) {
var elem = this[0];
if (elem) {
if (jQuery.nodeName(elem, "option")) {
// attributes.value is undefined in Blackberry 4.7 but
// uses .value. See #6932
var val = elem.attributes.value;
return !val || val.specified ? elem.value : elem.text;
}
// We need to handle select boxes special
if (jQuery.nodeName(elem, "select")) {
var index = elem.selectedIndex,
values = [],
options = elem.options,
one = elem.type === "select-one";
// Nothing was selected
if (index < 0) {
return null;
}
// Loop through all the selected options
for (var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++) {
var option = options[i];
// Don't return options that are disabled or in a disabled optgroup
if (option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && (!option.parentNode.disabled || !jQuery.nodeName(option.parentNode, "optgroup"))) {
// Get the specific value for the option
value = jQuery(option).val();
// We don't need an array for one selects
if (one) {
return value;
}
// Multi-Selects return an array
values.push(value);
}
}
return values;
}
// Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
if (rradiocheck.test(elem.type) && !jQuery.support.checkOn) {
return elem.getAttribute("value") === null ? "on" : elem.value;
}
// Everything else, we just grab the value
return (elem.value || "").replace(rreturn, "");
}
return undefined;
}
var isFunction = jQuery.isFunction(value);
return this.each(function (i) {
var self = jQuery(this),
val = value;
if (this.nodeType !== 1) {
return;
}
if (isFunction) {
val = value.call(this, i, self.val());
}
// Treat null/undefined as ""; convert numbers to string
if (val == null) {
val = "";
} else if (typeof val === "number") {
val += "";
} else if (jQuery.isArray(val)) {
val = jQuery.map(val, function (value) {
return value == null ? "" : value + "";
});
}
if (jQuery.isArray(val) && rradiocheck.test(this.type)) {
this.checked = jQuery.inArray(self.val(), val) >= 0;
} else if (jQuery.nodeName(this, "select")) {
var values = jQuery.makeArray(val);
jQuery("option", this).each(function () {
this.selected = jQuery.inArray(jQuery(this).val(), values) >= 0;
});
if (!values.length) {
this.selectedIndex = -1;
}
} else {
this.value = val;
}
});
}
If we break the above wall down we can get
function (value) {
if (arguments.length === 0) {
return (this[0].value || "")
}
this.value = val;
return this;
}
Of course jQuery has a lot more code to deal with various edge cases and special things.
In essence jQuery takes a selector. finds the elements. Stores them internally then returns you an object.
This object has all kinds of methods that allow you to mutate the underlying dom objects stored internally. .val is one of them.

There are plenty of articles on how jQuery works (there are screencasts too).
jQuery, as you've noticed, is basically a bunch of methods operating on an array of elements. It is also intended to normalize browser differences under the hood.
Take the basic usage $("#xyz").val();
I can even tell you what jQuery is doing behind the scenes, but I don't think you really want to know. :)
var jQuery = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
return new jQuery.fn.init( selector, context );
},
// ...
jQuery.fn = jQuery.prototype = {
init: function( selector, context ) {
// ...
},
// ...
};
// Give the init function the jQuery prototype for later instantiation
jQuery.fn.init.prototype = jQuery.fn;
So basically $(selector) means newjQuery.fn.init(selector), it's just a shortcut for easier typing (and also to prevent the "bug" where fogetting new binds this to the global object, instead of the current instance).
Also, the so-called plug-ins added as jQuery.fn.ext are mapped to jQuery.fn.init.prototype as you can see in the last line, it's another shortcut. So when you call $(selector) everything that is added to jQuery.fn will also be on jQuery.fn.init.prototype and so the new instance will have those methods as $(selector).ext(...).
// as you use it today
jQuery.fn.plugin = function ( ... ) { ... }
$(selector).plugin( ... )
// as it would be without shortcuts
jQuery.fn.init.prototype.plugin = function ( ... ) { ... }
(new jQuery.fn.init(selector)).plugin( ... )

Related

Exists (-like) function for jQuery? [duplicate]

How can I check the existence of an element in jQuery?
The current code that I have is this:
if ($(selector).length > 0) {
// Do something
}
Is there a more elegant way to approach this? Perhaps a plugin or a function?
In JavaScript, everything is 'truthy' or 'falsy', and for numbers 0 means false, everything else true. So you could write:
if ($(selector).length)
You don't need that >0 part.
Yes!
jQuery.fn.exists = function(){ return this.length > 0; }
if ($(selector).exists()) {
// Do something
}
This is in response to: Herding Code podcast with Jeff Atwood
If you used
jQuery.fn.exists = function(){return ($(this).length > 0);}
if ($(selector).exists()) { }
you would imply that chaining was possible when it is not.
This would be better:
jQuery.exists = function(selector) {return ($(selector).length > 0);}
if ($.exists(selector)) { }
Alternatively, from the FAQ:
if ( $('#myDiv').length ) { /* Do something */ }
You could also use the following. If there are no values in the jQuery object array then getting the first item in the array would return undefined.
if ( $('#myDiv')[0] ) { /* Do something */ }
You can use this:
// if element exists
if($('selector').length){ /* do something */ }
// if element does not exist
if(!$('selector').length){ /* do something */ }
The fastest and most semantically self explaining way to check for existence is actually by using plain JavaScript:
if (document.getElementById('element_id')) {
// Do something
}
It is a bit longer to write than the jQuery length alternative, but executes faster since it is a native JS method.
And it is better than the alternative of writing your own jQuery function. That alternative is slower, for the reasons #snover stated. But it would also give other programmers the impression that the exists() function is something inherent to jQuery. JavaScript would/should be understood by others editing your code, without increased knowledge debt.
NB: Notice the lack of an '#' before the element_id (since this is plain JS, not jQuery).
You can save a few bytes by writing:
if ($(selector)[0]) { ... }
This works because each jQuery object also masquerades as an array, so we can use the array dereferencing operator to get the first item from the array. It returns undefined if there is no item at the specified index.
You can use:
if ($(selector).is('*')) {
// Do something
}
A little more elegant, perhaps.
This plugin can be used in an if statement like if ($(ele).exist()) { /* DO WORK */ } or using a callback.
Plugin
;;(function($) {
if (!$.exist) {
$.extend({
exist: function() {
var ele, cbmExist, cbmNotExist;
if (arguments.length) {
for (x in arguments) {
switch (typeof arguments[x]) {
case 'function':
if (typeof cbmExist == "undefined") cbmExist = arguments[x];
else cbmNotExist = arguments[x];
break;
case 'object':
if (arguments[x] instanceof jQuery) ele = arguments[x];
else {
var obj = arguments[x];
for (y in obj) {
if (typeof obj[y] == 'function') {
if (typeof cbmExist == "undefined") cbmExist = obj[y];
else cbmNotExist = obj[y];
}
if (typeof obj[y] == 'object' && obj[y] instanceof jQuery) ele = obj[y];
if (typeof obj[y] == 'string') ele = $(obj[y]);
}
}
break;
case 'string':
ele = $(arguments[x]);
break;
}
}
}
if (typeof cbmExist == 'function') {
var exist = ele.length > 0 ? true : false;
if (exist) {
return ele.each(function(i) { cbmExist.apply(this, [exist, ele, i]); });
}
else if (typeof cbmNotExist == 'function') {
cbmNotExist.apply(ele, [exist, ele]);
return ele;
}
else {
if (ele.length <= 1) return ele.length > 0 ? true : false;
else return ele.length;
}
}
else {
if (ele.length <= 1) return ele.length > 0 ? true : false;
else return ele.length;
}
return false;
}
});
$.fn.extend({
exist: function() {
var args = [$(this)];
if (arguments.length) for (x in arguments) args.push(arguments[x]);
return $.exist.apply($, args);
}
});
}
})(jQuery);
jsFiddle
You may specify one or two callbacks. The first one will fire if the element exists, the second one will fire if the element does not exist. However, if you choose to pass only one function, it will only fire when the element exists. Thus, the chain will die if the selected element does not exist. Of course, if it does exist, the first function will fire and the chain will continue.
Keep in mind that using the callback variant helps maintain chainability – the element is returned and you can continue chaining commands as with any other jQuery method!
Example Uses
if ($.exist('#eleID')) { /* DO WORK */ } // param as STRING
if ($.exist($('#eleID'))) { /* DO WORK */ } // param as jQuery OBJECT
if ($('#eleID').exist()) { /* DO WORK */ } // enduced on jQuery OBJECT
$.exist('#eleID', function() { // param is STRING && CALLBACK METHOD
/* DO WORK */
/* This will ONLY fire if the element EXIST */
}, function() { // param is STRING && CALLBACK METHOD
/* DO WORK */
/* This will ONLY fire if the element DOES NOT EXIST */
})
$('#eleID').exist(function() { // enduced on jQuery OBJECT with CALLBACK METHOD
/* DO WORK */
/* This will ONLY fire if the element EXIST */
})
$.exist({ // param is OBJECT containing 2 key|value pairs: element = STRING, callback = METHOD
element: '#eleID',
callback: function() {
/* DO WORK */
/* This will ONLY fire if the element EXIST */
}
})
I see most of the answers here are not accurate as they should be, they check element length, it can be OK in many cases, but not 100%, imagine if number pass to the function instead, so I prototype a function which check all conditions and return the answer as it should be:
$.fn.exists = $.fn.exists || function() {
return !!(this.length && (this[0] instanceof HTMLDocument || this[0] instanceof HTMLElement));
}
This will check both length and type, Now you can check it this way:
$(1980).exists(); //return false
$([1,2,3]).exists(); //return false
$({name: 'stackoverflow', url: 'http://www.stackoverflow.com'}).exists(); //return false
$([{nodeName: 'foo'}]).exists() // returns false
$('div').exists(); //return true
$('.header').exists(); //return true
$(document).exists(); //return true
$('body').exists(); //return true
There's no need for jQuery really. With plain JavaScript it's easier and semantically correct to check for:
if(document.getElementById("myElement")) {
//Do something...
}
If for any reason you don't want to put an id to the element, you can still use any other JavaScript method designed to access the DOM.
jQuery is really cool, but don't let pure JavaScript fall into oblivion...
You could use this:
jQuery.fn.extend({
exists: function() { return this.length }
});
if($(selector).exists()){/*do something*/}
The reason all of the previous answers require the .length parameter is that they are mostly using jquery's $() selector which has querySelectorAll behind the curtains (or they are using it directly). This method is rather slow because it needs to parse the entire DOM tree looking for all matches to that selector and populating an array with them.
The ['length'] parameter is not needed or useful and the code will be a lot faster if you directly use document.querySelector(selector) instead, because it returns the first element it matches or null if not found.
function elementIfExists(selector){ //named this way on purpose, see below
return document.querySelector(selector);
}
/* usage: */
var myelement = elementIfExists("#myid") || myfallbackelement;
However this method leaves us with the actual object being returned; which is fine if it isn't going to be saved as variable and used repeatedly (thus keeping the reference around if we forget).
var myel=elementIfExists("#myid");
// now we are using a reference to the element which will linger after removal
myel.getParentNode.removeChild(myel);
console.log(elementIfExists("#myid")); /* null */
console.log(myel); /* giant table lingering around detached from document */
myel=null; /* now it can be garbage collected */
In some cases this may be desired. It can be used in a for loop like this:
/* locally scoped myel gets garbage collected even with the break; */
for (var myel; myel = elementIfExist(sel); myel.getParentNode.removeChild(myel))
if (myel == myblacklistedel) break;
If you don't actually need the element and want to get/store just a true/false, just double not it !! It works for shoes that come untied, so why knot here?
function elementExists(selector){
return !!document.querySelector(selector);
}
/* usage: */
var hastables = elementExists("table"); /* will be true or false */
if (hastables){
/* insert css style sheet for our pretty tables */
}
setTimeOut(function (){if (hastables && !elementExists("#mytablecss"))
alert("bad table layouts");},3000);
Is $.contains() what you want?
jQuery.contains( container, contained )
The $.contains() method returns true if the DOM element provided by the second argument is a descendant of the DOM element provided by the first argument, whether it is a direct child or nested more deeply. Otherwise, it returns false. Only element nodes are supported; if the second argument is a text or comment node, $.contains() will return false.
Note: The first argument must be a DOM element, not a jQuery object or plain JavaScript object.
You can check element is present or not using length in java script.
If length is greater than zero then element is present if length is zero then
element is not present
// These by Id
if ($("#elementid").length > 0) {
// Element is Present
} else {
// Element is not Present
}
// These by Class
if ($(".elementClass").length > 0) {
// Element is Present
} else {
// Element is not Present
}
I have found if ($(selector).length) {} to be insufficient. It will silently break your app when selector is an empty object {}.
var $target = $({});
console.log($target, $target.length);
// Console output:
// -------------------------------------
// [▼ Object ] 1
// ► __proto__: Object
My only suggestion is to perform an additional check for {}.
if ($.isEmptyObject(selector) || !$(selector).length) {
throw new Error('Unable to work with the given selector.');
}
I'm still looking for a better solution though as this one is a bit heavy.
Edit: WARNING! This doesn't work in IE when selector is a string.
$.isEmptyObject('hello') // FALSE in Chrome and TRUE in IE
Checking for existence of an element is documented neatly in the official jQuery website itself!
Use the .length property of the jQuery collection returned by your
selector:
if ($("#myDiv").length) {
$("#myDiv").show();
}
Note that it isn't always necessary to test whether an element exists.
The following code will show the element if it exists, and do nothing
(with no errors) if it does not:
$("#myDiv").show();
this is very similar to all of the answers, but why not use the ! operator twice so you can get a boolean:
jQuery.fn.exists = function(){return !!this.length};
if ($(selector).exists()) {
// the element exists, now what?...
}
No need for jQuery (basic solution)
if(document.querySelector('.a-class')) {
// do something
}
Much more performant option below (notice the lack of a dot before a-class).
if(document.getElementsByClassName('a-class')[0]) {
// do something
}
querySelector uses a proper matching engine like $() (sizzle) in jQuery and uses more computing power but in 99% of cases will do just fine. The second option is more explicit and tells the code exactly what to do. It's much faster according to JSBench https://jsbench.me/65l2up3t8i
$(selector).length && //Do something
Try testing for DOM element
if (!!$(selector)[0]) // do stuff
Inspired by hiway's answer I came up with the following:
$.fn.exists = function() {
return $.contains( document.documentElement, this[0] );
}
jQuery.contains takes two DOM elements and checks whether the first one contains the second one.
Using document.documentElement as the first argument fulfills the semantics of the exists method when we want to apply it solely to check the existence of an element in the current document.
Below, I've put together a snippet that compares jQuery.exists() against the $(sel)[0] and $(sel).length approaches which both return truthy values for $(4) while $(4).exists() returns false. In the context of checking for existence of an element in the DOM this seems to be the desired result.
$.fn.exists = function() {
return $.contains(document.documentElement, this[0]);
}
var testFuncs = [
function(jq) { return !!jq[0]; },
function(jq) { return !!jq.length; },
function(jq) { return jq.exists(); },
];
var inputs = [
["$()",$()],
["$(4)",$(4)],
["$('#idoexist')",$('#idoexist')],
["$('#idontexist')",$('#idontexist')]
];
for( var i = 0, l = inputs.length, tr, input; i < l; i++ ) {
input = inputs[i][1];
tr = "<tr><td>" + inputs[i][0] + "</td><td>"
+ testFuncs[0](input) + "</td><td>"
+ testFuncs[1](input) + "</td><td>"
+ testFuncs[2](input) + "</td></tr>";
$("table").append(tr);
}
td { border: 1px solid black }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="idoexist">#idoexist</div>
<table style>
<tr>
<td>Input</td><td>!!$(sel)[0]</td><td>!!$(sel).length</td><td>$(sel).exists()</td>
</tr>
</table>
<script>
$.fn.exists = function() {
return $.contains(document.documentElement, this[0]);
}
</script>
I just like to use plain vanilla javascript to do this.
function isExists(selector){
return document.querySelectorAll(selector).length>0;
}
I stumbled upon this question and i'd like to share a snippet of code i currently use:
$.fn.exists = function(callback) {
var self = this;
var wrapper = (function(){
function notExists () {}
notExists.prototype.otherwise = function(fallback){
if (!self.length) {
fallback.call();
}
};
return new notExists;
})();
if(self.length) {
callback.call();
}
return wrapper;
}
And now i can write code like this -
$("#elem").exists(function(){
alert ("it exists");
}).otherwise(function(){
alert ("it doesn't exist");
});
It might seem a lot of code, but when written in CoffeeScript it is quite small:
$.fn.exists = (callback) ->
exists = #length
callback.call() if exists
new class
otherwise: (fallback) ->
fallback.call() if not exists
I had a case where I wanted to see if an object exists inside of another so I added something to the first answer to check for a selector inside the selector..
// Checks if an object exists.
// Usage:
//
// $(selector).exists()
//
// Or:
//
// $(selector).exists(anotherSelector);
jQuery.fn.exists = function(selector) {
return selector ? this.find(selector).length : this.length;
};
How about:
function exists(selector) {
return $(selector).length;
}
if (exists(selector)) {
// do something
}
It's very minimal and saves you having to enclose the selector with $() every time.
I'm using this:
$.fn.ifExists = function(fn) {
if (this.length) {
$(fn(this));
}
};
$("#element").ifExists(
function($this){
$this.addClass('someClass').animate({marginTop:20},function(){alert('ok')});
}
);
Execute the chain only if a jQuery element exist - http://jsfiddle.net/andres_314/vbNM3/2/
$("selector") returns an object which has the length property. If the selector finds any elements, they will be included in the object. So if you check its length you can see if any elements exist. In JavaScript 0 == false, so if you don't get 0 your code will run.
if($("selector").length){
//code in the case
}
Here is my favorite exist method in jQuery
$.fn.exist = function(callback) {
return $(this).each(function () {
var target = $(this);
if (this.length > 0 && typeof callback === 'function') {
callback.call(target);
}
});
};
and other version which supports callback when selector does not exist
$.fn.exist = function(onExist, onNotExist) {
return $(this).each(function() {
var target = $(this);
if (this.length > 0) {
if (typeof onExist === 'function') {
onExist.call(target);
}
} else {
if (typeof onNotExist === 'function') {
onNotExist.call(target);
}
}
});
};
Example:
$('#foo .bar').exist(
function () {
// Stuff when '#foo .bar' exists
},
function () {
// Stuff when '#foo .bar' does not exist
}
);
You don't have to check if it's greater than 0 like $(selector).length > 0, $(selector).length it's enough and an elegant way to check the existence of elements. I don't think that it is worth to write a function only for this, if you want to do more extra things, then yes.
if($(selector).length){
// true if length is not 0
} else {
// false if length is 0
}
Here is the complete example of different situations and way to check if element exists using direct if on jQuery selector may or may not work because it returns array or elements.
var a = null;
var b = []
var c = undefined ;
if(a) { console.log(" a exist")} else { console.log("a doesn't exit")}
// output: a doesn't exit
if(b) { console.log(" b exist")} else { console.log("b doesn't exit")}
// output: b exist
if(c) { console.log(" c exist")} else { console.log("c doesn't exit")}
// output: c doesn't exit
FINAL SOLUTION
if($("#xysyxxs").length){ console.log("xusyxxs exist")} else { console.log("xusyxxs doesnn't exist") }
//output : xusyxxs doesnn't exist
if($(".xysyxxs").length){ console.log("xusyxxs exist")} else { console.log("xusyxxs doesnn't exist") }
//output : xusyxxs doesnn't exist
Demo
console.log("existing id", $('#id-1').length)
console.log("non existing id", $('#id-2').length)
console.log("existing class single instance", $('.cls-1').length)
console.log("existing class multiple instance", $('.cls-2').length)
console.log("non existing class", $('.cls-3').length)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="id-1">
<div class="cls-1 cls-2"></div>
<div class="cls-2"></div>
</div>

shorter version of jquery function

Ok, there is no problem, but i just got curious how to shorten this function.
$('input#sum').blur(function() {
var fieldVal = $(this).val();
$(this).val(formatNumber(fieldVal));
});
I get field value on blur modify it with formatNumber custom function and return. But is see I have 3 selectors there, is there a way to shorten this?
Format number function is:
function formatNumber(input) {
// modify and return input
}
You sure can, by passing a function to val():
$('input#sum').blur(function() {
$(this).val(function(_,v){ return formatNumber(v); });
});
Documentation
val() - function
$('input#sum').blur(function() {
this.value = formatNumber(this.value);
});
//1 selector!
I don't even see why you would need jQuery there. Don't abuse jQuery when you don't actually need it.
Take a look at jQuery's source code at line 7294:
val: function( value ) {
var hooks, ret, isFunction,
elem = this[0];
if ( !arguments.length ) {
if ( elem ) {
hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
return ret;
}
ret = elem.value;
return typeof ret === "string" ?
// handle most common string cases
ret.replace(rreturn, "") :
// handle cases where value is null/undef or number
ret == null ? "" : ret;
}
return;
}
//...
}
If you get rid of the hook part which simply replace newlines into \r\n and ignore the bottom special null case, the only thing left is just ret = elem.value. Now you know that you can safely use this.value instead of $(this).val().
$('input#sum').blur(function() {
$(this).val(formatNumber($(this).val()));
});
Doesn't solve your selectors problem, but it's shorter..
You can directly put formatted value in .val(). And use id selector $('#sum') instead of $('input#sum') directly, but make sure that you have unique id through out the html page.
$('#sum').blur(function() {
$(this).val(formatNumber($(this).val()));
});
You can use normal Javascript and create a formatNumber function extends String (or another type).
// Your function
String.prototype.formatNumber = function () {
// return the modified value of this
return this;
};
$('selector').blur(function() {
this.value = this.value.formatNumber();
});
UPDATED:
Better you can extends the HTMLInputElement and add the function to it.
// Extends the HTMLInputElement
HTMLInputElement.prototype.formatNumber = function(){
// Your function here
this.value = this.value.toFixed(0); // An example
};
$('input').blur(function() {
this.formatNumber(); // 1 line
});

What does $('#id').html(x) do differently to el.innerHTML = x

I'm storing stuff in javascript/DOM and submitting an ajax call. In the success and/or .done function when I do:
$('#results').html(data);
The javascript/DOM model becomes corrupted but when I do:
var el = document.getElementById('results');
el.innerHTML = data;
then everything works as expected. I know there isn't much information here but my question is what else is the jQuery html() doing apart from setting the innerHTML that may be effecting the state of the page.
The main reason to use the html function with a string rather than innerHTML is to prevent memory leaks or inconsistent in memory data : this function removes event handlers or other jQuery data linked to the removed elements.
If data is a string, there is no reason for $('#results').html(data); to "corrupt" your DOM more than by using innerHTML.
In Internet Explorer 9 and earlier tables in the DOM were read-only. That meant that trying to do el.innerHTML = newHTML; would result in an error being thrown if el was a TBODY, TR, etc. The jQuery .html() function handles that case for you by using a fallback method - this.empty().append(value) in the jQuery source - allowing you to use the same code for all of the browsers, regardless of version.
It may be worth taking a look at the code for the method in the jQuery source:
html : function (value) {
return jQuery.access(this, function (value) {
var elem = this[0] || {},
i = 0,
l = this.length;
if (value === undefined) {
return elem.nodeType === 1 ?
elem.innerHTML.replace(rinlinejQuery, "") :
undefined;
}
// See if we can take a shortcut and just use innerHTML
if (typeof value === "string" && !rnoInnerhtml.test(value) &&
(jQuery.support.htmlSerialize || !rnoshimcache.test(value)) &&
(jQuery.support.leadingWhitespace || !rleadingWhitespace.test(value)) &&
!wrapMap[(rtagName.exec(value) || ["", ""])[1].toLowerCase()]) {
value = value.replace(rxhtmlTag, "<$1></$2>");
try {
for (; i < l; i++) {
// Remove element nodes and prevent memory leaks
elem = this[i] || {};
if (elem.nodeType === 1) {
jQuery.cleanData(getAll(elem, false));
elem.innerHTML = value;
}
}
elem = 0;
// If using innerHTML throws an exception, use the fallback method
} catch (e) {}
}
if (elem) {
this.empty().append(value);
}
}, null, value, arguments.length);
}

Alternative to jQuery's .toggle() method that supports eventData?

The jQuery documentation for the .toggle() method states:
The .toggle() method is provided for convenience. It is relatively straightforward to implement the same behavior by hand, and this can be necessary if the assumptions built into .toggle() prove limiting.
The assumptions built into .toggle have proven limiting for my current task, but the documentation doesn't elaborate on how to implement the same behavior. I need to pass eventData to the handler functions provided to toggle(), but it appears that only .bind() will support this, not .toggle().
My first inclination is to use a flag that's global to a single handler function to store the click state. In other words, rather than:
$('a').toggle(function() {
alert('odd number of clicks');
}, function() {
alert('even number of clicks');
});
do this:
var clicks = true;
$('a').click(function() {
if (clicks) {
alert('odd number of clicks');
clicks = false;
} else {
alert('even number of clicks');
clicks = true;
}
});
I haven't tested the latter, but I suspect it would work. Is this the best way to do something like this, or is there a better way that I'm missing?
Seems like a reasonable way to do it... I'd just suggest that you make use of jQuery's data storage utilities rather than introducing an extra variable (which could become a headache if you wanted to keep track of a whole bunch of links). So based of your example:
$('a').click(function() {
var clicks = $(this).data('clicks');
if (clicks) {
alert('odd number of clicks');
} else {
alert('even number of clicks');
}
$(this).data("clicks", !clicks);
});
Here is a plugin that implements an alternative to .toggle(), especially since it has been removed in jQuery 1.9+.
How to use:
The signature for this method is:
.cycle( functions [, callback] [, eventType])
functions [Array]: An array of functions to cycle between
callback [Function]: A function that will be executed on completion of each iteration. It will be passed the current iteration and the output of the current function. Can be used to do something with the return value of each function in the functions array.
eventType [String]: A string specifying the event types to cycle on, eg. "click mouseover"
An example of usage is:
$('a').cycle([
function() {
alert('odd number of clicks');
}, function() {
alert('even number of clicks');
}
]);
I've included a demonstration here.
Plugin code:
(function ($) {
if (!Array.prototype.reduce) {
Array.prototype.reduce = function reduce(accumulator) {
if (this === null || this === undefined) throw new TypeError("Object is null or undefined");
var i = 0,
l = this.length >> 0,
curr;
if (typeof accumulator !== "function") // ES5 : "If IsCallable(callbackfn) is false, throw a TypeError exception."
throw new TypeError("First argument is not callable");
if (arguments.length < 2) {
if (l === 0) throw new TypeError("Array length is 0 and no second argument");
curr = this[0];
i = 1; // start accumulating at the second element
} else curr = arguments[1];
while (i < l) {
if (i in this) curr = accumulator.call(undefined, curr, this[i], i, this);
++i;
}
return curr;
};
}
$.fn.cycle = function () {
var args = Array.prototype.slice.call(arguments).reduce(function (p, c, i, a) {
if (i == 0) {
p.functions = c;
} else if (typeof c == "function") {
p.callback = c;
} else if (typeof c == "string") {
p.events = c;
}
return p;
}, {});
args.events = args.events || "click";
console.log(args);
if (args.functions) {
var currIndex = 0;
function toggler(e) {
e.preventDefault();
var evaluation = args.functions[(currIndex++) % args.functions.length].apply(this);
if (args.callback) {
callback(currIndex, evaluation);
}
return evaluation;
}
return this.on(args.events, toggler);
} else {
//throw "Improper arguments to method \"alternate\"; no array provided";
}
};
})(jQuery);

Is there an "exists" function for jQuery?

How can I check the existence of an element in jQuery?
The current code that I have is this:
if ($(selector).length > 0) {
// Do something
}
Is there a more elegant way to approach this? Perhaps a plugin or a function?
In JavaScript, everything is 'truthy' or 'falsy', and for numbers 0 means false, everything else true. So you could write:
if ($(selector).length)
You don't need that >0 part.
Yes!
jQuery.fn.exists = function(){ return this.length > 0; }
if ($(selector).exists()) {
// Do something
}
This is in response to: Herding Code podcast with Jeff Atwood
If you used
jQuery.fn.exists = function(){return ($(this).length > 0);}
if ($(selector).exists()) { }
you would imply that chaining was possible when it is not.
This would be better:
jQuery.exists = function(selector) {return ($(selector).length > 0);}
if ($.exists(selector)) { }
Alternatively, from the FAQ:
if ( $('#myDiv').length ) { /* Do something */ }
You could also use the following. If there are no values in the jQuery object array then getting the first item in the array would return undefined.
if ( $('#myDiv')[0] ) { /* Do something */ }
You can use this:
// if element exists
if($('selector').length){ /* do something */ }
// if element does not exist
if(!$('selector').length){ /* do something */ }
The fastest and most semantically self explaining way to check for existence is actually by using plain JavaScript:
if (document.getElementById('element_id')) {
// Do something
}
It is a bit longer to write than the jQuery length alternative, but executes faster since it is a native JS method.
And it is better than the alternative of writing your own jQuery function. That alternative is slower, for the reasons #snover stated. But it would also give other programmers the impression that the exists() function is something inherent to jQuery. JavaScript would/should be understood by others editing your code, without increased knowledge debt.
NB: Notice the lack of an '#' before the element_id (since this is plain JS, not jQuery).
You can save a few bytes by writing:
if ($(selector)[0]) { ... }
This works because each jQuery object also masquerades as an array, so we can use the array dereferencing operator to get the first item from the array. It returns undefined if there is no item at the specified index.
You can use:
if ($(selector).is('*')) {
// Do something
}
A little more elegant, perhaps.
This plugin can be used in an if statement like if ($(ele).exist()) { /* DO WORK */ } or using a callback.
Plugin
;;(function($) {
if (!$.exist) {
$.extend({
exist: function() {
var ele, cbmExist, cbmNotExist;
if (arguments.length) {
for (x in arguments) {
switch (typeof arguments[x]) {
case 'function':
if (typeof cbmExist == "undefined") cbmExist = arguments[x];
else cbmNotExist = arguments[x];
break;
case 'object':
if (arguments[x] instanceof jQuery) ele = arguments[x];
else {
var obj = arguments[x];
for (y in obj) {
if (typeof obj[y] == 'function') {
if (typeof cbmExist == "undefined") cbmExist = obj[y];
else cbmNotExist = obj[y];
}
if (typeof obj[y] == 'object' && obj[y] instanceof jQuery) ele = obj[y];
if (typeof obj[y] == 'string') ele = $(obj[y]);
}
}
break;
case 'string':
ele = $(arguments[x]);
break;
}
}
}
if (typeof cbmExist == 'function') {
var exist = ele.length > 0 ? true : false;
if (exist) {
return ele.each(function(i) { cbmExist.apply(this, [exist, ele, i]); });
}
else if (typeof cbmNotExist == 'function') {
cbmNotExist.apply(ele, [exist, ele]);
return ele;
}
else {
if (ele.length <= 1) return ele.length > 0 ? true : false;
else return ele.length;
}
}
else {
if (ele.length <= 1) return ele.length > 0 ? true : false;
else return ele.length;
}
return false;
}
});
$.fn.extend({
exist: function() {
var args = [$(this)];
if (arguments.length) for (x in arguments) args.push(arguments[x]);
return $.exist.apply($, args);
}
});
}
})(jQuery);
jsFiddle
You may specify one or two callbacks. The first one will fire if the element exists, the second one will fire if the element does not exist. However, if you choose to pass only one function, it will only fire when the element exists. Thus, the chain will die if the selected element does not exist. Of course, if it does exist, the first function will fire and the chain will continue.
Keep in mind that using the callback variant helps maintain chainability – the element is returned and you can continue chaining commands as with any other jQuery method!
Example Uses
if ($.exist('#eleID')) { /* DO WORK */ } // param as STRING
if ($.exist($('#eleID'))) { /* DO WORK */ } // param as jQuery OBJECT
if ($('#eleID').exist()) { /* DO WORK */ } // enduced on jQuery OBJECT
$.exist('#eleID', function() { // param is STRING && CALLBACK METHOD
/* DO WORK */
/* This will ONLY fire if the element EXIST */
}, function() { // param is STRING && CALLBACK METHOD
/* DO WORK */
/* This will ONLY fire if the element DOES NOT EXIST */
})
$('#eleID').exist(function() { // enduced on jQuery OBJECT with CALLBACK METHOD
/* DO WORK */
/* This will ONLY fire if the element EXIST */
})
$.exist({ // param is OBJECT containing 2 key|value pairs: element = STRING, callback = METHOD
element: '#eleID',
callback: function() {
/* DO WORK */
/* This will ONLY fire if the element EXIST */
}
})
I see most of the answers here are not accurate as they should be, they check element length, it can be OK in many cases, but not 100%, imagine if number pass to the function instead, so I prototype a function which check all conditions and return the answer as it should be:
$.fn.exists = $.fn.exists || function() {
return !!(this.length && (this[0] instanceof HTMLDocument || this[0] instanceof HTMLElement));
}
This will check both length and type, Now you can check it this way:
$(1980).exists(); //return false
$([1,2,3]).exists(); //return false
$({name: 'stackoverflow', url: 'http://www.stackoverflow.com'}).exists(); //return false
$([{nodeName: 'foo'}]).exists() // returns false
$('div').exists(); //return true
$('.header').exists(); //return true
$(document).exists(); //return true
$('body').exists(); //return true
There's no need for jQuery really. With plain JavaScript it's easier and semantically correct to check for:
if(document.getElementById("myElement")) {
//Do something...
}
If for any reason you don't want to put an id to the element, you can still use any other JavaScript method designed to access the DOM.
jQuery is really cool, but don't let pure JavaScript fall into oblivion...
You could use this:
jQuery.fn.extend({
exists: function() { return this.length }
});
if($(selector).exists()){/*do something*/}
The reason all of the previous answers require the .length parameter is that they are mostly using jquery's $() selector which has querySelectorAll behind the curtains (or they are using it directly). This method is rather slow because it needs to parse the entire DOM tree looking for all matches to that selector and populating an array with them.
The ['length'] parameter is not needed or useful and the code will be a lot faster if you directly use document.querySelector(selector) instead, because it returns the first element it matches or null if not found.
function elementIfExists(selector){ //named this way on purpose, see below
return document.querySelector(selector);
}
/* usage: */
var myelement = elementIfExists("#myid") || myfallbackelement;
However this method leaves us with the actual object being returned; which is fine if it isn't going to be saved as variable and used repeatedly (thus keeping the reference around if we forget).
var myel=elementIfExists("#myid");
// now we are using a reference to the element which will linger after removal
myel.getParentNode.removeChild(myel);
console.log(elementIfExists("#myid")); /* null */
console.log(myel); /* giant table lingering around detached from document */
myel=null; /* now it can be garbage collected */
In some cases this may be desired. It can be used in a for loop like this:
/* locally scoped myel gets garbage collected even with the break; */
for (var myel; myel = elementIfExist(sel); myel.getParentNode.removeChild(myel))
if (myel == myblacklistedel) break;
If you don't actually need the element and want to get/store just a true/false, just double not it !! It works for shoes that come untied, so why knot here?
function elementExists(selector){
return !!document.querySelector(selector);
}
/* usage: */
var hastables = elementExists("table"); /* will be true or false */
if (hastables){
/* insert css style sheet for our pretty tables */
}
setTimeOut(function (){if (hastables && !elementExists("#mytablecss"))
alert("bad table layouts");},3000);
Is $.contains() what you want?
jQuery.contains( container, contained )
The $.contains() method returns true if the DOM element provided by the second argument is a descendant of the DOM element provided by the first argument, whether it is a direct child or nested more deeply. Otherwise, it returns false. Only element nodes are supported; if the second argument is a text or comment node, $.contains() will return false.
Note: The first argument must be a DOM element, not a jQuery object or plain JavaScript object.
You can check element is present or not using length in java script.
If length is greater than zero then element is present if length is zero then
element is not present
// These by Id
if ($("#elementid").length > 0) {
// Element is Present
} else {
// Element is not Present
}
// These by Class
if ($(".elementClass").length > 0) {
// Element is Present
} else {
// Element is not Present
}
I have found if ($(selector).length) {} to be insufficient. It will silently break your app when selector is an empty object {}.
var $target = $({});
console.log($target, $target.length);
// Console output:
// -------------------------------------
// [▼ Object ] 1
// ► __proto__: Object
My only suggestion is to perform an additional check for {}.
if ($.isEmptyObject(selector) || !$(selector).length) {
throw new Error('Unable to work with the given selector.');
}
I'm still looking for a better solution though as this one is a bit heavy.
Edit: WARNING! This doesn't work in IE when selector is a string.
$.isEmptyObject('hello') // FALSE in Chrome and TRUE in IE
Checking for existence of an element is documented neatly in the official jQuery website itself!
Use the .length property of the jQuery collection returned by your
selector:
if ($("#myDiv").length) {
$("#myDiv").show();
}
Note that it isn't always necessary to test whether an element exists.
The following code will show the element if it exists, and do nothing
(with no errors) if it does not:
$("#myDiv").show();
this is very similar to all of the answers, but why not use the ! operator twice so you can get a boolean:
jQuery.fn.exists = function(){return !!this.length};
if ($(selector).exists()) {
// the element exists, now what?...
}
No need for jQuery (basic solution)
if(document.querySelector('.a-class')) {
// do something
}
Much more performant option below (notice the lack of a dot before a-class).
if(document.getElementsByClassName('a-class')[0]) {
// do something
}
querySelector uses a proper matching engine like $() (sizzle) in jQuery and uses more computing power but in 99% of cases will do just fine. The second option is more explicit and tells the code exactly what to do. It's much faster according to JSBench https://jsbench.me/65l2up3t8i
$(selector).length && //Do something
Try testing for DOM element
if (!!$(selector)[0]) // do stuff
Inspired by hiway's answer I came up with the following:
$.fn.exists = function() {
return $.contains( document.documentElement, this[0] );
}
jQuery.contains takes two DOM elements and checks whether the first one contains the second one.
Using document.documentElement as the first argument fulfills the semantics of the exists method when we want to apply it solely to check the existence of an element in the current document.
Below, I've put together a snippet that compares jQuery.exists() against the $(sel)[0] and $(sel).length approaches which both return truthy values for $(4) while $(4).exists() returns false. In the context of checking for existence of an element in the DOM this seems to be the desired result.
$.fn.exists = function() {
return $.contains(document.documentElement, this[0]);
}
var testFuncs = [
function(jq) { return !!jq[0]; },
function(jq) { return !!jq.length; },
function(jq) { return jq.exists(); },
];
var inputs = [
["$()",$()],
["$(4)",$(4)],
["$('#idoexist')",$('#idoexist')],
["$('#idontexist')",$('#idontexist')]
];
for( var i = 0, l = inputs.length, tr, input; i < l; i++ ) {
input = inputs[i][1];
tr = "<tr><td>" + inputs[i][0] + "</td><td>"
+ testFuncs[0](input) + "</td><td>"
+ testFuncs[1](input) + "</td><td>"
+ testFuncs[2](input) + "</td></tr>";
$("table").append(tr);
}
td { border: 1px solid black }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="idoexist">#idoexist</div>
<table style>
<tr>
<td>Input</td><td>!!$(sel)[0]</td><td>!!$(sel).length</td><td>$(sel).exists()</td>
</tr>
</table>
<script>
$.fn.exists = function() {
return $.contains(document.documentElement, this[0]);
}
</script>
I just like to use plain vanilla javascript to do this.
function isExists(selector){
return document.querySelectorAll(selector).length>0;
}
I stumbled upon this question and i'd like to share a snippet of code i currently use:
$.fn.exists = function(callback) {
var self = this;
var wrapper = (function(){
function notExists () {}
notExists.prototype.otherwise = function(fallback){
if (!self.length) {
fallback.call();
}
};
return new notExists;
})();
if(self.length) {
callback.call();
}
return wrapper;
}
And now i can write code like this -
$("#elem").exists(function(){
alert ("it exists");
}).otherwise(function(){
alert ("it doesn't exist");
});
It might seem a lot of code, but when written in CoffeeScript it is quite small:
$.fn.exists = (callback) ->
exists = #length
callback.call() if exists
new class
otherwise: (fallback) ->
fallback.call() if not exists
I had a case where I wanted to see if an object exists inside of another so I added something to the first answer to check for a selector inside the selector..
// Checks if an object exists.
// Usage:
//
// $(selector).exists()
//
// Or:
//
// $(selector).exists(anotherSelector);
jQuery.fn.exists = function(selector) {
return selector ? this.find(selector).length : this.length;
};
How about:
function exists(selector) {
return $(selector).length;
}
if (exists(selector)) {
// do something
}
It's very minimal and saves you having to enclose the selector with $() every time.
I'm using this:
$.fn.ifExists = function(fn) {
if (this.length) {
$(fn(this));
}
};
$("#element").ifExists(
function($this){
$this.addClass('someClass').animate({marginTop:20},function(){alert('ok')});
}
);
Execute the chain only if a jQuery element exist - http://jsfiddle.net/andres_314/vbNM3/2/
$("selector") returns an object which has the length property. If the selector finds any elements, they will be included in the object. So if you check its length you can see if any elements exist. In JavaScript 0 == false, so if you don't get 0 your code will run.
if($("selector").length){
//code in the case
}
Here is my favorite exist method in jQuery
$.fn.exist = function(callback) {
return $(this).each(function () {
var target = $(this);
if (this.length > 0 && typeof callback === 'function') {
callback.call(target);
}
});
};
and other version which supports callback when selector does not exist
$.fn.exist = function(onExist, onNotExist) {
return $(this).each(function() {
var target = $(this);
if (this.length > 0) {
if (typeof onExist === 'function') {
onExist.call(target);
}
} else {
if (typeof onNotExist === 'function') {
onNotExist.call(target);
}
}
});
};
Example:
$('#foo .bar').exist(
function () {
// Stuff when '#foo .bar' exists
},
function () {
// Stuff when '#foo .bar' does not exist
}
);
You don't have to check if it's greater than 0 like $(selector).length > 0, $(selector).length it's enough and an elegant way to check the existence of elements. I don't think that it is worth to write a function only for this, if you want to do more extra things, then yes.
if($(selector).length){
// true if length is not 0
} else {
// false if length is 0
}
Here is the complete example of different situations and way to check if element exists using direct if on jQuery selector may or may not work because it returns array or elements.
var a = null;
var b = []
var c = undefined ;
if(a) { console.log(" a exist")} else { console.log("a doesn't exit")}
// output: a doesn't exit
if(b) { console.log(" b exist")} else { console.log("b doesn't exit")}
// output: b exist
if(c) { console.log(" c exist")} else { console.log("c doesn't exit")}
// output: c doesn't exit
FINAL SOLUTION
if($("#xysyxxs").length){ console.log("xusyxxs exist")} else { console.log("xusyxxs doesnn't exist") }
//output : xusyxxs doesnn't exist
if($(".xysyxxs").length){ console.log("xusyxxs exist")} else { console.log("xusyxxs doesnn't exist") }
//output : xusyxxs doesnn't exist
Demo
console.log("existing id", $('#id-1').length)
console.log("non existing id", $('#id-2').length)
console.log("existing class single instance", $('.cls-1').length)
console.log("existing class multiple instance", $('.cls-2').length)
console.log("non existing class", $('.cls-3').length)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="id-1">
<div class="cls-1 cls-2"></div>
<div class="cls-2"></div>
</div>

Categories

Resources