Hi Sebastien,

Session overriding app defaults allows you to set a different theme for the session. Like a custom CSS for that session.

I'm talking about simple library settings objects, like yours I put in the previous mail and like Select2's etc.

I did not mean extending IJavaScriptLibrarySettings, just a brand new object that has methods like: getJQueryUICSSResourceReference() etc. I dont think it would be a good idea to start analyzing the class hierarchies of these settings objects.

I originally wanted to just raise awareness about the inability to have page specific customizations in most Wicket libraries out there. I was hoping to arrive at some kind of best practice for locating library settings, which allows for per page customizations. My idea was that each library, like yours for example, would implement it independently.

The more I think about it, the more it looks like a really good implementation will consist of too many parts for each library to implement independently.

Martin's last email looks like he would also like the solution to be a reusable one, so that all JS libraries can gain advantage of using the settings locator.

Last night I started working on some classes to implement just this idea in a re-usable way. Unfortunately, the code that came out was quite ugly. Just not a very neat solution. I'm going to continue working on this, and hopefully come up with something that is respectable. I'll create a github repo when I have something worthwhile.

I have another, similar idea which I did not discuss in the last email, but which I am now thinking of doing at the same time: It's becoming less and less accurate to say a JS library depends on JQuery. More often than not, a JS library depends on specific versions or version ranges of JQuery. I would like to be able to declare dependencies on JQuery, and provide a version range. All components etc that renderHead() can then specify which versions of JQuery they can work with, and I have a custom IHeaderResponseDecorator that records what different components wants, and during close() picks a version that will work with all the components on the page.

I think this, second idea will help with the concerns you raised. I haven't worked out exactly how I'm going to implement this yet, but I'm pretty sure it should be easy with subclassing HeaderItem and a custom IHeaderResponse. Will also implement some features from wicketstuff-jslibraries.

I'll post once I have some code to show.

Cheers,
Jesse

On 24/03/2014 16:46, Sebastien wrote:
Hi,

I like the idea too... Even, I am not sure to have understood the use-case
about the Session scope here, but I trust you :)

I've got one question...
Imagine you are supplying 2 libraries, "plugin1" and "plugin2" for instance

The libraries definitions would be
IPlugin1LibrarySettings extends IJavaScriptLibrarySettings
IPlugin2LibrarySettings extends IJavaScriptLibrarySettings

Then, you define you custom script like:
MyLibrarySettings extends JavaScriptLibrarySettings implements
IPlugin1LibrarySettings, IPlugin2LibrarySettings

By doing this, I *cannot* have the same getters for returning the plugin's
JavaScriptResourceReference, ie:
IPlugin1LibrarySettings#getPluginJavaScriptResourceReference
IPlugin2LibrarySettings#getPluginJavaScriptResourceReference

So, user wishing to provides its own library have to check all
IxxxLibrarySettings interfaces to not overlap an existing getter name, even
interfaces of satellite projects (but he will never do it of course...). Do
you see the point?

I think that, by writing a new strategy for loading/customizing javascript
library resource references, it would be nice to solve this question in the
meantime... (if you are waiting for my solution, I should tell you that I
do not have it yet! ;) )

What so you think?

Best regards,
Sebastien.


On Mon, Mar 24, 2014 at 12:12 PM, Martin Grigorov <mgrigo...@apache.org>wrote:

On Mon, Mar 24, 2014 at 12:59 PM, Jesse Long <j...@unknown.za.net> wrote:

On 24/03/2014 12:05, Martin Grigorov wrote:

Hi Jesse,



On Mon, Mar 24, 2014 at 11:11 AM, Jesse Long <j...@unknown.za.net>
wrote:
  Hi All,
Wicket uses mostly ResourceReferences to render and manage the URLs for
CSS and JavaScript files to be included in the output.

When we use libraries like JQuery UI, Bootstrap etc, it is often a
requirement to allow the user to provide his own customized resource
references. Typically, our code that integrates Wicket with these
libraries
provides a "settings" object, which contains getters and setters for
resource references, as well as some other variables that manipulate
the
libraries behavior.

eg: https://github.com/sebfz1/wicket-jquery-ui/blob/master/
wicket-jquery-ui-core/src/main/java/com/googlecode/
wicket/jquery/core/settings/IJQueryLibrarySettings.java

I want to propose some behavior regarding these settings objects, which
will hopefully make our lives a little easier. Initially, I just want
to
generate discussion. We can talk and decide what is the best plan (or
if
any plan is needed).

At the moment, the general pattern I have observed is: Settings objects
are configured on the Application. renderHead() retrieves the settings
object from the Application, and uses the resource reference configured
that settings object to render the header items. Sometimes, if there is
no
Application, or no settings object registered with the application,
then
the default resource references packaged with the wicket integration of
the
library are used.

The problem I have with this is that it only really allows for one set
of
resources references/settings per application. (Yes, I know
wicket-bootstrap has theme providers etc, but I'm talking about your
day
to
day Wicket/JS library integration that uses the pattern above). If you
have
page A and page B, which both use JQueryUI, for example, and both
require
*different* customized JQueryUI resource references, or each require
different settings for the JQueryUI library, then it becomes
complicated.
What I have been doing recently is this: settings object are
Serializable.
There are default settings if no settings object can be found. Settings
objects can be registered to Application using MetaData pattern (saves
us
having to use a special type of Application), and, importantly,
settings
objects can also be registered to Pages, again using the MetaData
pattern.

This way, you can have separate settings for each page, and have
multiple
pages using wildly different customizations of the library.

Basically, renderHead() code looks something like this:

renderHead(Component component, IHeaderResponse response)
{
      MyLibrarySettings settings = MyLibrary.getSettings(component);

      // render head using MyLibrary settings.
}

and you have helper methods like:

public class MyLibrary
{
      private static final MetaDataKey<MyLibrarySettings> key = ...;

      public static void setApplicationSettings(Application app,
MyLibrarySettings settings)
      {
          app.setMetaData(key, settings);
      }

      public static void setPageSettings(Page page, MyLibrarySettings
settings)
      {
          page.serMetaData(key, settings);
      }

      public static void getSettings(Component component,
MyLibrarySettings
settings)
      {
          MyLibrarySettings settings = component.getPage().
getMetaData(key);

          if (settings == null){
              settings = Application.get().getMetaData(key);
          }

          if (settings == null){
              settings = getDefaultMyLibrarySettings();
          }

          return settings;
      }
}

What do you all think?

  I like the idea.
Here are the improvements I see:
- use the Session in between, so you can have settings per user session
- always check for Session/Application.exists() before calling #get()
- extract an interface so MetaData impl can be an option when the
settings
are Serializable. Someone may prefer to store the settings otherwise and
keep the page size smaller


Hi Martin,

Thanks for your input.

You talk about an alternative to find page specific settings, are you
thinking of something like the following?

if (page instanceof IMyLibrarySettingsProvider){
     ((IMyLibrarySettingsProvider)page).getMyLibrarySettings();
}

The API would be: ILibrarySettingsProvider#get(Component).
It is up to the provider impl to decide how to load the settings - from the
component's (page's) metadata or to load them from external storage by
using the component id (same as page id), component path, or anything else
as a key.


Point taken regarding Application/Session #exists() before #get().

Adding sessions: I think the order should be: page, session, application.
Session specific settings really means, "having per session overriding of
application defaults". The requirement for having page level settings is
there because the app level settings are not enough. If we check session
level first, we are back in a situation where we cannot have two
different
customizations on different pages. Do you agree?

Yes. First ask the component/page, then maybe the request cycle ?!, then
the session and finally the application.
This way you can have library settings with request scope too. Not sure
whether this is needed. But settings per component/page is also not very
common requirement.


Regarding extracting an interface. I agree, and think this is a good
idea.
However, it will require another setting on the app level - getter,
setter
for the locator/strategy for locating settings.

Yes. This way all this can be reused for wicket-jquery-ui,
wicket-bootstrap, and any other library. Otherwise it will be something
specific for your app or just one of those libs.




---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org
For additional commands, e-mail: users-h...@wicket.apache.org

Reply via email to