Jx.JxNativeJsUtils

This class is used to interact with other native JavaScript codes. Basically, this class is used to build the UI in the platform's main UI. It also contains the functions to include JavaScript and other static resources to the page, adding callbacks, and so on.


/**
 * Native JS utilities. Singleton to simulate static functions in Java.
 */
Ext.ns('JxNativeJsUtils');

// wrapper to provide OO javascript capability when dealing with
// javascript event handling. Sample usage:
// window.onload = Jx.JxUtilities.addCallback(myFuncName, thisUsedInMyFunc)
JxNativeJsUtils.addCallback = function(method, obj) {
  var temp = function() {
     return method.apply(obj, arguments);
  } ;
  return temp;
};

// enable native scripts to
JxNativeJsUtils.addToUICanvas = function(oldCompId, newComp) {
  var oldComp = Ext.getCmp(oldCompId);
  var container = oldComp.ownerCt;
  container.remove(oldComp);
  container.add(newComp);
  if (oldComp.selectedData != undefined) {
      newComp.selectedData = oldComp.selectedData;
      newComp.getSelectedRecord = function () {return newComp.selectedData;};
  }
  // hook for notification, path is now a reserve word
  if (! oldComp.keepNewCompPath)
    newComp.initialConfig.path = oldComp.path;
  newComp.nativeJsPageId = oldComp.pageId;
  JxObjLocator.getIdSetter().init(newComp);
  // now layout the container
  if (container.rendered) {
    container.doLayout();
  }
};

////////////////////////////////////////////////////////////////////////////////
// Utility to add window to Module Panel.
///////////////////////////////////////////////////////////////////////////////
JxNativeJsUtils.createBubblePanel = function(oldCompId, cmp, title, buttons) {
  var mPanel = Ext.getCmp("my.mainviewpanel");
  var config = {
    category: 'base',
    width: cmp.width + 35,
    height: cmp.height + 35,
    y: 0,
    maximized: false,
    xtype: 'jxpanel',
    autoScroll: true,
    items: [ cmp ],
    nativeJsPageId: cmp.nativeJsPageId,
    initDraggable: Ext.emptyFn //Workaround: Disable drag
  };
  if (cmp.reloadData) {
    Ext.apply(config, {
      reloadData: function() { cmp.reloadData(); }
    });
   }
  //Add place for Buttons
  if (buttons) {
    var extraConfig = {
      buttons: buttons,
      height: config.height + 40
    };
    Ext.apply(config, extraConfig);
  }
  //Not able to put new comp on framework provided
  //component. Need to close that before adding new window.
  if (oldCompId) {
    var oldComp = Ext.getCmp(oldCompId);
    if (oldComp) {
      oldComp = oldComp.findParentByType('window');
      if (oldComp) {
        oldComp.destroy();
      }
    }
  }
  //Hide Active Window
  var lastWindow = mPanel.getLastWindow();
  if (lastWindow) {
    lastWindow.hide();
  }
  
  //Show New Window
  Ext.apply(config, { x : mPanel.computeXPosition(config)} );
  mPanel.createWindowFromConfig(config, title, 'jx-window-transparent', true);
};

/**
 * Workaround for Ext 3.1.1 and IE7 issue
 * of "parentNode null or not an object".
 */
JxNativeJsUtils.overrideInsertAfter = function() {
  if (Ext.version === '3.1.1' && Ext.isIE7) {  
    Ext.override(Ext.Element, {
      insertAfter: function(el){
        el = Ext.getDom(el);
        if (el.parentNode) {
          el.parentNode.insertBefore(this.dom, el.nextSibling);
        }
        return this;
      }
    });
  }
};

// include anything used by native java script. currently support only 2 types, 'css' or 'js'
// return dom element created/found
JxNativeJsUtils.includeAny = function(type, src, onloadCallback) {
    var el;
    if (type == 'js') {
      var selstr = 'script[src='+ src + ']';
      el = Ext.DomQuery.selectNode(selstr);
      if (! el) {
        el = document.createElement('script');
        el.type = 'text/javascript';
        el.src = src;
      }
    } else if (type == 'css') {
      var selstr = 'link[href=' + src + ']';
      el = Ext.DomQuery.selectNode(selstr);
      if (! el) {
        el = document.createElement('link');
        el.type = 'text/css';
        el.rel = 'stylesheet';
        el.href = src;
      }     
    }

    // real loading
    el = Ext.get(el);
    if (el.jxloaded === undefined) {
      // never loaded before
      el.jxloaded = false;
      if (type == 'js') {
        if (Ext.isIE) {
          var func = function() {
            var el = this.jxel;
            if ("loaded" === el.dom.readyState || "complete" === el.dom.readyState) {
              el.jxloaded = true;
              onloadCallback();
              el.un('readystatechange', this, this);
              delete this.jxel;
            }
          };
          func.jxel = el;
          el.on('readystatechange', func, func);
        } else {
          var func = function() {
            var el = this.jxel;
            el.jxloaded = true;
            onloadCallback();
            el.un('load', this, this);
            delete this.jxel;
          };
          func.jxel = el;
          el.on('load', func, func );
          }
      } else { // type == 'css'
        if (Ext.isIE) {
          el.jxloaded = true;
          // TODO: IE cant detect if css is loaded completely
          onloadCallback();
        } else {
          var func = function() {
            var el = this.jxel;
            try {
              el.dom.sheet.cssRules;
              el.jxloaded = true;
              onloadCallback();
              delete this.jxel;
              window.clearInterval(this.jxintid);
            } catch (e) {
            }
          };
          func.jxel = el;
          func.jxintid = window.setInterval(func.createDelegate(func), 100);
        }
      }
      // launching loading
      var head = document.getElementsByTagName('head')[0];
      head.appendChild(el.dom);
    } else if (el.jxloaded) {
      // loaded
      onloadCallback();
    } else {
      // in the middle of loading
      var func = function() {
        var el = this.jxel;
        if (el.jxloaded) {
          onloadCallback();
          delete this.jxel;
          window.clearInterval(this.jxintid);
        }
      };
      func.jxel = el;
      func.jxintid = window.setInterval(func.createDelegate(func), 100);
    }
};
// include multiple files used by native java script. When every file is loaded
// onloadCallback is called.
// currently support only 2 types, 'css' or 'js'
// @param file Array of files (each item contains type and path
// @param onloadCallback Callback when all files are loaded
JxNativeJsUtils.includeMany = function(files, onloadCallback) {
  var includeAnyCallback = {
    indx: 0,
    files: files,
    exec: function() {
      var lastIndx = files.length -1;
      var nextIndx = this.indx;
      this.indx++;
      if (nextIndx < lastIndx) {
        JxNativeJsUtils.includeAny(files[nextIndx][0],
            files[nextIndx][1],
            this.exec.createDelegate(this));
      } else if (nextIndx === lastIndx) {
        JxNativeJsUtils.includeAny(files[nextIndx][0], files[nextIndx][1], onloadCallback)
      }
    }
  };
  includeAnyCallback.exec();
};

// interceptor of JxConnection.request
// the idea was to figure out if request is js related, if so, make it a local request
JxNativeJsUtils.jsReader = function(o) {
  if (!o.url || o.url.match('/CMPServlet'))
    return true; // old framework stuff
  // process params
  //
  var fnm;
  var qMrk = o.url.indexOf('?');
  var params = {};
  var url;
  if (qMrk > 0) {
    params = Ext.urlDecode(o.url.substring(qMrk + 1));
    if (params.jxtype && params.jxtype != 'js') {
      delete params.jxtype;
    }
    url = fnm = o.url.substring(0, qMrk);
  } else {
    url = fnm = o.url;
  }
  var index = fnm.lastIndexOf('.js');// /a/b/c.js
  if (index > 0) {
    params.jxtype = 'js';
    fnm = fnm.substring(0, index);
  }
  if (! params.jxtype) {
    return true; // not a nativejs
  }
  fnm = fnm.substring(fnm.lastIndexOf('/') + 1);
  var fnmEntry;
  if (params.jxentry) {
    fnmEntry = params.jxentry;
  } else {
    fnmEntry = fnm;
  }
  var result = {
      data: {
        xtype: 'jxnativejscontainer',
        category: 'base',
        jsFilename: url,
        entryFunc: fnmEntry,
        pageId: '$' + fnm,
        path: '$' + fnm,
        jxoptions: o, // old options preserved
        items: [ { }]
      }};
  Ext.applyIf(result.data, params);
  if (o.success) {
    myExecute(o.success, o.scope, [result.data, result.message, o]);
  }
  return false;
};

// interceptor of JxConnection.request
// the idea was to figure out if request is iframe related, if so, make it a local request
JxNativeJsUtils.ifReader = function(o) {
  if (!o.url || o.url.match('/CMPServlet'))
    return true; // old framework stuff
  // for url does not ends with .html...need to add parameter jxtype=html
  var index = o.url.lastIndexOf('.html'); // /a/b/c.html
  var frameSize = {
     jxwidth: 300,
     jxheight: 500
  };
  var hasHtmlExt = false;
  if (index < 0) {
    // case without .html, look for jxtype=html
    // /a/b/c?jxtype=html
    index = o.url.lastIndexOf('jxtype=html');
    if (index < 0) {
      return true; // definitely not an iframe request
    }
    o.url = o.url.replace('jxtype=html', ''); // consume it
  }  else {
    hasHtmlExt = true;
  }
  // /a/b/c.html?jxwidth=100&jxheight=100 or /a/b/c?jxwidth=100&jxheight=100&jxtype=html
  index = o.url.lastIndexOf('?');
  if (index < 0) {
    index = o.url.length;
  } else {
    // see if there is size parameters
    var paramsStr = o.url.substring(index+1);
    var params = Ext.urlDecode(paramsStr);
    Ext.apply(frameSize, params);
  }
  var fnm = o.url.substring(0, index);
  index = fnm.lastIndexOf('/') + 1;
  var endIndex;
  if (hasHtmlExt) {
    endIndex = fnm.length - ".html".length;
  } else {
    endIndex = fnm.length;
  }
  fnm = fnm.substring(index, endIndex); // file name is also name space...
  var result = {
      data: {
        width: frameSize.jxwidth,
        height: frameSize.jxheight,
        xtype: 'jxifnativejscontainer',
        category: 'base',
        fileName: o.url,
        nativeJsPageId: '$' + fnm,
        path: '$' + fnm,
        items: [ { }]
      }};

  if (o.success) {
    myExecute(o.success, o.scope, [result.data, result.message, o]);
  }
  return false;
};