Package org.cruxframework.crux.core.client.utils

Source Code of org.cruxframework.crux.core.client.utils.ScriptTagHandler$ScriptInjector

/*
* Copyright 2011 cruxframework.org.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.cruxframework.crux.core.client.utils;

import java.util.ArrayList;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.dom.client.ScriptElement;

/**
*
* @author Thiago da Rosa de Bustamante
*
*/
public class ScriptTagHandler
{
  private static ScriptInjector injector = null;
  private static ArrayList<Element> scripts;

  /**
   * Evaluates any script inserted on the given element using element.innerHTML.
   * @param element
   */
  public static void evaluateScripts(Element element, ScriptLoadCallback callback)
  {
    if (scripts == null)
    {
       scripts = new ArrayList<Element>();
    }
    NodeList<Element> scriptElements = element.getElementsByTagName("script");
   
    if (scriptElements != null)
    {
      for (int i = 0; i < scriptElements.getLength(); i++)
      {
        scripts.add(scriptElements.getItem(i));
      }
    }
    processNextScript(callback);
  }
 
  private static void processNextScript(final ScriptLoadCallback callback)
  {
    if (scripts.size() > 0)
    {
      final ScriptElement script = scripts.remove(0).cast();
      final ScriptElement cloneScript = cloneScript(script); // if cloned using node.cloneNode(), browser does not evaluate the
                                   // inner javascript when tag is attached
      Scheduler.get().scheduleDeferred(new ScheduledCommand()
      {
        @Override
        public void execute()
        {
          processScriptTag(script, cloneScript, callback);
        }
      });
    }
    else if (callback != null)
    {
      callback.onLoaded();
    }
  }
 
  private static void processScriptTag(final ScriptElement script, final ScriptElement cloneScript, final ScriptLoadCallback callback)
    {
    handleDocWriteFunction();
    String src = script.getSrc();
    ScriptLoadCallback tagCallback = new ScriptLoadCallback()
    {
      @Override
      public void onLoaded()
      {
        String content = getDocWrittenContent();
        restoreDocWriteFunction();
        processNextScript(callback);
        final DivElement wrapperElement = Document.get().createDivElement();
        wrapperElement.setInnerHTML(content);
        cloneScript.getParentElement().insertAfter(wrapperElement, cloneScript);
        Scheduler.get().scheduleDeferred(new ScheduledCommand()
        {
          @Override
          public void execute()
          {
            evaluateScripts(wrapperElement, null);
          }
        });
      }
    };

    // If it is a cross domain script, the content loading is assynchronous
    boolean xDomain = isXDomain(src);
    if (xDomain)
    {
      handleXDomainScriptLoad(cloneScript, tagCallback);
    }
   
        script.getParentElement().replaceChild(cloneScript, script);
       
        if (!xDomain)
        {
          tagCallback.onLoaded();
        }
    }

  private static native boolean isXDomain(String src)/*-{
    if (!src)
    {
      return false;
    }
    var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec(src);
    return parts && ( parts[1] && parts[1] != location.protocol || parts[2] != location.host );
  }-*/;
 
  private static ScriptElement cloneScript(ScriptElement script)
  {
    Document doc = Document.get();
    ScriptElement cloneScript = doc.createScriptElement();
    cloneScript.setType("text/javascript");
    cloneScript.setLang("javascript");
    if (script.hasAttribute("src"))
    {
      cloneScript.setSrc(script.getSrc());
    }
    else
    {
      getScriptInjector().copyScriptContent(script, cloneScript);
    }
   
    return cloneScript;
  }
 
  private static native void handleDocWriteFunction()/*-{
    $wnd.__crux_content = '';
    $wnd.__crux_originalWrite = $doc.write;
    $doc.write = function(s) {
        $wnd.__crux_content += s;
    };
  }-*/;

 
  private static native String getDocWrittenContent()/*-{
    return $wnd.__crux_content;
  }-*/;
 
 
  private static native void restoreDocWriteFunction()/*-{
    $wnd.__crux_content = '';
    $doc.write = $wnd.__crux_originalWrite;
  }-*/;

  private static native void handleXDomainScriptLoad(ScriptElement script, ScriptLoadCallback callback)/*-{
    script.onload = script.onreadystatechange = function(){
      if (!this.readyState || this.readyState == "loaded" || this.readyState == "complete") {
        if (callback)
        {
          callback.@org.cruxframework.crux.core.client.utils.ScriptTagHandler.ScriptLoadCallback::onLoaded()();
        }

        script.onload = script.onreadystatechange = null;
        script.parentNode.removeChild( script );
      }
    };   
  }-*/;

  private static ScriptInjector getScriptInjector()
  {
    if (injector == null)
    {
      injector = GWT.create(ScriptInjector.class);
    }
    return injector;
  }

  public static interface ScriptLoadCallback
  {
    void onLoaded();
  }
 
  static class ScriptInjector
  {
    protected void copyScriptContent(ScriptElement script, ScriptElement cloneScript)
    {
      String text = script.getInnerHTML();
      if (StringUtils.isEmpty(text))
      {
        text = script.getText();
      }
      cloneScript.appendChild(Document.get().createTextNode(text));
    }
  }
 
  static class IEScriptInjector extends ScriptInjector
  {
    protected void copyScriptContent(ScriptElement script, ScriptElement cloneScript)
    {
      cloneScript.setText(script.getText());
    }
  }
}
TOP

Related Classes of org.cruxframework.crux.core.client.utils.ScriptTagHandler$ScriptInjector

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.