Feb 13 2009

0

Visual Sorting Explained

Category: Mootools, UtilitiesTags: , , ,

I am getting the impression that my previous post was a bit esoteric. It has some valid uses and I want to help visualize how you might use the ‘visualSort’ method on Elements.

Lets first take a look at the demo I put up.

In the above image we have selected 5 elements. As you can see none of them are aligned and they actually overlap. However, the human eye discerns that there are 2 lines of elements. 3 on the top row, 2 on the bottom. The ‘visualSort’ method allows you to see elements like a users would in your code.

How visualSort solves this problem is two fold. First, it takes all the elements and sorts them by the ‘top’ coordinate. Once this sort is complete a second sort is performed. The first element is grabbed and an index is made based off the ‘tolerance’ (defaults to .5 or 50%). What this means is the height of the element is taken and multiplied by the ‘tolerance’. This result is added to the to the top value to get a tolerance range.

For example if chocolate had a top of 10px and was 20px in height. The tolerance would be within 10-20px. Any following element that has a top pixel within this range will be added to the same row. As an element is added to a row they are sorted by the left pixel to make sure they are in the correct order. If an element is not within that range a new row is created along with a new tolerance. The cycle repeats until all elements have been processed.

Continue reading “Visual Sorting Explained”

Tags: , , ,


Feb 13 2009

1

Visual Sorting

Category: Mootools, UtilitiesTags: , , ,

As promised I have been cleaning up the code to my most recent demo. I will be releasing a much more polished API along with documentation in the near future. Stay tuned.

I just completed one of the biggest headaches. Visual sorting. This allows DOM elements to be sorted in the same way humans would visually. I tried to make this as simple as possible to use.

I extended ‘Elements’ with a new method ‘visualSort’. The tricky part with a visual sort is the fuzzy logic needed to handle elements being offset. If you play with the demo you will get a feel for what I am talking about. In the demo, there is no need for pixel perfect alignment of elements to be considered on the same row. To require this would make the UI completely useless. To have this kind of fuzzy range matching ‘visualSort’ has a tolerance parameter. This allows you to define how much elements can be offset before it is considered a new ‘row’. Currently, tolerance defaults to .5 (50%). I also established a second parameter ‘flatten’. If set to true the sorted list will be flattened and returned as an Elements object. Currently ‘visualSort’ defaults to false which returns a multidimensional array.

In writing this code I tried to optimize the sorting as much as possible. I see a few places that can be tweaked but overall it should be fast. I didn’t use any sort() methods. I handle all my own sorting as I iterate through the elements. Feel free to ask questions about the logic or code.

Enjoy! My Brain still hurts.

 
Elements.implement({
 
	visualSort : function(tolerance,flatten){
 
		var tolerance = (tolerance) || .5;
		var idx = [], el, c1, c2, placed;
 
		for(var i = 0, l = this.length; i < l; i++){
			el = this[i]; c1 = el.getCoordinates();
			if(!i) idx[0] = [el, c1];
			else {
				j = 0; placed = false;
				while(j < i && !placed ){
					c2 = idx[j][1];
					if(c1.top < c2.top) placed = true;
					else j++;
				}
				idx.splice(j,0,[el,c1]);
			}
		}
 
		var rows = [], row = 0, sorted = [], slen, threshold;
		for(i = 0; i < l; i++){
			c1 = idx[i][1];
			if(!i){
				rows[row] = [c1.top,(c1.top + c1.height*tolerance)];
				sorted[row] = [ idx[i] ];
			}
			else {
				threshold = rows[row];
				if((threshold[0] <= c1.top) && (c1.top <= threshold[1]) ){
					j = 0; placed = false; slen = sorted[row].length;
					while(j < slen && !placed){
						c2 = sorted[row][j][1];
						if(c1.left < c2.left) placed = true;
						else j++
					}
					sorted[row].splice(j,0,idx[i]);
				} else {
					row++;
					rows[row] = [c1.top,(c1.top + c1.height*tolerance)];
					sorted[row] = [idx[i]];
				}
			}
		}
 
		var result = [];
		for(i = 0, l = sorted.length; i < l; i++){
			result[i] = [];
			for(j = 0, len = sorted[i].length; j < len; j++){
				result[i][j] = sorted[i][j][0];
			}
		}
 
		if(flatten) return $$(result.flatten());
		return result;
 
	}
 
});

Example Usage:

var sorted = $$('your selector').visualSort(.7);

I believe the value of this will be seen in Drag and Drop interfaces and layout managers. It could have some potential use for serializing specific components. If you find a use for it please share.

The demo has been updated with this code, it works in IE now.

Tags: , , ,


Feb 09 2009

13

Advanced UI component using Rubberband and Drag.Group

I knew after posting Drag.Group I needed to get a demo up quickly. The code is not completely refined yet so use at your own risk. I will be making updates over the next couple of days and will keep you posted.

A while back ago I posted an update to the Rubberband class. Its hard to understand the class unless you actually use it. One of the limitations that I found was the use of draggable elements. The coordinate locations were not updated and as a result the rubberband feature didn’t work.

I have made steps to add this functionality in place, currently the API is a bit broken and I am cleaning up how the coordinates are stored. In the meantime, I am providing a proof of concept.

Enjoy the demo!
Continue reading “Advanced UI component using Rubberband and Drag.Group”

Tags: , , , ,


Dec 04 2008

2

Image Transitions Demo

When I first launched my blog I released the Transitions class at the same time. The header of my blog at that time was my demo. I have since changed the look of my blog and as a result the demo was removed. I have had a number of requests to get it back online so here you go.

Transitions Demo

Overall I am quite happy with how these effects turned out. I think they provide for some nice alternatives over the standard image transition effects that are commonly used today.

I hope you enjoy.

Tags: , ,


Dec 04 2008

3

VisitSpy - Where have you been lately?

Category: Javascript, MootoolsTags: , ,

As many are aware Javascript has been crippled by design. These design decisions were put in place to protect your privacy from rouge websites. VisitSpy is not a Javascript exploit, it is an exploit in CSS. CSS has built in styling for displaying links in different colors to communicate to you, the user, that you have previously viewed the link. With this visual cue we can use Javascript to find out if you have visited a site.

I think it is important to note that I did not discover this exploit, Jeremiah Grossman did. He provided a proof of concept but it is not full proof. His code requires a specific color to be used for the link. In VisitSpy I have implemented a dynamic stylesheet to prevent any kind of misreadings. I definitely feel that there are some ethical concerns to using such a technique. I myself have only used the follow script to make sure it works. It is not implemented on my site nor do I ever plan to. Some may ask “Then why even posted it?”. Information is power. To prevent this exploit while you surf around the internet I recommend you checkout SafeHistory for Firefox. SafeHistory, hides all visited links unless the link was directly linked to the current site. With this plugin the CSS exploit is removed.

Now onto the fun part!
Continue reading “VisitSpy - Where have you been lately?”

Tags: , ,


Dec 04 2008

5

Registry Class for Mootools

I have been building some pretty large apps lately and I found the need for the registry design pattern in some of my javascript. I went with this approach because I wanted to minimize the power my objects had, yet I needed some kind of blackboard where all objects could check and report to.

In addition I found that implementing events onto the class made for a very effective event handler as well.

var Registry = new Class({
 
	Implements : [Events],
 
	conf : {},
 
	set : function(path,value){
		var fragments = path.split('/');
 
		if( fragments.shift() !== '') return false; // remove empty, first component
		if(fragments.length > 0 && fragments[fragments.length - 1] == '') fragments.pop();
 
		var obj = {}; var ref = obj; var len = fragments.length;
		if( len > 0){
			for(i = 0; i < len-1; i++){
				ref[fragments[i]] = {};
				ref = ref[fragments[i]];
			}					
			ref[fragments[len-1]] = value;
			this.conf = $merge(this.conf,obj);
		} else {
			this.conf = value;
		}
	},
 
	get : function(path){
		var fragments = path.split('/');
 
		if( fragments.shift() !== '') return null;
		if(fragments.length > 0 && fragments[fragments.length -1] == '') fragments.pop();
 
		var ref = this.conf; var path_exists = true; var i = 0; var len = fragments.length;
		while(path_exists && i < len){
			path_exists = path_exists && (ref[fragments[i]] !== undefined);
			ref = ref[fragments[i]]; i++;
		}
 
		return ref;
	}
 
});

The class is pretty simple but it provides for a powerful hierarchical syntax. Only two methods are supplied ‘get’ and ’set’.

Example:

var reg = new Registry();
 
reg.set('/Options/Default',{'name' : 'test', 'version' : 1});
 
reg.set('/Options/Default/name', 'changed');
 
reg.set('/dynamically/creates/nested/objects', true);
 
reg.get('/Options/Default');
/* returns
{
 name : 'changed',
 version : 1
}
*/
 
reg.get('/Options/Default/version'); // returns 1
 
reg.get('/');
/* returns
{
 Options : {
	Default : {
		name : 'changed',
		version : 1
	}
 },
 
 dynamically : {
	creates : {
		nested : {
			objects : true
		}
	}
 }
}
*/

I found it extremely useful for configuration objects for classes that were initialized in a tree fashion. It also seemed to help with the readability and organization of code. I also had several places where I had multiple objects doing completely different things to the same Request.JSON result. With this class I just stored it in a single place and fired off my event. I found it extremely useful to use the class as a global event manager for cases such as this. I ended up using a dot notation naming convention for my events which helped greatly in documentation and API design.

reg.addEvent('App.initialize',function(){});
 
reg.addEvent('App.shutdown',function(){});
 
reg.addEvent('Data.feed1.loaded',function(){});
 
reg.fireEvent('App.shutdown');

In my actual production code I had my Registry class implement my Singleton Class Mutator. This way I could initialize the registry object multiple times in my code without the need to worry about scope.

Tags: , , ,


Oct 10 2008

4

Mootools Singleton Class Mutator

Category: MutatorTags: , ,

I got really excited about Class Mutators within Mootools after reading Jan Kassens blog. If you have ever used Mootools, you have probably seen the standard Mutators. Extends and Implements. These allow you to augment your Classes to help create an inheritance model within Mootools. What I failed to realize is that Mutators goes well beyond that. They have the ability to ‘morph’ your Classes to make your code easier to read and maintain.

I went ahead and implemented the Singleton pattern into Mootools classes.

Class.Mutators.Singleton = function(self,flag){
	if(!flag) return;
	self.constructor.__instance = undefined;
	if($defined(self.initialize) && $type(self.initialize) == 'function') var init = self.initialize;
	self.initialize = function(){
		if(!$defined(this.constructor.__instance)){
			if($defined(init) && $type(init) == 'function') init.apply(this,arguments);
			this.constructor.__instance = this;
		}
		return this.constructor.__instance;
	}
}

Use:

   var Counter = new Class({
         Singleton : true,
 
        initialize : function(){
              this.count = 0;
        },
 
        hit : function(){
             return ++this.count;
       }
  });
 
var a = new Counter();
a.hit(); // returns 1
a.hit(); // return 2
var b = new Counter();
b.hit(); // return 3 !!!

Honestly, this is more for the OO purist out there. I would have to agree with Valerio that the best way to implement a singleton in javascript is to use a basic object. However, I do think that this could be useful in rare occasions.

Tags: , ,


Oct 07 2008

1

Mouse Ghost Decay

Category: JavascriptTags: ,

After posting Mouse Ghost I had the idea to implement a decay feature. The way this class works is a bit different from the original script, so I haven’t had time to properly refactor into a single class. I’m not sure its worth it ;-)

Anyways, enjoy.
Continue reading “Mouse Ghost Decay”

Tags: ,


Oct 06 2008

5

Mouse Ghost

A friend of mine was really impressed with a flash demo that creates a cursor that follows the mouse. It works by recording the mouse coordinates, after the mouse stops moving it plays back the mouse movement.

I took a few minutes to create the same effect using javascript. While my version doesn’t have an image cursor it would be trivial to add one. I also set options to specify the delay, offsets, size and color. Since the script is fairly simple I thought I would take sometime explaining how I wrote it using classes in Mootools and why.

When I develop in Mootools, the majority of the time I break my problems into classes. Many people have issues with the concept of classes in javascript because classes technically don’t exist. This has to do with the fact that Javascript doesn’t follow traditional languages in its object inheritance, it uses prototype inheritance. Classes in Mootools is a object factory that makes dealing with the prototype chain much easier. In addition, Mootools provides some very nice functionality to make classes even more powerful. Enough with the technical jargon and on to the tutorial.

The first thing I do is create a skeleton.

var MouseGhost = new Class({
 
		Implements : [Options],
 
		options : {
 
		},
 
      		initialize : function(options){
			this.setOptions(options);
		}
});

Class is provided within the Mootools framework. It accepts an object that it uses to extend the prototype chain. Mootools has a few special features, like Mutators. They let you effect the Class your creating to make code reuse easier. Here I am using a standard mutator, Implements. My class implements the Options Class. By doing so, it will now have a new method called ’setOptions’. This makes it easy to configure my objects when I initialize them with the ‘new’ keyword.
Continue reading “Mouse Ghost”

Tags: , ,


Oct 01 2008

1

Rubberband Select

Category: UtilitiesTags: , ,

A while back, Chris Esler wrote a terrific script for custom selection of elements within the DOM called Rubberband. I have found the use of Rubberband extremely handy when dealing with complex UI management. While Rubberband functioned exactly as described I found a few minor issues that I needed resolved before implementing.

The major annoyance I had with Rubberband was the actual selecting part. When selecting, the browser also selects and highlights the DOM in the background. I found this to be annoying and distracting, both hurt usability.

The second issue I found had to do with recycling the object. In my case, I was adding and removing elements to my selectable area. This required me to use the rebuild function. I found a slight bug that prevented this from working.

Both of these issues are no more!

Click to download Rubberband (enhanced)

Tags: , ,


Next Page »