This is quite the vexing question, but please bear with me.
It's a well known feature of the javascript DOM that if you have a form field with name="something", the form's javascript DOM representation will have a something property that is a reference to the field's DOM representation.
Now, if the field's name ("something") is equal to one of the form's native properties, it will take its place in the javascript object. For instance, for a form:
<form id="Form"><input name="submit" /></form>
we'll have:
var s=document.getElementById("Form").submit; // s is the input
instead of
var s=document.getElementById("Form").submit; // s is the native submit function
Is there a way to access the native property at all in a situation like this?
Thanks.
Edit: Just to clarify two points:
I'd like to be able to access any property, not just functions
I mean this as a general question. A logical solution would be not to provoke name clashes in the first place.
I don't think there is a way to access the native function if you have an input named 'submit.' I just ran across this same topic in Chapter 11 of Secrets of the Javascript Ninja by John Resig and Bear Bibeault. I think if anyone knows the ins and outs of JS and the DOM, it's them.
The following should do the trick:
HTMLFormElement.prototype.submit.call(document.getElementById("Form"))
It will use the native method and invoke it in the context of the element that's on the page.
I tried to post this as an edit to Ivo's answer, but it was rejected. The message is cryptic, but if what they meant was that I added too much to the original, then I think it's wrong, since I was merely trying to complete it. If the reason was different, feel free to comment. With this edit I'd have accepted Ivo's answer, but without it I think it is incomplete.
Ivo's answer works for native functions, but it isn't applicable to attributes. For attributes it seems there is a number of ways, all similar but none of them perfect, to retrieve the value. I've tested the following on IE9, which is all I have available here, but http://www.quirksmode.org/dom/w3c_core.html#attributes indicates the behaviours are generally, if not completely, consistent:
form.attributes['name'] // node representing the 'name' attribute
form.getAttribute('name') // input with name="name"
form.attributes['submit'] // null
form.getAttribute('submit') // input with name="submit"
form.attributes['onsubmit'] // node representing the 'onsubmit' attribute,
// whose value is a string
form.getAttribute('onsubmit') // input with name="submit"
Based on this, it seems that (again, notice I didn't test it thoroughly):
For value attributes, one may use the attributes['attribute name'] approach, which should work down to IE6.
For prototype functions, one may use the prototype.fn.call approach
For function attributes, maybe one can retrieve the source code of the attribute and use that, but I'd rather not have to.
Since getAttribute seems to return the named input instead of the attribute, at least in IE, it seems pretty useless.
Answering my original question, it looks like in the majority of cases there will be ways to access the properties, but it will depend on the property and eventually the browser.
Related
In Backbone.js, there are two ways you can get the value of a single attribute:
var foo = model.get('foo');
var foo = model.attributes.foo;
The .get() approach is the one recommended in the docs, but presumably it's a bit slower, as it involves an extra function call.
Are there any reasons why I shouldn't use the .attributes approach? Are there any cases where it would cause unexpected behaviour?
It's a matter of encapsulation. By using a get method you are saying I don't care how it's implemented I just want that attribute. So in future if you want to override your get method to return something more meaningful, you would not have make a code change everywhere you are using that attribute.
For e.g., If your model has an attribute cost associated with it which is a number.
model.get('cost') //would give you that number say 1999.99
Now in future suppose you want it to return a formatted string, you can override the get method.
model.get('cost') // same method would now give you $1999.99 or EUR 1999,99 in french :)
Also you are reducing the amount of code and increasing the readability.
model.get('foo') reads much better than model.attributes.foo; and it's shorter as well.
As you mentioned, in your question, the .get() approach is the one recommended in the docs. Although calling the attribute directly is going to save you a few nano seconds, you should not do it.
The reason is because it may encourage someone reading your code to use that same method to set an attribute: model.attributes.foo = 'blah';
I probably don't have to tell you that this would be bad. The code may appear to work because you're getting the correct value on the model, but you are bypassing all the change tracking logic built in to backbone. No events will be triggered if you set an attribute that way.
That being said - if no one else is reading your code or changing your code but you, and you care about those extra nanoseconds that much, and you know that you will never make that type of a mistake in the future. Then by all means, use the attributes property directly.
I am learning jquery and started my first attempt at building a form validation script based on what I know so far (which isnt much).
This is really only the Radio button portion of the validation script, but I thought I get on the right track -coding wise- before I went too far. There are some fundamental issues that I know need addressing.
The Script (jsFiddle): http://jsfiddle.net/pkdsleeper/xNt5n/
The Questions:
a. How best to remove the global variables using
b. jsLint recommends "use strict", so I added it, but im not sure what it does.
c. any good refs?
d. Generally, feel free to rip this code apart (cuz I AM trying to learn) but
please explain my errors in noob-speak :)
Thanks In advance
sleeper
a. How best to remove the global variables using
Wrap it in an anonymous function and assign it to the form as a submit listener.
b. jsLint recommends "use strict", so I added it, but im not sure what it does. any good ref's?
Don't bother. It's just a buzz-word for those trying to be hip. You can't use strict mode features on the general web because way too many browsers don't support them. You can use it with otherwise compliant ES 3 code, but it's only useful as a debugging tool for errors that should have been found during testing anyway (e.g. calling constructors without new).
No c?
d. Generally, feel free to rip this code apart (cuz I AM trying to learn) but please explain my errors in noob-speak :)
> $rdoGroup = [], // an empty array which will be used to hold
You seem to be using $ to indicate a variable that references a jQuery object, but $rdoGroup is just an array. That may be confusing later.
> $rdoGroup.push($(this).attr("name"));
The $ function is very expensive, don't use it if you don't need to. Standard HTML attributes are available in all browsers as DOM properties, so:
$rdoGroup.push(this.name);
Is up to 100 times more efficient, depending on the browser.
> for (i = 0; i < $rdoGroup.length; i++) {
> if ($rdoGroup[c].toString() !== $(this).attr("name").toString()) {
The values assigned to $rdoGroup are strings, calling their toString method is redundant.
As above, use this.name. The name property is a string, so no need for toString.
I think the exercise would be easier without jQuery, which seems to be getting in the way far more than helping. If you are trying to learn javascript, I'd suggest that you learn javascript without using any library.
Once you are reasonably confident with using javascript, then you are far better equipped to use a library for the things the library is good with, and not using it for the things it isn't good at.
a. Well, you got rid of the globals pretty well. But as your code looks right now, you can wrap the entire thing in (function(){ ... all your current code in here ... }()) and leave nothing behind in global scope.
b. For "use strict" see this question
c. typeof questions['c'] === "undefined"...
d. Currently, your js is too tied to the markup (html) and vice-versa. If you add or remove something in the form, you'll have to edit your js. If you want to use the validation for another form, you'll have to start the whole thing over again.
Validators are prime candidates for "unobtrusive javascript"/progressive enhancement (here's some material: A List Apart & Wikipedia). Basically, your markup (the html), your styling (the css), and your "behaviors" (the javascript) should all be separate, so they can be changed independently. Here's something you can try:
Add a class name to your form(s) (e.g. "validate")
Set up your js to look for form.validate when the page has loaded
For each form it finds, add a submit event handler
When the handler fires, you search the given form for inputs with various other class names you specify (e.g. "required" or "phone-number" or whatever). The class names tell your code, what kinds of validations should be done. For instance, <input type="text" class="required zip-code"> would mean that a) it's a zip-code, and b) it's a required field.
If there are any validation errors, cancel the submit and alert the user somehow. Otherwise, let the submit proceed.
That's obviously a very rough outline, but I'm not gonna write your code for you :)
The point is, that if you ever need more forms or different forms or something like that you have a generic validation script, and all you need to do is "mark" the inputs with the appropriate class names.
All that being said: There are tons of jQuery plugins out there that do form validation. It's definitely still a good exercise to write one yourself, but it's also a good idea to look at what's already there, and how it works. Don't look at the code right away, but read up on how those validators are used (e.g. do they use class names or something else?) and try to figure out how they work.
I needed to figure out how to get the value of a field on my form from within a handler function but I didn't know how to reference the field and kept getting errors. I spent time looking at the API, code examples and googling. Finally I found one example which works (I imagine there are others).
Assuming a form named MyForm and a field 'myField'
var myVal = myForm.getForm().findField("myField").getValue();
Maybe I'm just too new at this, but I don't think it's obvious from looking at the API docs.
So my question is, when you're trying to figure something out, what's your approach.
Thanks!
Assuming you have set the id of the field, you can use Ext.getCmp(id) to have the ComponentManager look it up. There's also Ext.getDom(id) which basically acts as a wrapper to getElementById.
In addition, many event handler functions allow setting the scope of the function itself. The documentation for that event should note which object is setting the scope. You may be able to set the form field as the scope object and use this.getValue() but it's hard to say without knowing exactly what you're trying to do.
To answer the question at hand: the more you code, the more you grok. Ext JS has a bit of a learning curve but the example source code provided in the download is a great place to start. There are several errors and omissions in the documentation though, so the most authoritative place to go for answers is straight into the source. Reading up on JavaScript callbacks doesn't hurt either.
I have this piece of code that I've written and read that in order for it to work correctly I must use parameters so I did and it works perfectly, however I cant figure out for the life of me what parameters are and how they work. I read through a ton of articles all over the web but I just couldn't figure out how parameters work. How does one parameter know to grab instructions from another. The whole idea is just really frustrating. Also this is kind of a side question. Can I getElementBy Class instead of Id or is there anything similar to get getElementById() for classes? Thanks so much in advance.
Below is the code that is in the script.js file:
function setValue(field)
{
if(''!=field.defaultValue)
{
if(field.value==field.defaultValue)
{
field.value='';
}
else if(''==field.value)
{
field.value=field.defaultValue;
}
}
}
and I called this script to run with the code below:
<textarea id="info"
class="textArea"
name="comment"
cols="40" rows="10"
onfocus="setValue(this)"
onblur="setValue(this)">
Whats Your Name
</textarea>
Parameters
If by "parameter" you mean "argument", it's not at all clear what you mean by "How does one parameter know to grab instructions from another." Arguments/parameters don't grab "instructions" from each other.
Since it's not at all clear what you're actually asking here, I won't go into any kind of detail, but I will warn that function arguments actually work a bit differently in JavaScript than in many other languages like C, C#, or Java.
The traditional model is a special memory area called a "stack": The caller pushes arguments onto the stack, and the callee (the function being called) pulls them off the stack.
JavaScript doesn't use the stack model, though. Instead, when a function is called, an object called an execution context is allocated, and along with it something called a variable object, and the arguments (and a few other things) end up being properties on the variable object. (This happens invisibly behind the scenes, you don't actually get direct references to either object, but the fact of them is clear from edge case behaviors.)
Getting Elements by Class Name
There's getElementsByClassName which is widely-supported except by IE. But if you search for "getElementsByClassName IE" you'll find a variety of implementations for IE that you can drop into your page.
When I hear the word "parameter", I usually think of references that are passed into methods for execution. Is that what you mean? Whether it's a function or an object method, that's usually the name that we give to the object references that are passed in. Is that what you have in mind?
Yes, it's possible to query for a DOM element using div names, as long as you've written your page to do so. jQuery is the library that most people are using to manipulate the DOM in an HTML page. It has lots of methods for querying for different DOM elements. Perhaps that is what you want.
Well, I think many people call them parameters while many others call them arguments, but they are both the same: They are what you pass to a function. What that does with the parameters/arguments is completely dependent on the function. You could pass a DOM element, a string, an object, you name it.. but the function ultimately decides what to do with it.
Your side-question about getElementByClass, there is getElementsbyClassName, but its not cross-browser compatible, meaning it only works in certain browsers. There are libraries that handle all of the cross-browser madness for you though, such as Sizzle.
Well, I admit: I've extensively used jQuery.attr to store custom data in DOM elements in many, many scripts. I'm wondering if convert all my script to use jQuery.data instead of jQuery.attr. As far as I understand, the advantages of jQuery.data are:
produce neat and valid HTML code
can store any type of data (objects, array,...) on elements
The main advantage of custom attributes are:
If WEB pages are not strict HTML, I can produce HTML code with custom attributes on the server
In firebug it's easy to inspect my HTML code in search of my custom attributes
Can someone tell me if I miss something or if exists issues that makes use of jQuery.data highly preferable?
You pretty much got it. But do you know every HTML attribute? There are a lot of attributes that are used by screen-readers and other usability tools that are not standard (yet). What happens when you accidentally use the role attribute and a screen-reader picks that up? Using $.data isn't only neater, it's safer for you and makes more sense.
EDIT: I learned something last night that is pertinent to this question. In HTML5, you ca specify custom attributes for storing data. These custom attributes must be specified using the prefix "data-". See the spec for more detailed information.
What this means, is that you do not have to go back and change all of your old code, because you will never have to worry about overlapping with other attributes if you prefix with "data-". However, if you need to store more complicated data types than strings, use $.data.
I think that you don't miss anything but storing data on dom elements attributes is always a bad practice so i think you should use the $.data function.