Javascript alternative to jquery html() - javascript

How would you write this jQuery method
$('body').html(node);
for setting html to node in Javascript?
thank you

Yes thats possible:
document.body.innerHTML="<h1>Hello World</h1>";
http://www.tizag.com/javascriptT/javascript-innerHTML.php

If node is a DOM node rather than an HTML string, you should use DOM methods instead on innerHTML:
while (document.body.firstChild) {
document.body.removeChild(document.body.firstChild);
}
document.body.appendChild(node);
See MDC docs:
firstChild
removeChild
appendChild

You are looking for the innerHTML property:
document.getElementById("test").innerHTML = "";

document.body.innerHTML = 'my html here';

And for the more general case than just setting the body....
// replace a single element by its ID
// i.e. $("#myDivId")
var myDiv = document.getElementById("myDivId");
myDiv.innerHtml = "foo";
// replace all elements of a given tag name
// i.e. $("span")
var allSpanTags = document.getElementsByTagName("span");
allSpanTags[0].innerHtml = "foo"; // or loop over the array or whatever.
// by class name
// i.e. $(".myClass")
var allMyClass = document.getElementsByClassName("myClass");

For reference, here's the way that jquery does it:
html: function( value ) {
if ( value === undefined ) {
return this[0] && this[0].nodeType === 1 ?
this[0].innerHTML.replace(rinlinejQuery, "") :
null;
// See if we can take a shortcut and just use innerHTML
} else if ( typeof value === "string" && !rnocache.test( value ) &&
(jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
!wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
value = value.replace(rxhtmlTag, "<$1></$2>");
try {
for ( var i = 0, l = this.length; i < l; i++ ) {
// Remove element nodes and prevent memory leaks
if ( this[i].nodeType === 1 ) {
jQuery.cleanData( this[i].getElementsByTagName("*") );
this[i].innerHTML = value;
}
}
// If using innerHTML throws an exception, use the fallback method
} catch(e) {
this.empty().append( value );
}
} else if ( jQuery.isFunction( value ) ) {
this.each(function(i){
var self = jQuery( this );
self.html( value.call(this, i, self.html()) );
});
} else {
this.empty().append( value );
}
return this;
},
It uses innerHTML when it can, but it also has a fallback method.

If it's the body tag that you want HTML to be inserted into, try this:
document.body.innerHTML = node;
or
document.getElementsByTagName('body')[0].innerHTML = node;

Related

Show and set multiple attributes of an element using attr() in jQuery's attr() method [mainly style attribute] [duplicate]

I am trying to go through an element and get all the attributes of that element to output them, for example an tag may have 3 or more attributes, unknown to me and I need to get the names and values of these attributes. I was thinking something along the lines of:
$(this).attr().each(function(index, element) {
var name = $(this).name;
var value = $(this).value;
//Do something with name and value...
});
Could anyone tell me if this is even possible, and if so what the correct syntax would be?
The attributes property contains them all:
$(this).each(function() {
$.each(this.attributes, function() {
// this.attributes is not a plain object, but an array
// of attribute nodes, which contain both the name and value
if(this.specified) {
console.log(this.name, this.value);
}
});
});
What you can also do is extending .attr so that you can call it like .attr() to get a plain object of all attributes:
(function(old) {
$.fn.attr = function() {
if(arguments.length === 0) {
if(this.length === 0) {
return null;
}
var obj = {};
$.each(this[0].attributes, function() {
if(this.specified) {
obj[this.name] = this.value;
}
});
return obj;
}
return old.apply(this, arguments);
};
})($.fn.attr);
Usage:
var $div = $("<div data-a='1' id='b'>");
$div.attr(); // { "data-a": "1", "id": "b" }
Here is an overview of the many ways that can be done, for my own reference as well as yours :) The functions return a hash of attribute names and their values.
Vanilla JS:
function getAttributes ( node ) {
var i,
attributeNodes = node.attributes,
length = attributeNodes.length,
attrs = {};
for ( i = 0; i < length; i++ ) attrs[attributeNodes[i].name] = attributeNodes[i].value;
return attrs;
}
Vanilla JS with Array.reduce
Works for browsers supporting ES 5.1 (2011). Requires IE9+, does not work in IE8.
function getAttributes ( node ) {
var attributeNodeArray = Array.prototype.slice.call( node.attributes );
return attributeNodeArray.reduce( function ( attrs, attribute ) {
attrs[attribute.name] = attribute.value;
return attrs;
}, {} );
}
jQuery
This function expects a jQuery object, not a DOM element.
function getAttributes ( $node ) {
var attrs = {};
$.each( $node[0].attributes, function ( index, attribute ) {
attrs[attribute.name] = attribute.value;
} );
return attrs;
}
Underscore
Also works for lodash.
function getAttributes ( node ) {
return _.reduce( node.attributes, function ( attrs, attribute ) {
attrs[attribute.name] = attribute.value;
return attrs;
}, {} );
}
lodash
Is even more concise than the Underscore version, but only works for lodash, not for Underscore. Requires IE9+, is buggy in IE8. Kudos to #AlJey for that one.
function getAttributes ( node ) {
return _.transform( node.attributes, function ( attrs, attribute ) {
attrs[attribute.name] = attribute.value;
}, {} );
}
Test page
At JS Bin, there is a live test page covering all these functions. The test includes boolean attributes (hidden) and enumerated attributes (contenteditable="").
A debugging script (jquery solution based on the answer above by hashchange)
function getAttributes ( $node ) {
$.each( $node[0].attributes, function ( index, attribute ) {
console.log(attribute.name+':'+attribute.value);
} );
}
getAttributes($(this)); // find out what attributes are available
with LoDash you could simply do this:
_.transform(this.attributes, function (result, item) {
item.specified && (result[item.name] = item.value);
}, {});
Using javascript function it is easier to get all the attributes of an element in NamedArrayFormat.
$("#myTestDiv").click(function(){
var attrs = document.getElementById("myTestDiv").attributes;
$.each(attrs,function(i,elem){
$("#attrs").html( $("#attrs").html()+"<br><b>"+elem.name+"</b>:<i>"+elem.value+"</i>");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="myTestDiv" ekind="div" etype="text" name="stack">
click This
</div>
<div id="attrs">Attributes are <div>
Simple solution by Underscore.js
For example: Get all links text who's parents have class someClass
_.pluck($('.someClass').find('a'), 'text');
Working fiddle
My suggestion:
$.fn.attrs = function (fnc) {
var obj = {};
$.each(this[0].attributes, function() {
if(this.name == 'value') return; // Avoid someone (optional)
if(this.specified) obj[this.name] = this.value;
});
return obj;
}
var a = $(el).attrs();
Here is a one-liner for you.
JQuery Users:
Replace $jQueryObject with your jQuery object. i.e $('div').
Object.values($jQueryObject.get(0).attributes).map(attr => console.log(`${attr.name + ' : ' + attr.value}`));
Vanilla Javascript Users:
Replace $domElement with your HTML DOM selector. i.e document.getElementById('demo').
Object.values($domElement.attributes).map(attr => console.log(`${attr.name + ' : ' + attr.value}`));
Cheers!!

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
});

Get all attributes of an element using jQuery

I am trying to go through an element and get all the attributes of that element to output them, for example an tag may have 3 or more attributes, unknown to me and I need to get the names and values of these attributes. I was thinking something along the lines of:
$(this).attr().each(function(index, element) {
var name = $(this).name;
var value = $(this).value;
//Do something with name and value...
});
Could anyone tell me if this is even possible, and if so what the correct syntax would be?
The attributes property contains them all:
$(this).each(function() {
$.each(this.attributes, function() {
// this.attributes is not a plain object, but an array
// of attribute nodes, which contain both the name and value
if(this.specified) {
console.log(this.name, this.value);
}
});
});
What you can also do is extending .attr so that you can call it like .attr() to get a plain object of all attributes:
(function(old) {
$.fn.attr = function() {
if(arguments.length === 0) {
if(this.length === 0) {
return null;
}
var obj = {};
$.each(this[0].attributes, function() {
if(this.specified) {
obj[this.name] = this.value;
}
});
return obj;
}
return old.apply(this, arguments);
};
})($.fn.attr);
Usage:
var $div = $("<div data-a='1' id='b'>");
$div.attr(); // { "data-a": "1", "id": "b" }
Here is an overview of the many ways that can be done, for my own reference as well as yours :) The functions return a hash of attribute names and their values.
Vanilla JS:
function getAttributes ( node ) {
var i,
attributeNodes = node.attributes,
length = attributeNodes.length,
attrs = {};
for ( i = 0; i < length; i++ ) attrs[attributeNodes[i].name] = attributeNodes[i].value;
return attrs;
}
Vanilla JS with Array.reduce
Works for browsers supporting ES 5.1 (2011). Requires IE9+, does not work in IE8.
function getAttributes ( node ) {
var attributeNodeArray = Array.prototype.slice.call( node.attributes );
return attributeNodeArray.reduce( function ( attrs, attribute ) {
attrs[attribute.name] = attribute.value;
return attrs;
}, {} );
}
jQuery
This function expects a jQuery object, not a DOM element.
function getAttributes ( $node ) {
var attrs = {};
$.each( $node[0].attributes, function ( index, attribute ) {
attrs[attribute.name] = attribute.value;
} );
return attrs;
}
Underscore
Also works for lodash.
function getAttributes ( node ) {
return _.reduce( node.attributes, function ( attrs, attribute ) {
attrs[attribute.name] = attribute.value;
return attrs;
}, {} );
}
lodash
Is even more concise than the Underscore version, but only works for lodash, not for Underscore. Requires IE9+, is buggy in IE8. Kudos to #AlJey for that one.
function getAttributes ( node ) {
return _.transform( node.attributes, function ( attrs, attribute ) {
attrs[attribute.name] = attribute.value;
}, {} );
}
Test page
At JS Bin, there is a live test page covering all these functions. The test includes boolean attributes (hidden) and enumerated attributes (contenteditable="").
A debugging script (jquery solution based on the answer above by hashchange)
function getAttributes ( $node ) {
$.each( $node[0].attributes, function ( index, attribute ) {
console.log(attribute.name+':'+attribute.value);
} );
}
getAttributes($(this)); // find out what attributes are available
with LoDash you could simply do this:
_.transform(this.attributes, function (result, item) {
item.specified && (result[item.name] = item.value);
}, {});
Using javascript function it is easier to get all the attributes of an element in NamedArrayFormat.
$("#myTestDiv").click(function(){
var attrs = document.getElementById("myTestDiv").attributes;
$.each(attrs,function(i,elem){
$("#attrs").html( $("#attrs").html()+"<br><b>"+elem.name+"</b>:<i>"+elem.value+"</i>");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="myTestDiv" ekind="div" etype="text" name="stack">
click This
</div>
<div id="attrs">Attributes are <div>
Simple solution by Underscore.js
For example: Get all links text who's parents have class someClass
_.pluck($('.someClass').find('a'), 'text');
Working fiddle
My suggestion:
$.fn.attrs = function (fnc) {
var obj = {};
$.each(this[0].attributes, function() {
if(this.name == 'value') return; // Avoid someone (optional)
if(this.specified) obj[this.name] = this.value;
});
return obj;
}
var a = $(el).attrs();
Here is a one-liner for you.
JQuery Users:
Replace $jQueryObject with your jQuery object. i.e $('div').
Object.values($jQueryObject.get(0).attributes).map(attr => console.log(`${attr.name + ' : ' + attr.value}`));
Vanilla Javascript Users:
Replace $domElement with your HTML DOM selector. i.e document.getElementById('demo').
Object.values($domElement.attributes).map(attr => console.log(`${attr.name + ' : ' + attr.value}`));
Cheers!!

For what reason i can't retrieve element by ID once climbed on his parent?

in html i've a code like this
<body>
<script src="debug.js"></script>
<button id="proof" onclick="debug('result:', this);">proof</button>
</body>
and in javascript:
function debug(msg, e)
{
var log = document.getElementById("debuglog");
if (!log)// If no element with the id "debuglog" exists, create one.
{
log = document.createElement("div"); /
log.id = "debuglog";
log.innerHTML = "<h1>Debug Log</h1>";
document.body.appendChild(log);
}
var pre = document.createElement("pre");
var text = document.createTextNode(msg + e.parentNode.getElementById("proof")); //<--PROBLEM HERE
pre.appendChild(text);
log.appendChild(pre);
}
}
Note that the code works if into the text node i write msg + e.parentNode, once i add .getElementById("proof"), no result is retrieved (i think that the script goes in error in runtime phase).
What i want to do is "navigate" throught the html elements, calling his parents and his childrens
getElementById is a prototype of document, not a prototype of each and every element (inside the document).
So if you want to restrict getElementById to search children of a specific element instead of searching the entire document (in the same way one can do getElementsByTagName using a specific element as the parent) you'll need to add your own proto-type to all elements (but IE does not support prototyping on HTMLElement) or write your own function.
See this page for some suggestions, but keep in mind, an Id should always be unique inside a page, so simply using document.getElementById that is built-in and optimized in the browser is still going to be faster.
Update:
Here is a rewrite of the function I linked to, without the errors and a faster reverse-while loop:
function GetChildById( dNode, id ) {
var i, dResult = null;
if ( dNode.getAttribute('id') === id ) { return dNode; }
i=dNode.childNodes.length;
while ( i-- ) {
if ( dNode.childNodes[i].nodeType === 1 ) {
dResult = GetChildById( dNode.childNodes[i], id );
if ( dResult !== null )
break;
}
}
return dResult;
}
Usage: GetChildById( node, 'id' )
Demo: jsfiddle
But like axel.michel said: don't do that, it's useless.
Since the ID has to be a unique element on a page, you can simply access it by using document.getElementById('YOURID'). It is method of document so your script throws an error. If you want to implement something like this, you have to do it by a custom function:
function youShouldNotDoThis( element, id ) {
var hit = null;
if ( element.getAttribute('id') == id ) {
return element;
}
for ( var i = 0, l = element.childNodes.length; i < l; i++ ) {
if ( element.childNodes[i].nodeType == 1 ) {
hit = youShouldNotDoThis( element.childNodes[i], id );
if ( hit != null ) {
break;
}
}
}
return hit;
}
And in your script fragment:
var whyEver = youShouldNotDoThis(e.parentNode,'proof');
var text = document.createTextNode(msg + whyEver); //<--NO MORE PROBLEM HERE
And again, you should not do this by the Attribute ID, because ID should be unique, but you can easily change this function to scan for something different than ID.

Jquery Evolution from simple plain 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( ... )

Categories

Resources