<commit_before>/*! angular-deckgrid (v0.5.0) - Copyright: 2013 - 2014, André König (andre.koenig@posteo.de) - MIT */
/*
 * angular-deckgrid
 *
 * Copyright(c) 2013-2014 André König <andre.koenig@posteo.de>
 * MIT Licensed
 *
 */

/**
 * @author André König (andre.koenig@posteo.de)
 *
 */

angular.module('akoenig.deckgrid', []);

angular.module('akoenig.deckgrid').directive('deckgrid', [

    'DeckgridDescriptor',

    function initialize (DeckgridDescriptor) {

        'use strict';

        return DeckgridDescriptor.create();
    }
]);
/*
 * angular-deckgrid
 *
 * Copyright(c) 2013-2014 André König <andre.koenig@posteo.de>
 * MIT Licensed
 *
 */

/**
 * @author André König (andre.koenig@posteo.de)
 *
 */

angular.module('akoenig.deckgrid').factory('DeckgridDescriptor', [

    'Deckgrid',
    '$templateCache',

    function initialize (Deckgrid, $templateCache) {

        'use strict';

        /**
         * This is a wrapper around the AngularJS
         * directive description object.
         *
         */
        function Descriptor () {
            this.restrict = 'AE';

            this.template = '
' +
                                '

' +
                            '
';

            this.scope = {
                'model': '=source'
            };

            //
            // Will be created in the linking function.
            //
            this.$$deckgrid = null;

            this.transclude = true;
            this.link = this.$$link.bind(this);

            //
            // Will be incremented if using inline templates.
            //
            this.$$templateKeyIndex = 0;

        }

        /**
         * @private
         *
         * Cleanup method. Will be called when the
         * deckgrid directive should be destroyed.
         *
         */
        Descriptor.prototype.$$destroy = function $$destroy () {
            this.$$deckgrid.destroy();
        };

        /**
         * @private
         *
         * The deckgrid link method. Will instantiate the deckgrid.
         *
         */
        Descriptor.prototype.$$link = function $$link (scope, elem, attrs, nullController, transclude) {
            var templateKey = 'deckgrid/innerHtmlTemplate' + (++this.$$templateKeyIndex) + '.html';

            scope.$on('$destroy', this.$$destroy.bind(this));

            if (angular.isUndefined(attrs.cardtemplate)) {
                if (angular.isUndefined(attrs.cardtemplatestring)) {
                    // use the provided inner html as template
                    transclude(scope, function onTransclude (innerHTML) {
                        var extractedInnerHTML = [],
                            i = 0,
                            len = innerHTML.length,
                            outerHTML;

                        for (i; i < len; i = i + 1) {
                            outerHTML = innerHTML[i].outerHTML;

                            if (angular.isDefined(outerHTML)) {
                                extractedInnerHTML.push(outerHTML);
                            }
                        }

                        $templateCache.put(templateKey, extractedInnerHTML.join());
                    });
                } else {
                    // use the provided template string
                    //
                    // note: the attr is accessed via the elem object, as the attrs content
                    // is already compiled and thus lacks the {{...}} expressions
                    $templateCache.put(templateKey, elem.attr('cardtemplatestring'));
                }

                scope.cardTemplate = templateKey;
            } else {
                // use the provided template file
                scope.cardTemplate = attrs.cardtemplate;
            }

            scope.mother = scope.$parent;

            this.$$deckgrid = Deckgrid.create(scope, elem[0]);
        };

        return {
            create : function create () {
                return new Descriptor();
            }
        };
    }
]);

/*
 * angular-deckgrid
 *
 * Copyright(c) 2013-2014 André König <andre.koenig@posteo.de>
 * MIT Licensed
 *
 */

/**
 * @author André König (andre.koenig@posteo.de)
 *
 */

angular.module('akoenig.deckgrid').factory('Deckgrid', [

    '$window',
    '$log',

    function initialize ($window, $log) {

        'use strict';

        /**
         * The deckgrid directive.
         *
         */
        function Deckgrid (scope, element) {
            var self = this,
                watcher,
                mql;

            this.$$elem = element;
            this.$$watchers = [];

            this.$$scope = scope;
            this.$$scope.columns = [];

            //
            // The layout configuration will be parsed from
            // the pseudo "before element." There you have to save all
            // the column configurations.
            //
            this.$$scope.layout = this.$$getLayout();

            this.$$createColumns();

            //
            // Register model change.
            //
            watcher = this.$$scope.$watchCollection('model', this.$$onModelChange.bind(this));

            this.$$watchers.push(watcher);

            //
            // Register media query change events.
            //
            angular.forEach(self.$$getMediaQueries(), function onIteration (rule) {
                var handler = self.$$onMediaQueryChange.bind(self);

                function onDestroy () {
                    rule.removeListener(handler);
                }

                rule.addListener(handler);

                self.$$watchers.push(onDestroy);
            });

            mql = $window.matchMedia('(orientation: portrait)');
            mql.addListener(self.$$onMediaQueryChange.bind(self));

        }

        /**
         * @private
         *
         * Extracts the media queries out of the stylesheets.
         *
         * This method will fetch the media queries out of the stylesheets that are
         * responsible for styling the angular-deckgrid.
         *
         * @return {array} An array with all respective styles.
         *
         */
        Deckgrid.prototype.$$getMediaQueries = function $$getMediaQueries () {
            var stylesheets = [],
                mediaQueries = [];

            stylesheets = Array.prototype.concat.call(
                Array.prototype.slice.call(document.querySelectorAll('style[type=\'text/css\']')),
                Array.prototype.slice.call(document.querySelectorAll('link[rel=\'stylesheet\']'))
            );

            function extractRules (stylesheet) {
                try {
                    return (stylesheet.sheet.cssRules || []);
                } catch (e) {
                    return [];
                }
            }

            function hasDeckgridStyles (rule) {
                var regexe   = /\[(\w*-)?deckgrid\]::?before/g,
                    i        = 0,
                    selector = '';

                if (!rule.media || angular.isUndefined(rule.cssRules)) {
                    return false;
                }

                i = rule.cssRules.length - 1;

                for (i; i >= 0; i = i - 1) {
                    selector = rule.cssRules[i].selectorText;

                    if (angular.isDefined(selector) && selector.match(regexe)) {
                        return true;
                    }
                }

                return false;
            }

            angular.forEach(stylesheets, function onIteration (stylesheet) {
                var rules = extractRules(stylesheet);

                angular.forEach(rules, function inRuleIteration (rule) {
                    if (hasDeckgridStyles(rule)) {
                        mediaQueries.push($window.matchMedia(rule.media.mediaText));
                    }
                });
            });

            return mediaQueries;
        };

        /**
         * @private
         *
         * Creates the column segmentation. With other words:
         * This method creates the internal data structure from the
         * passed "source" attribute. Every card within this "source"
         * model will be passed into this internal column structure by
         * reference. So if you modify the data within your controller
         * this directive will reflect these changes immediately.
         *
         * NOTE that calling this method will trigger a complete template "redraw".
         *
         */
        Deckgrid.prototype.$$createColumns = function $$createColumns () {
            var self = this;

            if (!this.$$scope.layout) {
                return $log.error('angular-deckgrid: No CSS configuration found (see ' +
                                   'https://github.com/akoenig/angular-deckgrid#the-grid-configuration)');
            }

            this.$$scope.columns = [];

            angular.forEach(this.$$scope.model, function onIteration (card, index) {
                var column = (index % self.$$scope.layout.columns) | 0;

                if (!self.$$scope.columns[column]) {
                    self.$$scope.columns[column] = [];
                }

                card.$index = index;
                self.$$scope.columns[column].push(card);
            });
        };

        /**
         * @private
         *
         * Parses the configuration out of the configured CSS styles.
         *
         * Example:
         *
         *     .deckgrid::before {
         *         content: '3 .column.size-1-3';
         *     }
         *
         * Will result in a three column grid where each column will have the
         * classes: "column size-1-3".
         *
         * You are responsible for defining the respective styles within your CSS.
         *
         */
        Deckgrid.prototype.$$getLayout = function $$getLayout () {
            var content = $window.getComputedStyle(this.$$elem, ':before').content,
                layout;

            if (content) {
                content = content.replace(/'/g, '');  // before e.g. '3 .column.size-1of3'
                content = content.replace(/"/g, '');  // before e.g. "3 .column.size-1of3"
                content = content.split(' ');

                if (2 === content.length) {
                    layout = {};
                    layout.columns = (content[0] | 0);
                    layout.classList = content[1].replace(/\./g, ' ').trim();
                }
            }

            return layout;
        };

        /**
         * @private
         *
         * Event that will be triggered if a CSS media query changed.
         *
         */
        Deckgrid.prototype.$$onMediaQueryChange = function $$onMediaQueryChange () {
            var self = this,
                layout = this.$$getLayout();

            //
            // Okay, the layout has changed.
            // Creating a new column structure is not avoidable.
            //
            if (layout.columns !== this.$$scope.layout.columns) {
                self.$$scope.layout = layout;

                self.$$scope.$apply(function onApply () {
                    self.$$createColumns();
                });
            }
        };

        /**
         * @private
         *
         * Event that will be triggered when the source model has changed.
         *
         */
        Deckgrid.prototype.$$onModelChange = function $$onModelChange (newModel, oldModel) {
            var self = this;

            newModel = newModel || [];
            oldModel = oldModel || [];

            if (!angular.equals(oldModel, newModel)) {
                self.$$createColumns();
            }
        };

        /**
         * Destroys the directive. Takes care of cleaning all
         * watchers and event handlers.
         *
         */
        Deckgrid.prototype.destroy = function destroy () {
            var i = this.$$watchers.length - 1;

            for (i; i >= 0; i = i - 1) {
                this.$$watchers[i]();
            }
        };

        return {
            create : function create (scope, element) {
                return new Deckgrid(scope, element);
            }
        };
    }
]);
<commit_msg>Adapting fix #27 by @pandaiolo<commit_after>/*! angular-deckgrid (v0.5.0) - Copyright: 2013 - 2014, André König (andre.koenig@posteo.de) - MIT */
/*
 * angular-deckgrid
 *
 * Copyright(c) 2013-2014 André König <andre.koenig@posteo.de>
 * MIT Licensed
 *
 */

/**
 * @author André König (andre.koenig@posteo.de)
 *
 */

angular.module('akoenig.deckgrid', []);

angular.module('akoenig.deckgrid').directive('deckgrid', [

    'DeckgridDescriptor',

    function initialize (DeckgridDescriptor) {

        'use strict';

        return DeckgridDescriptor.create();
    }
]);
/*
 * angular-deckgrid
 *
 * Copyright(c) 2013-2014 André König <andre.koenig@posteo.de>
 * MIT Licensed
 *
 */

/**
 * @author André König (andre.koenig@posteo.de)
 *
 */

angular.module('akoenig.deckgrid').factory('DeckgridDescriptor', [

    'Deckgrid',
    '$templateCache',
    '$window',
    '$q',

    function initialize (Deckgrid, $templateCache, $window, $q) {

        'use strict';

        /**
         * This is a wrapper around the AngularJS
         * directive description object.
         *
         */
        function Descriptor () {
            this.restrict = 'AE';

            this.template = '
' +
                                '

' +
                            '
';

            this.scope = {
                'model': '=source'
            };

            //
            // Will be created in the linking function.
            //
            this.$$deckgrid = null;

            this.transclude = true;
            this.link = this.$$link.bind(this);

            //
            // Will be incremented if using inline templates.
            //
            this.$$templateKeyIndex = 0;

        }

        /**
         * @private
         *
         * Cleanup method. Will be called when the
         * deckgrid directive should be destroyed.
         *
         */
        Descriptor.prototype.$$destroy = function $$destroy () {
            this.$$deckgrid.destroy();
        };

        /**
         * @private
         *
         * The deckgrid link method. Will instantiate the deckgrid.
         *
         */
        Descriptor.prototype.$$link = function $$link (scope, elem, attrs, nullController, transclude) {
            var templateKey = 'deckgrid/innerHtmlTemplate' + (++this.$$templateKeyIndex) + '.html',
                self = this,
                styleReady = $q.defer(),
                domWatch;

            scope.$on('$destroy', this.$$destroy.bind(this));

            if (attrs.cardtemplate === undefined) {
                if (attrs.cardtemplatestring === undefined) {
                    // use the provided inner html as template
                    transclude(scope, function onTransclude (innerHTML) {
                        var extractedInnerHTML = [],
                            i = 0,
                            len = innerHTML.length,
                            outerHTML;

                        for (i; i < len; i = i + 1) {
                            outerHTML = innerHTML[i].outerHTML;

                            if (outerHTML !== undefined) {
                                extractedInnerHTML.push(outerHTML);
                            }
                        }

                        $templateCache.put(templateKey, extractedInnerHTML.join());
                    });
                } else {
                    // use the provided template string
                    //
                    // note: the attr is accessed via the elem object, as the attrs content
                    // is already compiled and thus lacks the {{...}} expressions
                    $templateCache.put(templateKey, elem.attr('cardtemplatestring'));
                }

                scope.cardTemplate = templateKey;
            } else {
                // use the provided template file
                scope.cardTemplate = attrs.cardtemplate;
            }

            scope.mother = scope.$parent;

            // Wait for style to be ready on deckgrid element
           domWatch = scope.$watch(function() {
                return $window.getComputedStyle(elem[0], ':before').content;
            }, function(content) {
                if (content !== '') {
                    styleReady.resolve();
                    // Clear the watcher once element is initialized
                    domWatch();
                }
            });
            styleReady.promise.then(function() {
                self.$$deckgrid = Deckgrid.create(scope, elem[0]);
            });
        };

        return {
            create : function create () {
                return new Descriptor();
            }
        };
    }
]);

/*
 * angular-deckgrid
 *
 * Copyright(c) 2013-2014 André König <andre.koenig@posteo.de>
 * MIT Licensed
 *
 */

/**
 * @author André König (andre.koenig@posteo.de)
 *
 */

angular.module('akoenig.deckgrid').factory('Deckgrid', [

    '$window',
    '$log',

    function initialize ($window, $log) {

        'use strict';

        /**
         * The deckgrid directive.
         *
         */
        function Deckgrid (scope, element) {
            var self = this,
                watcher,
                mql;

            this.$$elem = element;
            this.$$watchers = [];

            this.$$scope = scope;
            this.$$scope.columns = [];

            //
            // The layout configuration will be parsed from
            // the pseudo "before element." There you have to save all
            // the column configurations.
            //
            this.$$scope.layout = this.$$getLayout();

            this.$$createColumns();

            //
            // Register model change.
            //
            watcher = this.$$scope.$watchCollection('model', this.$$onModelChange.bind(this));

            this.$$watchers.push(watcher);

            //
            // Register media query change events.
            //
            angular.forEach(self.$$getMediaQueries(), function onIteration (rule) {
                var handler = self.$$onMediaQueryChange.bind(self);

                function onDestroy () {
                    rule.removeListener(handler);
                }

                rule.addListener(handler);

                self.$$watchers.push(onDestroy);
            });

            mql = $window.matchMedia('(orientation: portrait)');
            mql.addListener(self.$$onMediaQueryChange.bind(self));

        }

        /**
         * @private
         *
         * Extracts the media queries out of the stylesheets.
         *
         * This method will fetch the media queries out of the stylesheets that are
         * responsible for styling the angular-deckgrid.
         *
         * @return {array} An array with all respective styles.
         *
         */
        Deckgrid.prototype.$$getMediaQueries = function $$getMediaQueries () {
            var stylesheets = [],
                mediaQueries = [];

            stylesheets = Array.prototype.concat.call(
                Array.prototype.slice.call(document.querySelectorAll('style[type=\'text/css\']')),
                Array.prototype.slice.call(document.querySelectorAll('link[rel=\'stylesheet\']'))
            );

            function extractRules (stylesheet) {
                try {
                    return (stylesheet.sheet.cssRules || []);
                } catch (e) {
                    return [];
                }
            }

            function hasDeckgridStyles (rule) {
                var regexe   = /\[(\w*-)?deckgrid\]::?before/g,
                    i        = 0,
                    selector = '';

                if (!rule.media || angular.isUndefined(rule.cssRules)) {
                    return false;
                }

                i = rule.cssRules.length - 1;

                for (i; i >= 0; i = i - 1) {
                    selector = rule.cssRules[i].selectorText;

                    if (angular.isDefined(selector) && selector.match(regexe)) {
                        return true;
                    }
                }

                return false;
            }

            angular.forEach(stylesheets, function onIteration (stylesheet) {
                var rules = extractRules(stylesheet);

                angular.forEach(rules, function inRuleIteration (rule) {
                    if (hasDeckgridStyles(rule)) {
                        mediaQueries.push($window.matchMedia(rule.media.mediaText));
                    }
                });
            });

            return mediaQueries;
        };

        /**
         * @private
         *
         * Creates the column segmentation. With other words:
         * This method creates the internal data structure from the
         * passed "source" attribute. Every card within this "source"
         * model will be passed into this internal column structure by
         * reference. So if you modify the data within your controller
         * this directive will reflect these changes immediately.
         *
         * NOTE that calling this method will trigger a complete template "redraw".
         *
         */
        Deckgrid.prototype.$$createColumns = function $$createColumns () {
            var self = this;

            if (!this.$$scope.layout) {
                return $log.error('angular-deckgrid: No CSS configuration found (see ' +
                                   'https://github.com/akoenig/angular-deckgrid#the-grid-configuration)');
            }

            this.$$scope.columns = [];

            angular.forEach(this.$$scope.model, function onIteration (card, index) {
                var column = (index % self.$$scope.layout.columns) | 0;

                if (!self.$$scope.columns[column]) {
                    self.$$scope.columns[column] = [];
                }

                card.$index = index;
                self.$$scope.columns[column].push(card);
            });
        };

        /**
         * @private
         *
         * Parses the configuration out of the configured CSS styles.
         *
         * Example:
         *
         *     .deckgrid::before {
         *         content: '3 .column.size-1-3';
         *     }
         *
         * Will result in a three column grid where each column will have the
         * classes: "column size-1-3".
         *
         * You are responsible for defining the respective styles within your CSS.
         *
         */
        Deckgrid.prototype.$$getLayout = function $$getLayout () {
            var content = $window.getComputedStyle(this.$$elem, ':before').content,
                layout;

            if (content) {
                content = content.replace(/'/g, '');  // before e.g. '3 .column.size-1of3'
                content = content.replace(/"/g, '');  // before e.g. "3 .column.size-1of3"
                content = content.split(' ');

                if (2 === content.length) {
                    layout = {};
                    layout.columns = (content[0] | 0);
                    layout.classList = content[1].replace(/\./g, ' ').trim();
                }
            }

            return layout;
        };

        /**
         * @private
         *
         * Event that will be triggered if a CSS media query changed.
         *
         */
        Deckgrid.prototype.$$onMediaQueryChange = function $$onMediaQueryChange () {
            var self = this,
                layout = this.$$getLayout();

            //
            // Okay, the layout has changed.
            // Creating a new column structure is not avoidable.
            //
            if (layout.columns !== this.$$scope.layout.columns) {
                self.$$scope.layout = layout;

                self.$$scope.$apply(function onApply () {
                    self.$$createColumns();
                });
            }
        };

        /**
         * @private
         *
         * Event that will be triggered when the source model has changed.
         *
         */
        Deckgrid.prototype.$$onModelChange = function $$onModelChange (newModel, oldModel) {
            var self = this;

            newModel = newModel || [];
            oldModel = oldModel || [];

            if (!angular.equals(oldModel, newModel)) {
                self.$$createColumns();
            }
        };

        /**
         * Destroys the directive. Takes care of cleaning all
         * watchers and event handlers.
         *
         */
        Deckgrid.prototype.destroy = function destroy () {
            var i = this.$$watchers.length - 1;

            for (i; i >= 0; i = i - 1) {
                this.$$watchers[i]();
            }
        };

        return {
            create : function create (scope, element) {
                return new Deckgrid(scope, element);
            }
        };
    }
]);
<|endoftext|>


<commit_before>(function (root, factory) {
  // AMD
  if (typeof define === 'function' && define.amd) {
    define(['angular', 'intercom'], function (angular, intercom) {
      return factory({}, angular, intercom);
    });
  }
  // Node.js
  else if (typeof exports === 'object') {
    module.exports = factory({}, require('angular'), require('intercom'));
  }
  // Angular
  else if (angular) {
    factory(root, root.angular, root.Intercom);
  }
}(this, function (global, angular, Intercom) {
  'use strict';
  if (Intercom && global && !global.Intercom) { global.Intercom = Intercom; }

  function _capitalize_(string) {
    return (!string) ? '' : string.charAt(0).toUpperCase() + string.substring(1).toLowerCase();
  }
  var intercomSettings = global.IntercomSettings || global.intercomSettings;

  // if intercom exist then reattach
  var intercom_exist = false;
  if (angular.isFunction(Intercom)) {
    global.Intercom('reattach_activator');
    if (intercomSettings) {
      global.Intercom('update', intercomSettings);
    }
    intercom_exist = true;
  } else {
    // build Intercom for async loading
    var build_intercom = function() {
      build_intercom.c(arguments);
    };
    build_intercom.q = [];
    build_intercom.c = function(args) {
      build_intercom.q.push(args);
    };
    global.Intercom = build_intercom;
  }

  angular.module('ngIntercom', [])
  .value('IntercomSettings', {})
  .provider('$intercom', function() {

    var provider = this;
    var config = {
      'asyncLoading': false,
      'scriptUrl': 'https://widget.intercom.io/widget/',// <INSERT APP_ID HERE>
      'appID': '',
      'development': false
    };
    angular.forEach(config, function(val, key) {
      provider[key] = function(newValue) {
        config[key] = newValue || val;
        return provider;
      };
    });

    // Create a script tag with moment as the source
    // and call our onScriptLoad callback when it
    // has been loaded
    function createScript(url, appID) {
      if (!document) { return; }
      var script = document.createElement('script');
      script.type = 'text/javascript';
      script.async = true;
      script.src = url+appID;
      // Attach the script tag to the document head
      var s = document.getElementsByTagName('head')[0];
      s.appendChild(script);
    }

    provider.$get = ['$rootScope', 'IntercomSettings', function($rootScope, IntercomSettings) {
      var _options = {};

      if (config.appID) {
        _options.app_id = _options.app_id || config.appID;
      }
      angular.extend(_options, IntercomSettings);

      if (intercom_exist) {
        global.Intercom('reattach_activator');
        global.Intercom('update', _options );
      }

      if (config.asyncLoading) {
        createScript(config.scriptUrl, config.appID);
      }

      function $intercom() {
        global.Intercom.apply(Intercom, arguments);
        return this;
      }

      var methods = {
        boot: function(options) {
          angular.extend(_options, options || {});
          if (!_options.app_id && config.appID) {
            _options.app_id = config.appID;
          }
          if (options.app_id && options.app_id !== _options.app_id) {
            _options.app_id = options.app_id;
          }
          global.Intercom('boot', _options);
          return $intercom;
        },
        update: function(data) {
          if (data) {
            if (!data.app_id && config.appID) {
              data.app_id = config.appID;
            }
            if (data.app_id && data.app_id !== config.app_id) {
              config.app_id = data.app_id;
            }
            global.Intercom('update', data);
          } else {
            global.Intercom('update');
          }
          console.log('update data', data);
          return $intercom;
        },
        trackEvent: function(eventName, data) {
          global.Intercom('trackEvent', eventName, data);
          return $intercom;
        },
        showMessages: function(data) {
          if (data) {
            global.Intercom('showMessages', data);
          } else {
            global.Intercom('showMessages');
          }
          return $intercom;
        },
        hideMessages: function() {
          global.Intercom('hideMessages');
          return $intercom;
        },
        shutdown: function() {
          global.Intercom('shutdown');
          return $intercom;
        },
        hide: function() {
          global.Intercom('hide');
          return $intercom;
        },
        show: function() {
          global.Intercom('show');
          return $intercom;
        },
        reattachActivator: function() {
          global.Intercom('reattach_activator');
          return $intercom;
        }
      };

      function buildMethod(func, method) {
        $intercom[method] = func;
        $intercom['$'+method] = function() {
          func.apply(Intercom, arguments);
          if (!$rootScope.$$phase) { $rootScope.$apply(); }
          return $intercom;
        };
      }

      angular.forEach(methods, buildMethod);

      var isEvent = {
        'show': true,
        'hide': true,
        'activatorClick': true
      };

      $intercom.$on = function(event, callback) {
        if (!isEvent[event]) { return; }
        global.Intercom('on'+_capitalize_(event), function() {
          console.log('on', event);
          if ($rootScope.$$phase) {
            callback();
          } else {
            $rootScope.$apply(callback);
          }
        });
        return $intercom;
      };

      $intercom.on = function(event, callback) {
        if (!isEvent[event]) { return; }
        global.Intercom('on'+_capitalize_(event), callback);
        return $intercom;
      };

      $intercom._extend = function(method) {
        if (!method) { return; }
        buildMethod(method, function() {
          var args = Array.prototype.slice.call(arguments);
          global.Intercom.apply(Intercom, args.unshift(method));
          return $intercom;
        });
      };

      return $intercom;
    }]; // end $get
  }) // end provider
  .provider('Intercom', function() {
    this.$get = ['$intercom', '$log', function($intercom, $log) {
      $log.warn('Please use $intercom rather than Intercom https://github.com/gdi2290/angular-intercom');
      return $intercom;
    }];
  });

  angular.module('angular-intercom', ['ngIntercom']);

  return angular.module('ngIntercom');

  // Intercom's script break down
  /*
  (function(){
    // if intercom exist then reattach
    var _intercom = window.Intercom;
    if (typeof _intercom === "function" ) {
      _global.intercom('reattach_activator');
      _global.intercom('update', window.intercomSettings );
    } else {

      // build Intercom for async loading
      var intercom = function() {
        intercom.c(arguments);
      };
      intercom.q = [];
      intercom.c = function(args) {
        intercom.q.push(args);
      };
      window.Intercom = intercom;

      function listener() {
        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.async = true;
        script.src='https://widget.intercom.io/widget/<INSERT APP_ID HERE>';
        var $script = document.getElementsByTagName('script')[0];
        $script.parentNode.insertBefore(script, $script);
      }

      if (window.attachEvent) {
        window.attachEvent('onload',listener);
      } else {
        window.addEventListener('load',listener,false);
      }
    }
  })();
  */
}));

<commit_msg>Removed console.log statements.<commit_after>(function (root, factory) {
  // AMD
  if (typeof define === 'function' && define.amd) {
    define(['angular', 'intercom'], function (angular, intercom) {
      return factory({}, angular, intercom);
    });
  }
  // Node.js
  else if (typeof exports === 'object') {
    module.exports = factory({}, require('angular'), require('intercom'));
  }
  // Angular
  else if (angular) {
    factory(root, root.angular, root.Intercom);
  }
}(this, function (global, angular, Intercom) {
  'use strict';
  if (Intercom && global && !global.Intercom) { global.Intercom = Intercom; }

  function _capitalize_(string) {
    return (!string) ? '' : string.charAt(0).toUpperCase() + string.substring(1).toLowerCase();
  }
  var intercomSettings = global.IntercomSettings || global.intercomSettings;

  // if intercom exist then reattach
  var intercom_exist = false;
  if (angular.isFunction(Intercom)) {
    global.Intercom('reattach_activator');
    if (intercomSettings) {
      global.Intercom('update', intercomSettings);
    }
    intercom_exist = true;
  } else {
    // build Intercom for async loading
    var build_intercom = function() {
      build_intercom.c(arguments);
    };
    build_intercom.q = [];
    build_intercom.c = function(args) {
      build_intercom.q.push(args);
    };
    global.Intercom = build_intercom;
  }

  angular.module('ngIntercom', [])
  .value('IntercomSettings', {})
  .provider('$intercom', function() {

    var provider = this;
    var config = {
      'asyncLoading': false,
      'scriptUrl': 'https://widget.intercom.io/widget/',// <INSERT APP_ID HERE>
      'appID': '',
      'development': false
    };
    angular.forEach(config, function(val, key) {
      provider[key] = function(newValue) {
        config[key] = newValue || val;
        return provider;
      };
    });

    // Create a script tag with moment as the source
    // and call our onScriptLoad callback when it
    // has been loaded
    function createScript(url, appID) {
      if (!document) { return; }
      var script = document.createElement('script');
      script.type = 'text/javascript';
      script.async = true;
      script.src = url+appID;
      // Attach the script tag to the document head
      var s = document.getElementsByTagName('head')[0];
      s.appendChild(script);
    }

    provider.$get = ['$rootScope', 'IntercomSettings', function($rootScope, IntercomSettings) {
      var _options = {};

      if (config.appID) {
        _options.app_id = _options.app_id || config.appID;
      }
      angular.extend(_options, IntercomSettings);

      if (intercom_exist) {
        global.Intercom('reattach_activator');
        global.Intercom('update', _options );
      }

      if (config.asyncLoading) {
        createScript(config.scriptUrl, config.appID);
      }

      function $intercom() {
        global.Intercom.apply(Intercom, arguments);
        return this;
      }

      var methods = {
        boot: function(options) {
          angular.extend(_options, options || {});
          if (!_options.app_id && config.appID) {
            _options.app_id = config.appID;
          }
          if (options.app_id && options.app_id !== _options.app_id) {
            _options.app_id = options.app_id;
          }
          global.Intercom('boot', _options);
          return $intercom;
        },
        update: function(data) {
          if (data) {
            if (!data.app_id && config.appID) {
              data.app_id = config.appID;
            }
            if (data.app_id && data.app_id !== config.app_id) {
              config.app_id = data.app_id;
            }
            global.Intercom('update', data);
          } else {
            global.Intercom('update');
          }
          return $intercom;
        },
        trackEvent: function(eventName, data) {
          global.Intercom('trackEvent', eventName, data);
          return $intercom;
        },
        showMessages: function(data) {
          if (data) {
            global.Intercom('showMessages', data);
          } else {
            global.Intercom('showMessages');
          }
          return $intercom;
        },
        hideMessages: function() {
          global.Intercom('hideMessages');
          return $intercom;
        },
        shutdown: function() {
          global.Intercom('shutdown');
          return $intercom;
        },
        hide: function() {
          global.Intercom('hide');
          return $intercom;
        },
        show: function() {
          global.Intercom('show');
          return $intercom;
        },
        reattachActivator: function() {
          global.Intercom('reattach_activator');
          return $intercom;
        }
      };

      function buildMethod(func, method) {
        $intercom[method] = func;
        $intercom['$'+method] = function() {
          func.apply(Intercom, arguments);
          if (!$rootScope.$$phase) { $rootScope.$apply(); }
          return $intercom;
        };
      }

      angular.forEach(methods, buildMethod);

      var isEvent = {
        'show': true,
        'hide': true,
        'activatorClick': true
      };

      $intercom.$on = function(event, callback) {
        if (!isEvent[event]) { return; }
        global.Intercom('on'+_capitalize_(event), function() {
          if ($rootScope.$$phase) {
            callback();
          } else {
            $rootScope.$apply(callback);
          }
        });
        return $intercom;
      };

      $intercom.on = function(event, callback) {
        if (!isEvent[event]) { return; }
        global.Intercom('on'+_capitalize_(event), callback);
        return $intercom;
      };

      $intercom._extend = function(method) {
        if (!method) { return; }
        buildMethod(method, function() {
          var args = Array.prototype.slice.call(arguments);
          global.Intercom.apply(Intercom, args.unshift(method));
          return $intercom;
        });
      };

      return $intercom;
    }]; // end $get
  }) // end provider
  .provider('Intercom', function() {
    this.$get = ['$intercom', '$log', function($intercom, $log) {
      $log.warn('Please use $intercom rather than Intercom https://github.com/gdi2290/angular-intercom');
      return $intercom;
    }];
  });

  angular.module('angular-intercom', ['ngIntercom']);

  return angular.module('ngIntercom');

  // Intercom's script break down
  /*
  (function(){
    // if intercom exist then reattach
    var _intercom = window.Intercom;
    if (typeof _intercom === "function" ) {
      _global.intercom('reattach_activator');
      _global.intercom('update', window.intercomSettings );
    } else {

      // build Intercom for async loading
      var intercom = function() {
        intercom.c(arguments);
      };
      intercom.q = [];
      intercom.c = function(args) {
        intercom.q.push(args);
      };
      window.Intercom = intercom;

      function listener() {
        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.async = true;
        script.src='https://widget.intercom.io/widget/<INSERT APP_ID HERE>';
        var $script = document.getElementsByTagName('script')[0];
        $script.parentNode.insertBefore(script, $script);
      }

      if (window.attachEvent) {
        window.attachEvent('onload',listener);
      } else {
        window.addEventListener('load',listener,false);
      }
    }
  })();
  */
}));

<|endoftext|>


<commit_before>/**
 * This module defines the p5.Shader class
 * @module Lights, Camera
 * @submodule Shaders
 * @for p5
 * @requires core
 */

'use strict';

var p5 = require('../core/core');

/**
 * Shader class for WEBGL Mode
 * @class p5.Shader
 * @param {p5.RendererGL} renderer an instance of p5.RendererGL that
 * will provide the GL context for this new p5.Shader
 * @param {String} vertSrc source code for the vertex shader (as a string)
 * @param {String} fragSrc source code for the fragment shader (as a string)
 */
p5.Shader = function(renderer, vertSrc, fragSrc) {
  // TODO: adapt this to not take ids, but rather,
  // to take the source for a vertex and fragment shader
  // to enable custom shaders at some later date
  this._renderer = renderer;
  this._vertSrc = vertSrc;
  this._fragSrc = fragSrc;
  this._vertShader = -1;
  this._fragShader = -1;
  this._glProgram = 0;
  this._loadedAttributes = false;
  this.attributes = {};
  this._loadedUniforms = false;
  this.uniforms = {};
  this._bound = false;
  this.samplers = [];
};

/**
 * Creates, compiles, and links the shader based on its
 * sources for the vertex and fragment shaders (provided
 * to the constructor). Populates known attributes and
 * uniforms from the shader.
 * @method init
 * @chainable
 * @private
 */
p5.Shader.prototype.init = function() {
  if (this._glProgram === 0 /* or context is stale? */) {
    var gl = this._renderer.GL;

    // @todo: once custom shading is allowed,
    // friendly error messages should be used here to share
    // compiler and linker errors.

    //set up the shader by
    // 1. creating and getting a gl id for the shader program,
    // 2. compliling its vertex & fragment sources,
    // 3. linking the vertex and fragment shaders
    this._vertShader = gl.createShader(gl.VERTEX_SHADER);
    //load in our default vertex shader
    gl.shaderSource(this._vertShader, this._vertSrc);
    gl.compileShader(this._vertShader);
    // if our vertex shader failed compilation?
    if (!gl.getShaderParameter(this._vertShader, gl.COMPILE_STATUS)) {
      console.error(
        'Yikes! An error occurred compiling the vertex shader:' +
          gl.getShaderInfoLog(this._vertShader)
      );
      return null;
    }

    this._fragShader = gl.createShader(gl.FRAGMENT_SHADER);
    //load in our material frag shader
    gl.shaderSource(this._fragShader, this._fragSrc);
    gl.compileShader(this._fragShader);
    // if our frag shader failed compilation?
    if (!gl.getShaderParameter(this._fragShader, gl.COMPILE_STATUS)) {
      console.error(
        'Darn! An error occurred compiling the fragment shader:' +
          gl.getShaderInfoLog(this._fragShader)
      );
      return null;
    }

    this._glProgram = gl.createProgram();
    gl.attachShader(this._glProgram, this._vertShader);
    gl.attachShader(this._glProgram, this._fragShader);
    gl.linkProgram(this._glProgram);
    if (!gl.getProgramParameter(this._glProgram, gl.LINK_STATUS)) {
      console.error(
        'Snap! Error linking shader program: ' +
          gl.getProgramInfoLog(this._glProgram)
      );
    }

    this._loadAttributes();
    this._loadUniforms();
  }
  return this;
};

/**
 * Queries the active attributes for this shader and loads
 * their names and locations into the attributes array.
 * @method _loadAttributes
 * @private
 */
p5.Shader.prototype._loadAttributes = function() {
  if (this._loadedAttributes) {
    return;
  }

  this.attributes = {};

  var gl = this._renderer.GL;

  var numAttributes = gl.getProgramParameter(
    this._glProgram,
    gl.ACTIVE_ATTRIBUTES
  );
  for (var i = 0; i < numAttributes; ++i) {
    var attributeInfo = gl.getActiveAttrib(this._glProgram, i);
    var name = attributeInfo.name;
    var location = gl.getAttribLocation(this._glProgram, name);
    var attribute = {};
    attribute.name = name;
    attribute.location = location;
    attribute.type = attributeInfo.type;
    attribute.size = attributeInfo.size;
    this.attributes[name] = attribute;
  }

  this._loadedAttributes = true;
};

/**
 * Queries the active uniforms for this shader and loads
 * their names and locations into the uniforms array.
 * @method _loadUniforms
 * @private
 */
p5.Shader.prototype._loadUniforms = function() {
  if (this._loadedUniforms) {
    return;
  }

  var gl = this._renderer.GL;

  // Inspect shader and cache uniform info
  var numUniforms = gl.getProgramParameter(this._glProgram, gl.ACTIVE_UNIFORMS);

  var samplerIndex = 0;
  for (var i = 0; i < numUniforms; ++i) {
    var uniformInfo = gl.getActiveUniform(this._glProgram, i);
    var uniform = {};
    uniform.location = gl.getUniformLocation(this._glProgram, uniformInfo.name);
    uniform.size = uniformInfo.size;
    var uniformName = uniformInfo.name;
    //uniforms thats are arrays have their name returned as
    //someUniform[0] which is a bit silly so we trim it
    //off here. The size property tells us that its an array
    //so we dont lose any information by doing this
    if (uniformInfo.size > 1) {
      uniformName = uniformName.substring(0, uniformName.indexOf('[0]'));
    }
    uniform.name = uniformName;
    uniform.type = uniformInfo.type;
    if (uniform.type === gl.SAMPLER_2D) {
      uniform.samplerIndex = samplerIndex;
      samplerIndex++;
      this.samplers.push(uniform);
    }
    this.uniforms[uniformName] = uniform;
  }
  this._loadedUniforms = true;
};

p5.Shader.prototype.compile = function() {
  // TODO
};

/**
 * initializes (if needed) and binds the shader program.
 * @method bindShader
 * @private
 */
p5.Shader.prototype.bindShader = function() {
  this.init();
  if (!this._bound) {
    this.useProgram();
    this._bound = true;
    this.bindTextures();

    this._renderer._setDefaultCamera();
    this._setMatrixUniforms();
    if (this === this._renderer.curStrokeShader) {
      this._setViewportUniform();
    }
  }
};

/**
 * @method unbindShader
 * @chainable
 * @private
 */
p5.Shader.prototype.unbindShader = function() {
  if (this._bound) {
    this.unbindTextures();
    //this._renderer.GL.useProgram(0); ??
    this._bound = false;
  }
  return this;
};

p5.Shader.prototype.bindTextures = function() {
  var gl = this._renderer.GL;
  for (var i = 0; i < this.samplers.length; i++) {
    var uniform = this.samplers[i];
    var tex = uniform.texture;
    if (tex === undefined) {
      // user hasn't yet supplied a texture for this slot.
      // (or there may not be one--maybe just lighting),
      // so we supply a default texture instead.
      tex = this._renderer._getEmptyTexture();
    }
    gl.activeTexture(gl.TEXTURE0 + uniform.samplerIndex);
    tex.bindTexture();
    tex.update();
    gl.uniform1i(uniform.location, uniform.samplerIndex);
  }
};

p5.Shader.prototype.unbindTextures = function() {
  // TODO: migrate stuff from material.js here
  // - OR - have material.js define this function
};

p5.Shader.prototype._setMatrixUniforms = function() {
  this.setUniform('uProjectionMatrix', this._renderer.uPMatrix.mat4);
  this.setUniform('uModelViewMatrix', this._renderer.uMVMatrix.mat4);
  this.setUniform('uViewMatrix', this._renderer.cameraMatrix.mat4);
  if (this === this._renderer.curFillShader) {
    this._renderer.uNMatrix.inverseTranspose(this._renderer.uMVMatrix);
    this.setUniform('uNormalMatrix', this._renderer.uNMatrix.mat3);
  }
};

p5.Shader.prototype._setViewportUniform = function() {
  this.setUniform('uViewport', this._renderer._viewport);
};

/**
 * @method useProgram
 * @chainable
 * @private
 */
p5.Shader.prototype.useProgram = function() {
  var gl = this._renderer.GL;
  gl.useProgram(this._glProgram);
  return this;
};

/**
 * Wrapper around gl.uniform functions.
 * As we store uniform info in the shader we can use that
 * to do type checking on the supplied data and call
 * the appropriate function.
 * @method setUniform
 * @chainable
 * @param {String} uniformName the name of the uniform in the
 * shader program
 * @param {Object|Number|Boolean|Number[]} data the data to be associated
 * with that uniform; type varies (could be a single numerical value, array,
 * matrix, or texture / sampler reference)
 */
p5.Shader.prototype.setUniform = function(uniformName, data) {
  //@todo update all current gl.uniformXX calls

  var uniform = this.uniforms[uniformName];
  if (!uniform) {
    //@todo warning?
    return;
  }
  var location = uniform.location;

  var gl = this._renderer.GL;
  // todo: is this safe to do here?
  // todo: store the values another way?
  this.useProgram();

  // TODO BIND?

  switch (uniform.type) {
    case gl.BOOL:
      if (data === true) {
        gl.uniform1i(location, 1);
      } else {
        gl.uniform1i(location, 0);
      }
      break;
    case gl.INT:
      if (uniform.size > 1) {
        data.length && gl.uniform1iv(location, data);
      } else {
        gl.uniform1i(location, data);
      }
      break;
    case gl.FLOAT:
      if (uniform.size > 1) {
        data.length && gl.uniform1fv(location, data);
      } else {
        gl.uniform1f(location, data);
      }
      break;
    case gl.FLOAT_MAT3:
      gl.uniformMatrix3fv(location, false, data);
      break;
    case gl.FLOAT_MAT4:
      gl.uniformMatrix4fv(location, false, data);
      break;
    case gl.FLOAT_VEC2:
      if (uniform.size > 1) {
        data.length && gl.uniform2fv(location, data);
      } else {
        gl.uniform2f(location, data[0], data[1]);
      }
      break;
    case gl.FLOAT_VEC3:
      if (uniform.size > 1) {
        data.length && gl.uniform3fv(location, data);
      } else {
        gl.uniform3f(location, data[0], data[1], data[2]);
      }
      break;
    case gl.FLOAT_VEC4:
      if (uniform.size > 1) {
        data.length && gl.uniform4fv(location, data);
      } else {
        gl.uniform4f(location, data[0], data[1], data[2], data[3]);
      }
      break;
    case gl.SAMPLER_2D:
      gl.activeTexture(gl.TEXTURE0 + uniform.samplerIndex);
      uniform.texture = this._renderer.getTexture(data);
      gl.uniform1i(uniform.location, uniform.samplerIndex);
      break;
    //@todo complete all types
  }
  return this;
};

/* NONE OF THIS IS FAST OR EFFICIENT BUT BEAR WITH ME
 *
 * these shader "type" query methods are used by various
 * facilities of the renderer to determine if changing
 * the shader type for the required action (for example,
 * do we need to load the default lighting shader if the
 * current shader cannot handle lighting?)
 *
 **/

p5.Shader.prototype.isLightShader = function() {
  return (
    this.uniforms.uUseLighting !== undefined ||
    this.uniforms.uAmbientLightCount !== undefined ||
    this.uniforms.uDirectionalLightCount !== undefined ||
    this.uniforms.uPointLightCount !== undefined ||
    this.uniforms.uAmbientColor !== undefined ||
    this.uniforms.uDirectionalColor !== undefined ||
    this.uniforms.uPointLightLocation !== undefined ||
    this.uniforms.uPointLightColor !== undefined ||
    this.uniforms.uLightingDirection !== undefined ||
    this.uniforms.uSpecular !== undefined
  );
};

p5.Shader.prototype.isTextureShader = function() {
  return this.samplerIndex > 0;
};

p5.Shader.prototype.isColorShader = function() {
  return (
    this.attributes.aVertexColor !== undefined ||
    this.uniforms.uMaterialColor !== undefined
  );
};

p5.Shader.prototype.isTexLightShader = function() {
  return this.isLightShader() && this.isTextureShader();
};

p5.Shader.prototype.isStrokeShader = function() {
  return this.uniforms.uStrokeWeight !== undefined;
};

/**
 * @method enableAttrib
 * @chainable
 * @private
 */
p5.Shader.prototype.enableAttrib = function(
  loc,
  size,
  type,
  normalized,
  stride,
  offset
) {
  var gl = this._renderer.GL;
  if (loc !== -1) {
    gl.enableVertexAttribArray(loc);
    gl.vertexAttribPointer(loc, size, type, normalized, stride, offset);
  }
  return this;
};

module.exports = p5.Shader;
<commit_msg>webgl: add support for ivec2, ivec3, ivec4 uniforms<commit_after>/**
 * This module defines the p5.Shader class
 * @module Lights, Camera
 * @submodule Shaders
 * @for p5
 * @requires core
 */

'use strict';

var p5 = require('../core/core');

/**
 * Shader class for WEBGL Mode
 * @class p5.Shader
 * @param {p5.RendererGL} renderer an instance of p5.RendererGL that
 * will provide the GL context for this new p5.Shader
 * @param {String} vertSrc source code for the vertex shader (as a string)
 * @param {String} fragSrc source code for the fragment shader (as a string)
 */
p5.Shader = function(renderer, vertSrc, fragSrc) {
  // TODO: adapt this to not take ids, but rather,
  // to take the source for a vertex and fragment shader
  // to enable custom shaders at some later date
  this._renderer = renderer;
  this._vertSrc = vertSrc;
  this._fragSrc = fragSrc;
  this._vertShader = -1;
  this._fragShader = -1;
  this._glProgram = 0;
  this._loadedAttributes = false;
  this.attributes = {};
  this._loadedUniforms = false;
  this.uniforms = {};
  this._bound = false;
  this.samplers = [];
};

/**
 * Creates, compiles, and links the shader based on its
 * sources for the vertex and fragment shaders (provided
 * to the constructor). Populates known attributes and
 * uniforms from the shader.
 * @method init
 * @chainable
 * @private
 */
p5.Shader.prototype.init = function() {
  if (this._glProgram === 0 /* or context is stale? */) {
    var gl = this._renderer.GL;

    // @todo: once custom shading is allowed,
    // friendly error messages should be used here to share
    // compiler and linker errors.

    //set up the shader by
    // 1. creating and getting a gl id for the shader program,
    // 2. compliling its vertex & fragment sources,
    // 3. linking the vertex and fragment shaders
    this._vertShader = gl.createShader(gl.VERTEX_SHADER);
    //load in our default vertex shader
    gl.shaderSource(this._vertShader, this._vertSrc);
    gl.compileShader(this._vertShader);
    // if our vertex shader failed compilation?
    if (!gl.getShaderParameter(this._vertShader, gl.COMPILE_STATUS)) {
      console.error(
        'Yikes! An error occurred compiling the vertex shader:' +
          gl.getShaderInfoLog(this._vertShader)
      );
      return null;
    }

    this._fragShader = gl.createShader(gl.FRAGMENT_SHADER);
    //load in our material frag shader
    gl.shaderSource(this._fragShader, this._fragSrc);
    gl.compileShader(this._fragShader);
    // if our frag shader failed compilation?
    if (!gl.getShaderParameter(this._fragShader, gl.COMPILE_STATUS)) {
      console.error(
        'Darn! An error occurred compiling the fragment shader:' +
          gl.getShaderInfoLog(this._fragShader)
      );
      return null;
    }

    this._glProgram = gl.createProgram();
    gl.attachShader(this._glProgram, this._vertShader);
    gl.attachShader(this._glProgram, this._fragShader);
    gl.linkProgram(this._glProgram);
    if (!gl.getProgramParameter(this._glProgram, gl.LINK_STATUS)) {
      console.error(
        'Snap! Error linking shader program: ' +
          gl.getProgramInfoLog(this._glProgram)
      );
    }

    this._loadAttributes();
    this._loadUniforms();
  }
  return this;
};

/**
 * Queries the active attributes for this shader and loads
 * their names and locations into the attributes array.
 * @method _loadAttributes
 * @private
 */
p5.Shader.prototype._loadAttributes = function() {
  if (this._loadedAttributes) {
    return;
  }

  this.attributes = {};

  var gl = this._renderer.GL;

  var numAttributes = gl.getProgramParameter(
    this._glProgram,
    gl.ACTIVE_ATTRIBUTES
  );
  for (var i = 0; i < numAttributes; ++i) {
    var attributeInfo = gl.getActiveAttrib(this._glProgram, i);
    var name = attributeInfo.name;
    var location = gl.getAttribLocation(this._glProgram, name);
    var attribute = {};
    attribute.name = name;
    attribute.location = location;
    attribute.type = attributeInfo.type;
    attribute.size = attributeInfo.size;
    this.attributes[name] = attribute;
  }

  this._loadedAttributes = true;
};

/**
 * Queries the active uniforms for this shader and loads
 * their names and locations into the uniforms array.
 * @method _loadUniforms
 * @private
 */
p5.Shader.prototype._loadUniforms = function() {
  if (this._loadedUniforms) {
    return;
  }

  var gl = this._renderer.GL;

  // Inspect shader and cache uniform info
  var numUniforms = gl.getProgramParameter(this._glProgram, gl.ACTIVE_UNIFORMS);

  var samplerIndex = 0;
  for (var i = 0; i < numUniforms; ++i) {
    var uniformInfo = gl.getActiveUniform(this._glProgram, i);
    var uniform = {};
    uniform.location = gl.getUniformLocation(this._glProgram, uniformInfo.name);
    uniform.size = uniformInfo.size;
    var uniformName = uniformInfo.name;
    //uniforms thats are arrays have their name returned as
    //someUniform[0] which is a bit silly so we trim it
    //off here. The size property tells us that its an array
    //so we dont lose any information by doing this
    if (uniformInfo.size > 1) {
      uniformName = uniformName.substring(0, uniformName.indexOf('[0]'));
    }
    uniform.name = uniformName;
    uniform.type = uniformInfo.type;
    if (uniform.type === gl.SAMPLER_2D) {
      uniform.samplerIndex = samplerIndex;
      samplerIndex++;
      this.samplers.push(uniform);
    }
    this.uniforms[uniformName] = uniform;
  }
  this._loadedUniforms = true;
};

p5.Shader.prototype.compile = function() {
  // TODO
};

/**
 * initializes (if needed) and binds the shader program.
 * @method bindShader
 * @private
 */
p5.Shader.prototype.bindShader = function() {
  this.init();
  if (!this._bound) {
    this.useProgram();
    this._bound = true;
    this.bindTextures();

    this._renderer._setDefaultCamera();
    this._setMatrixUniforms();
    if (this === this._renderer.curStrokeShader) {
      this._setViewportUniform();
    }
  }
};

/**
 * @method unbindShader
 * @chainable
 * @private
 */
p5.Shader.prototype.unbindShader = function() {
  if (this._bound) {
    this.unbindTextures();
    //this._renderer.GL.useProgram(0); ??
    this._bound = false;
  }
  return this;
};

p5.Shader.prototype.bindTextures = function() {
  var gl = this._renderer.GL;
  for (var i = 0; i < this.samplers.length; i++) {
    var uniform = this.samplers[i];
    var tex = uniform.texture;
    if (tex === undefined) {
      // user hasn't yet supplied a texture for this slot.
      // (or there may not be one--maybe just lighting),
      // so we supply a default texture instead.
      tex = this._renderer._getEmptyTexture();
    }
    gl.activeTexture(gl.TEXTURE0 + uniform.samplerIndex);
    tex.bindTexture();
    tex.update();
    gl.uniform1i(uniform.location, uniform.samplerIndex);
  }
};

p5.Shader.prototype.unbindTextures = function() {
  // TODO: migrate stuff from material.js here
  // - OR - have material.js define this function
};

p5.Shader.prototype._setMatrixUniforms = function() {
  this.setUniform('uProjectionMatrix', this._renderer.uPMatrix.mat4);
  this.setUniform('uModelViewMatrix', this._renderer.uMVMatrix.mat4);
  this.setUniform('uViewMatrix', this._renderer.cameraMatrix.mat4);
  if (this === this._renderer.curFillShader) {
    this._renderer.uNMatrix.inverseTranspose(this._renderer.uMVMatrix);
    this.setUniform('uNormalMatrix', this._renderer.uNMatrix.mat3);
  }
};

p5.Shader.prototype._setViewportUniform = function() {
  this.setUniform('uViewport', this._renderer._viewport);
};

/**
 * @method useProgram
 * @chainable
 * @private
 */
p5.Shader.prototype.useProgram = function() {
  var gl = this._renderer.GL;
  gl.useProgram(this._glProgram);
  return this;
};

/**
 * Wrapper around gl.uniform functions.
 * As we store uniform info in the shader we can use that
 * to do type checking on the supplied data and call
 * the appropriate function.
 * @method setUniform
 * @chainable
 * @param {String} uniformName the name of the uniform in the
 * shader program
 * @param {Object|Number|Boolean|Number[]} data the data to be associated
 * with that uniform; type varies (could be a single numerical value, array,
 * matrix, or texture / sampler reference)
 */
p5.Shader.prototype.setUniform = function(uniformName, data) {
  //@todo update all current gl.uniformXX calls

  var uniform = this.uniforms[uniformName];
  if (!uniform) {
    //@todo warning?
    return;
  }
  var location = uniform.location;

  var gl = this._renderer.GL;
  // todo: is this safe to do here?
  // todo: store the values another way?
  this.useProgram();

  // TODO BIND?

  switch (uniform.type) {
    case gl.BOOL:
      if (data === true) {
        gl.uniform1i(location, 1);
      } else {
        gl.uniform1i(location, 0);
      }
      break;
    case gl.INT:
      if (uniform.size > 1) {
        data.length && gl.uniform1iv(location, data);
      } else {
        gl.uniform1i(location, data);
      }
      break;
    case gl.FLOAT:
      if (uniform.size > 1) {
        data.length && gl.uniform1fv(location, data);
      } else {
        gl.uniform1f(location, data);
      }
      break;
    case gl.FLOAT_MAT3:
      gl.uniformMatrix3fv(location, false, data);
      break;
    case gl.FLOAT_MAT4:
      gl.uniformMatrix4fv(location, false, data);
      break;
    case gl.FLOAT_VEC2:
      if (uniform.size > 1) {
        data.length && gl.uniform2fv(location, data);
      } else {
        gl.uniform2f(location, data[0], data[1]);
      }
      break;
    case gl.FLOAT_VEC3:
      if (uniform.size > 1) {
        data.length && gl.uniform3fv(location, data);
      } else {
        gl.uniform3f(location, data[0], data[1], data[2]);
      }
      break;
    case gl.FLOAT_VEC4:
      if (uniform.size > 1) {
        data.length && gl.uniform4fv(location, data);
      } else {
        gl.uniform4f(location, data[0], data[1], data[2], data[3]);
      }
      break;
    case gl.INT_VEC2:
      if (uniform.size > 1) {
        data.length && gl.uniform2iv(location, data);
      } else {
        gl.uniform2i(location, data[0], data[1]);
      }
      break;
    case gl.INT_VEC3:
      if (uniform.size > 1) {
        data.length && gl.uniform3iv(location, data);
      } else {
        gl.uniform3i(location, data[0], data[1], data[2]);
      }
      break;
    case gl.INT_VEC4:
      if (uniform.size > 1) {
        data.length && gl.uniform4iv(location, data);
      } else {
        gl.uniform4i(location, data[0], data[1], data[2], data[3]);
      }
      break;
    case gl.SAMPLER_2D:
      gl.activeTexture(gl.TEXTURE0 + uniform.samplerIndex);
      uniform.texture = this._renderer.getTexture(data);
      gl.uniform1i(uniform.location, uniform.samplerIndex);
      break;
    //@todo complete all types
  }
  return this;
};

/* NONE OF THIS IS FAST OR EFFICIENT BUT BEAR WITH ME
 *
 * these shader "type" query methods are used by various
 * facilities of the renderer to determine if changing
 * the shader type for the required action (for example,
 * do we need to load the default lighting shader if the
 * current shader cannot handle lighting?)
 *
 **/

p5.Shader.prototype.isLightShader = function() {
  return (
    this.uniforms.uUseLighting !== undefined ||
    this.uniforms.uAmbientLightCount !== undefined ||
    this.uniforms.uDirectionalLightCount !== undefined ||
    this.uniforms.uPointLightCount !== undefined ||
    this.uniforms.uAmbientColor !== undefined ||
    this.uniforms.uDirectionalColor !== undefined ||
    this.uniforms.uPointLightLocation !== undefined ||
    this.uniforms.uPointLightColor !== undefined ||
    this.uniforms.uLightingDirection !== undefined ||
    this.uniforms.uSpecular !== undefined
  );
};

p5.Shader.prototype.isTextureShader = function() {
  return this.samplerIndex > 0;
};

p5.Shader.prototype.isColorShader = function() {
  return (
    this.attributes.aVertexColor !== undefined ||
    this.uniforms.uMaterialColor !== undefined
  );
};

p5.Shader.prototype.isTexLightShader = function() {
  return this.isLightShader() && this.isTextureShader();
};

p5.Shader.prototype.isStrokeShader = function() {
  return this.uniforms.uStrokeWeight !== undefined;
};

/**
 * @method enableAttrib
 * @chainable
 * @private
 */
p5.Shader.prototype.enableAttrib = function(
  loc,
  size,
  type,
  normalized,
  stride,
  offset
) {
  var gl = this._renderer.GL;
  if (loc !== -1) {
    gl.enableVertexAttribArray(loc);
    gl.vertexAttribPointer(loc, size, type, normalized, stride, offset);
  }
  return this;
};

module.exports = p5.Shader;
<|endoftext|>


<commit_before>'use strict';

/**
 */
(function() {

// Get our script tag.
var allScriptTags = document.getElementsByTagName('script');
var angularJsLoaderScriptTag = allScriptTags[allScriptTags.length - 1];

var mainModulePathArg = getAttribute('app');
var rootPathArg = getAttribute('root', '');
var timeoutArg = getAttribute('timeout', 30000);

var angularModuleOriginalFn = angular.module;
var bootstrapLockCount = 0;
var loadedModuleMap = {};

var config = {};

var defaultTransformPathList = [
    function isAbsoluteUrl(path) {
        return path.search(/^(https?:)?\/\/.+/) == 0 ? null : path;
    },
    function prependRootPath(path) {
        return (rootPathArg ? rootPathArg + '/' : '') + path;
    },
    function appendJsExtension(path) {
        return path.search(/\.js$/) == -1 ? path + '.js' : path;
    }
];

function getConfig(name, defaultValue) {
    if (name in config) {
        return config[name];
    }
    else {
        return defaultValue;
    }
}

function transformPath(path, transformList) {
    var original = path;
    for (var i = 0, fn; fn = transformList[i]; i++) {
        var old = path;
        path = fn(path, original);
        if (path === null) {
            return old;
        }
    }
    return path;
}

function pathFromModuleName(name) {
    var map = getConfig('path', {});
    if (map[name] === null) return null;

    var transformList = getConfig('pathTransform', [])
                                .concat(defaultTransformPathList);
    var path = transformPath(name in map ? map[name] : name, transformList);

    return path;
}

function insertScript(path, successFn, errorFn) {
    var newScriptTag = document.createElement('script');
    newScriptTag.type = "text/javascript";
    newScriptTag.src = path;
    if (successFn) {
        newScriptTag.addEventListener('load', function(ev) {
            successFn(ev);
        });
    }
    else if (errorFn) {
        newScriptTag.addEventListener('error', function(ev) {
            errorFn(ev);
        });
    }
    document.head.appendChild(newScriptTag);
}

function maybeBootstrap(path) {
    if (!(path in loadedModuleMap)) {
        throw new Error('Path "' + path + '" was not loaded.');
    }
    else if (loadedModuleMap[path]) {
        throw new Error('Path "' + path + '" was loaded twice.');
    }

    loadedModuleMap[path] = true;
    // Wait until the current Javascript code is entirely loaded before
    // checking the bootstrap lock.
    if (--bootstrapLockCount == 0) {
        window.setTimeout(function() {
            // We check again in case the file introduced new dependencies.
            if (bootstrapLockCount == 0) {
                angular.bootstrap(document, [mainModulePathArg]);
            }
        }, 0);
    }
}

function getAttribute(name, defaultValue) {
    if (angularJsLoaderScriptTag.attributes[name]) {
        return angularJsLoaderScriptTag.attributes[name].value;
    }
    else if (typeof defaultValue == 'undefined') {
        throw new Error('Need to specify an "' + name
                      + '" attribute to angularjs-script.');
    }
}

function loaderFn(path, successFn) {
    if (typeof path == 'string') {
        path = [path];
    }
    function recursiveLoader() {
        if (path.length) {
            var p = path.shift();

            p = pathFromModuleName(p);
            if (!p || p in loadedModuleMap) {
                return recursiveLoader();
            }
            insertScript(p, recursiveLoader);
        }
        else {
            successFn();
        }
    }
    recursiveLoader();
}

angular.extend(loaderFn, {
    config: function(cfg) {
        angular.extend(config, cfg);
        return loaderFn;
    }
});

angular.extend(angular, {
    loader: loaderFn,
    requires: function(path, checkerFn) {
        if (typeof path == 'object') {
            for (var name in path) {
                angular.requires(name, path[name]);
            }
            return angular;
        }
        path = pathFromModuleName(path);
        if (!path || path in loadedModuleMap) {
            return angular;
        }

        loadedModuleMap[path] = false;
        insertScript(path);
        if (checkerFn) {
            // We can specify either a function to be called, a string
            // representing the name of an object or an array of strings.
            if (typeof checkerFn != 'function') {
                var variable = checkerFn;
                if (!(variable instanceof Array)) {
                    variable = [variable];
                }
                checkerFn = function() {
                    for (var i = 0; i < variable.length; i++) {
                        if (typeof window[variable] == 'undefined') {
                            return false;
                        }
                    }
                    return true;
                }
            }
            if (typeof checkerFn == 'null' || checkerFn()) {
                return angular;
            }

            bootstrapLockCount++;

            var start = +new Date();
            var interval = window.setInterval(function() {
                if (checkerFn()) {
                    maybeBootstrap(path);
                    // For every interval created we will clear it by design.
                    window.clearInterval(interval);
                }
                else if (new Date() - start >= timeoutArg) {
                    throw new Error('Timed out loading "' + path + '".');
                }
            });
        }
        return angular;
    },
    module: function() {
        var name = arguments[0];
        var requires = arguments[1];
        var ret = angularModuleOriginalFn.apply(angular, arguments);

        // If module() was called with only 1 argument, it was to get the module
        // and not create a new one.
        if (arguments.length == 1) {
            return ret;
        }

        if (requires instanceof Array) {
            for (var i = 0; i < requires.length; i++) {
                var path = pathFromModuleName(requires[i]);
                if (!path || path in loadedModuleMap) {
                    continue;
                }

                loadedModuleMap[path] = false;
                insertScript(path);

                // We do it here because the call above might throw.
                bootstrapLockCount++;
            }
        }

        var path = pathFromModuleName(name);
        if (path) {
            maybeBootstrap(path);  // If we're done, bootstrap angular.
        }
        return ret;
    }
});

// Load the first module.
bootstrapLockCount++;
var mainModulePath = pathFromModuleName(mainModulePathArg);
loadedModuleMap[mainModulePath] = false;
insertScript(mainModulePath);

})();<commit_msg>Correctly count scripts when loading using angular.loader().<commit_after>'use strict';

/**
 */
(function() {

// Get our script tag.
var allScriptTags = document.getElementsByTagName('script');
var angularJsLoaderScriptTag = allScriptTags[allScriptTags.length - 1];

var mainModulePathArg = getAttribute('app');
var rootPathArg = getAttribute('root', '');
var timeoutArg = getAttribute('timeout', 30000);

var angularModuleOriginalFn = angular.module;
var bootstrapLockCount = 0;
var loadedModuleMap = {};

var config = {};

var defaultTransformPathList = [
    function isAbsoluteUrl(path) {
        return path.search(/^(https?:)?\/\/.+/) == 0 ? null : path;
    },
    function prependRootPath(path) {
        return (rootPathArg ? rootPathArg + '/' : '') + path;
    },
    function appendJsExtension(path) {
        return path.search(/\.js$/) == -1 ? path + '.js' : path;
    }
];

function getConfig(name, defaultValue) {
    if (name in config) {
        return config[name];
    }
    else {
        return defaultValue;
    }
}

function transformPath(path, transformList) {
    var original = path;
    for (var i = 0, fn; fn = transformList[i]; i++) {
        var old = path;
        path = fn(path, original);
        if (path === null) {
            return old;
        }
    }
    return path;
}

function pathFromModuleName(name) {
    var map = getConfig('path', {});
    if (map[name] === null) return null;

    var transformList = getConfig('pathTransform', [])
                                .concat(defaultTransformPathList);
    var path = transformPath(name in map ? map[name] : name, transformList);

    return path;
}

function insertScript(path, successFn, errorFn) {
    var newScriptTag = document.createElement('script');
    newScriptTag.type = "text/javascript";
    newScriptTag.src = path;
    if (successFn) {
        newScriptTag.addEventListener('load', function(ev) {
            successFn(ev);
        });
    }
    else if (errorFn) {
        newScriptTag.addEventListener('error', function(ev) {
            errorFn(ev);
        });
    }
    document.head.appendChild(newScriptTag);
}

function maybeBootstrap(path) {
    if (!(path in loadedModuleMap)) {
        throw new Error('Path "' + path + '" was not loaded.');
    }
    else if (loadedModuleMap[path]) {
        throw new Error('Path "' + path + '" was loaded twice.');
    }

    loadedModuleMap[path] = true;
    // Wait until the current Javascript code is entirely loaded before
    // checking the bootstrap lock.
    if (--bootstrapLockCount == 0) {
        window.setTimeout(function() {
            // We check again in case the file introduced new dependencies.
            if (bootstrapLockCount == 0) {
                angular.bootstrap(document, [mainModulePathArg]);
            }
        }, 0);
    }
}

function getAttribute(name, defaultValue) {
    if (angularJsLoaderScriptTag.attributes[name]) {
        return angularJsLoaderScriptTag.attributes[name].value;
    }
    else if (typeof defaultValue == 'undefined') {
        throw new Error('Need to specify an "' + name
                      + '" attribute to angularjs-script.');
    }
}

function loaderFn(path, successFn) {
    if (typeof path == 'string') {
        path = [path];
    }
    function recursiveLoader() {
        if (path.length) {
            var p = path.shift();

            p = pathFromModuleName(p);
            if (!p || p in loadedModuleMap) {
                return recursiveLoader();
            }
            loadedModuleMap[p] = false;
            bootstrapLockCount++;
            insertScript(p, function() {
                maybeBootstrap(p);
                recursiveLoader();
            });
        }
        else {
            successFn();
        }
    }
    recursiveLoader();
}

angular.extend(loaderFn, {
    config: function(cfg) {
        angular.extend(config, cfg);
        return loaderFn;
    }
});

angular.extend(angular, {
    loader: loaderFn,
    requires: function(path, checkerFn) {
        if (typeof path == 'object') {
            for (var name in path) {
                angular.requires(name, path[name]);
            }
            return angular;
        }
        path = pathFromModuleName(path);
        if (!path || path in loadedModuleMap) {
            return angular;
        }

        loadedModuleMap[path] = false;
        insertScript(path);
        if (checkerFn) {
            // We can specify either a function to be called, a string
            // representing the name of an object or an array of strings.
            if (typeof checkerFn != 'function') {
                var variable = checkerFn;
                if (!(variable instanceof Array)) {
                    variable = [variable];
                }
                checkerFn = function() {
                    for (var i = 0; i < variable.length; i++) {
                        if (typeof window[variable] == 'undefined') {
                            return false;
                        }
                    }
                    return true;
                }
            }
            if (typeof checkerFn == 'null' || checkerFn()) {
                return angular;
            }

            bootstrapLockCount++;

            var start = +new Date();
            var interval = window.setInterval(function() {
                if (checkerFn()) {
                    maybeBootstrap(path);
                    // For every interval created we will clear it by design.
                    window.clearInterval(interval);
                }
                else if (new Date() - start >= timeoutArg) {
                    throw new Error('Timed out loading "' + path + '".');
                }
            });
        }
        return angular;
    },
    module: function() {
        var name = arguments[0];
        var requires = arguments[1];
        var ret = angularModuleOriginalFn.apply(angular, arguments);

        // If module() was called with only 1 argument, it was to get the module
        // and not create a new one.
        if (arguments.length == 1) {
            return ret;
        }

        if (requires instanceof Array) {
            for (var i = 0; i < requires.length; i++) {
                var path = pathFromModuleName(requires[i]);
                if (!path || path in loadedModuleMap) {
                    continue;
                }

                loadedModuleMap[path] = false;
                insertScript(path);

                // We do it here because the call above might throw.
                bootstrapLockCount++;
            }
        }

        var path = pathFromModuleName(name);
        if (path) {
            maybeBootstrap(path);  // If we're done, bootstrap angular.
        }
        return ret;
    }
});

// Load the first module.
bootstrapLockCount++;
var mainModulePath = pathFromModuleName(mainModulePathArg);
loadedModuleMap[mainModulePath] = false;
insertScript(mainModulePath);

})();<|endoftext|>


<commit_before>import moment from 'moment';
import stripTags from 'striptags';

export default class Row {
    constructor(data, columns) {
        this.data = data;
        this.columns = columns;
    }

    getValue(columnName) {
        return this.data[columnName];
    }

    getColumn(columnName) {
        return this.columns.filter(column => column.properties.show === columnName)[0];
    }

    getFilterableValue(columnName) {
        const value = this.getValue(columnName).toString().toLowerCase();

        return stripTags(value);
    }

    getSortableValue(columnName) {
        const dataType = this.getColumn(columnName).properties.dataType;

        let value = this.getValue(columnName);

        if (value instanceof String) {
            value = value.toLowerCase();
        }

        if (dataType.startsWith('date')) {
            // eslint-disable-next-line no-unused-vars
            const [_, format]  = dataType.split(':');

            return moment(value, format).format('x');
        }

        if (dataType === 'numeric') {
            return value;
        }

        return value.toString();
    }

    passesFilter(filter) {
        return this.columns
            .filter(column =>  column.isFilterable())
            .map(column => this.getFilterableValue(column.getFilterFieldName()))
            .filter(filterableValue => filterableValue.includes(filter.toLowerCase()))
            .length;
    }
}

<commit_msg>nitpick<commit_after>import moment from 'moment';
import stripTags from 'striptags';

export default class Row {
    constructor(data, columns) {
        this.data = data;
        this.columns = columns;
    }

    getValue(columnName) {
        return this.data[columnName];
    }

    getColumn(columnName) {
        return this.columns.filter(column => column.properties.show === columnName)[0];
    }

    getFilterableValue(columnName) {
        const value = this.getValue(columnName).toString().toLowerCase();

        return stripTags(value);
    }

    getSortableValue(columnName) {
        const dataType = this.getColumn(columnName).properties.dataType;

        let value = this.getValue(columnName);

        if (value instanceof String) {
            value = value.toLowerCase();
        }

        if (dataType.startsWith('date')) {
            // eslint-disable-next-line no-unused-vars
            const [_, format]  = dataType.split(':');

            return moment(value, format).format('x');
        }

        if (dataType === 'numeric') {
            return value;
        }

        return value.toString();
    }

    passesFilter(filter) {
        return this.columns
            .filter(column => column.isFilterable())
            .map(column => this.getFilterableValue(column.getFilterFieldName()))
            .filter(filterableValue => filterableValue.includes(filter.toLowerCase()))
            .length;
    }
}

<|endoftext|>