Background
As of jQuery 1.9 the .attr(..) method no longer returns property values, instead we now have to use .prop(..). Unfortunately this also applies to attributes specified via an attributes selector i.e. $("input[value=]")
See
http://jquery.com/upgrade-guide/1.9/#attr-versus-prop-
and a good SO discussion on the differences between .attr and .prop :
.prop() vs .attr()
My Situation
I'm currently using selectors like $("input[value=]") and $("select[value=]")
to select input elements that have no value set. However, this no longer works with jQuery 1.9, instead I'm now doing something like this:
var hasValue = function () { return !!($(this).val().length); };
var hasNoValue = function () { return !($(this).val().length); };
$("input").filter(hasValue);
$("select").filter(hasValue);
My actual selectors are a little larger, checking multiple elements with or without values so now I'm having to split my 1 selector string into multiple selectors with .filter(..) method calls in between.
Question
Is there an equivalent to $("[value=]"), $("[value!=]"), $("[value='abc']") which uses the property instead of the attribute? And if not, is there a cleaner way than using the .filter(hasValue) and .filter(hasNoValue) methods?
Thanks
Using .filter seems to be the only way, but it's not too bad and you can actually make it a little more accurate by using .val:
$(":input").filter(function () { return $(this).val() === ""; });
If this really is that reprehensible to you, you could create a custom selector.
$.expr[':'].emptyInput = function (elem) {
return $(elem).is(":input") && $(elem).val() === "";
};
http://jsfiddle.net/ExplosionPIlls/zaZPp/
EDIT: You may also be able to get away with using this.value instead of $(elem).val().
According to the upgrade guide:
However, when a selector like "input[value=abc]" is used, it should always select by the value attribute and not any change made to the property by the user, for example from them typing into a text input. As of jQuery 1.9, this behaves correctly and consistently. Earlier versions of jQuery would sometimes use the property when they should have used the attribute.
So this answers your first question - there is not a direct equivalent, the point is to use the attribute instead of the property.
Your code seems fine, but if you want to be more standardized and re-usable you could create an additional filter. Like so:
(function($) {
$.expr[':'].hasValue = function(element) {
var $element = $(element);
return element.is(':input') && element.val();
};
}(window.jQuery));
This will allow you to select stuff like that:
// Select input elements with value and select elements without value.
$('input:hasValue,select:not(:hasValue)');
And other various combinations you need.
I came across this and just wanted to post another solution I found that works in some situations where some of the other suggested solutions are not appropriate.
Simply add this event handler to your code
$('input').on('keyup', function(){
var value = $(this).val();
$(this).attr('value', value);
});
Related
I know I've seen a beautifully straightforward answer to a similar question before, but I haven't been able to remember or locate it, so apologies in advance.
I'm not new to coding, but I've had no formal training with Javascript/jQuery. Everything else I used has been strictly typed, so I'm still struggling with how JS does typing. I have a function that fires every time a child of a specific class is changed (I'm writing this for Sharepoint, so there is some working-around that has to be done.)
Why is it when I write this:
$(".listen *").change(function(event) {
var element = event.target;
if (element.title == 'Workstation')) {
alert(element.val());
}
}
I get an error that .val() is not a function, and I have to instead write
$(".listen *").change(function(event) {
var element = event.target;
if (element.title == 'Workstation')) {
alert($('#' + element.id).val());
}
}
What is the difference between the object that "element" is and the object retrieved by using the id? Aren't they both jQuery objects? I realize that not all objects returned by my function might actually have a value to return, but I don't understand how the distinction is being made.
Thanks!
In your first code block the 'element' variable is not a jQuery object, it is a DOM object. The .val() method is not defined for DOM objects. It is only defined for jQuery objects.
In your second code block $('#' .element.id) returns a jQuery object that does have the val() method defined.
So to answer your question, No they are not both jQuery objects, only the second one is.
You must make jQuery object from your dom (event.target) like that;
$(".listen *").change(function(event) {
var element = $(event.target);
if (element.attr('title') == 'Workstation')) {
alert(element.val());
}
}
Then you can use your jQuery object as you want. By the way, if you want to catch the changed element, you can use $(this) instead of $(event.target).
$(".listen *").change(function(event) {
var element = $(this);
if (element.attr('title') == 'Workstation')) {
alert(element.val());
}
}
Hello this seems to be working on IE8 :
var clsName = link.parents("div.fixed_column").attr("class").split(" ");
if($.inArray("column_one", clsName)
While this one reports error (Object expected errror in jquery).
var clsName = link.parents("div.fixed_column").attr("class");
What is the right way to do this? I thought purpose of inArray was that jquery will handle cross browser issues.
Unfortunately, this is indirectly answering your question, but... You seem to be looking to detect if an element has a class, and since you're already using jQuery, just use the hasClass method - http://api.jquery.com/hasClass/
For your specific code, try:
if (link.parents("div.fixed_column").hasClass("column_one")) {
// It has the "column_one" class
}
The more immediate answer to your question is that link.parents("div.fixed_column").attr("class") returns a single string. When the jQuery selector (div.fixed_column) returns multiple elements, which is very possible when using classes, using jQuery methods that get information (like .attr, using one parameter...to "get" the value) return the first matched element's value only.
So say the selector matches 3 elements:
["<div id='div30' class='fixed_column div30_class'></div>",
"<div id='div2' class='fixed_column div2_class'></div>",
"<div id='div17' class='fixed_column div17_class'></div>"]
Then the value returned from .attr("class") will be: fixed_column div30_class because it's the first matched element.
I'm not sure, but I think you're expecting jQuery to return an array of all the matched elements' values, which it just doesn't. So that doesn't mean jQuery isn't handling cross-browser issues, it just means you need to look up what the method does/returns.
I could've sworn that jQuery 2.0 has options for doing what you want - directly from calling the getters (or something similar), but I can't find it anymore :( Maybe I'm remembering incorrectly. Anyways, you could easily use $.each and/or $.map to look at every matched element, but it depends on what you were really trying to do with it.
You can't read the attributes of multiple elements into an array with .attr("class"). But why don't you just target the desired class in the selector like this?
var cols = link.parents("div.fixed_column.column_one");
Then change your conditional to check for an empty set:
if(cols.length) { ...
In this code, we can obtain value of element id as 2 differnt way and both way return resultat
$("#my_div").on("click", function () {
alert( $(this).attr("id") );
alert( this.id );
});
But i interest, second way, is it proper in this case? I ask this, because in code we use jquery selector and for jquery selector, write clear javascript: this is justified and will it work always? or may be better use jquery $(this) for jquery selector? or not differnce?
this.id will give you the internal DOM element property while $(this).attr("id") returns the value of 'id' attribute.
The alternative to this.id in jQuery is using prop() method: $(this).prop("id"). However, using pure this.id construction will be easier and faster.
The main jQuery constructor can take a number of different types of argument.
In that context, this is not a selector, it is an HTMLElementNode (which jQuery calls an element).
This is perfectly OK and documented.
There is no need to spend the resources in wrapping an element in a jQuery object if you are just going to grab its ID. There aren't any compatibility problems between browsers for that.
Grabbing the id property of an HTMLElementNode takes less code and is faster then wrapping the whole thing in jQuery.
Yes, your second way is proper.
$("#my_div").on("click", function () {
// this is available within this function
alert( this.id );
});
this refers to an HTMLDOMElement within the function, and wrapping that this within $() will give you an jQuery object.
If you define another function within the click handler. Ex:
$("#my_div").on("click", function () {
// keep reference of this
var that = this;
function test() {
// this will not available here directly
// instead of that you can use reference
alert(that.id);
}
});
And $(this).attr('id'), this.id or $(this).prop('id') will give you the same result.
For choosing the best method is not always clear.
In this case you want the this.id, because the other solution requires much more calls behind the scenes (obvious calls to jQuery and attr).
If you need more information that mite differ from browser, you want the jQuery way.
If an element doesn't exist, how do I get a string of the selector that was searched?
For example:
$( 'parent child.class' ).plugin( )
In my plugin, I want to get the string "parent child.class", but $( 'parent child.class' ) doesn't exist.
I'm going to start digging through the jQuery source code, but I figured I'd ask in case someone with more intimate knowledge knows this.
You can't.
jQuery objects have a .selector property, which you could use within your plugin (though it seems to be intended for use interally with jQuery), but - and it's a big but - not all jQuery objects are created with a selector string. Consider this example use of .yourPlugin():
$('div.someClass').add(document.getElementById("test"))
.add("<div>Hello</div>")
.filter(function() {
return $(this).attr("data-test") == "blah";
})
.parents()
.yourPlugin();
It doesn't make sense to be thinking about what selector resulted in the jQuery object eventually passed to .yourPlugin(), regardless of whether it contains any elements.
(I suppose if you know your plugin will only ever be used by you and you'll only ever pass it jQuery objects created with a selector then you could use this.selector within your plugin...)
there is selector property:
$.fn.plugin = function() {
if (this.length == 0) {
return this.selector;
}
};
I'm trying to remove an element from a page based on it's background attribute.
Something like:
if ( $('td').attr('background','backgroundimageurl')){this.remove();}
But this does not work any suggestions?
You can also use filter to filter the result set based on your operations:
$( 'td' ).filter( function(){
// return true of it matches, thus, keeping it in the object
return $(this).css( 'backgroundImage' ) === 'someUrlOrWhatever';
}).remove();
Demo per roXon's request: http://jsfiddle.net/danheberden/9rTZj/
However, it would be better to do a check like
return /someDomain\.com\/path\/to\/whatever/.test( $( this ).css( 'backgroundImage' ) );
in the filter function. Different browsers will return different formatting for css rules, as roXon pointed out about the === approach won't work in FF because the returned string will be url("thePath") instead of url(thePath) like in webkit. Thus, just testing for the url value would be most flexible.
The reason it's not working is that in your code snippet, "this" is the current context (most likely the window).
This might do what you want:
$('td').each(function (i, e) {
if (e.style.foo === "bar") {
$(e).remove();
}
});
each iterates through all of the elements that matched. i is the number of the loop, and e is the current element. So we test each element and then act when we find the one with the style we want.
Even shorter example:
$('td[background="backgroundimageurl"]').remove();
Do some reading on jQuery selectors. They can be really useful :)
http://api.jquery.com/category/selectors/
Try this. When you were doing attr("background","backgroundurl") this was trying to set the background attr rather than find elements matching. This will do the trick.
if($("body").find("td").css("background-image") == "backgroundimageurl"){this.detach()};