Posts Tagged javascript

Primitive OOP observer pattern with ExtJS

Recently I embarked on a quest to design a framework which would help us keep track of large and complex javascript projects in easily identifiable and extendable patterns. After some thought and deliberation, we eventually settled on the observer pattern using Ext’s Ext.util.Observable object as the base object to use in responding to event broadcasts and the Ext.ux.BroadcastEvents plugin for managing global event broadcasts.

Here is the code I came up with for common component elements:

ComponentWrapperBase = Ext.extend(Ext.util.Observable, {
	delayBuild: false,

	eventObj: {
			"buildwidget": true,
			"showwidget": true,
			"destroy": true,
			"refresh": true
		},

	globalEvents: [],

	widget: null,
	widgetCfg: null,

	build: function() {
		if (this.widgetCfg && !this.widget) {
			//console.log("buildwidget", this);
			this.widget = Ext.ComponentMgr.create(this.widgetCfg);
			this.widget.wrapper = this;
			this.fireBuildEvent();
		}
	},

	fireBuildEvent: function() {
		this.fireEvent("buildwidget", this, this.widget);
	},

	showWidget: function(locationId) {
		if (this.widget) {
			if (this.widget.xtype == "window") {
					if (locationId != null) {
						this.widget.show(locationId);
					} else {
						this.widget.show();
					}
			}
			else {

				if (locationId != null) {
					this.widget.render(locationId);
				}
				else {
					this.widget.render();
				}
			}
			this.fireEvent("showwidget", this);
		}
	},

	constructor: function(config){
		if (config) {
			if (config.widgetCfg) {
				this.widgetCfg = config.widgetCfg;
			}

			if (config.delayBuild) {
				this.delayBuild = config.delayBuild;
			}

			// Copy configured listeners into *this* object so that the base class's
			// constructor will add them.
			if (config.listeners) {
				Ext.apply(this.listeners,config.listeners);
			}

			if(config.events && Ext.isArray(config.events)) {
				for (var i=0; i

This creates a simple widget wrapped in an Observable object. You can reach the contained widget through wrapper.widget. Using the framework above, here's how you could create a simple widget.

SimpleTextField = Ext.extend(ComponentWrapperBase, {
	widgetCfg: {
		xtype: 'textfield',
		fieldLabel: 'Name'
	},
	constructor: function(config){		// Constructor is not required, but I've included
							// it to demonstrate the flexibility of this framework
		if (config) {
			Ext.apply(this,config);
		}

		this.widgetCfg.value = 'John Smith';

		SimpleTextField.superclass.constructor.call(this);
	}
});

var simpleTextField = new SimpleTextField();
// Actual component is available at simpleTextField.widget, useful for adding to other containers

That's it! If you have any questions or comments, feel free to post them below.

  • Share/Bookmark

Tags: , , , , ,

Cleaning up unresponsive script errors

I recently worked on improving performance in a labor scheduling application. The app was originally designed to load all the employees at one time in one large chunk, processing and stuffing the data into various places as needed on startup. This all worked fairly well on average stores with 50-100 employee records until we discovered several stores with 100+ employee records which caused the browser to display an unresponsive script warning due to the rather heavy pre-processing algorithms.

After scouring the web for clues to help me get rid of this warning without changing settings on the browser, I found out that the only way to avoid these warnings was through a pseudo-threading pattern using setTimeout12.

One of the patterns I came up with to process a sequence of commands (such as adding records to a store) one at a time while still allowing the browser time to refresh and process other commands:

var chainedTasks = [
   function() {
      console.log('first set of tasks');
   },
   function() {
      console.log('second set of tasks');
   },
   function() {
      console.log('third set of tasks');
   }
];

var currentTaskNum = 0;
var isExecuting = false;
var emptask = {var emptask = {
	scope: this,
	interval: 100,
	run: function(){
		if(currentTaskNum > chainedTasks.length) {
			Ext.TaskMgr.stop(emptask);
		}

		if (!threadIsRunning) {
			threadIsRunning = true;
			if (typeof chainedTasks[currentTaskNum] === 'function') {
				chainedTasks[currentTaskNum](currentTaskNum);
			}
			currentTaskNum++;
			threadIsRunning = false;
		}
	}
};
Ext.TaskMgr.start(emptask);
  1. http://www.dojotoolkit.org/forum/support/general-support/need-suggestions-how-manage-firefox-warning-unresponsive-script []
  2. http://dev.opera.com/articles/view/efficient-javascript/?page=all []
  • Share/Bookmark

Tags: , , , ,

Javascript resources

Being a scripted language whose behavior can vary depending on the browser environment it is run in, Javascript can be particularly difficult to work with and debug sometimes. Here are a few tools I’ve found to be helpful:

These are the most helpful Javascript tools I’ve found. If you know of any more feel free to mention them in the comments below. Happy coding!

  • Share/Bookmark

Tags: , , ,

Warning: JSLint will hurt your feelings

JSLint is a very helpful code quality utility for javascript that purports to hurt your feelings but helps you write ECMAScript compliant code. Many development suites like Aptana now include lint checking while you code.

A major advantage of making sure your code is linted is that it ensures your code will not be mangled too badly by minification/obfuscators if you decide to use them later on.

  • Share/Bookmark

Tags: , , , , , , ,

Multi-threading in Web 2.0

I’ve been tasked with speeding up a web 2.0 application based on ExtJS 2.2.0 that contains several routines that take up quite a bit of time and, because IE6’s javascript processing engine is less than stellar1, I needed to find a way to “speed things up”.

Enter Ext.TaskMgr, a helpful ExtJS object that is essentially a glorified setTimeout implementation that allows us to run tasks that don’t block execution. This means we can set our more expensive blocks of code to run later but return control back to the user in the meantime. It’s not true multi-threading, but it does allow us to make the user interface a lot more responsive and in an age when users think 5 seconds is an eternity, perception is everything.

  1. In other words, it sucks pretty bad. []
  • Share/Bookmark

Tags: , , , ,

parseInt gotchas

Debugging an application today before launch I noticed a problem where it seemed to be parsing a specific time value (0900) incorrectly as (12:00 AM or ‘0000′).  During my search I ran across this oddity with the parseInt function of Javascript.

Apparently parseInt can also work with different base notations so it’s a good idea to specify base 10 in the manner parseInt(val,10) just to be safe if you are passing it numbers (such as time values) that may start with a zero and you don’t want invalid octal numbers (like 09) parsing to zero.

  • Share/Bookmark

Tags: , ,

Web browsers and time

Today I had an interesting task of figuring out why a piece of code I’d written a few weeks ago for autosaving user changes wasn’t being called as uniformly as we’d thought.

That is, on IE6 and FF, we were seeing a particular piece of code take almost twice as long to execute as it ought because (as we later found out) timings in javascript can’t be trusted.

So, if you need something to run on time, at regular intervals; use a polling pattern instead of relying on the usual javascript methods.

  • Share/Bookmark

Tags: , ,

Console.log is your friend

Although it only works in Chrome and FireBug, I’ve found console.log() to be an extremely handy tool for debugging javascript without having to step through code.

Here’s a bit of code I’ve found handy to make sure browsers without console.log don’t bomb out in case you forget to take your console.log statements out:

if (window.console == undefined) { window.console = {log:function(){},dir:function(){}}; }

Make sure to add this near the top of your scripts and you’ll be able to use console.log without fear of it causing problems in browsers like IE.

  • Share/Bookmark

Tags: ,

How many Mondays are in the month of…

I recently ran into a situation where I needed to know how many Monday’s were in a given month via javascript and figured I would make the function (which depends on Date extensions by ExtJS) for it available here in case anyone else runs into the same problem.

/*
 * This function takes a date and determines how many of each day of the week
 * are in the month.
 */
var getMonthlyDayOfWeekCount = function(sourceDate){
    var iDate = Date.parseDate(sourceDate.format('m') + '/1/' + sourceDate.format('Y'), 'm/j/Y');
    var days = [0, 0, 0, 0, 0, 0, 0];

    while (iDate.format('m') == sourceDate.format('m')) {
        days[iDate.format('w')]++;
        iDate = iDate.add(Date.DAY, 1);
    }

    return days;
};

/*
 * This function takes a date and returns an interger cotnaining the
 * occurance of this day in the month.
 *
 * Useful for when you want to know if this is the 1st or 3rd Saturday in
 * the month.
 */
var getDayInMonthCount = function(sourceDate){
    var iDate = Date.parseDate(sourceDate.format('m') + '/1/' + sourceDate.format('Y'), 'm/j/Y');
    count = 1;

    while (iDate.format('m') == sourceDate.format('m')) {
        if (iDate.format('z Y') == sourceDate.format('z Y')) {
            return count;
        }

        if (iDate.format('w') == sourceDate.format('w')) {
            count++;
        }
        iDate = iDate.add(Date.DAY, 1);
    }

    return count;
};
  • Share/Bookmark

Tags: ,