Sunday, March 22, 2009
Friday, February 20, 2009
The improvements to 2.2j (also included in 2.2.1j) are explained below.
I've been tinkering with SelectBoxFactory (Help Guide) mainly because I have been getting
some feedback and want to provide some real world use cases. The tool did not come out of the box with any hooks to accept onChange events, and many people asked how they could "retrieve" the values of the dropdown.
The result is SelectBoxFactory 2.2... (or 2.2j, same thing for now - from now on always in jQuery unless someone needs it in mooTools). Its a modest improvement, but one that I think will enable more people to use it, and to me thats a more important change.
So what can you do? Based on code that is now in the internal.js file, the following examples are now available...
With selectBoxItemHook(), you can now write any code you want to run as soon as someone or some code selects an item in the select box. This applies to dropdowns and single-select items. Its very simple, but entirely critical, since this interface is not exposed to the external world. Now it is.
With gatherAllChoices() I show how you can use the method _gatherChoices(type) to collect values from a particular dropdown. Because you may have various data requirements, the type argument can be any delimiter, or "array" as text, or "json" as text. The output of selections will come in that format. The purpose of gatherAllChoices() is to show that you can create one place where all dropdowns on the screen are collected (say, as part of a form).
When you call externalClick, a new event on the dropdown, it will cause the dropdown to make a selection for you but it won't cause the dropdown to open and close, which it would do, thinking that a user was touching it. Its actually an important addition if you think about it. This way you can make programmatic calls using selectBoxItemChooser(), another demo. selectBoxItemChooser is an example of code you might write that will select items for you based on another component. (The example here is a month button on a calendar that when pressed, triggers selects the next month in the dropdown for the user).
This is just the start of the use cases, and it is small, but the changes i made to the codebase are powerful and should enable you to really take these to the next step. See the updated sections in the (Help Guide) for more information.
Friday, October 10, 2008
This is just an experiment. Just some fun. I doubt the practicality of such an interface, but then again, I felt compelled to create it. Its CPU intensive and won't look good if you have an older machine (IE 7 looked ok for me on my 1GB/pentium 4), but not great. Other browsers worked wonderfully. If you view it as text, of course it speeds up.
I made it a mooTools 1.2 set of classes and you can have multiple polyhedra on one page in different styles, although for simplicity I am showing one. It starts off life as a base polyhedra class, then can become a cube, a pyramid, or whatever you want! I have made a cube, a pyramid and a diamond shape, but there is no limit as long as you know the coordinates.
The buttons show how you can not only switch between text and images, but also you can morph the classes from one to another.
Aside from the core logic for making the polyhedron, here is what I added/changed:
- Object itself or a handle can turn the cube. (its not great if you use the object itself as the handle and I have no example of this). The handle I added was the touchpad. You make it turn by clicking and dragging on the touchpad. The yellow spotlight indicates where you left off (it maps to the polyhedra).
- If you use the ctrl key and move up or down, you can scale the entire shape.
- Can take images as shown, or plain old text, as it was.
- I added opacity for a more real effect for the images. (although at the moment in IE there is a small bug where opacity is not working for text).
- You can mouseover an image for a closer view with some moo fx.
- Click on an image to see a "details" view that I did not flesh out, its just a wireframe. I would imagine some sort of ajax request here for details. Click the image again to return it.
- I added a scatter and a reconstruction effect.
- Different browsers scale the images differently. Looks awesome in firefox, but not great in ie 7. Not sure what to do there.
The following options for the container are:
- left, top: the usual, corresponds to the cube.
- handle: the thing to manipulate.
- polyType : a class that describes the shape.
- counterSpin: moves like a pilot joytick or moves naturally.
- rotateSpeed: correlates a mousemove with a cube turn. Really its supposed to make it faster or slower, but this is so CPU intensive that its hard to notice at low numbers
- opacity: the starting opacity.
- spacing: space between the faces.
- hideCenter : hides the center object if you want.
- contents : img or text (if not images, you automatically get spans)
- scale: Creates an arrangement of the polyFaces to the polySize overall. When you change this, you should change the default picture size, if there. Leave it at the default if your not sure
- height, width: The usual, corresponds to each polyFace.
- root: where to grab the images. If your showing text, use "".
- notFound: the image or text to show if a slot is empty (I left a few).
- data: an array of image names or text. Anything you want.
About other shapes:
This is not limited to regular shapes. Again, provided you know where to place the points, you can show and rotate any shape.
To do: make text color configurable, add example of non-regular shapes, show multiple.
The algorithm for the cube in 3 dimensions was inspired by: Thiemo Mättig. The "text" version is an emulation of his work, but in this new code. This uses very little of the original code, which serves as more of an inspiration, but that core logic does drive this.
Thanks to my colleague Sualeh for his help on extending the OOP concept.
Friday, October 3, 2008
The status of my system at the time was a 50% memory allocation (of 1 GB), iTunes running, a text editor running, and the one browser. No heavy background services were running (polling).
Give it a try below and help me test! Please send me your results... :) To be fair, try closing down your apps and let ONE browser test at a time, with ONE tab. Don't let other processes get in the way. This will be the cleanest number.
If you get different results than me, or if the documentFragment results are slower, then don't freak out. Although its unlikely that this would happen, remember there is an entire world of variables to consider that make this kind of testing tough to streamline. Thats why I am exposing this and want your help.
FYI: The mouseover event does exist in both tests, and is being allocated, even if the addOption test doesn't mouseover with any visual changes. These samples are both in their own iframes, to ensure no preference.
- You can perform two kinds of tests with both these boxes.
- The first is to put a large number into the box and run each. Then jot the results and refresh. (The first test simulates how a user would feel when a page loads and they have to wait for contents to render.)
- The second test is one where you load the boxes with a reasonable number, (say 100), then keep loading over and over again without refreshing. (The second test simulates an interface where a user is tasked with "adding elements" throughout their session. How does the box respond?)
Safari is by far the fastest rendering engine (all rendering engines are not the same! Google Chrome has added elements to their rendering engine, alongside webkit, that make it just slightly slower than Safari in the current 0.2. At least in my tests).
With this test I am creating divs that emulate a select box set of options. The top is my current performance, and the bottom is simply using addOption() to append native options to a select box in the DOM (I've tested this a dozen times in all, 10 times each browser (120 tests), ask me for the complete results and I will send.):
Firefox 3 (me) : 198 ms (.4 ms per item avg)
Firefox 3 (native addOption) : 358 ms (.7 ms per item avg)
Opera 9.5 (me) : 177 ms (.4 ms per div)
Opera 9.5 (native addOption) : 136 ms (.3 ms per div avg)
Safari 3.1 (me) : 78 ms (.2 ms per item)
Safari 3.1 (native addOption) : 50 ms (.1 ms per item avg)
Chrome .2 (me) : 203 ms (.4 ms per item)
Chrome .2 (native addOption) : 416 ms (.8 ms per item avg)
Ie7 (me) : 359 ms (.7 ms per item)
Ie7 (native addOption) : 382 ms (.8 ms per item avg)
The key to all of this is when and where. If you write your methods correctly, you can massage where code is invoked, and when to push your performance over the edge.
1. When it comes to large scale iterations, don't use the toolkit DOM methods to create and insert the bulk of your objects.
- I know, it's crazy. But hear me out. There are pain points somewhere in your application where things slow down when using a toolkit. What I am saying here is that during the page load, or when returning an ajax response of 150 divs (e.g.) - don't use the toolkit to wrap these up just to get special features.
- Meaning, don't use the append, create or addevent (bind) methods (see more detail below), but use everything else (createElement, onmouseover = function, setAttribute). You can certainly use these for most of your operations, sure, and that's the point of a toolkit. But not for these heavy iterations!
- Create your own internal "shadow" array in memory of these objects with its base styling and base events, then, when the DOM has rendered, and for the rest of your application, wrap jQuery (or new Elements $) around your items and proceed as normal to style and add effects - or wait for just the right time to invoke these styles and events.
- documentFragment is your #1 friend. Instead of appending to the DOM at the end of every iteration, append to a documentFragment Element, then lastly, append the documentFragment element to the DOM.
- This works 3x faster because it is all kept in memory - not in the DOM, where rendering is slow. It is added to the DOM later and without any effort on your part, the documentFragment melts away.
- This has been around for years and supported by all browsers.
- Except for id, className and title, make your custom attribute names be 2 characters or less. This will shave many milliseconds off your rendering time.
- Did you know that if you really plan, that you only have to bind one event to an object? Yes, the mouseover event! Inside that event, bind the rest of your events conditionally. Why pay that price over and over again during iterations?
- Here is where things get hairy in IE, but if you must make ie run faster, then do this: Set the className (or "class" in non-ie browsers) by hand using setAttribute. Faster than any toolkits "addclass". Don't even use the item.className = class. Just use setAttribute.
- to inject text. I saved 30-80 ms per item doing this
- ...not toolkit addEvents or bind. Except for the little trick I mentioned above, don't bind or addEvent() during heavy iterations.
- Aside from the two types of tests, you need to test both types of boxes. One uses documentFragment technique, and one uses addOption by comparison.
- Note: if you get the "browser / script is running too error" let me know. The documentFragment test works differently in different browsers, but the addOption test can't handle large numbers! Another testament to using documentFragment.
- Note: if you want to see how I did the tests, please grab the js file in the source. If you want an explanation of what I did, please comment and I will give much more detail (probably not necessary for this).
Tuesday, September 23, 2008
The thing to realize is that this is by no means a static graph. It is always accurate to the states and numbers of items in the select box (even if you add or remove items).
Granted, it took some time even beyond that demo to get the css to work. I had to deal with max-height, and list-style-type, and it took some time to wire the logic into this chart, but the results are enjoyable. The demo here is relatively positioned, but you can tell this graph and even the dropdown (or a mix) to be absolute, and it will coast over the text instead of pushing it aside. I have it relative for the demo.
The way I have this written, and with the options I added, you can use any labels and build up to 5 states, which hopefully is plenty. You can use any colors too, but the css demo uses background-position for the colors, so you will need to update a very small image. I will be building a skinning set so you can simply choose your color theme and away you go -that is not there yet.
The graphs are the default css colors and image from the site, but they are configurable, and the labels are no longer built into the image.
Sunday, September 21, 2008
Otherwise, see 2.0 below:
Welp, i'm finally done transforming the code to be usable as a tool if you have jQuery 1.2.6+. I've spent many a week trying to perfect this in various browsers, and compiling a help guide.
Please see this link for everything you need to know.:
Select Box Factory 2.0 for jQuery (Help Guide & Download)
(give it a second to load, i've added a ton of dropdowns and code for examples in an accordion widget).