User Action
From Ajax Patterns
There's an archived version of this pattern available, taken from the Ajax Pattern book draft, showing roughly how it appeared before the page became publicly editable.
对于红彤美容整形也许大家还不太相信它的神奇,看看韩国好多整过形的美女演员出演的电视剧,整形前是多么地
难看,整形后判若两人,大家看到的都是他们整形后的美丽容颜,那在中国的整形美容行业发展的怎么样呢?我们
现在来设想下,如果要是把网络红人“芙蓉姐姐”整形成香港明星李嘉欣,那么结果会怎么样呢?她们两个不同风格的人能整形出来什么效果
?芙蓉能整出李嘉欣的形象气质出来吗? 美容整形在国外一直是很热门的产业,许多面部有缺陷的女孩子经过整形以后能成为耀眼的明星。一些胸部整形过
的女星也能跟美国的艳星乔丹相媲美,演艺事业也蒸蒸日上,导演也亲睐她们,经常给她们抛来橄榄枝。[http://www.100woman.cn 处女膜修
复]手术,还你一个做纯洁女人的机会,双眼皮 手术,能给那些单眼皮女生一次跨越的机会,一下子跻身双眼皮行
列,男生们好象比较流行单眼皮,像Rain!割个双眼皮,轻松;做个双眼皮,方便;光子脱毛,快捷;
清除腋臭,简单;去整形美容医院,给自己一次完美的机会,去雅靓看看,能给你一个意外的惊喜! Evidence: 3/3
Tags: Action Change Click Control DHTML DOM Events Keyboard Mouse Move Type Widget
In A Blink
arrow from mouse being clicked into widget into script.
Goal Story
Pam is booking a trip on the corporate travel planner. She sees a form with the usual fields, and clicks on location. Suddenly, a list of cities fades in beside the form, and Pam selects Paris. Beside the city list, a second list appears, this one showing approved hotels. Pam chooses the Hilton and both lists disappear. Pam's pleased to proced with the destination on the updated form, which now reads, "Paris Hilton".
Problem
How can the application respond to events such as user actions?
Forces
- A rich application allows users to interact with it, frequently and in different ways.
- Responses to user actions must be as quick as possible, so as to streamline performance, keep user attention, and clarify the effects of user actions.
- Using form submissions as the only response to user activity is slow and limits interactivity.
Solution
Use Javascript event handlers to respond to user actions.
The essence of Ajax is rich browser-based interaction, and DOM events are the technology that make it happen. DOM objects can register event handlers, functions that are notified when events occurred. This callback model should be familiar to anyone who's worked with desktop GUI frameworks.
Let's say you want to run the following function when the user clicks a shutdown button.
function shutdown() {
if (confirm("Are you sure you want to shutdown?")) {
postShutdownMessageToServer();
}
}
The simplest way to set this up is to declare a button with an onclick event handler.
<button id="quit" onclick="shutdown();" />Quit</button>
Now, the web browser will arrange for shutdown() to be called whenever the button is clicked. However, we can improve on this, because the above declaration mixes Javascript with HTML. Cleaner to just declare the button and deal with an event handler in a separate Javascript file. Since we always want this behaviour, we should declare it as soon as the page loads. To run something when the page loads, we can use another event handler, one triggered by browser activity rather than a user action: onload.
<button id="quit" />Quit</button>
[.html]
window.onload = function() {
quit.onclick = shutdown;
}
[.js]
Instead of referencing a callback function, it's sometimes convenient to define the callback as a closure (anonymous function), as in:
*** quit.onclick = function() { ***
if (confirm("Are you sure you want to shutdown?")) {
postShutdownMessageToServer();
quit.onclick=null;
}
}
Registering events with Javascript, as opposed to in HTML tags, is an example of unobtrusive Javascript, the separation of Javascript and HTML. And defining the event handler in Javascript also has another benefit: you can dynamically redefine actions in response to system events. For example, our shutdown() method could include some code to avoid a double-shutdown.
function shutdown() {
if (confirm("Are you sure you want to shutdown?")) {
postShutdownMessageToServer();
*** quit.onclick=null; *** // Quit button no longer triggers an event.
}
}
Sometimes, it's not enough for the event handler to know that an event has occurred; it needs information about the event. For example, the same event handler might be used for three different buttons, in which case it will need to know which of the buttons was clicked. For this reason, the web browser creates an event object upon each user event, containing various bits of information. In Firefox, it's passed in to the event handler, so you just ensure an event paramter exists.
function shutdown(ev) {
...
}
Unfortunately, IE holds the event in a window attribute instead of passing it in, so for portability, include an "equaliser" statement to get hold of the event either way.
function shutdown(ev) {
ev = window.ev || ev;
....
}
The event object contains various information, such as which element was clicked and whereabouts the mouse was. The various event types are covered in the Decisions.
Notice the model here involves a single handler for any event type; the above commands set the handler, rather than add and remove handlers. It's often more convenient to do the latter, but portability concerns make it difficult. The feature is so useful that a competition was recently held to find the best addEvent() and removeEvent() functions, and you can find the winner, a fifteen-line script, online. Dojo Toolkit also supports these functions within a sophisticated event library.
Decisions
What events will the script listen for?
Many events are made available to Javascript code, and more come out with each new browser upgrade. Following are some frequently-used and portable events, along with typical applications. Check these out for more info on events: [1], [2].
Key pressing - onkeypress, onkeydown, onkeyup
- onkeypress and onkeydown occur immediately after a key is pressed, and will also repeat if the key is held down. onkeyup is called just once, upon the key's release.
- They can be used to enhance standard text editing. For instance, you can confine a phone number text field to contain only numbers, or you can show a word count while the user types.
- They're sometimes used to automatically leave a field once it's valid - e.g. to proceed to the next field after five digits have been added to a zipcode field. However, doing so is often counter-productive, as users generally perform faster when behaviour is consistent, even at the expense of minor technical shortcuts.
- Can be used to create keyboard shortcuts for custom controls. You can determine if the user's mouse is over the control with the onmouse* functions, and if so, respond to particular keypresses.
- Caution: Web browsers have their own keyboard events, such as Up and Down for scrolling and the popular Ctrl-D for bookmarking. In most cases, you won't be able to get hold of those combinations.
Keyboard focus - onblur, onfocus
- In the case of editable fields, onblur indicates that the user has left the field. This can result from various actions, such as hitting the TAB key, clicking the mouse outside the field, or switching to another browser tab or application window. It is often used to initiate a remote call or some validation technique.
- onfocus suggests the user has begun working on a particular object, so it can be used to show online help or change the display inside a Status Area.
Mouse button clicking - onclick, ondblclick, onmousedown, onmouseup
- These indicate a button has been clicked or double-clicked, or has been depressed or released. The button control is specifically geared for catching click events to let the user do something, and radiobuttons and checkboxes can also be associated with click listeners to indicate changes.
- onmousedown and onmouseup can be used for panning behaviour and for custom drag-and-drop functionality.
Mouse movement - onmouseover, onmouseout
- These indicate the mouse is over, or has just left, an element. It can be useful to keep a "pointerElement" variable to track which element is currently selected.
- They can be used to change an element's style when the mouse rolls over it. This shows it's active and can convey that this is the element that will be affected if the user clicks the mouse button right now, or perhaps hits a certain key.
- They can also be used to provide help or further information in a Status Area or Popup Information object.
Selection - onselect
- This event indicates when the user has selected some text.
- By tracking the selection, the application can provide information based on
what the user's selected. For example, you could let the user search on a term by selecting it, and then morph the "Search Results" element.
- By tracking the selection, the application can also allow transformations to
occur. For example, the textarea in many modern content management applications, such as mediawiki, allows the user to select some text and then change it, just like in a word processor. To italicise text on wikipedia, you select the text and click the <i> icon, which then wraps mediawiki markup () around the selected text.
Value change - onchange
- This event indicates a value has changed, so it's often used to initiate a remote call or some validation technique. An alternative to onblur. Unlike onblur, will only be called if the value was actually altered.
What attributes of the Event should be inspected?
The event object contains several useful pieces of information about the event, and what was going on at the time. Note that some of these attributes are set even for events you may not expect. For example, the ctrlKey modifier will be set even for a mouse-click event. This would allow you to detect a Ctrl-Mousepress action. However, not all attributes are always set, so you need to be careful in testing for portability.
Following are some of the portable, more frequently used, attributes of the event object.
Element - target (Firefox), srcElement (IE)
- These indicate which element the event occurred on. To equalise across browsers: element = event.target || event.srcElement
- They allow multiple objects to have event notifications routed to the same function. It's best to break such functions into separate functions, one for each element, if there are lots of if statements, deciding what to do according to which element was pressed. But if the element argument is used generically (e.g. element.innerHTML = "Closed"), then this is superior to having an equivalent function for each element.
Event type - type
- These indicate which event type took place, e.g. "click".
- A potential code smell, because it suggests the same function has been configured to handle multiple events. If it then needs to distinguish among the different types of events, it might be worth breaking it out into a handler function for each event type, with any common routines placed elsewhere.
Key code - which (Firefox), keyCode (IE)
- These indicate the Unicode value of the key that was pressed. Not strictly speaking portable, but easy enough to equalise. Since you can't directly register a function against a specific key, this property is the only way to decide if a certain key was pressed.
- Find character codes with this interactive Unicode chart generator.
Key modifiers - altKey, ctrlKey, shiftKey
- Each modifier is true if the corresponding special key was being held down while a key event occurred. You can use the modifiers to introduce keyboard shortcuts to the application. Since many single-modifier shortcuts are already used by one browser or another, portable applications usually need to use double-modifiers. Thus, key-handling function will need to perform a check like:
if (event.ctrlKey && event.shiftKey) {
... // perform ctl-shift shortcut
}
- There is also a meta-key modifier, generally not advisable as it's not supported by IE, and in any event only available on restricted keyboards.
Mouse buttons - button
- This indicates which mouse buttons were being associated with the event. * In IE, 1 is left, 2 is right, and middle is 4. Value represents the sum of all buttons being pressed.
- In Firefox, 0 is left, 1 is middle, and 2 is right.
- A painful area due to serious incompatibility issues. As well as the differences above, be aware of: (a) incompatibilities in handling of one button being depressed while another is already depressed; (b) incompatibilities in which events provide this property (sometimes only mouse-clicks; sometimes others). See, for instance, [3].
Mouse position - clientX, clientY
- These indicates position of mouse pointer when the event took place, relative to browser window.
- Useful for image-based applications, such as maps and simulators. It's often not practical to register event handlers here, so Javascript code - with possible help of web remoting - can determine exactly what the user clicked on by examining the co-ordinates.
Should event handlers be registered after the page has loaded?
Using Javascript and the DOM, redefining event handlers is easy enough to do, but should you do it? Redefining the effect of user events must be done with caution, as there is great potential to confuse users. Sometimes, event redefinition occurs simply because the programmer can't be bothered adding a new control, or the UI is so small that designers want to reuse an existing control. So before deciding to redefine an event, ask yourself if there are alternatives. For example, could you add a second button instead of redefining the first button's action?
A few examples where event redefinition might be worthwhile:
- For state transitions. The javascript may have separate start() and stop() methods, and you need a toggle button to flip the state, since that is clearer and less error-prone than separate "on" and "off" buttons.
- For enabling and disabling. There is already a disabled property available for standard controls, but for custom controls you may have created, you might use event redefinition to cancel or re-enable the effects of interacting with the control.
- For actions which depend on context information such as which field has input focus.
However, in all of these cases, note that it is usually simpler to have a single method, always registered in the same way, and to allow that method's Javascript decide where to route the event to.
How should event handlers be dynamically registered?
There are several options for changing event listener at runtime.
Where Javascript-based registration is used, there are several available syntaxes. The easiest, and probably the most portable, is to use the oneventtype attribute:
quitButton.onclick = shutdown;
This technique points the object's onclick attribute to a function. Note the lack of parentheses to indicate we're referring to the function itself, rather than trying to call it.
Another thing about this technique is that it follows a replacement model. Because you're working with a single attribute, each time you do so, you're going to remove the old one. A more sophisticated approach would be to hold a collection of listeners, all of which get notified of particular events. This would be a better representation of the standard Publish-Subscribe - or Observer (Gamma et. al.) - pattern, and match event-handling in modern GUI toolkits more closely.
And, in fact, that kind of model is supported by the W3C and implemented by Firefox. With the "multiple handlers" technique, here's an equivalent to the previous statement:
quitButton.addEventListener('click', shutdown, false);
The third argument relates to the conflict resolution strategy that's necessary when ancestors and descendents are listening for the same event. For example, clicking on a map begins to pan it, but clicking on certain individual points inside the map pops up a photo. The simplest strategy is to always leave the argument false, so that only the lowest-level registered listener is notified. See Quirksmode Events Order for more details.
Internet Explorer also supports a similar, though non-standard, model, using attachEvent in place of addEventListener and with different semantics. You can use a facade function that will work on both browsers if you need the multiple listener functionality. But unless you're doing anything sophisticated, the standard oneventtype is often the most satisfactory approach.
Real-World Examples
Bloglines
Bloglnes is a web-based RSS aggregator. You can change the current article by mouse-clicking on article titles. An interesting new feature is keyboard shortcuts - when the page contains numerous articles, clicking "j" and "k" will scroll up and down to the previous or next story.
Google Maps
Google Maps uses a dragging action to pan the map, and the arrow keys can also be used.
Backpack
37Signals Backpack maintains items in a list, and illustrates how you can use Drag-And-Drop in an Ajax application. Drag-And-Drop relies on monitoring the mouse button as well as position.
Code Examples
Here are a couple of basic examples from the Ajax demos. The Basic Time Demo handles a button click like this:
$("defaultTime").onclick=requestDefaultTime;
The wiki tracks which focus and blur events in order to show the user which message is being edited, and to upload any messages after a blur occurs. It also tracks mouse movement over each area, to provide an affordance indicating that the fields can be edited.
messageArea.onmouseout = onMessageMouseOut; messageArea.onmouseover = onMessageMouseOver; messageArea.onfocus = onMessageFocus; messageArea.onblur = onMessageBlur;
Each of these passes to getMessage, which identifies which message element was clicked.
function getMessage(event) {
event = event || window.event;
return event.target || event.srcElement;
}
Alternatives
"Click 'N' Wait" Forms
The conventional web application follows the "click 'n' wait" pattern, popular in 1970s mainframe-based client-server applications and revived in time for the late-1990s web generation, albeit in colour. The only type of interactivity is the user submitting a static form to a server-side CGI script, or clicking on a link. The script then reads some variables, does something, and outputs a whole new page of HTML. Submitting every few minutes is probably okay, but basic display changes are best performed in Javascript.
Richer Forms
The "richer form" is richer than static HTML, but less so than Ajax. It involves enhancing a standard form with dynamic behaviour, so as to make things clearer and help prevent the frustrating validation errors that often come back from the server. For instance, DHTML can be used to ensure a user enters only digits into a credit card field, or to add some popup instructions for a form field.
Related Patterns
Display Morphing, Page Rearrangement
Dynamic display changes, as dicussed in Display Morphing and Page Rearrangement, are often triggered by User Events.
XMLHttpRequest Call, IFrame Call
Web Remoting calls, as dicussed in XMLHttpRequest Call and IFrame Call, are often triggered by User Events.
Visual Metaphor
A manager instructs his PA how to respond to particular events. "When the client arrives, sit her down in the meeting room". If desired, he can later redefine the event-handling strategy. "When the client arrives, show her into my office".
Want to Know More?
QuirksMode: Introduction to Events 热转印机 有机玻璃 IBM服务器 Dell服务器 IBM服务器 HP服务器 CISCO交换机 IBM服务器 [4] 调查 单片机培训 工控机 北京搬家 顺义旅游 北京搬家 会议服务 装饰装潢 展览制作 北京装潢公司 北京装饰公司 北京装修公司 北京月嫂 门窗厂 代开发票 北京物流 顺义房产 北京搬家 门窗厂 北京保洁 [5] 代开发票 北京汽车陪练 空调维修 空调回收 大金中央空调 电地暖 冷库 格力中央空调 约克中央空调 风幕机 劳保用品 北京物流公司 机柜 机柜 电机修理 净化工程 五粮液酒 燃气灶维修 nba pictures futbol gol videoları modifiye araba resimleri anket nakliyat football videos hot girl and woman pictures seo danışmanlığı animal pictures google optimizasyon nakliyat counter strike iddaa tahminleri burç özellikleri car pictures evden eve nakliyat evden eve nakliyat evden eve nakliyat evden eve nakliyat nakliyat nakliyat evden eve nakliyat evden eve nakliyat evden eve nakliyat
Time your website with
WebWait - from the creator of AjaxPatterns.org
