javascript1Add my vote for this tag create new tag
, view all tags

Move to jQuery


TWiki's current javascript has been refactored and unit tested. But it will never be as up to date as other libraries. We should invest our development efforts smarter.

So now there is jQuery. Widely adopted, it has a large user community. And it incorporates many smart features like the selectors as we know from behaviour.js. It is also very small.

This means that using jQuery, BehaviourContrib becomes redundant.

Currently only pattern skin uses the default TWiki javascript files, plus a number of plugins.

After 4.2 I intend to update pattern skin with jquery javascripts. Of course I do need to do testing on large pages (we have experienced some problems on IE 6 and twisty code before using behaviour.js).

jQuery sources

-- Contributors: ArthurClemens - 03 Dec 2007


I've got TwistyContrib/Plugin/Bundle ported to jQuery. Releasing tomorrow as JQueryTwistyPlugin. I've installed it here already.

-- MichaelDaum - 03 Dec 2007

Great. Did you have to make many code changes?

-- ArthurClemens - 03 Dec 2007

can we not move to JQuery, rather move to a pluggable API?

From what I saw of Michael's work, thats almost where we are at the moment.

What I'd like to be able to do, is to select which javascript toolkit I use using the skin path - so SKIN=jquery,pattern or SKIN=dojo,pattern etc. Similarly, it means that people (like me) that create plugins like RestPlugin and JSPopupPlugin are able to add us the jspopup.dojo.tmpl style approach to automatically use the currently selected js toolkit - very simple for the user.

To do this, we need documentation and unit tests for each of the JS bits the core uses, and then to implemented those in our preffered toolkits

I am willing to do dojo and yui, as I use both regularly.

-- SvenDowideit - 03 Dec 2007

Sorry the JQueryPlugin does not integrate adding jquery to the SKIN anymore. This was too unstable for different skins and versions of skins.

The jQuery-based twisties are uploaded now.

-- MichaelDaum - 04 Dec 2007

Do you mean that Sven's idea is bad in practice?

-- ArthurClemens - 04 Dec 2007

mmmm, I have been using the skin path like that for many years, and havn't found it unstable - but then I use it like an API.

Micha, please tell us more?

-- SvenDowideit - 04 Dec 2007

It is not bad practice per se. It would be good practice if we had an easier way to add javascript and css using templating. I simply was not able to figure out how to integrate jquery reliable in all versions of PatternSkin, for all script actions. This is total mess right now.

Even Wysiwyg/TinyMCE isn't integrated via templating any more. Instead a perlbased approach is much much more reliable using addtoHEAD(). That's what you want in the end: adding some bits to the head. NOT being dependent on templating is safer for now.

However, addToHEAD() has its own flaws.

Javascript and css depend on a certain order in which they are loaded by the browser (e.g. jquery.js before any jquery plugin). In addition, the same javascript/css bits get added to the html head multiple times by different plugins and templates.

A solution would be to add individual html header bits more finegrained using a key of their own while calling addtoHEAD(). That would prevent the same bit being added multiple times. However, calling order to addToHEAD() is not granting the order in which things are put into the html head. Keys in TWiki::{_HTMLHEADERS} are sorted alphabetically and then rendered in that order while generating the html head.

Last not least, while addToHEAD() is available for perl plugins, any mechanism in template-land is totally decoupled from that. There is no %ADDTOHEAD{"..." key="..."}% (lets put all security issues of that aside for a moment). So right now you end up loading the same header bits multiple times even though you'd let plugins use appropriate keys, but templates don't know about these and have no way to cooperate in header construction that way.

-- MichaelDaum - 05 Dec 2007

ok, so we're back to needing to fix addToHead - we'll add that to the list.

-- SvenDowideit - 15 Dec 2007

I did not sense that Michael and Sven completely agreed with the original proposal.

So maybe right after the 4.2.0 release we bring this up at a release meeting.

If I interpret this wrong Sven/Michael please correct me.

-- KennethLavrsen - 17 Dec 2007

I would like to see this proposal migrated into an 'abstract JS interface for TWiki' - as that would allow TWiki to continue to integrate into existing enterprise web architectures, rather than adding a somewhat hardcoded dependance on JQuery.

-- SvenDowideit - 29 Dec 2007

Do you aim at adding another layer between TWiki and a third party javascript framework?

-- MichaelDaum - 29 Dec 2007

%TMPL::ADDTOHEAD would address the requirement for making templates cooperate with addToHead. See ProcessAddToHeadAdds

-- CrawfordCurrie - 29 Dec 2007

I am expecting that TWiki is the layer - but I am not prejudging the implementation at this point. All I'm hoping to ensure is to enable TWiki's users to be able to leverage their existing invesments in JS technology, without being forced to add a dependancy on one flavour.

-- SvenDowideit - 29 Dec 2007

Sven, true. Most javascript frameworks are designed to happily coexist. So there should be no real obstacle to use two frameworks at once, besides download performance. If we can reassure that, we don't need an abstraction anymore.

The only hassle I see for now is to get the correct ordering of js files to be loaded. I'd opt to at a prio argument in addition to the key to addToHead and some %TMPL:ADDTOHEAD%.

-- MichaelDaum - 29 Dec 2007

I'd rather have dependson than prio. And I'm not convinced about the 'happily coexist' - If your site uses Dojo UI elements, it looks quite naff to suddenly have one yui one - better to engineer TWiki so that it can be set to use whatever the end user prefers.

-- SvenDowideit - 29 Dec 2007

While I liked dependson, it becomes expensive to compute the header. A prio is much simpler and gives you at least some control over ordering.

-- MichaelDaum - 30 Dec 2007

The problem with prio is deciding the contract with other users of the scheme. Do you allocate 100, 200, 300 etc to the headers defined in the templates, keeping 101..199, 201..299 for plugins? It's arbitrary. In reality, the relationships are quite clear; "I need to be loaded after this other thing" is the most common requirement, and as long as that constraint is met, then you have sufficient information to establish an ordering. See ProcessAddToHeadAdds for more specification.

-- CrawfordCurrie - 30 Dec 2007

  • While I liked dependson, it becomes expensive to compute the header?
Why would you calculate such a thing more than once?

-- SvenDowideit - 02 Jan 2008

For now the header is assembled on every click based on what plugins have added stuff to it. In the end addToHead() is supposed to take effect during the current request . Is it possible to move it out of the view pipeline?

-- MichaelDaum - 03 Jan 2008

there is no need to recalculate the dependancies, even if you were to continue to generate the headers every time. I still have a patchset pending to move much of the template evaluation out of the view pipeline - guess we should make a TemplateCache feature request so I can finish it up and add it to GeorgeTown too.

-- SvenDowideit - 03 Jan 2008

Okay sounds good smile

-- MichaelDaum - 03 Jan 2008

I'm no loger sure what the proposal is here. Can someone please refactor?

-- CrawfordCurrie - 04 Feb 2008

Too much sand.

-- ArthurClemens - 04 Feb 2008

Discussed on GeorgetownReleaseMeeting2008x02x04. No decision. Need to be discussed on Codev more

-- KennethLavrsen - 04 Feb 2008

I will refactor this proposal to show in more detail the separation of TWiki Core and javascript, and a proposal how we can make it possible to provide pluggability. I guess that it will be renamed to PluggableTWikiJavascript, and the initial implementation would be a LegacyTWikiJavascriptContrib, that would contain the existing code, and a JQueryTWikiJavascriptContrib that will implement Arthur's proposal.

-- SvenDowideit - 05 Feb 2008

Having worked on the JQueryPlugin for some time now I'd propose a different approach than Sven. Infact, I think that I've understood the "TWiki as a layer for javascript frameworks" better than before. The different js tools offer a specific set of functionality which are able to be integrated into TWiki using specific %TAG%s. These are then resolved by the underlying jquery/dojo/foobar plugin, adding the necessary headers and function calls. So in order to have a PluggableTWikiJavascript, we only need to agree on a tag interface that all of the real implementations have to adher to. For example these could be:

  • %BUTTON{...}%
  • %TWISTY{...}% ...
  • %DROPAREA{}%

Sure, the individually javascript toolkits are not 100% exchangable. Nor are they all of the same quality. So a PluggableTWikiJavascript may very well not be able to cover all of the TWikiWidgets... Also, some javascript stuff does its work in the background only, not needing the normal wiki user to explicitly ask for it, e.g. shortening all anchor texts longer than 25 chars in attachment tables adding an ellipsis in the middle, or form validation.

The advantage of this approach is that no extra level of javascript indirection is added between twiki and the actual js toolkit.

Having worked with js toolkits that add a lot of onload event handler and then traverse the dom tree is, that this approach degrades very quickly, resulting in a poor interactive browser performance. Infact, the less you traverse the dom tree the better.

In contrast a js TWikiWidget, being implemented by a PluggableTWikiJavascript, can inject just the right amount of js calls for the js toolkit at hand and point it to exactly the location inside the dom tree that it should act on, thus circumventing dom traversal.

The difference in jQuery between

is very significant. The first traverses all of the dom tree, the second boils down to a document.getElementById(). Same holds for other js tookits that add "behaviors".

So having TWikiWidgets can help on this by: (a) generating the html stub by a twiki plugin and (b) generate #ids for it and (c) add the calls to the js toolkit to the header pointing it to these #ids.

-- MichaelDaum - 06 Feb 2008

I like that better.

-- CrawfordCurrie - 06 Feb 2008

Mmmm, Michael's suggestion is not an alternative, it is one important component (actually, its the user level layer) of the entire proposal. TWikiVariables that result in Widgets need to be able to be used (in the TWiki Editor) without any care by the user of the later choice of Javascript toolkit - requireing a standardised set of TWikiVariables, but that does not avoid the need for the other components of the proposal.

As Arthur pointed out in the Release meeting, it is also important to have a common coding API for all toolkit implementors to give to the implementors of TWikiExtensions that use javascript, and for there to be one simple place to change which toolkit is used by the results.

i say this, after spending the last years working with JQueryPlugin, DojoToolKitContrib, YahooUserInterfaceContrib, and several other javascript toolkits, and working to create javascript tools that work on classic skin, patternskin, natskin and moveabletypeskin.

To do this, I implement what Michael (and others) have called TWikiWidgets, that are instansiated by a TWiki plugin that uses twiki SKIN settings to select the correct toolkit's template file.

This should all become more concrete as the refactoring of this topic starts.

An interesting fact, is that RestPlugin turns the existing TWiki Form fields (in view mode) into an inline edit widget, and will do the same to the %FORMFIELD% TML - essentially treating the fact that its an existing core standard syntax as an API.

-- SvenDowideit - 06 Feb 2008

You wrote:
> it is also important to have a common coding API for all toolkit implementors

Do you mean you want to come up with a javascript layer to hide toolkits behind? Is this feasible? We could get away with a TWikiWidgets layer only.

Or do you mean a javascript interface to TWiki itself, e.g. a jQuery $.twiki extension and the like? That's two completely different things. A twiki javascript interface should be done using exactly the toolkit that fits best the job. No need for pluggability here.

-- MichaelDaum - 07 Feb 2008

no, I don't mean a layer that the toolkits hide behind. Arthur did point out however, that there are some common TWiki related manipulations that make sense to standardise, so that we don't find ourselves with a dozen subtly different implementations of (insert something here) that widget implementors all need. For now I'm keeping my mind open to the possibility that TWikiWidgets are only one layer of the cake.

-- SvenDowideit - 07 Feb 2008

> insert something here

dom or twiki topic?

-- MichaelDaum - 08 Feb 2008

This proposal was voted for at the release meeting.

Sad that noone that debate here shows up at release meetings any longer

[23:44] <Lavr_> Sure:  1 yes (accept original proposal) 2 no (reject)  0 (don't know or don't care).
[23:44] <Lavr_> 0
[23:44] <ColasNahaboo> 1
[23:44] * OliverKrueger just read a quarter of the topics and neither has an oppinion yet.
[23:44] <PeterThoeny_> 1
[23:44] <uebera||> 1
[23:45] <ArthurClemens_> 1
[23:45] <OliverKrueger> 0


-- KennethLavrsen - 14 Apr 2008

Bugs:Item5532 is waiting for Arthur's comment, and if he's interested, I can update it to be inline with my proposal.

I received notification that there was a meeting at 1am, 5 hours before the meeting (at a time that I am asleep). This is unnacceptable.

-- SvenDowideit - 14 Apr 2008

Sven, I am sorry for the delay in sending the invite, I was away with my family over the weekend. This meeting was actually already scheduled two weeks ago, and the next one is scheduled to be on 04/28 as you can see in GeorgetownReleaseMeeting2008x04x14 minutes.

-- PeterThoeny - 15 Apr 2008

The release meeting is at the same time each 2nd Monday and you were there with two Nicks, Sven. How can you say you did not know the meeting was happening? The same two proposals have been marked ready for release meeting for months. I can understand the proposer wanted a decision made.

Arthur wrote "Too much sand" 04 Feb 2008 and I understand that statement. The original proposal was simply to enhance PatternSkin to use jQuery instead of behavior but the discussion diverted into something much more general which I can understand Arthur could not find a way to comment and was way beyond the scope of the developer commitment.

We need to get better at

  • Addressing the actual proposals
  • Give a clear statement for or against the original proposal
  • Refactor the proposal in order to reach a consensus whenever possible.

The arguments at the release meeting for making a decision on this proposal was that the rest of the discussion on this topic was about extending APIs and not addressing the actual topic: "jQuery or not jQuery" and that deciding FOR this proposal would not prevent implementing APIs and other fine ideas at a later time.

-- KennethLavrsen - 15 Apr 2008

Yes, its a worry that trying to find the best possible technical solution that addresses a proposal is considered 'sand'. I'm finding that more and more proposals are becoming complaints that we don't just implement the simple, not completely worked through idea, and that anything that requires engineering is considered obstructive.

I want TWiki to be better and more able to meet our users needs, not just eh easiest to write.

-- SvenDowideit - 15 Apr 2008

I vote in favour of a move to JQuery. I would love to see Arthur implementing its proposal. I'm no JavaScript expert but I did use it quite a bit over the past two years in plug-ins or TWikiApplications. I came across JQuery three months ago thanks to MichaelDaum and its JQueryPlugin. I was amazed how much I could do with JQuery in very little time.

I understand Michael's idea of using %VARIABLES% to abstract the actual JavaScript library we use yet it has the following downsides:

  • Extra effort to implement
  • TWiki specific - If I learn JQuery instead I can reuse that knowledge in other platform
  • Limited power - It will only give access to a very limited subset of JQuery functionalities

What I'm trying to say is that having those variables for us TWiki geek to use is fine. But we could also make a decision to stick to JQuery for good, delivering a message like "TWiki is powered by JQuery" and create a special relationship between the two communities. It could attract JQuery developers to the TWiki platform and benefit both communities.

-- StephaneLenclud - 15 Apr 2008

I personally find jQuery to be too hackerish compared to the more complete Javascript toolkits - I prefer Dojo by a long way.

I think that in the absense of a everybody agrees, standout best option, we should be using TWikis plugability mechanisms to increase the choices that TWiki users have to integrate TWiki with their existing systems.

The thing that is really scary, is that using skin path to choose Javascript implementation is really simple.

I will be doing this to TwistyPlugin because I need a Dojo based version - perhaps its just a case of waiting to see how that goes (ie, before the next meeting)

The first stage - refactoring TwistyPlugin to use the javascript from JQueryTwistyPlugin, (I have not yet brought across Micha's good code changes from the Perl, as it would confuse this example) looks like:

Index: lib/TWiki/Plugins/TwistyPlugin/MANIFEST
--- lib/TWiki/Plugins/TwistyPlugin/MANIFEST   (revision 16680)
+++ lib/TWiki/Plugins/TwistyPlugin/MANIFEST   (working copy)
@@ -1,2 +1,6 @@
 data/TWiki/TwistyPlugin.txt 0644
 lib/TWiki/Plugins/TwistyPlugin.pm 0444
Index: lib/TWiki/Plugins/TwistyPlugin.pm
--- lib/TWiki/Plugins/TwistyPlugin.pm   (revision 16680)
+++ lib/TWiki/Plugins/TwistyPlugin.pm   (working copy)
@@ -106,24 +106,11 @@
     return if $doneHeader;
     $doneHeader = 1;
-    my $header .= <<'EOF';
-<style type="text/css" media="all">
-@import url("%PUBURL%/%TWIKIWEB%/TwistyContrib/twist.css");
-<script type='text/javascript' src='%PUBURL%/%TWIKIWEB%/BehaviourContrib/behaviour.compressed.js'></script>
-<script type="text/javascript" src="%PUBURL%/%TWIKIWEB%/TWikiJavascripts/twikilib.js"></script>
-<script type="text/javascript" src="%PUBURL%/%TWIKIWEB%/TWikiJavascripts/twikiPref.js"></script>
-<script type="text/javascript" src="%PUBURL%/%TWIKIWEB%/TWikiJavascripts/twikiCSS.js"></script>
-<script type="text/javascript" src="%PUBURL%/%TWIKIWEB%/TwistyContrib/twist.compressed.js"></script>
-<script type="text/javascript">
-// <![CDATA[
-var styleText = '<style type="text/css" media="all">.twikiMakeVisible{display:inline;}.twikiMakeVisibleInline{display:inline;}.twikiMakeVisibleBlock{display:block;}.twikiMakeHidden{display:none;}</style>';
-// ]]>
+    #get twistyplugin.tmpl by default
+    TWiki::Func::loadTemplate( lc($pluginName) );
+    my $header = TWiki::Func::expandTemplate('twisty:header');
-    TWiki::Func::addToHEAD( 'TWISTYPLUGIN_TWISTY', $header );
+    TWiki::Func::addToHEAD( 'TWISTYPLUGIN_TWISTY', $header||'<!-- twisty:header not found in %SKIN% -->' );
Index: templates/twistyplugin.jquery.tmpl
--- templates/twistyplugin.jquery.tmpl   (revision 0)
+++ templates/twistyplugin.jquery.tmpl   (revision 0)
@@ -0,0 +1,17 @@
+<style type="text/css" media="all">
+@import url("%PUBURL%/%TWIKIWEB%/JQueryTwistyPlugin/twist.css");
+<script type="text/javascript" src="%PUBURL%/%TWIKIWEB%/JQueryTwistyPlugin/twist.js"></script>
+<script type="text/javascript" src="%PUBURL%/%TWIKIWEB%/TWikiJavascripts/twikiPref.js"></script>
+<script type="text/javascript">
+// <![CDATA[
+var styleText = '<style type="text/css" media="all">.twikiMakeVisible{display:inline;}.twikiMakeVisibleInline{display:inline;}.twikiMakeVisibleBlock{display:block;}.twikiMakeHidden{display:none;}</style>';
+// ]]>
Index: templates/twistyplugin.tmpl
--- templates/twistyplugin.tmpl   (revision 0)
+++ templates/twistyplugin.tmpl   (revision 0)
@@ -0,0 +1,18 @@
+%{ this is the default fallback header for TwistyPlugin, thus using TwistyContrib (currently part of default TWiki ) }%
+<style type="text/css" media="all">
+@import url("%PUBURL%/%TWIKIWEB%/TwistyContrib/twist.css");
+<script type='text/javascript' src='%PUBURL%/%TWIKIWEB%/BehaviourContrib/behaviour.compressed.js'></script>
+<script type="text/javascript" src="%PUBURL%/%TWIKIWEB%/TWikiJavascripts/twikilib.js"></script>
+<script type="text/javascript" src="%PUBURL%/%TWIKIWEB%/TWikiJavascripts/twikiPref.js"></script>
+<script type="text/javascript" src="%PUBURL%/%TWIKIWEB%/TWikiJavascripts/twikiCSS.js"></script>
+<script type="text/javascript" src="%PUBURL%/%TWIKIWEB%/TwistyContrib/twist.compressed.js"></script>
+<script type="text/javascript">
+// <![CDATA[
+var styleText = '<style type="text/css" media="all">.twikiMakeVisible{display:inline;}.twikiMakeVisibleInline{display:inline;}.twikiMakeVisibleBlock{display:block;}.twikiMakeHidden{display:none;}</style>';
+// ]]>

Defering the choice of Javascript using the skin path (ie, if you set SKIN=jquery,pattern) (which works already) is that trivial, and so long as all javascript, and its attendant html is abstracted via this mechanism, reduces lock-in.

Next up, writing the Dojo version, and to templatize the HTML too.

-- SvenDowideit - 16 Apr 2008

Excelent points Stephane. I totally agree. Surely, jQuery can just be enabled on a topic without using %VARIABLES%. There are so many little cases where jQuery will be usable directly that you will never cover them all using variables, e.g. onclick events etc. JQuery is much too flexible that it would be reasonable to seal it behind twiki's plugin mechanisms. However, a standard set of variables does make a lot of sense, i.e. for standard users that don't know javascript, and who just want to have a tab interface for a couple of headlines. As Sven said, jquery can become hackerish. There definitely is a market to ease access to the most common widgets. Note also, that you can easily bring down interactive performance of a page using too many class-selectors. Lots of people do that instead of id-selectors. Even the manualas are using class-selectors most of the time. So it is no wonder that users tend to increase browser load more than needed when writing jquery directly. What the TWikiWidgets in the JQueryPlugin do is (a) automatically create IDs for those elements that are addressed by jquery and (b) create calls to the respective jquery plugin underneath and (c) add this to the html head, pointing it to the created IDs. Anything else is just syntactic sugar.

-- MichaelDaum - 16 Apr 2008

And here is step 2, TwistieWithOriginalOrJQueryOrDojo.patch TwistyPlugin with original, JQuery or Dojo JS, selectable using the SKIN path.

The details of how to add the tmpl portion to the Html Head will improve dramatically with ProcessAddToHeadAdds.

This is the approach I am advocating in All the TWiki Core, so that things can be extended (essentially future proofed) without preventing each developer from just implementing using their preferred toolkits. If all JS inclusions are moved to this mechanism, and Arthur (and Micha?) adds a 'jquery' version (the default version should really be NOPs) then Crawford and I are likely to add Dojo, and perhaps Vicki will have someone look into doing a YUI version.

-- SvenDowideit - 16 Apr 2008

That looks doable for plugins. I would have to investigate if this approach is feasible for skins as well.

-- ArthurClemens - 16 Apr 2008

I like it.

-- MichaelDaum - 17 Apr 2008

I have commited the switchable js backend changes to SVN - I think it would be beneficial to consider updating the 4.2 release branch with it too.

(Still need to merge Micha's perl changes)

-- SvenDowideit - 22 Apr 2008

Nokia and Microsoft are adopting jQuery as part of their official application development platform

-- ArthurClemens - 29 Sep 2008

2 years later, it is pretty clear that JQuery is the winner: http://www.google.com/trends?q=jquery,behaviour,dojo,yui

Creating an Javascript abstraction layer is too much work for too little gain. Best to simply standardize on JQuery. E.g. the PatternSkin should change from Behaviour to JQuery. The TopMenuSkin already does.

-- PeterThoeny - 2010-06-06

This is already in HelsinkiRelease (TWiki-5.0), but there is some dependency on Behaviour JS library that needs to be removed. Anyone taking this?

-- PeterThoeny - 2010-07-29

Ping. This is useful and powerful feature. The Behaviour JS library needs to be replaced in the WYSIWYG editor and possibly other places such as PatternSkin.

-- PeterThoeny - 2010-11-02

Topic attachments
I Attachment History Action Size Date Who Comment
Unknown file formatpatch TwistieWithOriginalOrJQueryOrDojo.patch r1 manage 13.1 K 2008-04-16 - 08:56 SvenDowideit step 2, TwistyPlugin with original, JQuery or Dojo JS, selectable using the SKIN path
Edit | Attach | Watch | Print version | History: r53 < r52 < r51 < r50 < r49 | Backlinks | Raw View | Raw edit | More topic actions
Topic revision: r53 - 2010-11-02 - PeterThoeny
  • Learn about TWiki  
  • Download TWiki
This site is powered by the TWiki collaboration platform Powered by Perl Hosted by OICcam.com Ideas, requests, problems regarding TWiki? Send feedback. Ask community in the support forum.
Copyright © 1999-2015 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.