jQuery: Get attributes from "live" element - javascript

I create a new window when i press a button. This window contains html input elements that i want to manipulate with jquery, but i can't catch the elements. Normally i would use the live function because the html is first added to the dom when the button is pressed, but its not working.
jQuery(document).ready(function () {
var opretKnap = jQuery("input[value='Open window']");
jQuery(opretKnap).live('click', function () {
var inputsDate = jQuery("input[vdfDataType]");
});
});

jQuery("input[vdfDataType]");
What's vdfDataType? That's not a standard HTML attribute. Are you meaning to use custom attributes? (It's a generally questionable strategy, especially when you want to select on them.)
Is the element you're trying to get in the current document? You say it's a ‘new window’, but if you actually mean a new window and not an in-page DOM pop-up, you won't be able to select it from the document that opened it.
jQuery(opretKnap).live
should be avoided:
the .live() method should always be called directly after a selector
That is, the argument in the jQuery() wrapper immediately before the live() call should be a selector string, such as "input[value='Open window']" directly. opretKnap is a jQuery wrapper already, so opretKnap.live() would be OK.
jQuery("input[value='Open window']")
Avoid using value as an attribute selector. Apart from it not really being very specific (what happens if a text field somewhere happens to have that string in it?), it's also unreliable for many cases in jQuery.
The value HTML attribute and the value DOM property are two different things for text inputs (and some others); the property gives the current field value, whereas the attribute gives the original value that was specified in the HTML before any user input. This attribute maps to the DOM defaultValue property, not value.
However, a bug in the Sizzle selector engine used by jQuery means it'll read the value property in preference. This would give the ‘wrong’ (but possibly desired) results... but not consistently, because in many cases the browser's own querySelectorAll call will be used for speed, short-cutting Sizzle's bug.
Whilst this might not affect you (eg. if you're selecting a button, whose value will never change), you should consider the [value=...] selector to be highly suspect, and avoid it whenever possible. Find another way to pick the particular input you want, such as a .class, #id, [name="something"] or [type=submit] if that's what it is.

Related

Why should HTML DOM properties be reflected into HTML DOM attributes as well?

It's said by this article that one of the important reasons for HTML properties to be reflected back to the DOM is because CSS selectors rely on attributes, but why's that? This could be done without the reflection based on the spec.
For people who don't know what I'm talking about, read below:
In browsers, CSS selectors rely on attributes to work.
#myButton[someAttribute] {
opacity: 0.5;
font-weight: bold
}
So in our JavaScript if we change the property of an element, eventually we have to reflect it to the HTML DOM as well like this:
// we have changed some property
myButton.someAttribute= true;
// but this is not adequate, we need to reflect as well
myButton.setAttribute('someAttribute', '');
so we get this:
<button id="myButton" someAttribute></button>
not this non-reflected button:
<button id="myButton"></button>
Not all DOM properties map to attributes. The ones that do reflect to and from attributes, do so to maintain parity with the document language — in this case, HTML, which only has a concept of attributes, which as you've correctly pointed out is relied on by Selectors.
If attribute selectors mapped directly to DOM properties without the DOM discriminating between attribute properties and other kinds of properties, then attribute selectors such as the following would match, even though none of these exist as attributes in HTML:
[classList]
[className]
[dataset]
[offsetLeft]
[offsetTop]
[offsetWidth]
[offsetHeight]
... as well as [someAttribute] matching elements with your non-existent someAttribute as a property even when you don't reflect it with setAttribute().
In fact, this is exactly why label[htmlFor] incorrectly matches label[for] elements in Internet Explorer 7, even though the for attribute in HTML is simply called for, not htmlFor — the DOM uses htmlFor to make up for the fact that for is a reserved word in many languages including JavaScript, the main DOM scripting language, preventing it from being used as a property ident.
DOM attributes and properties are not equivalent, but they're related.
Attributes are intended to be used to initialize DOM properties. When the HTML is parsed, all the attributes are used to initialize the corresponding DOM properties. If you later modify an attribute with setAttribute or removeAttribute, the corresponding property is also updated (similar to reloading the HTML with the new attribute).
But it doesn't go the other way. Updating a property doesn't change the corresponding attribute. This is why you can assign to the .value of an input, and see this reflected in the browser display, but when you look at the element in Developer Tools you still see the original value="whatever" attribute. In some cases this has special benefits -- when you click on the Reset button of a form, it resets all the value properties from their value attributes.
IMHO; Some attributes have a 1:1 mapping with their respective properties in the DOM. The reflection is automatically made for common attributes like id. You can also define your own attributes (your HTML will be considered invalid, but you can use the doctype to validate them). My guess is that due to this uncertainty created by rogue attributes. They preferred to map only the attribute:property which has predictable behaviour and usage. You can still use your custom attributes in your css but you're in manual mode. You got to keep your s**t together and reflect them yourself. This far west(freedom) mentality is one the things that made web tech so popular and easy to use. You can do things as you see fit. I do not recommend it for maintainability reasons but you could.
Your example uses a button, but the article is using the disabled property but with something other than a button. On a button, the browser will automatically reflect changes to the disabled property onto the attribute, and vice versa, but this doesn't happen with all elements. Change your example to use a div and you'll see that you'd need to manually coordinate the two if desired.
Or for custom attributes, use data- attributes instead. If you delete the property from my_element.dataset, I'm pretty sure the attribute will be deleted too.
This is to keep the HTML and DOM synchronized, because at some point CSS selectors will be checking the DOM element and relying on the attributes to be accurate.
If the DOM isn't accurate, then the CSS won't be accurate either. What if HTML didn't bother to reflect attributes back to the DOM?
Let's say the text of an input field is initially black, and you want the text to be red when it is disabled. Now let's say the user did something and a function you wrote disabled the input field through javascript.
If HTML didn't reflect that 'disabled' attribute back to the DOM, CSS would NEVER KNOW that the element was disabled.
So the text color would never be changed to red. Remember, CSS checks and relies on DOM attributes. If HTML doesn't change the DOM attributes, for all CSS cares about, nothing has changed so everything will remain the same.
For a less technical analogy, let's say CSS is Batman, HTML is Gotham Police Department, an Attribute is the bat-signal, and the DOM is the sky.
Batman(css) constantly checks the sky(dom) to see if his bat-signal light(attribute) is being shown by the Gotham Police Department(html). If there was some event(an attribute changed) which happened in Gotham where the Gotham Police Department(html) needed Batman(css) to help, but they just didn't bother to send him an update through the sky(dom) with the bat-signal(attribute update), Batman would never know there was a job that needs to be done.
I mean he's an awesome super hero so he would eventually find out but sadly, CSS is no Batman.
The article speaks about custom elements, and takes the example of a <div> element with it's natural behaviour for some properties like hidden or disabled.
So, first of all, don't take the sentence you mention as a directive from your god, because it's not.
Simply, if you have an application with some css using the disasbled property for specific styling, be aware that, if you want to :
create some custom elements
manipulate their attributes through Javascript, including disasbled
see the css applied for disasbled property of custom elements you are manipulating
Then, yes, you'll need to reflect back to DOM
Well, this is the first question I'm answering but I'll try either way.
To be honest, it's kinda hard to tell what you're asking but if you're looking to reflect HTMLElement property changes back on the DOM (via attributes). Then here's the code (using HTMLElement's):
// Defines a new property on an Object.
Object.defineProperty(HTMLElement.prototype, "someAttribute", {
// Configurable
configurable: true,
// Enumerable
enumerable: true,
/* Getter
(Allows you get the value like this =>
element.someAttribute // returns the value of "someAttribute"
)
*/
get: function() {
return this.getAttribute("someAttribute")
},
/* Setter
(Allows you to modify/ update the value like this =>
element.someAttribute = "lorem ipsum"
)
*/
set: function(data) {
this.setAttribute("someAttribute", data)
}
})
Hope this answered your question.

jQuery caches elements selected?

So I'm using this code to:
$('.something').on('click', function () {
console.log($(this).data('id'));
}
And for some reason, if I modify the data-id using the inspector, jQuery still sees the id that was there in the beginning. However, I tried the same thing using JS and it does see the changes. This makes me wondering if jQuery caches in some way the elements selected and uses them instead of the actual DOM.
Can someone please explain what happens and how jQuery does the event binding in the background?
Later edit: I want to specify that I'm talking about the "data-" attribute that I put in the HTML, not about the '.data()' provided by jQuery. Not sure if it's the same thing.
jQuery caches elements selected?
No. But the data managed by data is stored in an object cache maintained by jQuery, keyed by a unique identifier jQuery adds to the element (so it can look up the data). data is only initialized from data-* attributes, it is not an accessor for them. It's both more and less than that.
If you're interested, you can see that as an "expando" property on the element instance, it'll start with "jquery" and have a long number attached to it (currently; it's undocumented — for good reason — so this may change):
var foo = $("#foo");
console.log(foo.data("info")); // hi there
console.log("Expando name: " + Object.getOwnPropertyNames(foo[0]).find(name => name.startsWith("jQuery")));
<div id="foo" data-info="hi there"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Changing an elements ID using Javascript

I'm trying to change the id 'character' to 'characterSelected'
var character = document.getElementById('character');
var characterSelected = document.getElementById('characterSelected');
function klik() {
character.innerHTML = characterSelected;
}
character.addEventListener('click', klik);
This is what I have so far but it doensn't seem to work. I want to do this using Javascript only, no jQuery.
Thanks
You tried something, it didn't work. Now is the time to look up the standard properties and functions you're using incorrectly. If guessing doesn't work, always look for reliable documentation.
A good reference would be the Mozilla Developer Network (MDN). It's a wiki-style encyclopedia about the web, its standards and current browser compatibility. If you look at the page about innerHTML, you'll find the following:
The Element.innerHTML property sets or gets the HTML syntax describing
the element's descendants.
This means that the innerHTML property is used to replace the content of a tag as if you wrote that HTML inside it. Not what you want.
What you wanted was to change the id of an element. If you search for element id, you'll land on the Element.id page. And how practical, there's an example:
var idStr = elt.id; // Get the id.
elt.id = idStr; // Set the id
However, this is not going to fix your issues. You see, you guessed wrong when trying to use the getElementById function. This function looks at the page and finds the element with that id right now. If you don't have any element with the characterSelected id at first, then this variable you set is going to be null for the rest of time. Variables won't magically update when an element with that id is placed in the page.
And finally, you have missed the purpose of the id attribute itself.
Its purpose is to identify the element when linking (using a fragment
identifier), scripting, or styling (with CSS).
The purpose of an id is to identify an element uniquely. You might think: "that's what I'm doing". No. You're using an id to represent whether or not an element is selected. This is wrong. Depending on your objective, I would say: just store the selected element inside a variable. Then whenever you need to do something with the selected element, it's in that variable. If you need specific style for that element, then you could set a class to it. But the id isn't meant for this at all - in fact, an id isn't meant to change once an element is placed.

Manually setting focus to a <lockup> element in TVJS

I can't find any method in the Documentation to manually set the focus to an element.
It is supposed to support the DOM Element class, but when i do
var elem = ele.ownerDocument.getElementById("start");
elem.focus();
it does nothing. elem is correctly set, but it doesn't recognize the focus() method.
Apple's TVJS Framework doesn't provide any method in his classes to manually focus an element.
Neither in the standard Document Object Module classes it incorporates have any kind of method to directly access the DOM and focus an element.
The closes thing available is the autoHighlight attribute which allows to focus on render some specific elements in certain positions.
In pure js you can document.getElementById("start").autofocus; : On page load input is autofocus
Use autoHighlight for this purpose.
autoHightlight="true"
Both the containing element and one child element have to be set to true.

Where does jquery put .val() on a DIV?

jQuery (all versions tested up through 2.1.0) allows me to call .val("some value") on a DIV object to set a value on the DIV. It is not displayed and doesn't show up as an HTML5 data property in Chrome Developer Tools. And yet I can fetch the result later with a call to .val().
For example (from http://jsfiddle.net/X2nr6/ ):
HTML:
<div id="mydiv" style="display: none;">Some text</div>
<div id="debug"></div>
Javascript:
$('#mydiv').val('A value attached .');
$('#debug').text( $('#mydiv').val() );
Displayed result:
A value attached.
Where is the value stored? Not knowing where it is stored makes me worry that I am relying on a hack.
jQuery is just assigning to a value property on the div object (the HTMLDivElement instance for that div), even though it doesn't normally have one. Creating new properties on elements is allowed in every browser I've ever seen, so it works. I wouldn't use val with divs on a regular basis, though.
Here's a non-jQuery example:
var div = document.createElement('div');
console.log('value' in div); // false, divs don't normally have a value property
div.value = 42;
console.log('value' in div); // true, we've created a property on the element
console.log(div.value); // 42
Or the same sort of thing using jQuery:
var $div = $("<div>");
display(typeof $div.prop('value'));
$div.val(42);
display(typeof $div.prop('value'));
display($div.prop('value'));
This business of creating new, custom, non-standard properties on elements is called creating "expando" properties. They can be very handy. (jQuery uses them internally, for instance, to manage the data cache and a few other things — if you look closely at a DOM element you've set data on using data, you'll see a property with a name like jQuery1110028597884019836783; that's the key jQuery uses to find the element's data in jQuery's internal data cache. jQuery doesn't store the data in an expando on the element, because of IE garbage collection issues; it stores the key there, and the data in a JavaScript object.)
It stores it on a value property on the DOM object. You can see if by running your code and then inspecting the element in a DOM inspector. In Chrome, the value property will be listed under div#mydiv in the properties tab.
HTMLDivElement objects don't officially support such a property, so you are relying on a hack.
Use data() to store arbitrary data on an element.
$('#mydiv').data("myCustomValue", 'A value attached .');
Although the above answers are accurate, I'd like to complete something out.
jQuery is designed around the concept of wrapping all HTML elements in the jQuery object. That jQuery object happens to be an array that can hold more than one element.
jQuery also goes out of its way to hide this fact from you so that the average jQuery developer never has to worry about exactly what he has -- simply call the right method and the magic happens.
(You see this if you do a $(".someClassYouHaveLotsOf").hide() or $(".someClassYouHaveNoneOf").hide()`.)
jQuery's val() method is just a wrapper for accessing an HTML input element's value property. Since jQuery doesn't throw errors unless there is really no way what-so-ever, it silently helps you by accessing the value property on whatever HTML element it happens to have. div span or whatever.
In most browsers, this works -- mostly enough.
If you are really interested in setting values on HTML elements for use later, the data() method is far better suited. Straight HTML would use <element>.setAttribute("data-key", "value");
And that is about the only time you'll see me using the HTML attributes over properties, BTW.

Categories