Prototype: Difference between revisions
Jump to navigation
Jump to search
(→Events) |
No edit summary |
||
(10 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
= General = | |||
== Useful Links == | == Useful Links == | ||
Line 12: | Line 14: | ||
* evalJSON() works well, but not the same way as eval() as it is a String method, thus you call it directly on your JSON string. | * evalJSON() works well, but not the same way as eval() as it is a String method, thus you call it directly on your JSON string. | ||
== Ajax and JSON | == Browser Support == | ||
* Konqueror is not supported yet in Prototype. In particular, dom:loaded won't fire. [http://dev.rubyonrails.org/ticket/11262 The fix is simple though.] | |||
= Ajax and JSON = | |||
* If you put JSON information into the X-JSON HTTP header, it will get automatically evalued by Prototype and available as the json object (second argument of the callback). This way of transferring data is not recommended however. The main reason is that HTTP headers seem to be limited in size: with big strings, Jetty throws out an exception. There are other drawbacks: no new lines must be present on a HTTP header (only one line)... So it is better to use the following technique. | * If you put JSON information into the X-JSON HTTP header, it will get automatically evalued by Prototype and available as the json object (second argument of the callback). This way of transferring data is not recommended however. The main reason is that HTTP headers seem to be limited in size: with big strings, Jetty throws out an exception. There are other drawbacks: no new lines must be present on a HTTP header (only one line)... So it is better to use the following technique. | ||
Line 20: | Line 26: | ||
* Note that JavaScript code can also be directly executed if the correct MIME type is used. I am not too sure if JSON and JavaScript can be mixed easily. | * Note that JavaScript code can also be directly executed if the correct MIME type is used. I am not too sure if JSON and JavaScript can be mixed easily. | ||
== Element | = Classes and Objects = | ||
* When you need to extend a singleton instance, you can use Object.extend(). It is not necessary to allocate the result of this call to another variable, as the original object - instance - will be modified by this call. Essentially it would be used to add functionality to an existing class / object. You cannot however use the original instance "intact" once you called this method. | |||
* If you need more control, you probably need to create a Class with Prototype. This allows to properly subclass and create instances of whatever class you need. | |||
= Element = | |||
* When using getSyle() on an element, you must not use any kind of shorthand for the CSS property. Strangely, "border", "border-width" won't work for example. You must use "border-top-width". | * When using getSyle() on an element, you must not use any kind of shorthand for the CSS property. Strangely, "border", "border-width" won't work for example. You must use "border-top-width". | ||
* getWidth() won't work on an image that has not yet been loaded. The best is to set a callback on the load event of the image, and call getWidth() inside it. | |||
* You can call writeAttribute("width"): this will erase the width attribute. For image elements, this is useful for erasing width and height. Note that writeAttribute("width", "") will not behave as expected on IE (it will actually remove the image, eg set its width to 0). It is better to remove the attribute than setting it to an empty string. | |||
* Never use the parentNode attribute of an element. Use Prototype up() method, as parentNode does not return an extended element and thus fails on IE. | |||
= Events = | |||
* Registering an event on the body does not seem to work very well through Prototype. But you can just register the event directly on the ''document'' object and it will work as expected. '''Note:''' I was unable to reproduce this bug lately, maybe fixed in Prototype 1.6.0.2. | * Registering an event on the body does not seem to work very well through Prototype. But you can just register the event directly on the ''document'' object and it will work as expected. '''Note:''' I was unable to reproduce this bug lately, maybe fixed in Prototype 1.6.0.2. | ||
Line 30: | Line 48: | ||
* Usually an event propagates to parent elements. So be careful when you register events on elements that can be "blocked" by elements at the same level. It is then better to create a div containing all the elements you want the click event to trigger on, and then register the event on this container div. Since events propagate, you are sure to trigger the event. | * Usually an event propagates to parent elements. So be careful when you register events on elements that can be "blocked" by elements at the same level. It is then better to create a div containing all the elements you want the click event to trigger on, and then register the event on this container div. Since events propagate, you are sure to trigger the event. | ||
* Firing native events (mouseclick, mouseover, etc...) is not yet possible with Prototype, but may be supported in future versions. | * Firing native events (mouseclick, mouseover, etc...) is not yet possible with Prototype, but may be supported in future versions. | ||
* Unregistering events is done via the stopObserving() function. Without any argument, it will unregister all events on the given element. With an event name, it will unregister all the events of the given type. | |||
== Custom Events == | |||
* Firing custom events can be very powerful for certain kind of tasks. With custom events you gain the power to react when various functions are called; you can program almost in the same way as with a rich client GUI library like Qt or SWT. | |||
* Custom events *must* have a namespace, so their names look like: "namespace:myEvent". | |||
= Forms = | |||
* If you have a DOM element of a form, don't use element.readAtribute("value") to obtain its value as it will give you the initial value of the form. Use $F(element) directly (or element.getValue()). | * If you have a DOM element of a form, don't use element.readAtribute("value") to obtain its value as it will give you the initial value of the form. Use $F(element) directly (or element.getValue()). | ||
* For unchecking or checking checkboxes, use $("checkboxId").checked = true. Do not use writeAttribute("checked", "checked") as this does not work as expected. | |||
* setValue() is a Prototype add-on. '''Warning:''' it's currently undocumented in the official API documentation! | |||
= Hashes = | |||
* Don't try to use DOM elements as keys of the hash. That does not work well (maybe Prototype or the browser somehow serializes the elements). You can use the elements ids instead. | |||
= Viewport and Page = | |||
* It's important to understand the distinction between the viewport size (the browser's window size) and the page size. For example in CSS, setting the body height to 100% will make the body as long as the viewport, but *not* as the page. It's impossible in CSS to make an element as long as the page without using fixed height (not percentages), as percentages will eventually be considered with respect to the viewport. | |||
* This essentially means that some JS code is needed. Typically, to obtain the height of a page you would take the maximum of the viewport height and the body's height: | |||
var height = Math.max(document.body.getHeight(), document.viewport.getHeight()); |
Latest revision as of 13:43, 4 February 2009
General
Useful Links
- Excellent Prototype examples and tutorials.
- Good check list of things to do and to avoid in Prototype.
Notes
- Binding is one of the most useful functions in Prototype. In particular, when iterating over objects with an each and a defined function, the function won't be binded to the current object. You must manually bind it.
- When using classes, use the Prototype classes functions (Class.create()). In Prototype 1.6 the syntax is nice.
- evalJSON() works well, but not the same way as eval() as it is a String method, thus you call it directly on your JSON string.
Browser Support
- Konqueror is not supported yet in Prototype. In particular, dom:loaded won't fire. The fix is simple though.
Ajax and JSON
- If you put JSON information into the X-JSON HTTP header, it will get automatically evalued by Prototype and available as the json object (second argument of the callback). This way of transferring data is not recommended however. The main reason is that HTTP headers seem to be limited in size: with big strings, Jetty throws out an exception. There are other drawbacks: no new lines must be present on a HTTP header (only one line)... So it is better to use the following technique.
- The recommended way to send out data is to set the MIME type to "application/json" and then reply with a pure JSON response. Prototype will automatically evaluate the data and place it in the transport.responseJSON object. If you need to send HTML pages, they can be easily included as a JSON object. You never have to call evalJSON() with this technique.
- Note that JavaScript code can also be directly executed if the correct MIME type is used. I am not too sure if JSON and JavaScript can be mixed easily.
Classes and Objects
- When you need to extend a singleton instance, you can use Object.extend(). It is not necessary to allocate the result of this call to another variable, as the original object - instance - will be modified by this call. Essentially it would be used to add functionality to an existing class / object. You cannot however use the original instance "intact" once you called this method.
- If you need more control, you probably need to create a Class with Prototype. This allows to properly subclass and create instances of whatever class you need.
Element
- When using getSyle() on an element, you must not use any kind of shorthand for the CSS property. Strangely, "border", "border-width" won't work for example. You must use "border-top-width".
- getWidth() won't work on an image that has not yet been loaded. The best is to set a callback on the load event of the image, and call getWidth() inside it.
- You can call writeAttribute("width"): this will erase the width attribute. For image elements, this is useful for erasing width and height. Note that writeAttribute("width", "") will not behave as expected on IE (it will actually remove the image, eg set its width to 0). It is better to remove the attribute than setting it to an empty string.
- Never use the parentNode attribute of an element. Use Prototype up() method, as parentNode does not return an extended element and thus fails on IE.
Events
- Registering an event on the body does not seem to work very well through Prototype. But you can just register the event directly on the document object and it will work as expected. Note: I was unable to reproduce this bug lately, maybe fixed in Prototype 1.6.0.2.
- If you register two events on the same objects, both will fire, even if you stop one in the callback. Stopping an event only prevents its propagation to parent elements.
- Usually an event propagates to parent elements. So be careful when you register events on elements that can be "blocked" by elements at the same level. It is then better to create a div containing all the elements you want the click event to trigger on, and then register the event on this container div. Since events propagate, you are sure to trigger the event.
- Firing native events (mouseclick, mouseover, etc...) is not yet possible with Prototype, but may be supported in future versions.
- Unregistering events is done via the stopObserving() function. Without any argument, it will unregister all events on the given element. With an event name, it will unregister all the events of the given type.
Custom Events
- Firing custom events can be very powerful for certain kind of tasks. With custom events you gain the power to react when various functions are called; you can program almost in the same way as with a rich client GUI library like Qt or SWT.
- Custom events *must* have a namespace, so their names look like: "namespace:myEvent".
Forms
- If you have a DOM element of a form, don't use element.readAtribute("value") to obtain its value as it will give you the initial value of the form. Use $F(element) directly (or element.getValue()).
- For unchecking or checking checkboxes, use $("checkboxId").checked = true. Do not use writeAttribute("checked", "checked") as this does not work as expected.
- setValue() is a Prototype add-on. Warning: it's currently undocumented in the official API documentation!
Hashes
- Don't try to use DOM elements as keys of the hash. That does not work well (maybe Prototype or the browser somehow serializes the elements). You can use the elements ids instead.
Viewport and Page
- It's important to understand the distinction between the viewport size (the browser's window size) and the page size. For example in CSS, setting the body height to 100% will make the body as long as the viewport, but *not* as the page. It's impossible in CSS to make an element as long as the page without using fixed height (not percentages), as percentages will eventually be considered with respect to the viewport.
- This essentially means that some JS code is needed. Typically, to obtain the height of a page you would take the maximum of the viewport height and the body's height:
var height = Math.max(document.body.getHeight(), document.viewport.getHeight());