javascript and ui architecture best practices

Post on 06-May-2015

12.788 Views

Category:

Technology

3 Downloads

Preview:

Click to see full reader

DESCRIPTION

Day 5 of 7-days "JavaScript and Rich User Interfaces" training for my colleagues. It covers coding and design patterns.

TRANSCRIPT

JavaScript and UI ArchitectureBest Practices

Siarhei Barysiuks.barysiuk@sam-solutions.net

Our roadmap

Introduction: What will we cover today?

• Coding patterns JavaScript-specific best practices • Design patterns Language independent patterns, UI architecture

Coding patterns

Namespaces

Tip of the day

“Global variables should be avoided in order to lower the possibility of variable naming collisions. “

Namespaces: Defining namespace

//defining top-level packagevar MyApp = MyApp || {};

//defining package MyApp.string = MyApp.string || {};//defining packageMyApp.string.utils = { trim: function(str) { //code goes here }, reverse: function(str) { //code goes here }};

//defining package MyApp.dom = { addEventListener: function(element,

callback) { //code goes here }, removeEventListener: function(element, callback) { //code goes here }};

Namespaces: Usage in code

MyApp.string.utils.reverse(...);MyApp.string.utils.trim(...);

MyApp.dom.addEventListener(...);MyApp.dom.removeEventListener(...);

Namespaces: namespace() function

//defining top-level packagevar MyApp = MyApp || {};

//defines package structureMyApp.namespace = function(name) { if(name) { //some checks if name is valid var names = name.split("."); var current = MyApp; for(var i in names) { if(!current[names[i]]) { current[names[i]] = {}; } current = current[names[i]]; } return true; } return false;};

Namespaces: Defining namespace

//defining top-level packagevar MyApp = MyApp || {};

//defining package MyApp.string = MyApp.string || {};//defining packageMyApp.string.utils = { trim: function(str) { //code goes here }, reverse: function(str) { //code goes here }};

//defining package MyApp.namespace("string.utils");//defining packageMyApp.string.utils.trim = function(str) { //code goes here console.log("trim"); };MyApp.string.utils.reverse = function(str) { //code goes here console.log("reverse"); };

Questions?

Init-time branching

Tip of the day

“Branch some parts of the browser-specific code during initialization, when the script loads, rather than during runtime to avoid performance hit.”

Init-time branching: Defining browser-specific methodsMyApp.namespace("dom");MyApp.dom.addListener = null;

//all major browsersif(typeof window.addEventListener === 'function') { MyApp.dom.addListener = function(el, type, fn) { el.addEventListener(type, fn, false); }; }//IEelse if(typeof document.attachEvent === 'function') { MyApp.dom.addListener = function(el, type, fn) { el.attachEvent('on' + type, fn); };}//older browserselse { MyApp.dom.addListener = function(el, type, fn) { el['on' + type] = fn; }; }

Questions?

Lazy definition

Tip of the day

“The lazy definition pattern is very similar to the previous init-time branching pattern.

The difference is that the branching happens only when the function is called for the first time.”

Lazy definition: Defining browser-specific methodsvar MyApp = MyApp || {};

MyApp.dom = { addListener: function(el, type, fn){ if (typeof el.addEventListener === 'function') { MyApp.dom.addListener = function(el, type, fn) { el.addEventListener(type, fn, false); }; } else if (typeof el.attachEvent === 'function'){ MyApp.dom.addListener = function(el, type, fn) { el.attachEvent('on' + type, fn); }; } else { MyApp.dom.addListener = function(el, type, fn) { el['on' + type] = fn; }; } MyApp.dom.addListener(el, type, fn); } };

Override function first time

Questions?

Configuration object

Tip of the day

“Instead of having many parameters, you can use one parameter and make it an object.

The properties of the object are the actual parameters.”

var MyApp = MyApp || {}; MyApp.namespace("dom"); MyApp.dom.Button = function(text, type) { //some code here}

Configuration object: Ordinary constructor

MyApp.dom.Button = function(text, type, color, border, font) { //some code here}

Configuration object: Usage of configuration object

var MyApp = MyApp || {}; MyApp.namespace("dom"); MyApp.dom.Button = function(text, settings) { var type = settings.type || 'submit'; var font =settings.font ||'Verdana'; //..other props //some code here}

Questions?

Private properties and methods

Tip of the day

“Use local variables and methods inside a constructor to achieve the “private” level of protection.

Use naming conventions _doInternalOperation to show that the function is private/protected.”

var MyApp = MyApp || {}; MyApp.namespace("dom");

MyApp.dom.Button = function(text, settings) { //..process properties function setStyle(element, settings) { //setting style to element };

var button = //... //.. setStyle(button,settings); this.clone = function() { var clonedButton = //... //... setStyle(clonedButton, settings); } //some code here}

Private methods and properties: Private method

Questions?

Self-executing functions

Tip of the day

“Self-executing functions are especially suitable for one-off initialization tasks performed when the script loads.”

(function() { //code goes here})();

Self-executing functions: Usage

(function(){ // ... var jQuery = window.jQuery = window.$ = function( selector, context ) { // ... return new jQuery.fn.init( selector, context ); }; // ... jQuery.fn = jQuery.prototype = { init: function() { //... } };})();

Questions?

Chaining

Tip of the day

“Pretty convenient way to call several related methods on one line as if the methods are the links in a chain.”

var obj = new MyApp.dom.Element('span');

obj.setText('hello'); obj.setStyle('color', 'red'); obj.setStyle('font', 'Verdana');

document.body.appendChild(obj);

Chaining: Usage

var obj = new MyApp.dom.Element('span');

obj.setText('hello') .setStyle('color', 'red') .setStyle('font', 'Verdana'); document.body.appendChild(obj);

document.body.appendChild( new MyApp.dom.Element('span') .setText('hello') .setStyle('color', 'red') .setStyle('font', 'Verdana') );

Questions?

Design patterns

Unobtrusive JavaScript

Unobtrusive JavaScript: Separate JavaScript functionality

<a onclick="doSomething()" href="#">Click!</a>

<a href="backuplink.html" class="doSomething">Click!</a>

$('a.doSomething').click(function(){ // Do something here! alert('You did something, woo hoo!'); });

Unobtrusive JavaScript: Never depend on JavaScript

<script type="text/javascript"> var now = new Date(); if(now.getHours() < 12) document.write('Good Morning!'); else document.write('Good Afternoon!');</script>

<p title="Good Day Message">Good Morning!</p>

var now = new Date();if(now.getHours() >= 12){ var goodDay = $('p[title="Good Day Message"]'); goodDay.text('Good Afternoon!');}

Unobtrusive JavaScript: Never depend on JavaScript

<a href="javascript:window.open('page.html')">my page</a>

<a href="#" onclick="window.open('page.html')">my page</a>

<a href="page.html" onclick="window.open(this.href)">my page</a>

<a href="page.html" class="popup">my page</a>//some java script to open element with class ".popup" in a new window

Questions?

top related