This is my first stackoverflow question, so try to be nice. ;-D
My issue is this, I am refactoring some existing javascript code and using jQuery to do it. In several places I've come across javascript code similar to the following:
// some js code working with the customAttribute value
javascriptElementObject.customAttribue = void(0);
The javascriptElementObject is now a jQuery object and I have been attempting to use the following code to do the same thing:
// some js code working with the customAttribute value
javascriptElementObject.attr("customAttribute", void(0));
However, this does not seem to be doing anything. The following code works however:
javascriptElementObject.get(0).customAttribute = void(0);
I'm aware of jQuery's removeAttr() function, but have not used it so far because I don't know if it's equivalent to setting the attribute value to void(0).
So I guess that really means I have 2 questions:
Why doesn't the first jQuery version work?
Are .get(0).customAttribue = void(0); and .removeAttr("customAttribute); equivalent?
Thanks.
jQuery likes to overload its methods so:
obj.attr( name ) //retrieves the attribute value
obj.attr( name, value ) //sets the attribute
obj.attr( name, void(0) ) == obj.attr( name, null ) == obj.attr( name ) //i.e retrieving the attribute
You might want to try the following if you want to set an empty attribute
obj.attr( name, '' )
This will also apply to other methods jQuery.html() for example
What are you trying to accomplish?
If the goal is to remove the value in the name/value pair, you might as well just remove the attribute entirely. I'm not aware of any intrinsic value in maintaining an attribute that has no value; in less standards-compliant browsers it may even cause a problem.
In general, the syntax of $(selector).attr(name, value) and $(selector).removeAttr(name) work very well (at least I've never seen it fail.)
If you're trying to use void(0) to keep A HREFs from firing you'd be better off using a "return false" as the click event on those A tags.
The only way to work with custom attributes via jQuery objects is:
obj.get(0).myCustomAttr = 'some value';
That is because jQuery's attr() method will not work with custom attributes (except while applied on a XML-document).
Note also that meouw's answer regarding jQuery overloading functions is not precisely correct, because jQuery checks for the parameters passed to it in such a manner that:
jQuery.funcname(param)
and
jQuery.funcname(param, null)
differ, becacuse null !== undefined. For example:
var params_test = function(a) {
if (a === undefined) {
return 'called with no parameters';
} else {
return 'called with one parameter: ' + a;
}
};
params_test(); // results in 'called with no parameters'
params_test(null); // results in 'called with one parameter: null'
Uhmm, try this:
javascriptElementObject.attr("customAttribute", void(0));
var _void = javascriptElementObject.attr("customAttribute");
alert(_void);
Related
I am trying to get one field to copy over to another field when a div is clicked on, and the code that I have currently is not working. It's showing '0' in field1, even though field2 is set to 1 by default.
$(document).on('click', '#button', function() {
$('#textfield1').val === "document.getElementById('#textfield2').value";
Try with:
$(document).on('click', '#button', function() {
$('#textfield1').val($('#textfield2').val())
});
You're using an odd mix of JS and jQuery here.
Your main issue is that val() is a method, not a property. Therefore your code should look something like this:
$(document).on('click', '#button', function() {
$('#textfield1').val($('#textfield2').val());
});
I'd strongly suggest you familiarise yourself with the jQuery documentation, specifically val() in this case.
It's showing '0' in field1, even though field2 is set to 1 by default.
You were assigning a string to $('#textfield1').val method which is why your code was not having any effect on textfield1's value.
Make it
$(document).on('click', '#button', function() {
$('#textfield1').val( $('#textfield2').val()); //use jquery val method
}
Generally speaking, JQuery offers only functions, and not properties (as #Craicerjack stated), hence remove that === and pass the new value as an argument, as follows:
$('#textfield1').val("yourText");
Also, you're passing a CSS selector rather than just an element ID to the Document.prototype.getElementById() function. Remove that # qualifier!
Moreover, you shoudln't be using a stringified JavaScript expression as a value, otherwise you'll get that exact JS expression as the input value. Rather, don't put those quotes around the expression, so that the interpreter will be evaluating it. Below is some working code.
$('#textfield1').val(document.getElementById('textfield2').value);
However, as #Rory McCrossan pointed out, you're using an odd mix of plain DOM and JQuery, and that makes no sense. It would be more consistent to also read the value of the other text field using JQuery, as follows:
$('#textfield1').val($('#textfield2').val());
Alternatively, you may do not need JQuery and opt for the standard DOM interfaces like in the example below:
document.getElementById('textfield1').value = document.getElementById('textfield2').value;
I answered this question: Manipulate Custom Values with jQuery
With this jQuery:
$('img').attr('u', function(i,u) {
/* i is the index of the current image among all the images returned by the selector,
u is the current value of that attribute */
return u.slice(0, -1) + (parseInt(u.replace(/\D/g,''), 10) + 1);
});
Link to answer, JS Fiddle demo from that answer.
But then I felt I should show how to do it 'properly,' using the custom data-* attributes allowed under HTML5 (rather than the invalid, albeit functional, custom attributes), so I adapted the HTML to:
<img src="http://placekitten.com/400/500" class="className" click="" id='button4' data-u="button6" data-r="button5" data-l="ele1" data-d="" />
(No, I've got no idea what the click attribute's meant to do, or why it's there, so I left it alone.)
And tested the following jQuery:
$('img').data('u', function(i,u) {
/* i is the index of the current image among all the images returned by the selector,
u is the current value of that attribute */
return u.slice(0, -1) + (parseInt(u.replace(/\D/g,''), 10) + 1);
});
$('img').each(function(){
console.log($(this).data('u'));
});
JS Fiddle demo.
Now, with the data() method I realise that the attribute wouldn't be updated, which is why I used the console.log() to confirm the updated value, the output, however, is the anonymous function itself, not the value that I expected to be returned from that function. I realise this is unlikely to be a bug, and is probably the expected behaviour, but is there a way to use an anonymous function to update the attributes in the same way as, for example, that used within attr(), text(), etc..?
The difference between data and many of the other jquery functions (such as attr and many others) is that data can store any type of object. attr can only store string values. Because of this, it is completely valid to want to store a function using data.
If the jquery team were to make a similar signature for data, they would need to somehow distinguish between wanting to store the function and wanting to evaluate the function. It would likely get too confusing so they just did not include the ability to execute the function.
I think the best you can do is to use each.
Basically your expectation is wrong.
jQuery's .data does not modify the data attributes of the elements at all; it simply associates the data you provide with the element through a mechanism of its own choosing.
The implementation is intentionally left unspecified, and .data does not process this data at all; you put something in, and when you later ask for it that is exactly what you get back. The data is totally opaque from jQuery's perspective.
It's true that .data provides pre-population of an element's associated data from its HTML data- attributes as a convenience feature, but that is not its main mission. And of course the opaqueness of the data is still upheld in this case: when you ask for data, you get back exactly what was specified in the HTML.
If you need this capability, you can easily add it:
$.fn.fdata = function( name, callback ) {
return this.each( function( i, element ) {
var $element = $(element);
var data = callback( i, $element.data(name) );
$element.data( name, data );
});
};
Now you can use $(sel).fdata( name, callback ); and do what you want in the callback.
It may be tempting to extend the existing $().data() method to add the callback capability, but as other pointed out, this would break any other code that depends on being able to store a function reference as data.
Of course, it's also possible that merely adding this .fdata() method could break other code - if some other code on your page also tries to use the same method name in its own plugin. So it may be wiser to make this a simple function instead. The code is almost identical either way:
function updateData( selector, name, callback ) {
$(selector).each( function( i, element ) {
var $element = $(element);
var data = callback( i, $element.data(name) );
$element.data( name, data );
});
}
Does jQuery have a method to determine if an argument passed to function is a selector?
I am making a template for some jQuery plugins and I need to be able to check if the argument passed in is a jQuery selector. I want to allow for other data types and perform different methods based on what data type is passed. Detecting data types is easy, but selectors are just a string and can be constructed is many different ways.
My goal is to create plugins that are forgiving with what you pass in for the arguments and makes educated decisions about what to do with it. Take the jQuery UI plugins for example, in some plugins, lets say we pass a callback function in the argument place holder that is for a number for a speed, it still takes the callback and runs it and uses the default for speed. That's the kind of functionality I'm going for and selectors are a pretty unique case.
Has jQuery written a Regex for this? I couldn't find one in the code.
If not, I guess I'll just have to write a huge Regex for this?
To go straight to the point:
No, jQuery has no method to check if a selector is valid.
jQuery has lots of Regex' for this, that's why you cannot find one in the code.
You do not have to write a huge Regex for this, the answer is more simple as shown below.
I understand your problem because I experienced it, there are cases in which you're not in control of the selector to give to the jQuery function.
The problem not outlined enough is that if a selector is not valid jQuery throws an error (it is important because here is the answer).
Example using jQuery v1.9.1:
$('##somewhere');
It logs into the console the following line:
throw new Error( "Syntax error, unrecognized expression: " + msg );
which source is at row 4421 of the jQuery.js file (non-minified and uncompressed version).
So, instead of looking for an inner method of jQuery (which could surely simplify things but is not available), you can just listen the error thrown to establish if the selector is valid:
function isValidSelector(selector) {
if (typeof(selector) !== 'string') {
return false;
}
try {
var $element = $(selector);
} catch(error) {
return false;
}
return true;
}
You can also make it a jQuery plugin:
jQuery.extend({
isValidSelector: function(selector) {
if (typeof(selector) !== 'string') {
return false;
}
try {
var $element = $(selector);
} catch(error) {
return false;
}
return true;
}
});
to be used this way:
alert($.isValidSelector('#what?!?'));
Best regards.
EDIT:
added type validation: the selector must be a string.
Anyhow it is a partial solution, it does not return false for selectors defined as string objects var selector = new String('##wrong-selector#!');, which are not a primitive type.
Lots of strings can technically be a selector like $('blah') could select custom elements! There isn't any good way of knowing the intent of what to do with the argument passed to your function, so it's best to have a well defined structure like Gaby has commented.
Selector:
yourFunction({ selector: 'div' });
Or
yourFunction({ value: 'testing' });
Will take a different route in your code.
Without this technique the best you can do is just attempt for jQuery to find elements based on the selector, check with .length, if elements are found then assume the caller intended a jQuery selector. Another option could be just to document that a jQuery object must be passed i.e.:
yourFunction({ value: jQuery('div') });
Then for a different route you can do
if (value instanceof of jQuery) { .... }
There can not be a regex for this, since the selectors are extensible and anyone could add any number of personal selectors (with custom defined symbols etc) ...
Perhaps you should try passing your arguments as a single object with named parameters.
{ selector:'...',
otherargument:'somevalue',
afunction: function(){...}
}
The jQuery code for determining the selector is valid is about 108 lines long, so don't expect to determine if it's a valid selector or not in one RegEx statement.
Your best bet is probably to look at what jQuery determines to be a valid selector, and make a function that essentially checks the same way, but returns whether it's valid or not.
https://github.com/jquery/jquery/blob/master/src/core.js#L80-188
This does not answer your question, but i think it can be helpful. It checks not if an argument is a jQuery selector, however it tests whether the selector exists in the document.
$.fn.inDom = function() { return $(document).find(this).length; };
BTW: I dont use $(selector).length directly, since it will return 1 if the passed argument is an HTMLNode.
For better interpretation purposes:
$('foo').length // 0
$('.foo').length // 0
$('#foo').length // 0
$('<foo>').length // 1
$(document).find('foo').length // 0
$(document).find('.foo').length // 0
$(document).find('#foo').length // 0
$(document).find('<foo>').length // 0
I'm using 1 js for 2 different pages. 1 page doesn't have a div which the other does. So when I submit the values, I get a $( js error
for
$('.description'+save_id+'').html(description_val).show(); //update category description
I suspect that I get the error because there is nothing to show(). Is there a short code I can use to detect if the div.description exists otherwise don't do the function?
jQuery will not error if it has nothing to perform on. The show() would not be a problem. To answer your question, though, you can check the length property on the jQuery object returned from $.
If the description_val variable is undefined, then the code will fail.
Try using an if() statement to only run the code if description_val is not undefined.
if(description_val) {
$('.description'+save_id+'').html(description_val).show();
}
Or if for some reason the value of description_val may be a value that would equate to false, then do this:
if(description_val !== undefined) {
$('.description'+save_id+'').html(description_val).show();
}
From what you posted I'd check to make sure the variables you're using are all defined at this stage. To check for existence you can do this:
if ($('.description' + save_id).size() > 0) {
// code here that operates on the div.
}
This is essentially just a syntactic alternative to checking the length property.
Any good reason why $("p").html(0) makes all paragraphs empty as opposed to contain the character '0'?
Instead of assuming I found a bug in jQuery, it's probably a misunderstanding on my part.
jQuery only accepts a string as an argument for the val parameter of the html() method. If you pass a number like you are it will call the html() method override that sets the contents of the element but the value of the argument will end up being null or an empty string.
Try this:
$("p").html((0).toString())
Relevant documentation
I guess that at some point, it checks if (newContent == false), and doesn't continue with adding any content? I tried looking at the source, but got a bit lost...
I also guess that this would not be counted as a bug, since the function calls for a string, and if "0" is passed (as a string), it works as expected.
A workaround would be to do this:
var myNum = 0;
$('p').html('' + myNum);
The code performing the html call was within someone else's plugin and rather than modify it, making upgrading it tedious, I just wrote the following tiny plugin that modifies the html method to do as spoon16 recommended.
(function($) {
var oldHtml = $.fn.html;
$.fn.html = function (content) {
oldHtml.apply(this, [content.toString()]);
}
})(jQuery);
It's a little bit of a hack, but it's working for me and doesn't require me to modify the Plugin I'm using.
I just thought someone else might like to see this.
Try using text() instead html().
I geuss you missed part of how jQuery works,
$('p')
returns all paragraphs and the html( val ) function:
Set the html contents of every matched element. This property is not available on XML documents (although it will work for XHTML documents).
http://docs.jquery.com/Attributes/html#val
So if you just want to set the contents for the first p use
$("P").eq(0).html( 'something' );
or to get the html:
$("P").eq(0).html();
http://docs.jquery.com/Core/eq#position
more on jQuery selectors here:
http://docs.jquery.com/Selectors