Showing posts with label JavaScript-HTML. Show all posts
Showing posts with label JavaScript-HTML. Show all posts

DOJO Templates parsing is failed because of WebSeal Junction Cookie


PROBLEM: DOJO failed to load the page , i.e. failed to parse the template  

REASON: we have dojo templates name " sometemplate-name.html " and webseal junction that we use have junction cookie enabled (created junction with -j  option)

Webseal is adding following (junction cookie in the script block) to all .html pages, caused DOJO widget templates also got this script block added at end and failed to parse the template.
SCRIPT language="JavaScript">
<!-- 
document.cookie = "IV_JCT=%2Ftestjunct1; path=/";
//--> 
</SCRIPT>

Solution : Simplest solution we tried is rename the template file name to "sometemplate-name.txt"  (used ".txt" instead of the ".html")

IE6 freeze issue when GZIP compression enabled on load balancer for WP7


WP7 browser requirements clearly states that it doesn’t support IE6 for lot of functionalities but recently as part of theme development we had to support the IE6 browser for the portal 7 and IE6 browser is getting freeze very often . 

We tried following different steps to make the application works in IE6

1.       Make sure no of CSS files less than 31 (Click Here more details).

2.       Make sure you don’t have combination of HTTPS ,  Compression (GIP) &  chunked encoding enabled. Click Here for microsoft support article explains about the IE6 freezing.


Resources

Page Builder theme issues with IE9 - WP7


Basically Dojo 1.4 doesn’t support the IE 9 ( DOJO 1.4 Browser Support ) but Portal 7.0.0.0 or Portal 7.0.0.1 uses dojo 1.4.3 as default causing the page builder theme may not work properly in IE9 i.e. Symptoms are like portlets doesn’t show up , navigation menu may not behave proper ..etc



There are few ways we can overcome this issue


1.       Changing or adding any one of following line in the out of the box page builder theme head section

<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8" />

<meta http-equiv="X-UA-Compatible" content="IE=7" />
<meta http-equiv="X-UA-Compatible" content="IE=8" />

2.       Manually change the “Document Mode” or the “Browser Mode” using the IE developer tool in IE9


Note : It showing page default as IE8 in above picture because I have already set the EmulateIE8 meta tag in page builder theme.

Additional Info
1.       Dojo support for Microsoft Internet Explorer 9.0 is provided with Dojo 1.6.1
2.       Portal 7.0.0.2 support DOJO 1.6.1
3.       Existing PageBuilder2 themes using Dojo 1.4.3 (i.e. WebSphere Portal V7.0.0.0 and 7.0.0.1), but you can upgrade DOJO version alone to 1.6.1
4.       Internet Explorer Related
a.       All browsers needed two modes: quirks mode for the old rules, strict mode for the standard.
b.      Browser Mode determines the document mode and it’s chosen before IE request web content. Browser mode sends User-Agent (UA) string  to servers. Site(page) response will define the document mode.

Content Value
Details
IE=7
Display in IE7 Standards mode; Already supported in the IE8 Beta 1 release
IE=EmulateIE7
Display standards DOCTYPEs in IE7 Standards mode; Display quirks DOCTYPEs in Quirks mode

Resources:

IE6 limitations on the no of CSS files ( Maximum limit of 31 individual StyleSheets)


Recently was working on cross browser issues with UI team after I finished developing Portal Theme . Spent lot of time figuring out the issues with IE6 and finally realized limitation of IE6 with respect to the no of cascading style sheets(CSS) it can apply.

  • All style tags after the first 31 style tags are not applied. 
  • All style rules after the first 4,095 rules are not applied.

Click Here to find more details regarding the issue

Different ways of Handling CSS and JavaScript in WCM

We can handle CSS and JavaScript in WCM in following three different approaches.

Approach 1: Storing the CSS as Style Sheet Component and JavaScript as File Resource Components

Note:  You can upload the JavaScript file into WCM as the File Resource Component and refer that in presentation template as below

<script  language="javascript" src="<Component name="library/test-javascript-cmpnt" format="url"/>" />

Pros:
1. Out of box component

Cons:
1. Authors can't modify the CSS in the authoring interface when they have to make changes.
2. You can not refer the File Resource components(like images) stored in WCM like below

table{  
     background-image: url(<Component name="bckImage" format="url"/>); 
}

3. Need to place CSS and JavaScript on somewhere for future changes(outside of WCM).


Approach 2: Storing CSS and Javascript as HTML Components
Store CSS styles as HTML components and then embedded those components in presentation templates inside of <style> blocks. (Same for the javascript also)

Pros:
1.Authors can modify CSS classes inside the WCM authoring.
2.Additional request to load the CSS files is not required (fewer HTTP requests generates from page)

Cons:

1. Here CSS files are rendering from WCM, Can't take the advantage of browser caching
2. Response size and time may increase as Styles are coming from the JCR.

Approach 3: Storing CSS and Javascript as Content Item under some SiteArea

Steps to implementing CSS as a content item -
a). Create a authoring template with a single Body HTML element,
b). Create a presentation template that just refer Body element (you may not use Ephox RTE element because it includes <P> tags , causing CSS Styles failed )
c). Name ContentItem as *.css ("test.css").
d). You can add the above contentItem from other presentation templates as CSS or Javascript . Make sure to append "?subtype=css" to path of content item while referring in other Presentation templates to force WCM content to be rendered with text/css as MIME type instead of text/html (default MIME type for WCM content is text/html or text/plain).
Ex:
<link rel="StyleSheet" href="/wps/wcm/myconnect/library/Site/SiteArea/test.css?subtype=css" type="text/css"/>



Following are the advantages if you naming the ContentItem as *.css
a)  When site is pre rendered for delivering content, content items stored as *.css will generate files valid CSS file to pre render
b)  Even when content served through the WCM servlet , this allows the browser to cache the CSS file

Pros:
1.Authors can modify CSS classes inside the WCM authoring portlet with normal workflow process
2.Additional request to load the CSS files is not required (fewer HTTP requests generates from page)

Cons
1. Make sure this content item (css) doesn't pick up by some navigators or menu components as it is content item


Note:
a). In Second and Third approach approach , your CSS styles or javascript can refer File Resource Components(like for background images) that stored in WCM repository as components by simply using the Component Tag as below

body{
   background-image: url(<Component name="bckImage" format="url"/>);
}

b). "subtype" query string parameter only applies to the default content renderer and will not work on URLs which is used to invoke the component renderer (i.e. which contain srv=cmpnt in the query string parameter).

c). You may need to add an extension mapping for CSS to WcmConfigService.properties in older versions. Following are steps to do this.

  1. Search for the line "#mapping of mimetypes to extensions" in wcmconfigservices.properties file located under <Portal_root>\wcm\shared\app\config\wcmservices\ directory.
  2. There is an attribute named "mimetype.list=extensiontype.gif". Add ",extensiontype.css" (no spaces, include the dot ( . ) character at the front of the string) at the end of the line.
  3. Add a new line "extensiontype.css=text/css" (no spaces) after the "extensiontype.lzh=application/octet-stream"
  4. Save the file.
  5. Restart WebSphere Portal Server (WPS).

    Calling Javascript file from another JavaScript file

    Best of way to do this is using Document Object Model (DOM) , following simple function can perform this processing for this using DOM

    function includeJavascriptFile(jsFileName,pos) {
    var th = document.getElementsByTagName(pos)[0];
    var s = document.createElement('script');
    s.setAttribute('type','text/javascript');
    s.setAttribute('src',jsname);
    th.appendChild(s);
    }

    This function adds the necessary script tag into the end of the head or body section of the page for you. All that you then need to do from your Javascript in order to add another external javascript into the page is to call that function passing it the name of the file that contains the extra code that you want to include and whether to add it to the end of the head or the end of the body.

    includeJavascriptFile('externalFile1.js','body');
    includeJavascriptFile('externalFile2.js','head');

    Once the script tags have been added to the page you can then call any functions that you want from within that file.

    This method also useful to include the javascript files externally on the web page based on conditions like based on browser version include the different JS files

    Another sample code for the above approach is

    (function() {
        var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
        ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
        var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
      })();



    Following is another way to include the JS


    <script type="text/javascript">
      document.write(unescape("%3Cscript src='" + (document.location.protocol == "https:" ? "https://testhttps" : "http://testhttp") + ".sivavaka.com/testJava.js' %3E%3C/script%3E"));
     </script>
    
    

    JavaScript XML DOM parser - parsing XML using Javascript and set values to HTML elements

    Use following Code to parse the XML string in Javascript


    function generateTextBoxValue(sourceXMLStr){

    var expectedXML;
    if (window.DOMParser){
    var parser=new DOMParser();
    expectedXML=parser.parseFromString(decodeURIComponent(sourceXMLStr),"text/xml");
      //decodeURIComponent is used assuming sourceXMLStr is UTF-8 encoded otherwise call directly
    }else {// Internet Explorer
    expectedXML=new ActiveXObject("Microsoft.XMLDOM");
    expectedXML.async="false";
    expectedXML.loadXML(decodeURIComponent(sourceXMLStr));
    }

    var testModuleList=expectedXML.getElementsByTagName(TEST_XML_MODULE_ELEMENT_NAME);// constant contains testModule XML Element name

    for(var x=1;x<=testModuleList.length;x++){
    document.getElementById(testTextBox).value = testModuleList[x-1].childNodes[0].nodeValue;
    //fill your DOM elements based on your criteria
    }

    }

    Making AJAX call using DWR (Direct Web Remoting)

    This Article will explain how to make DWR (Direct Web Remoting) AJAX call from JSP

    Follow the simple Steps
    a         Copy the DWR jar file to the Lib directory under webcontent/WEB-INF (download from here)
    b        Copy the following xml snippet to the web.xml
    <servlet> 
    <servlet-name>dwr-invoker</servlet-name>
    <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
    <init-param>
                          <param-name>debug</param-name>
                          <param-value>true</param-value>
    </init-param>
    </servlet>
    <servlet-mapping>
    <servlet-name>dwr-invoker</servlet-name>
    <url-pattern>/dwr/*</url-pattern>
    </servlet-mapping>

    c         Create or Copy the dwr.xml under the WEB-INF directory and content of the file is as follows
    <!DOCTYPE dwr PUBLIC
        "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN"
        "http://getahead.org/dwr/dwr20.dtd">

    <dwr>
      <allow>
        <create creator="new" javascript=" AjaxDWRTest">
          <param name="class" value="com.vaka.siva.helper.AjaxDWRTest"/>
        </create>
      </allow>
    </dwr>

    d        Write a class with public methods and className  should be like as specified in dwr.xml (If you need the  HTTPServletSession then we use below extra code)

    public class AjaxDWRTest {
    public String getDisplayedTickets(int pageIndex) {
                                                   
                                                    WebContext ctx = WebContextFactory.get();
                                                    HttpServletRequest request = ctx.getHttpServletRequest();
                                                    HttpSession session = ctx.getSession();
                                                    if (session == null)return null;
                                                   
    //call to some helpers and do the processing
    //you can make backend calls now or you can make backend calls first and store it in the session and now retrieve from session

    return tktstr
    }
    e        In above XML , we have specified the AjaxDWRTest as javascript ,so DWR will create  that for us we just need to include the following in JSP where we need the AJAX call

    <script type="text/javascript" src='<%= renderResponse.encodeURL(renderRequest.getContextPath()+ "/dwr/interface/AjaxDWRTest.js") %>'>
    </script>
    <script type="text/javascript" src='<%= renderResponse.encodeURL(renderRequest.getContextPath()+ "/dwr/engine.js") %>'>

    f          Following is the way we invoke the callback method in JSP

    //Print the table with initial values List (this is not ajax call)
    <c:if test="${!empty SessionBean.initialTicketValuesMap}">
    <script type="text/javascript">
                   <portlet:namespace/>paintDynaSec(intialTicketValuesString);
    </script>
    </c:if>

    //following is AJAX call , when somebody click next page then we call below
    AjaxDWRTest.getDisplayedTickets(currentPageIndex, <portlet:namespace/>paintDynaSec);

    //Once AJAX backend call is over then above statement will automatically calls paintDynaSec javascript function with parameter that is returned from the AJAX
    function <portlet:namespace/>paintDynaSec(tktstr) {
                            ticketList.innerHTML =tktstr;
    }

    Making AJAX call using smiple XMLHTTPRequest Object

    This Article will explain how to make simple AJAX call from JSP 

    Follow the simple Steps 
    a.         Create a servlet (can be any server side component that listen to requests and respond back like JSP or PHP).
    b.       In JSP file, first get the XMLHttpRequest object (it is different for different browsers)
    c.         onreadystatechange property: After a request send to a server, we need a function to receive the data returned from the server. The onreadystatechange property stores the function that will process the response from a server. The function is stored in the property to be called automatically.
    xmlhttp.onreadystatechange=function()
    {
    // We are going to write some code here
    }
    d.        readyState property: The readyState property holds the status of the server's response each time the readyState property changes, the onreadystatechange function will be executed .Possible values for readyState property are
    i           0 – request is not intialized
    ii         1 – request has been setup
    iii        2 – request has sent
    iv       3 – request in progress
    v         4 – request is completed
    e.        To send off a request to the server, we use the open() and send() methods.
    i           Open(): The open() method takes three arguments. The first argument defines which method to use when sending the request (GET or POST). The second argument specifies the URL of the server-side script. The third argument specifies that the request should be handled asynchronously(true – asynchronous , false – synchronous )
    ii         Send: The send() method sends the request off to the server.
    f.          Sample is as follows
    //getting XMLHttpRequest Object
    function getXMLHTTPObject(){
    if(window.XMLHttpRequest){
    return new XMLHttpRequest();
    }
    if(typeof XMLHttpRequest != 'undefined'){
       return new XMLHttpRequest();
    }else{
      try{
      return new ActiveXObject("Msxml2.XMLHTTP");
      }catch(e){
      try{
              return new ActiveXObject("Microsoft.XMLHTTP");
      }catch(e){}
      }
    }
     return false;
    }
    //make AJAX call
    function invokeAjax(){
           xmlHTTP=getXMLHTTPObject();
           var ajaxServletURL="<%=response.encodeUrl(request.getContextPath())%>"+"/SivaAjaxServlet?name=siva";
           xmlHTTP.open("POST",ajaxServletURL,true);
           xmlHTTP.setRequestHeader ("Content-Type", "application/x-www-form-urlencoded");
           xmlHTTP.onreadystatechange=httpResponse;
           xmlHTTP.send(null);
    }
     //callback method
    function httpResponse(){
      if(xmlHTTP.readyState==4){
        document.getElementById("ajaxdiv").innerHTML=xmlHTTP.responseText;
      }
    }
     //simple html elements gets change after ajax call
    <div id="ajaxdiv">
     <table>
           <tr><td>Loading ....Ajax example</td><td><input type="button" onClick="invokeAjax()" name="but1" value="submit"/></td></tr>
     </table>
    </div></div>


    Invalidate the browser cache

    Set the following response headers to invalidate any browser Cache.


    response.setHeader("Pragma","no-cache"); 
    response.setHeader("Cache-Control","no-cache, no-store, must-revalidate"); response.setHeader("max-age","0");  


    Alternatively you can use the HTTP meta equivalent tags to do in HTML 

    <meta http-equiv="Cache-Control" content="no-store,no-cache, must-revalidate,post-check=0, pre-check=0,max-age=0">
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Expires" content="0"> 


    Click Here for more options on cahce-control

    Problems while working with elements (Nodes) in DOM (JavaScript) Dynamically.

    Issue 1: setAttribute doesn't work for all elements in IE (but it works fine in Mozilla and Chrome)


    var tableElement = document.createElement('table');
    tableElement.setAttribute("id","tableID");
    tableElement.setAttribute("name","tableName");
    tableElement.setAttribute("className","CSSClasName");

    Cross browser Solution for the above problem is use like below

    var tableElement = document.createElement('table');
    tableElement.id="tableId";
    tableElement.name="tableName";
    tableElement.className="CSSClassName";


    Issue 2: calling onClick event(Javascript Functions) on elements created using createElement (dynamic DOM)


    var upArrowButton=document.createElement("input");
    upArrowButton.type="button";
    upArrowButton.value="\u2191";
    upArrowButton.onclick="moveElementUp();";

    Above statements will call moveElementUp() method on onClick() Event in Mozilla and Chrome but it doesn't work in IE. To make it work across all the browsers use like below (anonymous function)

    upArrowButton.onclick=function(){ moveElementUp(); };

    Issue 3: removeChild() method need to call in reverse order to properly remove multiple element from parent Node


    var textareaArray= document.getElementById('parentID').getElementsByTagName('textarea');
    for(var x=0;x<hildren.length;x++){
    document.getElementById('parentID').removeChild(textAreaArray[x])
    }

    Above statements may not work properly to remove text area child nodes of the "parentID",  while removing the remove always remove the last child first . Following for do the job

    for(var x=textareaArray.length-1;x>=0;x--){
    document.getElementById('parentID').removeChild(textAreaArray[x])
    }


    Issue 4: Issue while retrieving child nodes with document.getElementsByTagName method

    var children = document.getElementById('parentID').getElementsByTagName('*');

    "children" array in above statement will be all decedents of "parentID" not only direct childrens. To get the direct children use the following statement

    var children = document.getElementById('parentID').childNodes; //this will return only direct decedents

    Setting HTML entity values (↑ ) to DOM dynamically (createElement)

    If you try to create and add the element to DOM as below , it doesn't take the HTML entity codes like "&uarr;" ,"&darr;" or char codes like  "&#8593;" .

    instead of Arrow marks

    var buttonEl = document.createElement('input');
    buttonEl.type = 'button';
    buttonEl.value = '&rarr;'


    Above code will just display as 

    To display actually up arrow and down arrows like below use the unique code corresponding to them like below

    for up arrow
    buttonEl.value = '\u2191'

    for downarrow
    buttonEl.value = '\u2193'

    javascript cloneNode doesn't copy the event handlers

    This article shows how to clone the javascript events along with node when we use the cloneNode method

    javascript cloneNode do shallow copy, it doesn't copy the event handler attached to that node or it children. following method will help you to attach javascript events after cloning.



    function cloneNodeWithEvents( orgNode ){

    var orgNodeEvenets = orgNode.getElementsByTagName('*');
    var cloneNode = orgNode.cloneNode( true );
    var cloneNodeEvents = cloneNode.getElementsByTagName('*');

    var allEvents = new Array('onabort','onbeforecopy','onbeforecut','onbeforepaste','onblur','onchange','onclick',
    'oncontextmenu','oncopy','ondblclick','ondrag','ondragend','ondragenter', 'ondragleave' ,
    'ondragover','ondragstart', 'ondrop','onerror','onfocus','oninput','oninvalid','onkeydown',
    'onkeypress', 'onkeyup','onload','onmousedown','onmousemove','onmouseout',
    'onmouseover','onmouseup', 'onmousewheel', 'onpaste','onreset', 'onresize','onscroll','onsearch', 'onselect','onselectstart','onsubmit','onunload');


    // The node root
    for( var j=0; j<allEvents.length ; j++ ){
    eval('if( orgNode.'+allEvents[j]+' ) cloneNode.'+allEvents[j]+' = orgNode.'+allEvents[j]);
    }

    // Node descendants
    for( var i=0 ; i<orgNodeEvenets.length ; i++ ){
    for( var j=0; j<allEvents.length ; j++ ){
    eval('if( orgNodeEvenets[i].'+allEvents[j]+' ) cloneNodeEvents[i].'+allEvents[j]+' = orgNodeEvenets[i].'+allEvents[j]);
    }
    }

    return cloneNode;

    }

    Incompatiable javascript's encodeURIComponent() and Java's URLEncoder.encode()

    There is incompatibility between the javascript encodeURIComponent and java URLEncoder.encode method.

    URLEncoder.encode (Java API for URLEncoder)
    When  you encode a string using the URLEncoder.encode method following rules apply

    • The alphanumeric characters "a" through "z", "A" through "Z" and "0" through "9" remain the same.
    • The special characters ".", "-", "*", and "_" remain the same.
    • The space character " " is converted into a plus sign "+".
    • All other characters are unsafe and are first converted into one or more bytes using some encoding scheme. Then each byte is represented by the 3-character string "%xy", where xy is the two-digit hexadecimal representation of the byte. The recommended encoding scheme to use is UTF-8. However, for compatibility reasons, if an encoding is not specified, then the default encoding of the platform is used.  

    from the above rules, java URLEncoder.encode will treat [-a-zA-Z0-9._*-] as litterals .

    JavaScript encodeURIComponent

         JavaScript's encodeURLComponenet [-a-zA-Z0-9._*~'()!] as litterals . and space will converts as "%20".

    Following is implementation of javascript compatiable encoding in java

    public static String encodeURIComponent(String originalStr){
        String encodeString= null;
        try{
          encodeString = URLEncoder.encode(s, "UTF-8") 
                             .replaceAll("\\+", "%20")
                             .replaceAll("\\%21", "!")
                             .replaceAll("\\%27", "'")
                             .replaceAll("\\%28", "(")
                             .replaceAll("\\%29", ")")
                             .replaceAll("\\%7E", "~");
    
        }catch (UnsupportedEncodingException e)    {
          System.out.println("Exception while encoding");
        }
    
        return encodeString;  } 
    
    
    
    
    Another approach if you are using the JAVA 6, using the javascript engine that ships with JDK1.6
    
    
    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    
    public static String encodeURIComponent(String originalStr){
            ScriptEngineManager factory = new ScriptEngineManager();
            ScriptEngine engine = factory.getEngineByName("JavaScript");
            engine.eval("print(encodeURIComponent(originalStr))");
    }
    
    
    

    Evaluating the javascript code returned by AJAX (Prototype)

    This Article address the common problem with AJAX calls, when AJAX response contains the javascript functions along with HTML.

    Problem Description: Javascript Returned by AJAX response doesn't work.

    Problem Cause: When any web page loads in to the browser , all javascript on that page gets loaded by browser and you can only call the javascript functions that is already loaded.

    Problem Solution: You can handle this scenarios in multiple ways but choose whichever is most suitable for you

    Approach 1:  If your AJAX response contains only the javascript functions you can use the java script "eval" method to run the scripts return by the AJAX response .




    Ex: simply call eval(document.getElementById('divID').innerHTML);


    But if your AJAX response contains both HTML and Javascript , you need to parse the response and find out the <script> blocks and do eval on that.

    Ex: Assume your ajax response will replace a div then put your response in a div or something and use the div id to grab the tag with a name = to script


    divID.getElementByTagName("script")
    loop through them and run
    eval(script.innerHTML);


    Approach 2: another way to do this use  Prototype AJAX.update method call to evaluate your javascript functions.


    Example :
    new Ajax.Updater(divID,URL,{asynchronous:true,evalScripts: true});


    divID = innerHTML of this divID get replaces with AJAX response
    URL =  server side URL to handle the AJAX response
    evalScripts = true means it evaluates the script elements inside the AJAX response

    If you use evalScripts: true, any <script> block will be evaluated. This does not mean it will get included in the page: they won't. Their content will simply be passed to the native eval() function. There are two consequences to this:
    • The local scope will be that of Prototype's internal processing function. Anything in your script declared with var will be discarded momentarily after evaluation, and at any rate will be invisible to the remainder of the page scripts.
    • If you define functions in there, you need to actually create them, otherwise they won't be accessible to the remainder of the page scripts. That is, the following code won't work:
    // This kind of script won't work if processed by Ajax.Updater:function coolFunc() {
      // Amazing stuff!}
    
    
    You will need to use the following syntax:
     // This kind of script WILL works if processed by Ajax.Updater:
    coolFunc = function() {
      // Amazing stuff!}

    Click Here for more detail on Prototype AJAX update function