Using object's method in the same object - javascript

Need help. I've got a library called Rigged, similar to jQuery.
This code is not complete, it's just an example of my code (my lib has over 500 lines yet)
(function () {
var arr = [];
var Rigged = function ( selector ) {
return Rigged.fn.init( selector );
};
Rigged.fn = Rigged.prototype = {
map: function ( callback ) {
var results = arr, i = 0;
for ( ; i < this.length; i++) {
results.push(callback.call(this, this[i], i));
}
return results;
},
each: function (callback) {
return this.map(callback);
},
// this is just example of my code
css: function (attr, value) {
if (attr == 'display') {
return this.each(function (current) {
current.style.display = value;
});
}
},
hide: function () {
return this.each(function (current) {
// here's a problem
current.css('display', 'none');
});
}
};
Rigged.init = Rigged.fn.init = function (selector) {
var elset, i = 0;
if (typeof selector === "string")
elset = document.querySelectorAll(selector);
else if (...)
.... etc
this.length = elset.length;
for ( ; i < this.length; i++) { this[i] = elset[i]; }
return this;
}
Rigged.ajax = Rigged.fn.ajax = function ( obj ) {
// code here
}
window.Rigged = window.$ = Rigged;
}());
So, I have no problem with calling map method or each, but in definition of method called hide it prints an error Uncaught TypeError: current.css is not a function in console.
When I call css in index file like $("#text").css('display', 'none); it works, but in Rigged.prototype it doesn't work. When I replace line current.css('display', 'none'); with current.style.display = 'none'; it normaly works.
Can anybody tell me why .css method doesn't work?
EDITED .map() method
+ e (callback) to current

You are adding DOM nodes to the object, not jQuery-like objects, dom nodes.
When you map each of your elements, you pass the DOM element to the callback function:
results.push(callback.call(this, this[i], i));
//-------------------------------^^^^^^^ here
When you do
current.css('display', 'none');
In your .hide() method, you are trying to call .css() on a DOM element, which has no such method, so you get an error.

Here is the solution.
hide: function () {
// Try to log `this`
console.log( this );
/*return this.each(function (current) {
current.css('display', 'none');
});*/
this.css('display', 'none');
}
You're running .each() twice when you calling .hide(). One within .hide() itself and second in .css() and this is the problem.

Related

javascript element like in jquery? How do I get with the "these" variable

this jquery code
$(".entry-content").click(function(){
console.log(this); // "this" <div class="entry-content"></div>
alert("aasasd");
});
I tried it myself to reach this parameter when using javascript. I can get it as a parameter from the callback function, but I couldn't get it like this.
function $( element ) {
element = document.querySelectorAll(element);
this.click = ( callback ) => {
for (let i = 0; i < element.length; i++) {
element[i].addEventListener("click", function() {
callback( element[i] );
});
}
}
return this;
}
$(".entry-content").click(function(element){
console.log(element); // The "element" is being sent from the callback () function.
alert("aasasd");
});
So instead, how do I access "this" as in jquery
Use .bind when assigning the listener to set a this value. With jQuery, this is just the element, or element[i].
Since you don't care about the indicies, only the elements, you could also consider iterating over the elements directly:
function $(selector) {
const elements = document.querySelectorAll(selector);
return {
click(callback) {
for (const element of elements) {
element.addEventListener('click', callback.bind(element));
}
}
};
}
$(".entry-content").click(function() {
console.log(this);
});
<button class="entry-content">click</button>
You can use function .bind to provide element scope
function $(selector) {
const elements = [...document.querySelectorAll(selector)];
return {
click(callback) {
elements.forEach((el) => el.addEventListener('click', callback.bind(el)));
},
};
}
$('.entry-content').click(function () {
console.log(this); // "this" <div class="entry-content"></div>
alert('aasasd');
});
<button class="entry-content">click</button>
You can use call() or apply() or bind to bind this
function $(element) {
element = document.querySelectorAll(element);
this.click = (callback) => {
for (let i = 0; i < element.length; i++) {
element[i].addEventListener("click", function(event) {
callback.call(element[i], event);
});
// element[i].addEventListener("click", function(event) {
// callback.apply(element[i], [event]);
// });
// element[i].addEventListener("click", callback.bind(element[i]));
}
}
return this;
}
$(".entry-content").click(function(event) {
console.log(event.target);
console.log(this);
});
<div class="entry-content">1</div>
<div class="entry-content">2</div>
<div class="entry-content">3</div>

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!!

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!!

String to jQuery function

Overview
I am trying to find the jQuery function that matches a selection attribute value and run that function on the selection.
Example.
$('[data-store="' + key + '"]').each(function() {
var $callback = $(this).attr('data-filter');
if($callback != null) {
var fn = window['$.fn.nl2br()'];
if(jQuery.isFunction(fn)) {
$(this).fn();
}
}
$(this).setValue(value);
});
Problem 1
I'm not sure how to create a jQuery function call from string.
I know I can call the function like this, $(this)'onclick'; however I have no way to check if it exists before trying to call it.
Normally I could do this:
var strfun = 'onclick';
var fn = body[strfun];
if(typeof fn === 'function') {
fn();
}
This seems to fail:
var fn = window['$.fn.nl2br()'];
if(jQuery.isFunction(fn)) {
$(this).fn();
}
EDIT:
I seem to be having success doing this:
if($callback != null) {
var fn = $(this)[$callback]();
if( typeof fn === 'function') {
$(this)[$callback]();
}
}
Problem 2
Using jQuery.isFunction() how do you check if a methods exists? can you do this with jQuery.isFunction()?
Example
Declare function:
$.fn.nl2br = function() {
return this.each(function() {
$(this).val().replace(/(<br>)|(<br \/>)|(<p>)|(<\/p>)/g, "\r\n");
});
};
Test if function existe, these options fail:
jQuery.isFunction($.fn.nl2br); // = false
jQuery.isFunction($.fn['nl2br']()); //false
Functions in JavaScript are referenced through their name just like any other variables. If you define var window.foobar = function() { ... } you should be able to reference the function through window.foobar and window['foobar']. By adding (), you are executing the function.
In your second example, you should be able to reference the function through $.fn['nl2br']:
$.fn.nl2br = function() {
return this.each(function() {
$(this).val().replace(/(<br>)|(<br \/>)|(<p>)|(<\/p>)/g, "\r\n");
});
};
console.log(jQuery.isFunction($.fn['nl2br']));
See a working example - http://jsfiddle.net/jaredhoyt/hXkZK/1/
var fn = window['$.fn.nl2br']();
and
jQuery.isFunction($.fn['nl2br']);

JQuery without a selector?

I'm trying to develop a cycling image slider and have a question about a document I'm referencing for development.
The JQuery function doesn't actually call a selector and I'm not exactly sure how to read it.
$.fn.cycle = function(options, arg2) {
var o = { s: this.selector, c: this.context };
The script above is in my javascript document and the method below is in my HTML doc calling to the script above.
$(document).ready(function() {
$('.headline').cycle({
fx: 'fade', // choose your transition type, ex: fade, scrollUp, shuffle,
cleartypeNoBg:true
});
.headline is a class that is defined in the HTML document. I'm confused because this has a selector and $.fn.cycle does not.
Is .headline passing in the value to .fn? If so, how is it passing in only to that section of the variable?
If you wish to see the full JQuery function it is here:
$.fn.cycle = function(options, arg2) {
var o = { s: this.selector, c: this.context };
// in 1.3+ we can fix mistakes with the ready state
if (this.length === 0 && options != 'stop') {
if (!$.isReady && o.s) {
log('DOM not ready, queuing slideshow');
$(function() {
$(o.s,o.c).cycle(options,arg2);
});
return this;
}
// is your DOM ready? http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
return this;
}
// iterate the matched nodeset
return this.each(function() {
var opts = handleArguments(this, options, arg2);
if (opts === false)
return;
opts.updateActivePagerLink = opts.updateActivePagerLink || $.fn.cycle.updateActivePagerLink;
// stop existing slideshow for this container (if there is one)
if (this.cycleTimeout)
clearTimeout(this.cycleTimeout);
this.cycleTimeout = this.cyclePause = 0;
var $cont = $(this);
var $slides = opts.slideExpr ? $(opts.slideExpr, this) : $cont.children();
var els = $slides.get();
if (els.length < 2) {
log('terminating; too few slides: ' + els.length);
return;
}
var opts2 = buildOptions($cont, $slides, els, opts, o);
if (opts2 === false)
return;
var startTime = opts2.continuous ? 10 : getTimeout(els[opts2.currSlide], els[opts2.nextSlide], opts2, !opts2.rev);
// if it's an auto slideshow, kick it off
if (startTime) {
startTime += (opts2.delay || 0);
if (startTime < 10)
startTime = 10;
debug('first timeout: ' + startTime);
this.cycleTimeout = setTimeout(function(){go(els,opts2,0,(!opts2.rev && !opts.backwards))}, startTime);
}
});
Your new function $.fn.cycle will be called in the context of the jQuery object:
var $foo;
$foo = $('.foo') //a jQuery object created by the factory function
$.fn.bar = function (a, b, c) {
//within the function, `this` is the jQuery selection
console.log(this, a, b, c);
};
$foo.bar(1, 2, 3); //will output $foo, 1, 2, 3
Typically jQuery plugins return this to maintain chainability. Additionally, they typically need to iterate over every element in the selection, so a common pattern to see is:
$.fn.foo = function () {
//in foo, `this` is a jQuery.init object
return this.each(function (index, element) {
//in each, `this` is a DOM node
var $this;
$this = $(this);
//do stuff
});
};
The selector is this in the plugin.
For example:
$.fn.cycle = function() {
console.log(this);
};
$('.headline').cycle(); //logs the `.headline` jQuery element
See fiddle: http://jsfiddle.net/maniator/eE6q2/
When you run $("selector"), then jQuery already selects the appropriate elements. After that, the .cycle plugin function is called, in which this refers to the set of matched elements.
Selection is done by the jQuery core and not by plugins. Plugins "merely" do something with the elements that are passed to it. Even $("selector"); will select elements although you don't do anything with them.

Categories

Resources