Search

Extension developers are increasingly needing advanced JavaScript library features, and there's recently been a lot of talk about including jQuery in the Symphony core to allow multiple extensions to share a single resource.

While I completely agree that the end result is a good thing, I don't think including a library in the core is the best way to achieve this. Here's my alternative solution:

  1. Developers should link to the minified version of their library of choice as hosted by Google. (For jQuery, the URL is http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js.)
  2. Symphony's internal addScriptToHead method should be patched so that multiple calls with the same URI only cause one <script> element to be rendered.

This doesn't restrict extensions to only being able to use the libraries Google endorses, because any URL that we can all agree on would do. Google's just seems most convenient for now. Developers can also start doing this in their extensions now, even before a 2.0.1 update containing this patch.

Some benefits of this approach are:

  • It's democratic - Symphony developers are not forced to use jQuery.
  • Updating (or not) to new versions of a library is under the control of the extension.
  • It's future-proof - in case a library stagnates, we're not stuck with a bunch of slow extensions.

I believe all extension-added JavaScript should be fully self-contained. Unfortunately, some extensions I've had a hand in (like TinyMCE and Map Location Field) rely on code in the core admin.js. This is a very bad practice, since updating the core JS risks breaking any of these extensions. Don't follow in these footsteps!

I think we really need a solution for the JavaScript framework problem, but as I wrote over in the other thread, I'm still not sure if Google should be the solution:

  1. We will be totally dependend on Google's services.
  2. JavaScript will stop working when the user is not connected to the internet (local installs).

These are two points I really don't like and I'd really prefer a core or extension based solution.

A few more questions we'll have to answer:

  1. How do we deal with custom JavaScript for fields when a user inserts multiple instances into the same section? The custom JavaScript functions should then only be loaded once, too.
  2. How do we deal with extensions calling different versions of the same framework? I'm sure this will result in compatibility issues.
  3. There need to be best practices for different frameworks so that we are sure that no conflicts arrise between them (e. g. jQuery and Mootools).
  4. How do we deal with the problem, that a user adding 5 field extensions may probably have 5 different framework inserted into the head of his admin pages? This will result in a total mess!

Furthermore, the more frameworks will be integrated by extensions (and we have to count each version of a framework as one) the more complicated debugging will become. I know that I'm in the minority of those prefering Mootools over jQuery and maybe it's not a good idea to let the extension developer decide which framework he is going to work with ...

I have no idea how to solve this best. But, as I've already posted elsewhere, I'd absolutely not be happy seeing a specific framework in Symphony's core. If I refer to framework I mean third party Javascript Libraries. Scott already mentioned my concerns about doing so as benefits doing not so. It'd make me sad seeing Symphony becoming addicted to the future of an elected Javascript Library. But, Nils, what you are mentioning, conerns me as well. Especially your last points and in particular point four.

Perhaps a best-way-guide or sticking with a pre-choosen number of libraries for extension development (Scott's approach, but more restricted) would reduce this. On the other hand doing so lets freedom fly and the mess you described in your last points still remain…

If it helps a lot, I've nothing against restriction. But the core (Symphony without extensions) should stay rock solid and still be functioning when third parties are gone, I think (not sure if I've overseen/neglected something).

I know, that I'm in the minority of those prefering Mootools over jQuery…

Not only you :)

On the other hand doing so lets freedom fly and the mess you described in your last points still remain…

To clarify what I wrote above: When I said I'd prefer a "core or extension based solution" this only refers to extensions using Javascript not to the admin script itself. I'm totally happy with the way it is and with the way it works. No need to change anything on this side.

As I'm one of the Mootools users I'd like to see something like this: A Mootools extension that other extensions can subscribe to so that always only one instance of the framework is called. Other extension should be able to specify if they need only core functionality or if they need more, too. These extensions should be able to specify the version number they have been designed for - if it is an older version the Mootools extension should add compatibility components. For jQuery there should be a separate extension designed for the needs of jQuery developers that for example allows the integration fo jQuery UI. (As I think more of it, it could be the same extension handling jQuery or Mootools calls - it should be some kind of official and be the only way JavaScript frameworks should be integrated).

This way all needed files are available in my own installation (no need for Google). Calls to frameworks would be reduced to a minimum and the usage of different frameworks would be possible ...

Sounds not bad to me :)

Would be interesting what others think…

I was thinking the same thing...

A Mootools extension that other extensions can subscribe to so that always only one instance of the framework is called. Other extension should be able to specify if they need only core functionality or if they need more, too. These extensions should be able to specify the version number they have been designed for - if it is an older version the Mootools extension should add compatibility components. For jQuery there should be a separate extension designed for the needs of jQuery developers that for example allows the integration fo jQuery UI. (As I think more of it, it could be the same extension handling jQuery or Mootools calls - it should be some kind of official and be the only way JavaScript frameworks should be integrated).

JavaScript will stop working when the user is not connected to the internet (local installs).

This is a pretty strong argument against my suggestion. Also, pulling third party javascript on privileged pages is very risky business unless you completely trust whoever hosts the file. Unless the community is willing to accept both of these problems, we'll need to figure out another solution.

A Mootools extension that other extensions can subscribe to so that always only one instance of the framework is called.

Nils, this is a clever idea, and at face value a generalised extension dependency system seems like it would have many benefits, and would also be fairly simple to implement. But when you dig deeper, a lot of problems become evident: if extension B depends on extension A, that means A can't be updated without a risk of breaking B.

Dependency is something we'd like to avoid wherever possible because it inhibits future improvements, both for extensions and the Symphony core.

I have another idea:

  1. The extension API has some way to declare a URL as "external".
  2. Any external resources that an extension uses are made known to the user, and the user can easily edit their paths.
  3. It doesn't matter whether extensions bundle or outsource jquery.js since the user can consolidate all jQuery extensions to only use a single resource.

I'm very wary of dependencies for another reason: referring to external resources does not scale to longterm on the web. The average lifetime of data on the web is around 10 years and no one knows how reliability will change in the future. What could the user do if an extension says it depends on another extension, but provides a dead link? My above suggestion would solve this problem in general, not just for javascript, and it also solves the issue of trust I mentioned by giving the user control over where resources are hosted.

How do we deal with the problem, that a user adding 5 field extensions may probably have 5 different framework inserted into the head of his admin pages?

To clarify, neither my initial suggestion nor revised suggestion will cause your pages to load 5 different libraries - they only allow for this possibility. If your page actually does load 5 different libraries, that's the result of both user and extension developer action, both of whom have the power to prevent this. Judging from past experience, the Symphony community seems very willing and capable of cooperating, and conversely, if for whatever reason you need to load 5 different libraries, I definitely don't wish to stand in your way.

But the core (Symphony without extensions) should stay rock solid and still be functioning when third parties are gone

This is exactly the development team's philosophy, and why we've stayed away from relying on third parties within the core so far.

I love the idea of including JavaScript libraries with the Symphony core except my libraries of choice are Prototype and Scriptolicious i would hate to be limited to the jquery library.

I discovered today that EE uses a similar method as to what has been suggested. For example there is a jQuery extension which other extensions can leverage.

I'd be happy with an extension for each major library (jQuery, Prototype, Mootools) which is an optional extension and that includes jQuery in the head. If the extensions were owned by the Symphony team then the decision could be made after each major release of the JS library to upgrade the extension.

I do a lot of development work offline (a long commute) and would find using a library hosted on Google or other a big handicap. Local JS is a must for my way of working.

So long as the libraries play safely with each other (for example jQuery has a compatibility mode to free up the $ function with Prototype), one could potentially have all libraries enabled at the same time.

I'd be happy to make these basic extensions; they are trivial in their simplest form.

I also support JavaScript libraries as an extension. I do not see any caveats.

I see a caveat with versioning. If the jQuery extension provides a specific release of jQuery then all other extensions must work with this version. If future releases aren't backwards compatible and our jQuery extension is updated, then extensions dependent on this will break.

Do we assume that the latest/greatest major release of each JS library is backwards compatible?

A question for Scott/Alistair — can extensions call other extensions? I'm thinking along the lines of a single JS library extension which would bundle jQuery, Mootools, Prototype etc, and other extensions call a method of this extension from a delegate call, when they want to include the JS. If this was implemented as a static/singleton, would it be possible for this inclusion to only occur once i.e. if 3 extensions all requested jQuery to be appended to the head on one page load, the JS lib extension only adds it once.

This way, the optional inclusion of JS is handled by our extensions themselves. If we don't need the JS then it never gets included in the page.

I'll try and investigate this further and get a proof of concept working.

What's wrong with my idea for editable paths to "external" resources?

It's a general solution, which means it doesn't just work for Javascript but also for anything we haven't forseen, like CSS libraries, third-party feeds, etc. which also provides an ad-hoc (and unsupported) mechanism for extensions to depend on one another. More importantly, it gives the user control of where Symphony looks for these resources, which is a form of security and future-proofing. (If a particular server is untrusted or no longer available, this is easily user-fixable and not hard-coded in the extension.)

I'm pretty keen on trying this for S3, but I wholeheartedly encourage experimentation with S2.

A question for Scott/Alistair — can extensions call other extensions?

I think the user should have control over this rather than the extension developer. A supported dependency mechanism could get hairy in all sorts of ways, e.g. legacy support tax and compatibility issues. I can describe these in more depth if anyone would like.

My personal requirements for extensions which pertain to this decision are:

  • Symphony and its extensions should be usable forever into the future (insofar as the technologies it uses continue to exist).
  • An extension should be useful even if no one is maintaining its code.
  • Developers should not be obligated to provide ongoing updates.
  • Developers should not be prohibited from providing updates.

I just don't think a dependency API satisfies those requirements as well as one where the user decides where the thing an extension depends on is located.

I'm not sure I completely understand your suggestion, Scott. How does your suggestion overcome the problem of multiple enabled extensions pulling in the same or different versions of the same JS library or external resource?

Are you suggesting that an extension developer marks their extension as using jQuery, but the user themselves can configure the URL to where jQuery exists? This works to an extent, but allowing the user to control which version of a resource to use does not allow the developer to code against a specific version.

If all developers knew to code against, say, jQuery 1.3.2 there would be commonality. If the extension declared both the library and its version, then we'd end up with the user needing to define the URLs of each individual version, which is counterproductive.

I'm of the opinion that there should be some ownership about what is included, so that extension developers have specific benchmarks to code to. Giving the control to the user to define the URL to these assets doesn't provide this to a developer.

Perhaps I don't fully understand your suggestion.

Sorry, I'm not very good at explaining things. Hopefully this screenshot should do the trick.

Imagine you had a settings page like this for every extension. There's an API for extensions to declare (maybe during the install process, or in a config file) resources as "external", which means they appear in this form and the user can change their paths if desired. This puts control for resource sharing, hosting, versioning and dependency management in the hands of the user.

Additionally, in order for this idea to work, methods in the AdministrationPage class like addScriptToHead() should be duplicate-aware, so that if multiple extensions active on a single page ask to include the same jquery.js file, only one <script> is rendered.

Attachments

This works to an extent, but allowing the user to control which version of a resource to use does not allow the developer to code against a specific version.

Giving control to the user seems like the perfect solution to this, as I see it. Suppose you have two extensions, one uses jQuery 1.3.1 and the other uses jQuery 1.3.2. The cautious user might choose separate paths to each build of the library, but I'd probably set their paths to both use 1.3.2, saving my bandwidth and CPU. If the user did not have control of this, it would be up to the developer of the first extension to check every new release of jQuery and update this extension if it's compatible. This does not jive with my requirement that "Developers should not be obligated to provide ongoing updates".

I'm of the opinion that there should be some ownership about what is included, so that extension developers have specific benchmarks to code to. Giving the control to the user to define the URL to these assets doesn't provide this to a developer.

This comes down to the meaning of "dependency". I don't think (PHP) code (functions, objects) should fall under this category. If Extension A wants to use a class defined in Extension B, why not just define that class in Extension A? This is partly the point of encouraging open source licensing of extensions.

So that just leaves things that are shared (like Javascript libraries) or third-party (like the user's Twitter feed) or otherwise customisable, which I think my idea provides a good fit for.

Hmm.. I guess my jQuery example is a little silly. I don't even know how you could have multiple versions of a library on a single page, and if you could, they'd need to be namespaced like jQuery131, etc. which would make it impossible to consolidate two extensions that expect different versions unless Symphony implements something like Google's Ajax Libraries API.

(EDIT: Ah, I'm wrong again. Google ajaxlibs doesn't sandbox libraries like I thought it did, like YUI 3 does with its modules. I wonder if anyone's tried doing that.)

That would imply, no matter which solution we go for, convention of library choice (and version!) is the only way to allow for consolidation. And that's a problem for future-proofing.

That would imply, no matter which solution we go for, convention of library choice (and version!) is the only way to allow for consolidation. And that's a problem for future-proofing.

I see two logical consequences:

  1. One framework for all (Prototype, jQuery, Mootools or any other choice) – used for admin.js, too,
  2. or a Symphony javascript framework that should be used by the core and by extensions, serving the basic needs (element selection, event handling, ajax, basic effects).

Both options would solve two main problems:

  • The high number of possibly needed javascript files (only one framework will be needed).
  • A complex API or user interface to coordinate different frameworks or multiple calls (the framework will always be present).

I see two potential problems:

  • Extensions may break if a framework changes fundamentally over the time and the development of an extension is discontinued. But old extension might also break, if Symphony's backend markup changes due to an version update.
  • All developers are forced to use one framework.

Nils, I think you're right, and I think the overall consensus points to option #1. jQuery seems to have the majority vote.

I don't think we'll have time to add this to the upcoming 2.0.2 release this week, but I'll definitely look into it soon after. Rowan has also pointed out other advantages to using a unified library, like the ability to remove/replace events (such as table row reordering), which is something I did not take care to expose with the admin JS.

jQuery seems to have the majority vote.

Harrumph, I'd vote for Mootools.

Harrumph, I'd vote for Mootools.

Me, too :)

Create an account or sign in to comment.

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details