JavaScript and UI Architecture Best Practices

14,754 views
14,439 views

Published on

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

Published in: Technology
0 Comments
18 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
14,754
On SlideShare
0
From Embeds
0
Number of Embeds
899
Actions
Shares
0
Downloads
442
Comments
0
Likes
18
Embeds 0
No embeds

No notes for slide

JavaScript and UI Architecture Best Practices

  1. 1. JavaScript and UI Architecture Best Practices Siarhei Barysiuk s.barysiuk@sam-solutions.net
  2. 2. Our roadmap
  3. 3. Introduction: What will we cover today? • Coding patterns JavaScript-specific best practices • Design patterns Language independent patterns, UI architecture
  4. 4. Coding patterns
  5. 5. Namespaces
  6. 6. Tip of the day “Global variables should be avoided in order to lower the possibility of variable naming collisions. “
  7. 7. Namespaces: Defining namespace //defining top-level package var MyApp = MyApp || {}; //defining package //defining package MyApp.dom = { MyApp.string = MyApp.string || {}; addEventListener: function(element, //defining package callback) { MyApp.string.utils = { //code goes here trim: function(str) { }, //code goes here removeEventListener: function(element, }, callback) { reverse: function(str) { //code goes here //code goes here } } }; };
  8. 8. Namespaces: Usage in code MyApp.string.utils.reverse(...); MyApp.string.utils.trim(...); MyApp.dom.addEventListener(...); MyApp.dom.removeEventListener(...);
  9. 9. Namespaces: namespace() function //defining top-level package var MyApp = MyApp || {}; //defines package structure MyApp.namespace = function(name) { if(name) { //some checks if name is valid var names = name.split(quot;.quot;); var current = MyApp; for(var i in names) { if(!current[names[i]]) { current[names[i]] = {}; } current = current[names[i]]; } return true; } return false; };
  10. 10. Namespaces: Defining namespace //defining top-level package var MyApp = MyApp || {}; //defining package //defining package MyApp.string = MyApp.string || {}; MyApp.namespace(quot;string.utilsquot;); //defining package //defining package MyApp.string.utils = { MyApp.string.utils.trim = function(str) { trim: function(str) { //code goes here //code goes here console.log(quot;trimquot;); }, }; reverse: function(str) { //code goes here MyApp.string.utils.reverse = function(str) { } //code goes here }; console.log(quot;reversequot;); };
  11. 11. Questions?
  12. 12. Init-time branching
  13. 13. 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.”
  14. 14. Init-time branching: Defining browser-specific methods MyApp.namespace(quot;domquot;); MyApp.dom.addListener = null; //all major browsers if(typeof window.addEventListener === 'function') { MyApp.dom.addListener = function(el, type, fn) { el.addEventListener(type, fn, false); }; } //IE else if(typeof document.attachEvent === 'function') { MyApp.dom.addListener = function(el, type, fn) { el.attachEvent('on' + type, fn); }; } //older browsers else { MyApp.dom.addListener = function(el, type, fn) { el['on' + type] = fn; }; }
  15. 15. Questions?
  16. 16. Lazy definition
  17. 17. 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.”
  18. 18. Lazy definition: Defining browser-specific methods var MyApp = MyApp || {}; Override function first time 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); } };
  19. 19. Questions?
  20. 20. Configuration object
  21. 21. 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.”
  22. 22. Configuration object: Ordinary constructor var MyApp = MyApp || {}; MyApp.namespace(quot;domquot;); MyApp.dom.Button = function(text, type) { //some code here } MyApp.dom.Button = function(text, type, color, border, font) { //some code here }
  23. 23. Configuration object: Usage of configuration object var MyApp = MyApp || {}; MyApp.namespace(quot;domquot;); MyApp.dom.Button = function(text, settings) { var type = settings.type || 'submit'; var font =settings.font ||'Verdana'; //..other props //some code here }
  24. 24. Questions?
  25. 25. Private properties and methods
  26. 26. 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.”
  27. 27. Private methods and properties: Private method var MyApp = MyApp || {}; MyApp.namespace(quot;domquot;); 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 }
  28. 28. Questions?
  29. 29. Self-executing functions
  30. 30. Tip of the day “Self-executing functions are especially suitable for one-off initialization tasks performed when the script loads.”
  31. 31. Self-executing functions: Usage (function() { //code goes here })(); (function(){ // ... var jQuery = window.jQuery = window.$ = function( selector, context ) { // ... return new jQuery.fn.init( selector, context ); }; // ... jQuery.fn = jQuery.prototype = { init: function() { //... } }; })();
  32. 32. Questions?
  33. 33. Chaining
  34. 34. 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.”
  35. 35. Chaining: Usage var obj = new MyApp.dom.Element('span'); var obj = new MyApp.dom.Element('span'); obj.setText('hello'); obj.setText('hello') obj.setStyle('color', 'red'); .setStyle('color', 'red') obj.setStyle('font', 'Verdana'); .setStyle('font', 'Verdana'); document.body.appendChild(obj); document.body.appendChild(obj); document.body.appendChild( new MyApp.dom.Element('span') .setText('hello') .setStyle('color', 'red') .setStyle('font', 'Verdana') );
  36. 36. Questions?
  37. 37. Design patterns
  38. 38. Unobtrusive JavaScript
  39. 39. Unobtrusive JavaScript: Separate JavaScript functionality <a onclick=quot;doSomething()quot; href=quot;#quot;>Click!</a> <a href=quot;backuplink.htmlquot; class=quot;doSomethingquot;>Click!</a> $('a.doSomething').click(function(){ // Do something here! alert('You did something, woo hoo!'); });
  40. 40. Unobtrusive JavaScript: Never depend on JavaScript <script type=quot;text/javascriptquot;> var now = new Date(); if(now.getHours() < 12) document.write('Good Morning!'); else document.write('Good Afternoon!'); </script> <p title=quot;Good Day Messagequot;>Good Morning!</p> var now = new Date(); if(now.getHours() >= 12) { var goodDay = $('p[title=quot;Good Day Messagequot;]'); goodDay.text('Good Afternoon!'); }
  41. 41. Unobtrusive JavaScript: Never depend on JavaScript <a href=quot;javascript:window.open('page.html')quot;>my page</a> <a href=quot;#quot; onclick=quot;window.open('page.html')quot;>my page</a> <a href=quot;page.htmlquot; onclick=quot;window.open(this.href)quot;>my page</a> <a href=quot;page.htmlquot; class=quot;popupquot;>my page</a> //some java script to open element with class quot;.popupquot; in a new window
  42. 42. Questions?

×