javascript and dom pattern implementation

67
CommunityOne :: May 5 :: 2008 JavaScript DOM Pattern Implementations Dave Johnson [email protected]

Upload: davejohnson

Post on 06-May-2015

6.192 views

Category:

Business


4 download

DESCRIPTION

Covers implementation details of five important Ajax design patterns in terms of DOM, CSS and JavaScript.

TRANSCRIPT

Page 1: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

JavaScript DOM PatternImplementations

Dave [email protected]

Page 2: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Agenda

• About me• Patterns Overview• Patterns

– Inline Editing– Composite Controls– Popup– Copy and Paste– Live Scrolling

Page 3: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

About

• Author Enterprise Ajax• http://blogs.nitobi.com/dave

Page 4: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Nitobi

• Nitobi co-founder, CTO• Located in Vancouver, Canada• Declarative, server integrated, Ajax

user-interface components• User interface consulting and training

services• Online usability service RobotReplay

Page 5: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Page 6: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Customers

Page 7: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Patterns

OVERVIEW

Page 8: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

“Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice”

A Pattern Language

Page 9: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Architectural Patterns

Literally.

• MVC• Peer-to-peer• SOA

Page 10: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Software Design Patterns

• Gang of Four (GoF)– Creational– Behavioural– Structural

• Others– Concurrency

Page 11: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

UI Design Patterns

• Bill Scott and others• Described as

– Problem– Context– Principle– Solution– Why / How

Page 12: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Ajax Design Patterns

• What we are talking about today

• Applies principles from all areas:– MVC– UI– OOP

Page 13: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Bad Patterns

• Increased complexity• Does not provide re-use• Language hacks

THE PROBLEMS

Page 14: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

ObserverEvent = function(type) {

this.handlers = {};this.guid = 0;

}Event.prototype.subscribe = function(func) {

this.handlers[this.guid++] = func;return guid;

}Event.prototype.notify = function(evtArgs) {

for (var item in this.handlers) {this.handlers[item].apply(this, arguments);

}}

Page 15: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

“The meaning of life is that it is to be lived, and it is not to be traded and conceptualized and squeezed into a pattern of systems”

Bruce Lee

Page 16: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Programmers Are Lazy

“If you have a difficult task, give it to a lazy person - they will find an easier way to do it.”

Hlade's Law

Page 17: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Ajax Patterns - Goals

• Making the web like the desktop• Improving user experience• More responsive applications• Remove web / desktop divide• Marriage of JavaScript, DOM, CSS

Page 18: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Describing Ajax Patterns

What is the patternWhen is the pattern appliedWhy use the patternHow is the pattern implemented

Page 19: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Best Practices

• Consider the user and the developer

• Common approaches– Progressive enhancement

http://en.wikipedia.org/wiki/Progressive_enhancement

– Unobtrusive JavaScripthttp://en.wikipedia.org/wiki/Unobtrusive_JavaScript

Page 20: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Pitfalls

• Cross browser• Cross doctype• I18n and localization• Accessibility

Page 21: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

THE PATTERNS

Page 22: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Inline Edit

• What edit in page without page refresh

• When titles, tags etc• Why remove page refreshes

Page 23: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

How

1. User invited to click on data field2. Field is replaced with an editing

control3. User blurs or saves and field is

saved behind the scenes and editor removed

Page 24: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Page 25: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

DOM

<div id="title" class="editable">Edit me!</div>

Page 26: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

CSS

#title {

width:200px;

border:1px solid black;

cursor:pointer;

cursor:hand;

}

Page 27: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Editedit: function(evt) {

//create the editorthis.editor = nitobi.html.createElement( “input”, { id : ”editor”, type : ”text”, value : this.node.innerHTML }, { width: this.node.offsetWidth, height: this.node.offsetHeight );this.node.replaceChild(this.editor, this.node.firstChild);

//set the focus so that it is ready to gothis.editor.focus();

//attach events for bluring and key handlingnitobi.html.attachEvent(this.editor, "blur", this.save);nitobi.html.attachEvent(this.editor, "keydown", this.keydown);

//detach the event for going into edit modenitobi.html.detachEvent(this.node, "click", this.edit);

}

Page 28: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Key Handling

keydown: function(evt) {

//check for enter key at least

if (evt.keyCode == 13) {

this.editor.blur();

}

}

Page 29: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Savingsave: function(evt) {

//send the data to the servervar xhr = new HttpRequest();xhr.onRequestComplete.subscribe(this.afterSave);xhr.open(“POST”, “mysite.com”, true);xhr.send(“title=“+this.editor.value);//revert to the view onlythis.node.innerHTML = this.editor.value;//show an activity indicatorthis.activity.style.display = “inline”;

},afterSave: function(httpResponse) {

//concurrency pattern//undo with command patternattachEvent(this.node, "click", this.edit);

}

Page 30: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Pitfalls / Best Practices

• Potential Pitfalls – page contents can move when changing

“modes”– too subtle invitation to edit– too many edit invitations– concurrency or failure

• Best Practices – avoid page jitter – make render & edit modes same size – activate on click– deactivate on blur

Page 31: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Composite Controls

• What inline edit multiple text fields• When simple forms, combo box• Why remove page refreshes

Page 32: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

How

1. Create a Form JavaScript class that implements IBlurable interface

2. All form elements have key and mouse events attached through IBlurable

3. When user clicks on fields the mousedown event on the newly clicked field blocks the blur on the previous field

4. When user clicks outside of the composite control the blur event is not blocked

Page 33: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Aside: Event Order

• Click on the first name field– mousedown– focus– mouseup– click

• Click on the last name field– mousedown (last name)– blur (first name)– focus (last name)– mouseup (last name)– click (last name)

• Also consider relatedTarget / fromElement

Page 34: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Page 35: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

DOM

<form id="form" name="form">

<label for="first">First: </label>

<input name="first" id="first">

<label for="last">Last: </label>

<input name="last" id="last">

</form>

Page 36: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

NameFormNameForm = function(node) {

this.form = node;//setup the blurable interfaceIBlurable.call(this, this.form.elements);this.onBlur.subscribe(this.save, this);

}

//implement the interface (ie copy over the methods)nitobi.lang.implement(NameForm, IBlurable);

NameForm.prototype.save = function(evt) {//same issues as inline edit casevar xhr = new nitobi.ajax.HttpRequest();xhr.open("POST", "http://nitobi.com/name", true);xhr.send(this.form);

};

Page 37: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Pitfalls / Best Practices

• Potential Pitfalls – event order differences across browsers– event problems on certain controls

(select, scrollbars)

• Best Practices – use for data validation behind the

scenes on sub-forms– consider both keyboard (tabbing) and

mouse events

Page 38: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Popup

• What display additional information• When details are required in context• Why remove page refresh

Page 39: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

How

1. User moves mouse over element that has mouseover event attached

2. Popup is displayed3. User moves over another part of the

trigger element firing mouseout event on a timeout

4. If show is called while waiting for a hide the hide is cancelled preventing flicker and allowing user to mouse over the contents of the popup

Page 40: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Page 41: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

DOM

<span id="title"><strong>

<a href="#">Iron Man</a></strong><span class="year">(2008)</span>

</span>

<div id="details">When wealthy ... <a href="#">(more)</a>

</div>

Page 42: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Aside: Event Bubbling

• Events bubble up through the DOM• They are also “captured”• Event handlers fire when trigged

from any child node

Page 43: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

CSS

#details {position: absolute;display: none;top: 0px;left: 0px;width: 300px;height: 100px;border: 1px solid black;background-color: white;

}

Page 44: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

ConstructorPopup = function(title, detail) {

this.detail = detail;//attach mouseover event for shownitobi.html.attachEvent(title, "mouseover", this.show);var _t = this;this.hideTimeout = null;//attach a delayed mouseout event for hidenitobi.html.attachEvent(title, "mouseout", function() {

_t.hideTimeout = setTimeout(_t.hide, 200);});

}

Page 45: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

ShowPopup.prototype.show = function(evt) {

if (this.hideTimeout != null) {//clear the hide timeout

clearTimeout(this.hideTimeout);this.hideTimeout

} else {//show the popupvar style = this.detail.style;style.display = "block";style.top = (evt.clientY + 5) + "px";style.left = (evt.clientX + 5) + "px";

}}

Page 46: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Pitfalls / Best Practices

• Potential Pitfalls – mouse event bubbling causes flickering

or moving of the popup– rogue popups– Interaction between trigger and

contents• Best Practices

– enable keyboard access– provide some way to close manually– make certain it disappears!

Page 47: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Copy and Paste

• What user can enter bulk data• When interop desktop and browser• Why remove page refreshes

Page 48: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

How - Copy

1. User clicks on focusable element (<a>)2. Filter for ctrl+c on keydown event3. Set value of hidden <textarea> to the

data that is to be copied4. Focus on the hidden <textarea>5. Magic6. Capture keyup event on hidden

<textarea> to focus back on your control7. <textarea> value now on OS clipboard

Page 49: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

How - Paste

1. User clicks on focusable element (<a>)2. Filter for ctrl+v on keydown event3. Focus on the hidden <textarea>4. Magic5. Capture keyup event on hidden

<textarea>6. Data from OS clipboard now in the

<textarea> where you can access it and focus back on your control

Page 50: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Page 51: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

DOM

<div id="copyable">

Copy this text

</div>

<textarea id=“clipboard”></textarea>

Page 52: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

CSS

#clipboard {position: absolute;

left: -5000px;

}

Page 53: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Constructorvar Copyable = function(node) {

//replace the contents with an <a> tag so that it is focusablethis.source = node;this.source.innerHTML = "<a href=\"#\" class=\"focusable\">"+this.source.innerHTML+"</a>";

//intercept all key presses to look for ctrl+c/vnitobi.html.attachEvent(this.source, "keydown", this.handleKey);

//create the clipboardthis.clipboard = nitobi.html.createElement("textarea", { id : "clipboard"+node.id } );document.body.appendChild(this.clipboard);

}

Page 54: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

handleKey

handleKey: function(evt) {var k = evt.keyCode;//offset keycode for modifier keysk = k + (evt.shiftKey?256:0)+

(evt.ctrlKey?512:0)+(evt.metaKey?1024:0);

//lookup the method in a mapvar handler = this.keyMap[k];//call that methodif (handler != null)

handler.call(this);}

Page 55: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Copycopy: function() {

//get the data we want to copyvar data = this.source.firstChild.innerHTML;if (!nitobi.browser.IE) {

//focus back control when the copy is completeattachEvent(this.clipboard, "keyup",

this.focus);//set the value, focus and select the valuethis.clipboard.value = data;this.clipboard.focus();

this.clipboard.setSelectionRange(0,data.length);} else {

window.clipboardData.setData("Text",data);}

}

Page 56: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Pastepaste: function() {

//catch the textarea keyup to grab the resultsnitobi.html.attachEventOnce(this.clipboard, "keyup", this.pasteReady);this.clipboard.focus();

},

pasteReady: function() {//get the clipboard value and insert itthis.source.firstChild.innerHTML = this.clipboard.value;//focus back on the controlthis.source.firstChild.focus();

}

Page 57: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Pitfalls / Best Practices

• Pitfalls– user is unaware of functionality– keyboard short cuts don’t match OS– no context menu support in some

browsers• Best Practices

– capture ctrl/cmd+c/v/x for different OS– support various formats depending on

use case

Page 58: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Live Scrolling

• What scroll through large datasets• When viewing, filtering, sorting• Why remove page refreshes

Page 59: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

How

1. Create clipping <div> and surface <div> where data goes

2. Repeat for a scrollbar3. Connect scrollbar scroll events to

position the data surface4. Retrieve data from the server as

user scrolls

Page 60: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Page 61: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

DOM

<div id=“viewport”><div id=“surface”>

<div id=“data”></div></div>

</div>

<div id=“scrollcontainer"><div id="scrollbar">

<div id=“range”></div></div>

</div>

Page 62: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

CSS#scrollcontainer {

width: 16px;height: 300px;overflow: hidden;

}#scrollbar {

height: 100%;width: 16px;//width: 17px;position: relative;overflow-x: hidden;overflow-y: scroll;

}#range {

overflow: hidden;width: 1px;height: 3000px;"

}

#viewport {position: relative;overflow: hidden;width: 300px;height: 300px;border: 1px solid black;

}

#surface {width: 2000px;height: 2000px;

}

Page 63: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Scrolling

var evt = “mousewheel”;

if (nitobi.browser.MOZ)

evt = “DOMMouseScroll”;

//attach the event to the surface

nitobi.html.attachEvent(

scollSurface, evt,

this.handleMouseWheel);

Page 64: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Pitfalls / Best Practices

• Potential Pitfalls – dual-scrollbar issue – sluggish performance – extremely large data sets

• Best Practices – provide dynamic tooltip showing location

within scroll – animate scroll – if desire a hybrid, use animation on paging.– support mouse scroll wheel

Page 65: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Acknowledgements

• Bill Scott• Michael Mahemoff• Andre Charland

Page 66: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

Thank You

Questions?

email: [email protected]: blogs.nitobi.com/davebook: enterpriseajax.comtweets: twitter.com/davejohnson

Page 67: JavaScript and DOM Pattern Implementation

CommunityOne :: May 5 :: 2008

http://flickr.com/photos/daveknapik/2115474105/http://flickr.com/photos/preciouskhyatt/2153351428/http://flickr.com/photos/sandcastlematt/403101240/