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: , , , ,