Get portlet type in Liferay 6.2 Hook - liferay-6.2

Inside Liferay 6.2 hook I want to know the portlet type(Asset Publisher/Web Content Display). Portlet name wont help me because User may have used custom title and in that case "Asset Publisher"/"Web Content Display" wont be accessible to me.
Exact hook file location where i want Portlet-type is: /html/portlet/portlet_css/view.jsp

Well without hooking other parts of Liferay you can't get it there (in java code). Portlet "Portlet CSS" is populated via javascript so there was apparently no need to send portletid as parameter.
To get portletId you should also hook /html/js/liferay/look_and_feel.js
autoLoad: false,
showLoading: false,
data: {
p_l_id: themeDisplay.getPlid(),
p_p_id: 113,
p_p_state: EXCLUSIVE,
doAsUserId: themeDisplay.getDoAsUserIdEncoded()
},
uri: themeDisplay.getPathMain() + '/portal/render_portlet'
modify it to be something like this
autoLoad: false,
showLoading: false,
data: {
p_l_id: themeDisplay.getPlid(),
p_p_id: 113,
p_p_state: EXCLUSIVE,
doAsUserId: themeDisplay.getDoAsUserIdEncoded(),
_113_portletId: instance._portletId
},
uri: themeDisplay.getPathMain() + '/portal/render_portlet'
comma and _113_portletId: instance._portletId were added.
After that you can put in hooked /html/portlet/portlet_css/view.jsp
String portletId = (String) renderRequest.getParameter("portletId");
portletId for Asset publisher will be something like 101_INSTANCE_reKokSN3aDaL
portletId for Web Content Display will be something like
56_INSTANCE_dxNxXuQ7ZuvB
so you can test wether portletId starts with 101, 56, ...
You can also get Portlet object with
PortletLocalServiceUtil.getPortletById(portletId);
UPDATE (answer to question in comment):
This portlet was not intended for such use, once it loads it stays rendered in html and all modifications are made with javascript.
When "Look and feel" is opened for first time after page load XHR request to server is made and "/html/portlet/portlet_css/view.jsp" is rendered.
Second time (for another portlet on the same page), javascript prepares modal for another (or same) porlet, "/html/portlet/portlet_css/view.jsp" will not be rendered again.
To force rerendering of "/html/portlet/portlet_css/view.jsp" modify again "/html/js/liferay/look_and_feel.js".
after (in my source it is line 136)
if (!content) {
content = A.Node.create('<div class="loading-animation" />');
}
add this
if (instance._currentPopup) {
A.one("#" + instance._currentPopup.get("id")).remove()
instance._currentPopup = null;
}
It should be before
if (!instance._currentPopup) {
instance._currentPopup = Liferay.Util.Window.getWindow(
...
Clear Liferay and browser cache.

You could get PortletDisplay object from ThemeDisplay context object and from PortletDisplay, you can get Title, PortletName etc.
Note that themeDisplay is already available and used in your jsp /html/portlet/portlet_css/view.jsp
PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
String title=portletDisplay.getTitle();
String portletName=portletDisplay.getPortletName();

Related

ExtJS - Handling Session Management

I want to know how i can save page data.first i will tell how my application works.
I have a container and i am adding panels to this dynamically.
something like this
--container
--add panel_1
---want to add panel_2 ? remove panel_1 and add panel_2 in that place
My problem is..Now i am planning to have a back button in panel 2..when user clicks ,will take him to panel_1 and i want to show what he entered...Please help me
have seen this (Extjs 4 Session Management)
I use an extra class with static members for holding data in MVC arch in ExtJS. So I save objects, arrays, vars etc in it from controller and use them later in project. Perhaps this help you as well. Save panel_1 object or data and goto panel_2, or viceversa
e.g.
Ext.define('MyApp.controller.Utility', {
statics : {
panel1: false,
panel2: false,
myFun : function() {
//some code
}
}
});
in any controller/view etc whenever you want to save an object or value, refer to this class but first add to require. .e.g.
var ut = MyApp.controller.Utility;
ut.panel1 = Ext.ComponentQuery.query('panel')[0];

when refreshed with new options, kendo popup window in iframe mode does not fetch the new url

EDIT: I have abandoned the conditional structure and just create the window fresh each time. That works. Still wondering whether refresh() works with urls though.
I have a conditional structure that resembles this one:
What is the proper way to load new content into a kendo window?
If the kendo window already exists, refresh() the window rather than create it anew.
The difference is, I'm using an iframe with url.
The problem: I set a different query string with setOptions before invoking refresh(), but the original url is being requested from the server again.
if (!kwindow) {
kwindow = $("#messagewindow").kendoWindow({
iframe: true,
width: "400px",
height: "600px",
title: "original title",
content: "foo.htm?id=1",
type: "GET"
}).data("kendoWindow");
}else {
kwindow.setOptions({
iframe: true,
type: "GET",
title: aDifferentTitle,
url : "foo.htm?id=2"
});
kwindow.refresh();
}
kwindow.open();
I know the the setOptions method is passing the options to the kendo window because the titlebar of the window correctly shows aDifferentTitle. However, looking at the network traffic monitor, the url requested from the server is foo.htm?id=1 but it should be foo.htm?id=2.
I cannot see what is wrong with my code and would be grateful if someone could point out the error to me.
The answer you were looking for was
kwindow.options.content.url = url;
Then the refresh icon / methods will work on the new url
To refresh from different URL you need to pass this through an option object to the refresh method (you do not need to use setOptions). Here is snippet from the documentation:
var windowObject = $("#window").data("kendoWindow");
windowObject.refresh("/feedbackForm");
windowObject.refresh({
url: "/feedbackForm"
});
I used the following and it seems to work in an MVC project:
window.setOptions({
title: "New Title"
});
window.refresh({
url: "/ControllerName/Action"
});
window.open();

jqgrid - saveRow url throwing an exception

In inline editing mode, clicking on "Save" is throwing an error.
var rowSave = function(id){
jQuery("#myjqgrid").jqGrid('saveRow',id,{
"succesfunc": function(response) {
return true;
},
"url": myjqgrid.json
"mtype": "GET"
});
}
Is it because the url is set to json?
Basically, I get JSON response when the grid is loaded the first time. After I edit the row in inline editing mode, the edited data should be sent to the server. When the data is saved on the server, it should return the updated JSON and the grid row data should be updated with the updated JSON response.
Looking at this doc page:
http://www.trirand.com/jqgridwiki/doku.php?id=wiki:inline_editing#saverow
in the section for saveRow it says:
url: if defined, this parameter replaces the editurl parameter from the options array. If set to 'clientArray', the data is not posted to the server but rather is saved only to the grid (presumably for later manual saving).
and a bit below:
Except when url (or editurl) is 'clientArray', when this method is called, the data from the particular row is POSTED to the server in format name: value, where the name is a name from colModel and the value is the new value.
so it seems you need to supply the server URL that will accept data here. In some of the examples on the same page you can see something like this:
...
editurl: "server.php",
...

TinyMCE not working in http request xhr ajax generated page

So i I have a page that contains links that call an httpRequest. The request calls a php file that grabs data from mysql and pre populates a form which is then returned to the browser/webpage. My problem is that when the page is returned to the browser via the httpRequest/ajax the text area does not display the tinymce editor, it just displays a normal text area. It looks like my request and ajax is working fine the text area just doesn't have the tinycme editor on it.
When i don't use ajax it works fine but when i put it in a separate file and call it via ajax it doesn't bring in the tinymce editor.
Does anyone know how to fix this problem so that my ajax generated page displays the text area with the tinymce editor. Thank you.
Lets presume that your thinyMCE instance is initialized with code below
// initialize tinyMCE in page
tinyMCE.init({
mode: "textareas",
theme: "advanced"
});
and you have some kind of button somewhere in the page. For purpose of this tip, i will not give it any ID but you may. Now, using jQuery you can easily attach event handler to that button which will call through AJAX your server and take content which you want to put tinyMCE editor. Code which will do such job would look somehow like below.
$(function() {
$("button").bind("click", function() {
var ed = tinyMCE.get('content');
ed.setProgressState(1); // Show progress
$.getJSON('/page/12.json', { /* your data */
}, function(data) {
ed.setProgressState(0); // Hide progress
ed.setContent(data["body"]);
}
});
});
});
You can see that on button.click ajax will call url /page/12.json which will return JSON as response. bare minimum of that response could be:
{
title: "Page title",
body: "<html><head><title>Page title</title>......</html>"
}
I attached anonymous function as callback which will handle response from server. and hide progress indicator which is shown before ajax call.
About JSON
JSON is shorten of JavaScript Object Notation. It is JavaScript code!!! So don't be confused about it. Using JSON you can make javascript object which can have attributes you can use later in your code to access particular peace of data which that object "holds". You can look at it as some kind of data structure if it is easier to you.
Anyway, to show you how this JSON can be created by hand look at examples below
var data = new Object();
data.title = "Page title";
data.body = "<html....";
or
var data = {
title: "page title",
body: "<html...."
};
it is very same thing.
If you want to learn more about JSON point your browser to http://json.org.
===== alternative =====
Alternative to json solution could be just plane ajax call to server and response can be plain HTML (from your question I can assume that you have something like this already). So instad of calling $.getJSON you can use $.get(url, callback); to do same thing. The code at the top of my answer will not dramatically change. Instead of geting JSON in response you will get string which is HTML.
----------- BOTTOM LINE -------
I prefer JSON since it can be easily extended later with other attributes, so there is no painful code changes later ;)
Problem here will be that when you return the full page and render it using the ajax response, your tinymce instance has not been shut down before.
In order to do this you can call this small piece of code before you render the ajax response:
tinymce.execCommand('mceRemoveControl',true,'editor_id');
In this case the editor should initialize correctly. You are not allowed to initialize a tinymce editor with the same id before shutting the first one down.
Strangely i ran into this problem yesterday. Following code should work, but YMMV. Trick is to use the correct steps in ajax events. I used the Regular TinyMCE and made use of the jQuery library already included.
Following goes into your tinyMCE initialization tinyMCE.init() . All of the below block should be outside the document.ready.
myTinyInit = {
//.......All essential keys/values ...........
setup : function(ed) {
ed.onChange.add(function( ed ) {
tinyMCE.triggerSave();
}) }
//.....................
};
// Init the tinyMCE
tinyMCE.init(myTinyInit);
This ensures the content is being saved regularly onto the textarea that holds the value. Next step is setting up the request events.
Normally tinyMCE mceAddControl before the ajax post and mceRemoveControl after the ajax success should do the trick. But I found that often does not work.
I used the form as the jQuery selector in my case.
jQuery( '.myForm' )
.find( 'textarea#myTextArea' )
.ajaxStart(function() {
// If you need to copy over the values, you can do it here.
// If you are using jQuery form plugin you can bind to form-pre-serialize event instead.
// jQuery( this ).val( tinyMCE.get( jQuery( this ).attr( 'id' )).getContent() );
}).ajaxSend( function() {
// ! - step 2
// My case was multiple editors.
myEds = tinyMCE.editors;
for( edd in myEds ) {
myEds[ eds ].remove();
}
// tinyMCE.get( 'myTextarea' ).remove();
// strangely mceRemoveControl didnt work for me.
// tinyMCE.execCommand( 'mceRemoveControl', false, jQuery( this ).attr('id'));
}).ajaxSuccess(function() {
// Now we got the form again, Let's put up tinyMCE again.
txtID = jQuery( this ).attr( 'id' );
// ! - step 3
tinyMCE.execCommand( 'mceAddControl', false, txtID );
// Restore the contents into TinyMCE.
tinyMCE.get( txtID ).setContent( jQuery( this ).val());
});
Problems i came across :
Using mceRemoveControl always gave me r is undefined error persistently.
If you get a blank tinyMCE editor, check the DOM whether the ID of the textarea is replaced with something like mce_02, this means that TinyMCE is being initialized again or something is wrong with the order. If so, the tinyMCE is duplicated with each save.
if you are new to JS, I recommend using jQuery with the form plugin, it might be easier for you. But do use the regular non-jquery tinyMCE, as it is well documented.
I fixed this problem by recalling the function after the ajax call. In this part of my ajax:
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("Content").innerHTML=xmlhttp.responseText;
tinymce();
Now it works fine.

In javascript, how can I uniquely identify one browser window from another which are under the same cookiedbased sessionId

The users of my web application may have more than one browser window open and pointed to the same page. I would like the state of certain things in the page (loaded via ajax) to be retained across postbacks. I can either store in a cookie or on my server. Either way, I can't think of how I can distinguish each window.
For example, say user Bob has two browser windows open to the ListOfSomething page. Each list has a LoadedPageNumber attribute which I need to persist. Otherwise users always end up on page 1 when they refresh. Bob might have loaded browser window 1 and pointed it to page 5 and then loaded browser window 2 and pointed it to page 14. If I just store the attribute based on session id, Bob will get page 14 in window 1 if he refreshes it.
Note that my state variables are actually much more complex than this simple example and my inability to persist them could lead to big problems (weaknesses in my app).
I need some kind of browser window id or something. It of course needs to be a cross-browser solution (IE6+, Wekbit?+, FF2+)
Any ideas?
Note on relevance: Keep in mind that this is useful also for the case where you're mixing older forms based pages with newer AJAX enabled items. Sometimes you need to postback the forms and you don't want to loose some client side state values.
you could set your own window name, the exact syntax escapes me right now, but you can use the current time and session id to create a unique id on window load, then use that id
This would be done the same way you set a name in the javascript window.open() function, (but you can do it to self, instead of new window)
googling shows:
self.window.name = myclass.getUniqueWindowId( thisSession );
UPDATE
Regarding your need to save this from refresh to refresh, i did some tests and it looks to save it from refresh to refresh. Using Firefox 3, on initial load, the window name is blank, and pressing CTRL+R over and over, and the window name was populated. i then commented out the setting the name code and reloaded and it still retained the name.
<script type="text/javascript">
alert( self.window.name );
self.window.name = "blah";
</script>
UPDATE
I have to make noticed the comment below on jQuery's 'jquery-session' plugin, which really works and offers way more than what's discussed here.
Although, one should also make it clear that it relies on HTML5's Web Storage, not supported by older IE versions.
Corporate still depends heavily on IE 7 ('and below' here in Brazil).
Based on self.window.name, THE solution for everything non-compliant to HTML5, I offer the following code snippet as a cross-browser solution:
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
<script language="javascript" type="text/jscript">
//----------------------------------------------------------------------
//-- guarantees that window.name is a GUID, and that it would
//-- be preserved whilst this window's life cicle
//----------------------------------------------------------------------
//-- window.name will be set to "GUID-<SOME_RANDOM_GUID>"
//----------------------------------------------------------------------
$(window).load(
function () {
//----------------------
var GUID = function () {
//------------------
var S4 = function () {
return(
Math.floor(
Math.random() * 0x10000 /* 65536 */
).toString(16)
);
};
//------------------
return (
S4() + S4() + "-" +
S4() + "-" +
S4() + "-" +
S4() + "-" +
S4() + S4() + S4()
);
};
//----------------------
if (!window.name.match(/^GUID-/)) {
window.name = "GUID-" + GUID();
}
}
) //--------------------------------------------------------------------
</script>
I found the GUID function here (for which I proposed some code clean-up).
You can use HTML5 session Storage ,just generate an unique id and set it on the session storage !
what is cool about that each window or tab has its own session storage.
for example :
if we run the following on 3 windows:
window 1:
sessionStorage.setItem('key' , 'window1');
window 2:
sessionStorage.setItem('key' , 'window2');
window 3:
sessionStorage.setItem('key' , 'window3');
sessionStorage.getItem('key' ); <<< this will return corresponding value on window!
window 1:
sessionStorage.getItem('key' ); returns window 1
window 2:
sessionStorage.getItem('key' ); returns window 2
window 3:
sessionStorage.getItem('key'); returns window 3
I believe you are trying to save a variable (separately on each tab/window).
sessionStorage works as charm.
The only problem you may face that browser should support HTML 5.
What about having your server randomly generate an ID and have that stored in the page (some javascript variable) when it's served? Then just include that ID in the ajax request. It wont' help on a browser refresh, but as long as the user leaves that page in place (and just lets the ajax stuff do its thing) it should work fine.
It's a long time ago, but the answer of Roy Rico helped me today, so I want to share my experience. To handle page refresh and page backbutton uses, I am doing it like that:
Your server checks if the browser sends the GUID with his request (only works with ajax or form submit)
If it is not there (browser refresh, backbutton) it just sends back a page with a small JavaScript script. This script creates the GUID and puts it into the window.name storage as described above. After that the script creates a form with the GUID as hidden field and submits it to the server. The action attribute uses the same URL as before (window.location.href)
--> Now the server recognizes the GUID and can deliver the content as needed.
Here is my code (the GUID I create on the server for security reasons, the syntax "${gUid} is from freemarker and just inserts the Guid from the server):
<script>
$(window).load(
function () {
if (!window.name.match(/^GUID-/)) {
window.name = "GUID-" + "${gUid}";
}
$('<form action='+window.location.href+' method="POST"><input type="hidden" name="X-GUID" id="X-GUID" value='+window.name+'></form>').appendTo('body').submit();
}
);
</script>
Hope that helps someone
By the way, this technique should only be used on "NON SEO PAGES", because of the need of JavaScript to get the content. But in general SEO pages have no need of identifying the tab session.
Of course nowadays you can make use of the HTML5 session storage, but I don't want to rely on that, because I also need older browser to work well.
In fact, with new Web Locks API you can acquire actual internal window id (a.k.a. clientId). LockManager.query() can provide info on held locks including owner's id. Might not work in some iframe context due to security restrictions, but in top window should generally be good.
function getCurrentWindowId() {
return new Promise((resolve) => {
let lockName;
tryGetLock(); // one attempt should almost always be enough
function tryGetLock() {
// generate some random lock name
lockName = 'get-self-id-' + (Math.random() * 0xffffffff >>> 0);
navigator.locks.request(lockName, { mode: 'exclusive', ifAvailable: true }, withLock);
}
function withLock(lock) {
// unsing setTimeout(0) here to execute client's code after releasing the lock
if (lock)
return navigator.locks.query()
.then(({ held }) => held.find(lock => lock.name === lockName).clientId)
.then(clientId => setTimeout(resolve, 0, clientId));
else {
// unlucky - just try another lock
setTimeout(tryGetLock, 0);
return Promise.resolve();
}
}
});
}
//usage
getCurrentWindowId().then(clientId => {
// do something with id
});
Works in Firefox 96 and Chrome 97. It feels like shame to make such awkward constructs just to get information that should be readily available.
window.name can be overwritten by custom javascript libraries, datetimepickers etc.
Instead of window.name I suggest you to use the DOM head meta tag to store your id
<html><head><meta id="windowID" content="{YOUR ID}">
After page is loaded, you have to load everything via ajax in that window, then you can attach this ID to every request as a header (or data) value. For example in JQuery with this code:
$(document)
.ajaxSend(function(event, jqXHR, ajaxOptions) {
jqXHR.setRequestHeader('windowID',
document.getElementById('windowID').content);
})
To use this solution, you have to have access to custom header values on server side. For example in Java servlet:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String windowName = request.getHeader("windowID");
If you store paging, sorting, filtering etc. information on server side as session attribute, you should store them separately attached to the separate window ID-s.

Resources