Just a future facing note, but HTML5 adds .classList which would likely perform better than any possible trick we could use with strings, arrays, or regexes.
~Daniel Friesen (Dantman, Nadir-Seen-Fire) Julian Aubourg wrote: > It may seem conter-intuitive but, in the end, the less you handle within the > VM the better. Since I want to support regexps, why make some special code > with branching and javascript based handling just for "simple" strings. > See, your code does apply a regexp on node.className. It should also split > the classNames parameter (because you can have multiple class names) and so > apply a regexp onto it. Except you will have to loop through the resulting > array in the VM and make everything a regexp could do by hand. The string > parameter transformed to a regexp applied onto node.className does all of > this. So in the end, transforming the string into a regexp, as complicated > and stupid as it seems, means less time within the VM and more within > built-in (compiled) functions. And, of course, on top of that, I don't have > custom code just for strings but common ground for both strings & regexps > which is an asset from a maintenance point of view. > > I'm not saying my solution is faster but I somehow doubt it is much slower > if at all, especially given assigning node.className seems to be the > bottleneck here. > > Have you tried the sample page? > > 2009/3/27 Daniel Friesen <[email protected]> > > >> Transforming every simple class check into a regex? That sounds like a >> horribly roundabout way to do something extremely simple. >> What happened to good old classic string testing? (" " + this.className >> + " ").indexOf(" foo "); >> A tiny bit of trickery, and that could be turned into a good possibility. >> >> (" " + node.className.replace(/\s+/, " ") + " ").indexOf(" " + className >> + " "); >> >> ~Daniel Friesen (Dantman, Nadir-Seen-Fire) >> >> Julian Aubourg wrote: >> >>> And gmail borked the sample page link :/ >>> http://www.tfuture.org/julian/classname.html >>> >>> 2009/3/27 Julian Aubourg <[email protected]> >>> >>> >>> >>>> So, I talked about making a plugin I would be the only one to use, >>>> >> didn't >> >>>> I? ;) >>>> http://www.tfuture.org/julian/jquery.classname.js >>>> >>>> The test page is here: http://www.tfuture.org/julian/classname.html< >>>> >> http://www.tfuture.org/julian/jquery.classname.js> >> >>>> (I borrowed a piece of internet from a friend) >>>> >>>> The plugin replaces jQuery.className and .hasClass(), .addClass(), >>>> .removeClass(). It also adds .replaceClass(). The thing is, it enables >>>> regexps so you can do something like .removeClass(/color\-.*/) and it >>>> >> will >> >>>> work. I'm currently thinking about re-implementing .toggleClass() using >>>> >> the >> >>>> same implementation trick. >>>> >>>> So anyway, what is the trick? >>>> >>>> Rather than splitting the classNames given AND the element.className, I >>>> transform the classNames into a single regular expression that's >>>> matched/used onto element.className. The beauty of it is, using this >>>> technique I can take regexps or strings as classNames, it just works. >>>> >> Also, >> >>>> the regexp is computed only once per call to every xxxClass() method but >>>> that's a trick that could be applied onto the current implementation. >>>> >>>> Now my real problem is that I try & get timings comparisons and I can't >>>> >> get >> >>>> it right. Results change given the order in which you do the tests Oo. I >>>> probably made a huge mistake in the way I handled my timers but it's >>>> >> like >> >>>> 4am and an half here in Paris and my eyes just refuse to find the >>>> >> problem >> >>>> (ANY HELP IS WELCOME ;) ). >>>> >>>> Sad about the timer thingy because at first glance it seemed to be a 20% >>>> performance gain on a single node. I'm pretty confident that the new >>>> implementations are at least on par with current ones (save from >>>> >> hasClass, >> >>>> given it uses .is() actually) but I'd like to be sure. >>>> >>>> -- Julian >>>> >>>> 2009/3/26 Julian Aubourg <[email protected]> >>>> >>>> >>>> >> $(node).filter('.color-black').removeClass('color-black').addClass('color-white').end() >> >>>>> And you find that more readable than >>>>> $(node).replaceClass('color-black','color-white') ? ;) >>>>> >>>>> The main issue here is that I dunno what the class will be in the first >>>>> place. I just know it will be "color-XXX" but I have no idea what the >>>>> >> XXX >> >>>>> is. All I have are clickable elements that basically say: "set >>>>> >> backroung to >> >>>>> red", "set background to green", etc etc. It could also be "set >>>>> >> background >> >>>>> to image1 and font-weight to bold" or anything else, the point is I'm >>>>> >> not >> >>>>> supposed to know the exact changes it is supposed to do visually to the >>>>> targeted element (that's the whole point: keeping the style info in the >>>>> >> css >> >>>>> and use classes to switch the visual properties). >>>>> >>>>> So clearly, the first step is to find which of the color-XXX the >>>>> >> element >> >>>>> is tagged with, then replace it with color-YYY as asked by the other >>>>> clickable element. So, yes, regexp support on hasClass / removeClass >>>>> >> would >> >>>>> be greatly appreciated (you don't wanna know how horrible my current >>>>> >> code is >> >>>>> -- basically relying on ids and a secondary structure to keep track of >>>>> >> the >> >>>>> actual color class -- hence duplicating the information). >>>>> >>>>> Now, onto the replaceClass. Well, node.removeClass(X).addClass(Y) is >>>>> basically: >>>>> - 1 split of X to arrayX >>>>> - 1 split of Y to arrayY >>>>> - (arrayX.length + arrayY.length) splits of the node's class attribute >>>>> - (arrayX.length + arrayY.length) times searches in the resulting split >>>>> >>>>> On a side note, I don't even get why add and remove actually delegate >>>>> >> to >> >>>>> jQuery.classname.has() knowing the function does a split of the class >>>>> attribute each time it is called rather then splitting the class >>>>> >> attribute >> >>>>> themselves and be done with it once and for all. It sure saves some >>>>> >> bytes in >> >>>>> the filesize department but it does not seem right to me from a >>>>> >> performance >> >>>>> point of view. >>>>> >>>>> Even if removeClass and addClass only did one split of the class >>>>> >> attribute >> >>>>> each, it would still be one split too many for a replacement. >>>>> >>>>> All I'm saying in the end is that a replaceClass() function would be >>>>> simpler in usage and much more efficient (depending on the performance >>>>> penalty of a regexped split) than chaining removeClass() and >>>>> >> addClass(). >> >>>>> I guess that, today, most people do set style properties manually but >>>>> class switching is so much more elegant, solid (since you don't have to >>>>> >> keep >> >>>>> track of which style properties were set previously so that you reset >>>>> >> them >> >>>>> before applying new ones) and efficient (you only change a string >>>>> >> portion in >> >>>>> an attribute and you don't have to go through jQuery's style engine). >>>>> >> I'm >> >>>>> just a bit puzzled jQuery makes it difficult by design in that it does >>>>> >> not >> >>>>> provide regexp support for class search and forces into an efficient >>>>> solution to change a class for another. >>>>> >>>>> Probably nitpicking anyway but then again, I'm just telling because I >>>>> >> have >> >>>>> a real-life case on the table right now ;) >>>>> >>>>> Oh well, I guess it's time to make another plugin no-one will use apart >>>>> from me ;) >>>>> >>>>> Thanks for the feedback, Dan, >>>>> >>>>> -- Julian >>>>> >>>>> 2009/3/26 Daniel Friesen <[email protected]> >>>>> >>>>> >>>>> >>>>> >>>>>> Having .hasClass / .removeClass support regex has been discussed >>>>>> >> before, >> >>>>>> there is a ticket open for one of them so it might be a possibility. >>>>>> >>>>>> I don't see much use for replaceClass, rather I think the semantics of >>>>>> reading it would be a little confusing. I can't even understand what >>>>>> >> the >> >>>>>> code you have there is even supposed to do. >>>>>> I see no reason to combine add and remove into one. >>>>>> >>>>>> Just a quick tip, if you're trying to do boolean stuff: >>>>>> >>>>>> >>>>>> >> $(node).filter('.color-black').removeClass('color-black').addClass('color-white').end()... >> >>>>>> That there would replace color-black with color-white but only for >>>>>> >> nodes >> >>>>>> with color-black, the .end() returns back to the original $(node) so >>>>>> chaining can continue. >>>>>> >>>>>> ~Daniel Friesen (Dantman, Nadir-Seen-Fire) >>>>>> >>>>>> Julian Aubourg wrote: >>>>>> >>>>>> >>>>>>> Hey all, >>>>>>> I'm working on a site that offers some customizability regarding >>>>>>> >>>>>>> >>>>>> elements >>>>>> >>>>>> >>>>>>> colors (background & font). Rather then setting the color with >>>>>>> >> .css(), >> >>>>>> I use >>>>>> >>>>>> >>>>>>> classes like color-red, color-green, etc (and of course, red is not >>>>>>> >> the >> >>>>>> css >>>>>> >>>>>> >>>>>>> "red" and green is not the css "green"). I find it much cleaner since >>>>>>> >>>>>>> >>>>>> I >>>>>> >>>>>> >>>>>>> need not have color values referenced within javascript or php (it's >>>>>>> >>>>>>> >>>>>> simply >>>>>> >>>>>> >>>>>>> in the css). >>>>>>> >>>>>>> However, the code seems unnecessarily bloated for switching classes. >>>>>>> >>>>>>> >>>>>> What >>>>>> >>>>>> >>>>>>> would be very useful imo, is to have hasClass accept regexp & return >>>>>>> >>>>>>> >>>>>> the >>>>>> >>>>>> >>>>>>> array of found classes and also a .replaceClass() function that would >>>>>>> >>>>>>> >>>>>> change >>>>>> >>>>>> >>>>>>> a class into another. That way I could do the following: >>>>>>> >>>>>>> var colorClasses = $.hasClass(/color-.+/); >>>>>>> if (colorClasses!==false) { >>>>>>> var currentColorClass = colorClasses[0]; >>>>>>> } >>>>>>> // Do stuff with the color class >>>>>>> $.replaceClass(currentColorClass,"color-"+newColor); >>>>>>> >>>>>>> As of today, I have only two solutions: >>>>>>> - keep the current color using $.data() or any other custom data >>>>>>> >>>>>>> >>>>>> container >>>>>> >>>>>> >>>>>>> - OR search the class attribute by hand (hoping classes are in a >>>>>>> >>>>>>> >>>>>> specific >>>>>> >>>>>> >>>>>>> order, you can imagine the mess) >>>>>>> >>>>>>> If that wasn't bad enough, after that, to replace the class, I have >>>>>>> >> to >> >>>>>> call >>>>>> >>>>>> >>>>>>> $.removeClass() and $.addClass() which seems pretty inefficient to >>>>>>> >> me. >> >>>>>>> I know I could probably do a plugin for that but I have the feeling >>>>>>> >>>>>>> >>>>>> that, if >>>>>> >>>>>> >>>>>>> embedded in jQuery with its class related code, it would be much more >>>>>>> efficient. >>>>>>> >>>>>>> I also know I could switch back to the .css("background-color",color) >>>>>>> >>>>>>> >>>>>> but it >>>>>> >>>>>> >>>>>>> kinda defeats the purpose of having the presentation information in >>>>>>> >> the >> >>>>>> css >>>>>> >>>>>> >>>>>>> and ONLY in the css which I find pretty nice for maintenance. >>>>>>> >>>>>>> Yes, and finally, am I crazy or couldn't this be quite useful? >>>>>>> >>>>>>> Take care, all, >>>>>>> >>>>>>> -- Julian >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>> > > > > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "jQuery Development" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/jquery-dev?hl=en -~----------~----~----~----~------~----~------~--~---
