Building jQuery based plugins in Liferay 6

jQuery is a fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. jQuery is designed to change the way that you write JavaScript. Refer to http://jquery.com/

Liferay portal 6 uses Alloy UI instead of jQuery, which means YUI3 (http://developer.yahoo.com/yui/3/) is included as core part, and jQuery is not included as core part anymore.  Ideally you can use whatever version of jQuery you need for your custom developments, refering to the blog post Can I have different jQuery versions in Liferay? and ticket LPS-10872.

This article will introduce how to build jQuery based plugins in Liferay 6. Hope that this article would be helpful to upgrade custom portlets from 5.1.x or 5.2.x to 6.x.

Build jQuery based plugins
Here I use Liferay 6.0.3 GA (revision 57559) and plugins SDK.

  • Build a project called “sample-jquery-portlet” with folder “docroot” and build.xml
  • Add CSS under the folder /docroot/css
  • Add images under the folder /docroot/css
  • Add jquery under the folder /docroot/js
  • Add liferay-display.xml, liferay-plugin-package.properties, liferay-portlet.xml, portlet.xml under the folder /docroot/WEB-INF

Especially, add following lines, for example, in the file liferay-portlet.xml.
<portlet>
    <portlet-name>1</portlet-name>
    <icon>/images/world.png</icon>
    <header-portlet-css>/css/style.css</header-portlet-css>
    <header-portlet-javascript>/js/jquery.js</header-portlet-javascript>
    <footer-portlet-javascript>/js/jquery-ui-custom.js</footer-portlet-javascript>
    <css-class-wrapper>sample-jquery-portlet</css-class-wrapper>
</portlet>

Note that the property header-portal-javascript sets the path of JavaScript that will be referenced in the page's header relative to the portal's context path; and the property footer-portal-javascript sets the path of JavaScript that will be referenced in the page's footer relative to the portal's context path.

  • Add JSP files under the folder /docroot/jsp.

Note that you may include addition JavaScript at JSP file like

<script type='text/javascript' src='js/jquery_1.4.2.js'></script>

Sample Screenshots

Testing environment: Liferay portal 6.0.2.and 6.0 GA (6.0.3 - revision 57559)

A few jQuery examples:

Fade in

Animate

Fade out

Do it yourself
You can download the WAR with source code at:

sample-jquery-portlet-6.0.2.1.war

and drop it to $PORTAL_HOME/deploy or use UI "Plugins Installation" under Control Panel. For more details, you may refer to the book Liferay Portal 6 Enterprise Intranets.

If you want to use different jQuery version other than 1.4.2, you can go to the folder ${sample.jquery.portlet.war}/js and update jquery.js with expected version.

Migration

Supposed that you have custom portlets heavily using jQuery in 5.1 or 5.2, now you are planning to migrate to 6.x.  You can simply add different version of jQuery jquery.js in portlet specification liferay-portlet.xml as follows.

<header-portlet-css>/css/style.css</header-portlet-css>
<header-portlet-javascript>/js/jquery.js</header-portlet-javascript>
<footer-portlet-javascript>/js/jquery-ui-custom.js</footer-portlet-javascript>

That's it. It is simple, isn't it? your comments?

Blogs
Great post, Jonas. jQuery is not only the default JavaScript framework in Liferay Portal 5.x, it is also widely used in out-of-box portlets from Liferay and custom portlets developed in Liferay community and enterprises. One of the most asked questions from my enterprise clients is how to handle the migration of jQuery-based portlets to Liferay Portal 6. With the solution explained in this blog, the migration shall be straight-forward. You can include your jQuery library in your own portlets running on Liferay Portal 6 and don't have to rewrite your portlets to use YUI3. Isn't it good to have both jQuery and YUI3 coexisted in your portal environment?
Hi Jonas,

it I want include jQuery in all *.war (many portlets in different war) what's the best way? Can I add jQuery as global include?

Thanks,
Denis.
Hi Denis, thanks. You may manage many portlets with hook in a single plugin and add following in init_js.jsp (included in init.jsp):

<script type='text/javascript' src='js/jquery_1.4.2.js'></script>

Hope that it helps,

your comments?
Hi Denis,
The best way to do that would be to simply include the jQuery javascript file from your theme. That will guarantee that it's global for all portlets.

You can also view my recent blog post for more info: http://www.liferay.com/web/nathan.cavanaugh/blog/-/blogs/using-jquery-or-any-javascript-library-in-liferay-6-0
Hi All,
I am new to liferay and portlet developement, i created my own portlet and it works fine in single column layout, but the problem is when i use it in 3 column layout in the center column, and if i refresh teh page , the page layout was changed to two column layout, i tried with this sample jquery portlet also, and i am getting the same problem,

Can any one pls suggest me am i missing anything..

Thanks in advance
Sorry All! Please help me!
I have problem with my ajax in liferay ( errors: "Liferay.fire is not a function" and "Liferay.Dockbar is not undefined")
I have I process2.js and declare process2.js in my jsp:

<script type="text/javascript" src="<%=HOST_URL%>/scripts/process.js"></script>
<script type="text/javascript" src="<%=HOST_URL%>/scripts/process2.js"></script>

(process2.js include AjaxGet2)

when i call AjaxGet2:
"AjaxGet2('<%=AddthongtinController%>','','add','divchild1','',"AjaxGet2('<%=ShowListAddController%>','','show','divchild2','','' );" ) my portlet is run ok. But Liferay.fire and Liferay.Dockbar not work. what's happen with my ajax and liferay????


Thank alot.
Hi, Nguyễn, Thanks. Simply, you may use the sample code: jQuery and AJAX as entry point. There are a lot of examples talking about jQuery and AJAX.

Refer to jQuery UI: http://jqueryui.com/

Hope that it helps.
Thank so much Jonas X Yuan!
But i wonder what happen with my ajax, it run ok, but seem have some scramble or conflict with Liferay.Dockbar and Liferay.fire . Can you read it, please:
process2.js:
---------------
function AjaxGet2(address,param,containerid,divchild,revattribute,func){
//showloading();
$.ajaxSetup ({
// Disable caching of AJAX responses */
cache: false
});
$('#'+divchild).html("<div class='ajaxLoading'> &#272;ang t&#7843;i d&#7919; li&#7879;u... </div>");
$.ajax(
{
url:address,
type:"GET",
cache: false,
datatype:"html",
data:param,
success:function(text){

showResponseText2(text,containerid,divchild,revattribute,func);
//closeloading();
}
}
);
}
-----------------
You can see clearly my process.js in link:
---
https://docs.google.com/leaf?id=0B_fgXf97eQg1ZjhiYWQ4NWUtN2I1ZS00NDQ2LThiOWEtNzYwNDhiMDNjZjZk&hl=en
---
And if my process2 unusable, you can help me for some code demo in jqueryui, please.(i looked for http://jqueryui.com/ but i don't see ...). So sorry! But i'm newbie. Sorry for my disturbing.
---------
Thank for you're help!!!
Oh, Jonas X. Yuan! I fixed this errors.
I think when my ajax return the object "text" which include something and have declares the Liferay.Dockbar and Liferay.Fire. So have conflict and duplicate.
For fix this error, i remove any code before <body></body> in object "text" return in my ajax.
I use javascript code:
----------------------------------------
AjaxGet2(address,param,containerid,divchild,revattribute,func){
...
...
...
$.ajax(
{
url:address,
type:"GET",
cache: false,
datatype:"html",
data:param,
success:function(text){
var str = text;
var indexBegin = str.indexOf('<body');
var indexEnd= str.indexOf('</body>');
var str1 = str.substring(indexBegin ,indexEnd+6);
showResponseText2(str1,containerid,divchild,revattribute,func);
//closeloading();
}
}
);
}
----------------------------------------
And now the liferay.Dockbar and another not die. But i wonder have anyway?
does header-portlet-xxx mean this xxx gets included during the header time of the page building and is available to body (i.e all the portlets that page can use this xxx) and footer jsp too.

Also, could you pl. explain what is this tag css-class-wrapper and where it is used.

Regards,
Raja Nagendra Kumar,
C.T.O
www.tejasoft.com
Hi Raja, Thanks. You can find info at

Applying jQuery and its custom UI in Liferay 6 plugins

http://www.liferay.com/web/jonas.yuan/blog/-/blogs/applying-jquery-and-its-custom-ui-in-liferay-6-plugins.

like:

Note that the property header-portal-javascript sets the path of JavaScript that will be referenced in the page's header relative to the portal's context path; and the property footer-portal-javascript sets the path of JavaScript that will be referenced in the page's footer relative to the portal's context path.

Similarly, the property header-portlet-css sets the path of CSS that will be referenced in the page's header relative to the portlet's context path; while the property footer-portlet-css sets the path of CSS that will be referenced in the page's footer relative to the portlet's context path.

Hope that it helps,

Thanks,

Jonas
Hi Jonas,

I have implemented this sample-jquery-portlet in LF6, Its looking very excellent and having many functionalities but I have to implement same thing in LF5.2.3

Which kind of changes I will have to make to run that same portlet in LF5.2.3 ?????...help me in that....

Thanks in Advance
Hi Mayur, Thanks.

For Liferay 5.2.5, you may refer to the post: Using jQuery (or any Javascript library) in Liferay 6.0 (by Nate) at http://www.liferay.com/web/nathan.cavanaugh/blog/-/blogs/using-jquery-or-any-javascript-library-in-liferay-6-0.

Hope that it helps.
If I need jquery widgets and scrolling 1.8.2 do I need to assemble them in a jquery-ui-custom.js? Another question: does your books available in ebook format? I live in Italy and I would like to download quickly.
Hi Alex, thanks.

By default, jquery widgets and scrolling should be included in UI 1.8.2. If possible, use UI latest version like 1.8.9 and jQuery 1.5.

Yes, ebook is available at https://www.packtpub.com/authors/profiles/jonas-x-yuan.

Hope that it helps.
hi,

Is there any way to completely avoid Alloy Ui/YUI being loaded on liferay portlets and use only jQuery
Hi Raghavendra, the portal core uses Alloy Ui/YUI as default settings. But in your portlets, you can avoid using Alloy Ui/YUI. Of course, you can just use jQuery as you expected. This is the beauty of Liferay portal.
Hi guys,
To remove AlloyUI altogether would break any of the bundled portlets that rely on it.

To ask a different question, what could AlloyUI do better to help you not wish to remove it? We're always looking for great feedback, so if there's an area of AlloyUI that you guys would like to see improved or feel it's falling short of your needs, don't hesitate to ask emoticon
Hi Nate, the reason behind to stick to jQuery is we have already developed few components based on jQuery framework and loading multiple frameworks is not good idea in page performance point of view.
Please help.
I added entries into ad-portlet/WEB-INF/liferay-portlet.xml as follows:

<portlet>
<portlet-name>admanager</portlet-name>
<icon>/images/icon.png</icon>
<header-portlet-css>css/style.css</header-portlet-css>
<header-portlet-javascript>javascripts/jquery.js</header-portlet-javascript>
<layout-cacheable>true</layout-cacheable>
<add-default-resource>true</add-default-resource>
</portlet>


but now the ad manager portlet errors loading up:

org.springframework.be

ans.factory.BeanDefinitionStoreException: IOException parsing XML document from PortletContext res
ource [/WEB-INF/context/admanager-portlet.xml]; nested exception is java.io.FileNotFoundException: Could not open Portle
tContext resource [/WEB-INF/context/admanager-portlet.xml]


any ideas what I'm doing wrong?
Hi Marc, you got
FileNotFoundException: Could not open Portle tContext resource [/WEB-INF/context/admanager-portlet.xml].

Could you please double check /WEB-INF/context/admanager-portlet.xml?

Thanks,
Hi jonas
I have the problem over loading the javascript file in my custom portlet.
In my liferay-portlet.xml file
<portlet>
<portlet-name>165</portlet-name>
<instanceable>true</instanceable>
<header-portlet-javascript>/html/portlet/book/main.js</header-portlet-javascript>
</portlet>
When I make some changes in my main.js file, the js file not being loaded that is after refresh the page i couldn't get the modified values. It forced me to restart the tomcat server. I cleared cookies of my browser but still having problem.
Note: I am using LR 6.0.6 and i m not using Plugin i m creating portlet in LR tomcat itself.
Hi Mani,

Just tested jQuery 1.6.2 and UI 1.8.14 in Liferay 6.1, the approach mentioned in this post was working properly.

By the way, what's the /html/portlet/book/main.js?

Do you refresh the page?

Thanks

Jonas
Hi Jonas,
Yes i am refreshing the page after make some changes in my main.js file but I couldn't get the modified values. Once I restart the server then only it is affecting the values.
/html/portlet/book/main.js - is my js file path
/html/portlet/book/view.jsp - is my jsp file path
[...] Hi, I want to use jQuery in a portlet, i found a way to do this in this blog : http://www.liferay.com/web/jonas.yuan/blog/-/blogs/building-jquery-based-plugins-in-liferay-6 I add this two line in... [...] Read More