1. #1
    Sencha User
    Join Date
    Feb 2012
    Location
    Copenhagen
    Posts
    32
    Vote Rating
    0
    Igor.Szyporyn is on a distinguished road

      0  

    Default Ext.ux.util.Dependencies

    Ext.ux.util.Dependencies


    Ext.ux.util.Dependencies
    A require type mixin for components to load other type resources than ext files

    Download: Ext.ux.util.Dependencies

    The actual loader is not written by me - but by Niels Liisberg, I just wrapped a mixin around it - thanks mate :-)

    Easily declare needed resources for your components, and allows for grouped loading for resources that are dependent on other resources.

    Here an example where some jquery dependent plugins will be loaded only when jquery is loaded

    Code:
    Ext.create('My.random.Class', {
      dependencies: [
        [
          'scripts/jquery.js',
          'styles/mystyle.css'
        ],
        [
          'plugins/jquery.plugin.js'
        ]
      ],
      items: [{
        title: 'Some sub panel',
        width: 300
      }],
      listeners: {
        'dependenciesinit': {
          fn: function() {
            console.log($, jQuery);
          }
        }
      }
    });
    Methods

    loadDependencies(src, callback) - src is an array or multidimensional array for sequential loading
    isDependencyInit() - check if the mixin is initialized
    isDependencyReady() - check if dependencies are loaded

    Events

    dependenciesinit - fires when the component is initialized and dependencies are loaded
    dependenciesloaded - fires when dependencies are loaded

    Code:
    /**
     * @class Ext.ux.util.Dependencies
     * <p>[introduction here]
     * Example usage:</p>
     * <pre><code>
    // [explanation here]
    Ext.define('My.random.Class', {
      extend: ['Ext.panel.Panel'],
      mixins: {
        dependencies: 'Ext.ux.mixins.Dependencies'
        },
        initComponent: function() {
        
        this.callParent();
    
    
        this.initDependencies();
        }
    });
    
    
    // [explanation here]
    var p = Ext.create('My.random.Class', {
      border: false,
      dependencies: [
        [
          'scripts/jquery.js',
          'styles/mystyle.css'
        ],
        [
          'plugins/jquery.plugin.js'
        ]
      ],
      items: [{
        title: 'Some sub panel',
        width: 300,
        autoHeight: true,
        html: 'Some content'
      }],
      listeners: {
        'dependenciesinit': {
          fn: function(self) {
            console.log($, jQuery);
          }
        }
      }
    });
    </code></pre>
     */
    
    
    Ext.define('Ext.ux.util.Dependencies', {
    
    
      statics: {
        _loaded: {}
      },
    
    
      /**
       * @private
       */
      _dependenciesStack: null,
    
    
      /**
       * @private
       */
      _dependenciesLoaded: null,
    
    
      /**
       * @private
       */
      _dependenciesRqsCnt: 0,
    
    
      /**
       * @private
       */
      _dependenciesPrevious: null,
    
    
      _dependenciesInitialized: false,
    
    
      /**
       * Performs initialization of this mixin. Component classes using this mixin should call this method
       * during their own initialization.
       */
      initDependencies: function(scope, callback) {
    
    
        scope || ( scope = this );
    
    
        if ( scope._dependenciesInitialized )
          return false;
    
    
        var me = scope,
          dependencies = me.dependencies || null,
          autoLoad = me.autoLoadDependencies || true;
    
    
        /**
         * @private
         */
        scope._dependenciesStack = [];
    
    
        /**
         * @private
         */
        scope._dependenciesLoaded = [];
    
    
        me._dependenciesInitialized = true;
    
    
        me.addEvents(
          /**
           * @event dependenciesloaded
           * Fires when the method loadDependencies is done loading
           * @param {Ext.ux.mixins.Dependencies} this
           */
          'dependenciesloaded',
          'dependenciesinit'
        );
    
    
        if ( dependencies && autoLoad ) {
    
    
          me.loadDependencies(dependencies, function() {
    
    
            me.fireEvent('dependenciesinit', me, me, me._dependenciesLoaded);
    
    
            if ( Ext.isFunction(callback) )
              callback.call(me, me);
          });
        }
      },
    
    
        /**
         * [explanation here]
         * @param {Array/String} src The dependencies to load, can be an array of strings, a string (one source file), an array of arrays (for nested dependencies)
         * @param {Function} value2 Callback function
         * @chainable
         */
      loadDependencies: function(src, callback) {
    
    
        var me = this,
          stackEntry,
          i = 0;
    
    
        src = me._filterDependencies(src);
    
    
        stackEntry = {
          inProcess: 0,
          callback: callback,
          previous : me._dependenciesPrevious
        };
    
    
        if ( src instanceof Array ) {
          
          for ( ; i < src.length; i++ ) {
            if (!src[i]) src.splice(i,1);
          }
    
    
          if ( src[0] instanceof Array ) {
            
            var s1 = src[0],
              s2 = src.slice(1);
            
            me.loadDependencies(s1, function () {
    
    
              if (s2.length === 0) {
                if (callback) callback.call();
              }
    
    
              else {
                me.loadDependencies(s2, function () {
                  if ( callback ) callback.call();
                });
              }
            });
    
    
            return;
          }
          
          if ( src.length ) {
    
    
            me._dependenciesPushStack(stackEntry, src.length);
            
            for ( i = 0 ; i < src.length; i++ ) {
              
              if ( src[i] ) {
                if ( !me.isSourceLoaded(src[i]) ) {
                  me.addLoadedSource(src[i]);
                }
                me._dependenciesLoadResource(src[i],stackEntry);
              }
            }
          }
        }
    
    
        else if ( src ) {
    
    
          // TODO: Check out all changes in this else if statement
    
    
          // START OF ADDED (force loading into the array loader part for easier check if already loaded)
          var a = [];
          a.push(src);
          me.loadDependencies(a);
          // END OF ADDED
    
    
          /* START OF REMOVED
    
    
            me._dependenciesPushStack(stackEntry, 1);
            me._dependenciesLoadResource(src, stackEntry);
          END OF REMOVED */
        }
    
    
        else {
          me.fireEvent('dependenciesloaded', me);
          if ( callback ) callback.call();
        }
    
    
        return me;
      },
    
    
      /**
       * @private
       */
      _filterDependencies: function(m_dependencies) {
    
    
        var i_this = this,
          a_proxy = [],
          a_dependencies;
    
    
        if ( !Ext.isArray(m_dependencies) ) {
          a_proxy.push(m_dependencies);
          a_dependencies = i_this._filterDependencies(a_proxy);
        }
        else {
          a_dependencies = m_dependencies;
        }
    
    
        Ext.Array.forEach(a_dependencies, function(m_dependency, n_index) {
          
          if ( Ext.isArray(m_dependency) ) {
            m_dependency = i_this._filterDependencies(m_dependency);
          }
          else {
    
    
            // only allow js and css files to be cached like this!
            var a_split = m_dependency.split('.'),
              s_type = a_split[a_split.length - 1];
    
    
            if ( s_type == 'js' || s_type == 'css' ) {
              
              if ( i_this.isSourceLoaded(m_dependency) ) {
                a_dependencies.splice(n_index, 1);
              }
            }
          }
        });
    
    
        return a_dependencies;
      },
    
    
      /**
       * @private
       */
      _dependenciesDoCallback: function(req) {
        
        var me = this;
    
    
        req.done = true;
        
        me._dependenciesRqsCnt --;
    
    
        // Handle memory leak in IE
        req.elm.onload = req.elm.onreadystatechange = null;
        
        if ( req.head && req.elm.parentNode ) {
          // You can't go and remove the item from the DOM structure if it's not loaded
          // You can have unexpected behaivor.
          // req.head.removeChild(req.elm);
        }
    
    
        // decement all previous requirements levels, This need to be seperate since callback can start increment
        for ( var se = req.stackEntry; se ; se=se.previous ) {
          se.inProcess --;
        }
    
    
        for ( se = req.stackEntry; se ; se=se.previous ) {
          
          if (se.callback &&  se.inProcess === 0) {
            
            var cb = se.callback;
            se.callback = null;
            cb.call();
            
            if ( me._dependenciesRqsCnt === 0 ) {
              
              me._dependenciesStack  = [];
              me.previous =null;
            }
          }
        }
      },
      
      /**
       * @private
       */
      _dependenciesLoadResource: function(src, stackEntry) {
    
    
        var me = this,
          req;
    
    
        req = {
          src: src,
          stackEntry: stackEntry,
          elm: {},
          head: document.getElementsByTagName("head")[0] || document.documentElement,
          done: false
        };
    
    
        me._dependenciesRqsCnt ++;
    
    
        if ( me._dependenciesLoaded[src] ) {
          me._dependenciesDoCallback(req);
          return;
        }
    
    
        me._dependenciesLoaded[src] = true;
    
    
        if ( src.right(4) == '.css' ) {
    
    
          req.elm = document.createElement('link');
          req.elm.rel  = 'stylesheet';
          req.elm.type = 'text/css';
          req.elm.href = src;
    
    
          (function() {
            // Load css file, scope is make for not population parent score with
            // img
            var img = document.createElement("img");
    
    
            img.style.position = "absolute";
            img.style.top = '-1000px';
            img.style.left = '-1000px';
    
    
            img.onerror = img.onload = function() {
              
              img.parentNode.removeChild(img);
              me._dependenciesDoCallback(req);
            };
    
    
            document.body.appendChild(img);
    
    
            img.src = src;
          })();
    
    
        }
    
    
        else if ( src.right(3) == '.js' ) {
          
          req.elm  = document.createElement('script');
          req.elm.type = 'text/javascript';
          req.elm.src = src;
          
          // This is for IE
          req.elm.onreadystatechange = function () {
            if ( (this.readyState !== "loaded" && this.readyState !== "complete" ) ||  (req.done) ) {
              return;
            }
            me._dependenciesDoCallback(req);
          };
    
    
          req.elm.onload = function () {
            me._dependenciesDoCallback(req);
          };
        }
        else {
    
    
          Ext.require(src, function () {
            me._dependenciesDoCallback(req);
          });
    
    
          return;
        }
    
    
        // Use insertBefore instead of appendChild  to circumvent an IE6 bug.
        // This arises when a base node is used (#2709 and #4378).
        //req.head.insertBefore( req.elm, req.head.firstChild );
    
    
        // AND: The new item needs to be the last item in the DOM structure.
        // Else you may cause unespected problems in browser.
        req.head.appendChild( req.elm );
    
    
        return;
      },
    
    
      /**
       * @private
       */
      _dependenciesPushStack: function(stackEntry, len) {
        
        var me = this;
    
    
        for ( var se = stackEntry; se ; se=se.previous ) {
          
          se.inProcess += len;
        }
    
    
        me._dependenciesStack.push(stackEntry);
        me._dependenciesPrevious = stackEntry;
      },
    
    
      addLoadedSource: function(s_src) {
    
    
        Ext.ux.util.Dependencies._loaded[s_src.toLowerCase()] = true;
      },
    
    
      isSourceLoaded: function(s_src) {
    
    
        return Ext.ux.util.Dependencies._loaded[s_src.toLowerCase()] ? true : false;
      },
    
    
      isDependencyReady: function() {
    
    
        var me = this,
          isReady;
    
    
        isReady = this._dependenciesRqsCnt === 0;
    
    
        return isReady;
      },
    
    
      isDependencyInit: function() {
    
    
        return this._dependenciesInitialized;
      }
    });

  2. #2
    Sencha - Support Team scottmartin's Avatar
    Join Date
    Jul 2010
    Location
    Houston, Tx
    Posts
    9,080
    Vote Rating
    467
    scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future

      0  

    Default


    You are on a role. You should see about placing some of these on our Sencha Market:
    https://market.sencha.com/

  3. #3
    Sencha User
    Join Date
    Feb 2012
    Location
    Copenhagen
    Posts
    32
    Vote Rating
    0
    Igor.Szyporyn is on a distinguished road

      0  

    Default


    Thanks have some more to share, but as my mate said - it is not a good idea to put them out there without a demo site.

    So I am quickly building a rough demo site for it, so people can check it out in action.

    Replies about bugs/wishes would be appreciated as I have been developing these in a specific environment so it has not been tested in the "wild" yet.

    Once they are stable enough, I will put them on the marketplace.

    I hope to learn a lot from sharing these as I have a lot to learn about ExtJS - so there may be some duh! mistakes as I learn the finer arts of this framework :-)
    Last edited by Igor.Szyporyn; 13 Dec 2013 at 12:33 PM. Reason: ended up as WoT

Thread Participants: 1