You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@wicket.apache.org by Jesse Long <jp...@unknown.za.net> on 2014/03/24 10:11:58 UTC

Best practice: JS/CSS library resource references

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?

Thanks,
Jesse

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


Re: Best practice: JS/CSS library resource references

Posted by Jesse Long <jp...@unknown.za.net>.
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 <mg...@apache.org>wrote:
>
>> On Mon, Mar 24, 2014 at 12:59 PM, Jesse Long <jp...@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 <jp...@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-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: Best practice: JS/CSS library resource references

Posted by Sebastien <se...@gmail.com>.
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 <mg...@apache.org>wrote:

> On Mon, Mar 24, 2014 at 12:59 PM, Jesse Long <jp...@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 <jp...@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.
>
>
> >
> >
> > Thanks,
> > Jesse
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> > For additional commands, e-mail: users-help@wicket.apache.org
> >
> >
>

Re: Best practice: JS/CSS library resource references

Posted by Martin Grigorov <mg...@apache.org>.
On Mon, Mar 24, 2014 at 12:59 PM, Jesse Long <jp...@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 <jp...@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.


>
>
> Thanks,
> Jesse
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>

Re: Best practice: JS/CSS library resource references

Posted by Jesse Long <jp...@unknown.za.net>.
On 24/03/2014 12:05, Martin Grigorov wrote:
> Hi Jesse,
>
>
>
> On Mon, Mar 24, 2014 at 11:11 AM, Jesse Long <jp...@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();
}

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?

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.

Thanks,
Jesse

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


Re: Best practice: JS/CSS library resource references

Posted by Martin Grigorov <mg...@apache.org>.
Hi Jesse,



On Mon, Mar 24, 2014 at 11:11 AM, Jesse Long <jp...@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


>
> Thanks,
> Jesse
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>