Fórum

JSF rendered HTML id Attribute being prepended with portlet name and id

thumbnail
Corné Aussems, modificado 8 Anos atrás.

JSF rendered HTML id Attribute being prepended with portlet name and id

Liferay Legend Postagens: 1313 Data de Entrada: 03/10/06 Postagens Recentes
Hi all,

I am upgrading a jsf 1.1 JSR 168 portlet suite from Liferay 6.0.6 EE to Liferay 6.2.0 EE.
In order to achieve that i needed the Liferay Portal Bridge instead of suns and therefor upgraded to JSF 1.2.

Here is the snippet of some JSF

<h:form id="AV_form_1">
	<t:div id="AV_kies_div" forceid="true">
		<h:selectonemenu id="PO_week_select" value="#{selectieBean.weekNummer}">
		<f:selectitems value="#{selectieBean.wekenSelect}" />
		</h:selectonemenu>
	</t:div>
</h:form>


In my old implementation this was the id and name attribute output:

<form id="AV_form_1" method="post" action="http://...">
	<div id="AV_kies_div">
		<select id="AV_form_1:PO_week_select" name="AV_form_1:PO_week_select" size="1">
			<option value="-1">Maak een keuze</option>
			<option value="1"></option>
			<option selected value="2">2</option>
			<option value="3">3</option>
		</select>
	</div>
</form>


In my new implementation this becomes the id and name attribute output:
<form action="http://..." id="_OVERZICHT_PARTIJ_FACTUUR_WAR_VDN_PORTLETS_:AV_form_1" method="post" name="_OVERZICHT_PARTIJ_FACTUUR_WAR_VDN_PORTLETS_:AV_form_1">
	<div id="AV_kies_div">
		<select id="_OVERZICHT_PARTIJ_FACTUUR_WAR_VDN_PORTLETS_:AV_form_1:PO_week_select" name="_OVERZICHT_PARTIJ_FACTUUR_WAR_VDN_PORTLETS_:AV_form_1:PO_week_select" size="1">
			<option value="-1">Maak een keuze</option>
			<option value="1"></option>
			<option selected value="2">2</option>
			<option value="3">3</option>
		</select>
	</div>
</form>


Why does it bother me? the Portlet suite has 20 portlets and we have hundred shared externalized javascripts (jQuery) and css selectors.

eg: this specific week selector snippet is part of a jspf that gets included in many portlets jsp pages

jQuery('#AV_form_1\\:AV_kies_div').css('display','none');

and css

#AV_form_1\003A AV_kies_div {
	position: relative;
...}


As you see i am able to use apache Tomahawk to force an id, which i already did in the past, but i now have to change and retest hundreds of lines of javascript and css selectors and or have redundant code per portlet.

So my question is:
Is there a possibility to stop Liferay from adding this prepending ?

Here you find the reference jsf 1.2 test Portlet that is ready to be deployed.
https://repo1.maven.org/maven2/com/liferay/faces/demos/jsf1-jsp-portlet/

Thanks for reading the issue so far, i hope you have some good ideas how to solve this.

Regards,
Corné
thumbnail
Kyle Joseph Stiemann, modificado 8 Anos atrás.

RE: JSF rendered HTML id Attribute being prepended with portlet name and id (Resposta)

Liferay Master Postagens: 760 Data de Entrada: 14/01/13 Postagens Recentes
Hi Corné,

JSR 301 and 329 require that standards-based JSF portlet bridges guarantee uniqueness of element ids by using an instance of PortletNamingContainerUIViewRoot. The reason for this spec requirement is that more than one JSF portlet can appear on the page, so each id must include the unique portlet id to avoid colliding with the ids of other instances of the same portlet*.

In order to fix this, you can either use CSS3 "attribue ends with" selectors (which have been supported in jQuery since 1.9 and supported in browsers for a long time) or prefix your selectors with the portletId somehow. I would recommend that you update your CSS selectors (whether in JQuery or CSS files) to use the "ends-with" selector: [id$="suffix"].

For your specific examples, here's how that would work:

jQuery('#AV_form_1\\:AV_kies_div').css('display','none');

would change to

jQuery('[id$="AV_form_1\\:AV_kies_div"]').css('display','none');

and

#AV_form_1\003A AV_kies_div {
position: relative;
...}


would change to

[id$="AV_form_1\003A AV_kies_div"] {
position: relative;
...}


jQuery Attribute Ends With Selector [name$=”value”] documentation.

Alternatively you could also try prefixing each selector with the portletId (or portlet namesapace): '#${portletNamespace}AV_form_1\\:AV_kies_div'. But that would require that you you include all your JS and CSS in JSP files so that EL expressions are processed. I'm not sure what effect that would have on performance, but it's a little scary.

- Kyle

*Client-side ids must be unique according to the HTML spec.
thumbnail
Corné Aussems, modificado 8 Anos atrás.

RE: JSF rendered HTML id Attribute being prepended with portlet name and id

Liferay Legend Postagens: 1313 Data de Entrada: 03/10/06 Postagens Recentes
Hi Kyle,
At first thanks for your interest and quick answers.

Kyle Joseph Stiemann:

JSR 301 and 329 require that standards-based JSF portlet bridges guarantee uniqueness of element ids by using an instance of PortletNamingContainerUIViewRoot. The reason for this spec requirement is that more than one JSF portlet can appear on the page, so each id must include the unique portlet id to avoid colliding with the ids of other instances of the same portlet*.

I do understand that there are good reasons to do as such. but we have non-instanceable portlets (they are page filling).
But hey the specs are forcing us to improve so that is unfortunate but acceptable.


In order to fix this, you can either use CSS3 "attribue ends with" selectors (which have been supported in jQuery since 1.9 and supported in browsers for a long time) or prefix your selectors with the portletId somehow. I would recommend that you update your CSS selectors (whether in JQuery or CSS files) to use the "ends-with" selector: [id$="suffix"].

For your specific examples, here's how that would work:

jQuery('#AV_form_1\\:AV_kies_div').css('display','none');

would change to

jQuery('[id$="AV_form_1\\:AV_kies_div"]').css('display','none');

and

#AV_form_1\003A AV_kies_div {
position: relative;
...}


would change to

[id$="AV_form_1\003A AV_kies_div"] {
position: relative;
...}


jQuery Attribute Ends With Selector [name$=”value”] documentation.


Actually i tried this but somehow it failed. I will retry with a different jQuery version.


Alternatively you could also try prefixing each selector with the portletId (or portlet namesapace): '#${portletNamespace}AV_form_1\\:AV_kies_div'. But that would require that you you include all your JS and CSS in JSP files so that EL expressions are processed. I'm not sure what effect that would have on performance, but it's a little scary.

Thought of this as a last resort myself.

*Client-side ids must be unique according to the HTML spec.

I know that and they are when only used in a non instanceable portlet.

Again thanks
i'll keep you updated on my endeavours with jQuery.
thumbnail
Corné Aussems, modificado 8 Anos atrás.

RE: JSF rendered HTML id Attribute being prepended with portlet name and id

Liferay Legend Postagens: 1313 Data de Entrada: 03/10/06 Postagens Recentes
Hi,

Kyle was right i did it wrong in my first trials, i am horrible in CSS and a bad googled example made up the wrong mixture.

Just sharing some of my experiences;





<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<!--
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
-->




h:form
<form id="_FOOPORTLET_WAR_FOO_PORTLETS_:FOOID_form_1"> 
   t:div
	<div id="FOOID_form_1:FOOID_kies_div">

		<input type="text id=" _FOOPORTLET_WAR_FOO_PORTLETS_:FOOID_form_1:FOOID_input_1" val="HELLO"></div>
	
</form>



<div id="console"></div>

<script>

function jquery(exp){ 
	try{
		var out = $(exp);
		dwS( exp + ' found:' + out.length  );
	} catch (e){ dwE(e); }
}

function dwE(str){ dw(str,'red')}
function dwS(str){ dw(str,'green')}
function dw(str,color){$("#console").append("<div style='background-color:"+color+"'>"+str+"</div><br/>")}

// Originals
jquery("#FOOID_form_1\\:FOOID_kies_div]"); 

// CSS3
jquery("id$[#FOOID_form_1\\:FOOID_kies_div]"); 
jquery("id$[#FOOID_form_1:FOOID_kies_div]");
jquery("id$[#FOOID_form_1:FOOID_kies_div]");
jquery("id$[FOOID_form_1:FOOID_kies_div]");

jquery("id[FOOID_form_1\\:FOOID_kies_div]");
jquery("id*[FOOID_form_1\\:FOOID_kies_div]");
jquery("id$[FOOID_form_1\\:FOOID_kies_div]");
jquery("id^[FOOID_form_1\\:FOOID_kies_div]");

jquery("[id=FOOID_form_1\\:FOOID_kies_div]");  // found
jquery("[id*=FOOID_form_1\\:FOOID_kies_div]"); // found
jquery("[id$=FOOID_form_1\\:FOOID_kies_div]"); // found
jquery("[id^=FOOID_form_1\\:FOOID_kies_div]"); // found

jquery("[id=_FOOPORTLET_WAR_FOO_PORTLETS_\\:FOOID_form_1\\:FOOID_input_1]"); // found
jquery("[id^=_FOOPORTLET_WAR_FOO_PORTLETS_\\:FOOID_form_1\\:FOOID_input_1]"); // found
jquery("[id*=FOOID_form_1\\:FOOID_kies_div]"); // found
jquery("[id$=FOOID_form_1\\:FOOID_kies_div]"); // found


</script>


thumbnail
Kyle Joseph Stiemann, modificado 8 Anos atrás.

RE: JSF rendered HTML id Attribute being prepended with portlet name and id

Liferay Master Postagens: 760 Data de Entrada: 14/01/13 Postagens Recentes
Thanks for sharing your findings, Corné! And thanks for using Liferay Faces!

- Kyle