jquery .each produces 'undefined' whenever .data is used on the elements returned - dom

I'm trying to process all select elements with a specific data- attribute set.
I've got the loop working to pick up the element, but whenever I try to find the value of its other data- attributes I get undefined error messages.
Here is the loop:
$('select[data-hm-observed="1"]').each(function(idx, sel) {
alert(sel.getAttribute('data-hm-url'));
alert(sel.data('hmUrl'));
});
In the loop the first alert works, but the second produces:
TypeError: 'undefined' is not a function (evaluating
'sel.data('hmUrl')')
If I use the Safari console I can get the select object, put it in a variable, and interrogate its data- attributes without issue.
It seems that the .each() is having an effect on the sel variable contents - but I can't understand what.
Using JQuery 1.7.1
UPDATE:
Just discovered that if I change the loop so that it explicitly gets the element again, it all works:
$('select[data-hm-observed="1"]').each(function(idx, sel) {
xx = $(sel);
alert(sel.getAttribute('data-hm-url'));
alert(xx.data('hmUrl'));
});
Is this the correct solution?
Can I infer from this that the element passed into the loop by .each hasn't been 'processed' by jquery, and that I have to pull it myself via $(...) so that jquery does its stuff to it - this doesn't feel right - but its working.

sel is a DOM Object here, not equipped with the abilities of a jQuery Object. First, you should turn this DOM Object into a jQuery Object like this:
alert( $(sel).data('hmUrl') );
Alternatively, you can also use $(this).data('hmUrl'), because this will refer to sel (the current DOM element in the iteration).
See also .each() 2nd Example

Related

Appending element to body in VBScript

I found the you can append an element to an element by ID in VBScript:
document.getElementById("td1").appendChild img
How can I append to the body? In JavaScript you would do document.body but that throws an object required document.body in vbscript.
You could try using getElementsByTagName("body") instead (see MSDN docs).
Note that even though you'll likely have just one body tag, this function is designed to return a list of nodes, so you'll need to grab the first element before calling appendChild on it.
See also: does document.getElementsByTagName work in vbscript?

JsViews/JsRender temporary/contextual helper variable in for loop

I'm trying to store a temporary/contextual variable in a for loop for later use inside another for loop. I used http://borismoore.github.io/jsrender/demos/step-by-step/11_accessing-parent-data.html as a reference.
{^{for instances ~templateId=templateId}}
{{:~templateId}}
<select data-link="templateId" class="selected-visible" name="select-template">
{^{for ~root.templates}}
<option data-link="{:name} value{:id} selected{:id == ~templateId}"></option>
{{/for}}
</select>
{{/for}}
Each data object in the instances array has a templateId property that is set to a certain value and each object in the templates array has an id property.
The first problem is that my debug {{:~templateId}} is not showing up. It seems the variable is not assigned.
After only using the ~helper set within the template markup, I have tried explicitly defining the helper in my "viewmodel" with
$.views.helpers({templateId: 0});
Now the value gets printed when I do not set it in the for loop, but when I set it in the for loop it disappears again.
The next problem might be that the ~templateId helper is not available in a ~root-scoped for loop, because the helper should only be available in child views of the instances loop?
The ultimate goal is to select the correct value in the select, so if other solutions are available, please do tell.
You need to remove ~templateId=templateId from your template...
Explanation:
The syntax ~helper is used to access helpers/contextual parameters, which can be either be passed in/registered externally, as shown here http://www.jsviews.com/#helpers, or can be created/set within a template, as in the example you linked to {{for movies ~theater=theater}} , or in this one: ~frstNm=firstName: http://www.jsviews.com/#samples/jsr/paths.
So generally you will either pass a helper in, or create it within the template - not both.
In your example above you are first passing ~templateId in - as 0 - and then you are redefining it as a contextual parameter, using ~templateId=templateId (which is actually setting its value to undefined, since ...=templateId sets it to the value of the templateId property of the current data - undefined, in your case).

GWT Query selector not working

GWT Query selector i.e. $("#id") not working inside callback function. However xyz.find("#id") works, where xyz -> Gquery variable. Is it that callback function doesn't support $ selector or is there some other problem.
Are you sure that the element with id "id" is attached to the dom when the callback function is called ?
When you execute $("#id"), gQuery try to find elements matching the selectors within the set of elements of the DOM tree .
When you execute xyz.find("#id"), gQuery try to find elements matching the selectors inside the array of elements selected by xyz no matter the elements are still or not in the dom tree.

jQuery: Select all 'select' elements with certain val()

Does anyone know of an easy way, using jQuery, to select all <select> elements whose val() attribute yields a certain value?
I'm trying to do some validation logic and would like to just select all those elements with a single selector, then apply a warning class to each of their parents. This I know how to do once I select all the elements, but I didn't see a selector that handles this case.
Am I going to have to select all of the <select> elements into a selector, then iterate through them and check each of their values? I was hoping there would be a simpler way.
Thanks.
Why doesn't select[value=x] work? Well firstly because <select> doesn't actually have a value attribute. There is not a single value of a select box: there may be no selected options (there shouldn't normally be, but there can be in at least IE), and, in a <select multiple>, there can be any number of selected options.
Even input[value=x] doesn't work, even though <input> does have a value attribute. Well, it does work, it just doesn't do what you think. It fetches the value of the value="..." attribute in the HTML, not the current value you have entered into the form. The value="..." attribute actually corresponds to the defaultValue property and not value.
Similarly, option[value=x][selected] doesn't work because it is checking the <option selected> attribute from the HTML source (selected attribute -> defaultSelected property) and not the current selectedness of the option (selected property not attribute) - which might have changed since the page was loaded.
Except in IE, which gets the value, selected etc form attributes wrong.
Except (again): Tesserex's example may seem to work, and the reason for that is that that it's using a non-standard jQuery-specific selector, :has. This causes the native querySelectorAll methods of modern browsers to fail, and consequently jQuery falls back to its own (native JavaScript, slow) selector engine instead. This selector engine has a bug where it confuses properties for attributes, allowing [value=x] to do what you expected, and not fail like it should! (Update: this is probably no longer the case in newer jQuery versions.)
Summary: form field state checking and selectors don't mix. Apart from these issues, you also have to worry about escaping issues - for example, what if the value you want to test against contains quotes or square brackets?
So instead, yes, you should check it manually. For example using a filter:
$('select').filter(function() {
return $(this).val()==='the target value';
}).parent().addClass('warning');
(There is a value property in HTML5 and supported by modern browsers, that when you read it gives you the value of the first selected <option>. jQuery's val() is safe to use here because it provides the same method of getting the first selected option even on browsers that don't support this.)
The existing answers don't work on select tags, but I found something that does. Ask for a select that has a selected option.
$("select:has(option[value=blah]:selected)")
You can use :
$("select[value=X]");
where X is the value against which you want to check the select's value.
Attribute selectors Is what you're looking for I believe.
Something like $+('element[attribute="value"]')
See also:
*= anywhere
^= starts with
$= ends with
~= contains word
etc.
You can create a change event that puts the value in a custom attribute on the select element whenever the value changes. You can then use a simple selector to find all of the select elements that have that value. For example:
$("select").on("change", function (e) {
var $select = $(e.currentTarget);
$select.attr("select-value", $select.val());
});
And then you can do this:
var $matches = $("select[select-value='" + searchVal + "']");
$matches will have all of your matching selects.
This is a lot easier than having to iterate through elements. Remember to set select-value to the initial value when rendering the page so you don't need to trigger a change event for each select so the select-value is set.

JQuery. Accessing Elements in the DOM below and object

I'm using an API that returns a JQuery Object which is a reference to a DIV container. I know my structure inside of the DIV container. I basically need to read some attributes from the first .
I've tried chaining the standard selectors off of my object but I get an error.
XML filter is applied to non-XML value ({selector:"div.panes > div.slice(0,1)", context:({}), 0:({}), length:1})
[Break on this error] var svideo = $(api.getCurrentPane()).('a').get(0);
Change your code to use .find() when you're going for descendant elements, like this for the DOM element reference directly:
$(api.getCurrentPane()).find('a').get(0)
//or..
$(api.getCurrentPane()).find('a')[0]
or if you want a jQuery object...
$(api.getCurrentPane()).find('a:first')
//or..
$(api.getCurrentPane()).find('a:eq(0)')
//or..
$(api.getCurrentPane()).find('a').eq(0)