<commit_before>// # Mink Base module
// This module defines utility methods and properties used by the framework

// ## UMD Definition
// Every module - even the base - is wrapped in an UMD definition, making it easier to integrate with your development process
(function (factory) {
  if (typeof define === 'function' && define.amd) {
    // ### AMD
    // To use with any AMD loader such as Require or Almond
    define([], function(){
      return (window.mink = factory());
    });
  } else if (typeof exports === 'object') {
    // ### Node/CommonJS
    // To use with Browserify
    window.mink = module.exports = factory();
  } else {
    // ### Browser globals
    // Plain and simple browser globals
    window.mink = factory();
  }
}(function () {
  'use strict';

  // Gets the helper API from the current script element's data attribute. This way, you can define a specific helper without having to create a script tag before mink.
  function currentScript() {
    var cs = document.currentScript;
    if(!cs){
      // @TODO: This approach has a shortcoming with AMD loading.
      var scripts = document.getElementsByTagName('script');
      cs = scripts[scripts.length - 1];
    }
    return window[cs.getAttribute('data-helper')];
  }

  // If mink is previously defined, we use that definition.
  var mink = window.mink || {};

  // ## Helper hierarchy
  // Programmatical definition comes first. Definition in data-attribute comes second. Zepto comes third for mobile first as a default, if present. Ender comes after as our packaged helper. jQuery after that. kInk and $ if all else fails.
  mink.helper = mink.$ = mink.$ || currentScript() || window.Zepto || window.ender || window.jQuery || window.kink || window.$ || false;

  // Warn the user if no helper is defined
  if (!mink.$) {
    console.warn('No helper ($) available!');
  }

  // This property will contain pointers to all mink module constructors
  mink.fn = mink.fn || {};

  // A pointer for mink inside the helper API.
  mink.$.fn.mink = mink;

  // ## Module Defaults
  // mink modules default settings. These sensible defaults will be overriden by module defaults and runtime options
  mink.defaults = mink.defaults || {
    // The name of the module
    name: 'mink',
    // A unique identifier used to namespace events, and preserve the module instance
    namespace: 'minkModule',
    // Whether debug content should be outputted to console
    debug: false,
    // Whether extra debug content should be outputted
    verbose: false,
    // Whether to track performance data
    performance: false,
    // A flag to auto initialize the module
    autoInit: true
  };

  // ## Module registry
  // An internal registry of all the module instances in the page
  mink._registry = mink._registry || {};

  // ## Module factory
  // Method to create module constructors.
  mink.factory = function(defaults) {
    defaults = defaults || {};
    function mod(element, options){
      var
        $ = mink.$,
        // Extend settings to merge run-time settings with defaults
        settings = $.extend({}, $.fn.mink.defaults, defaults, options || {}),

        // Alias settings object for convenience and performance
        namespace = settings.namespace,
        performance = [],
        module = this;

      // Initialize the registry key for the modules if it's not set yets
      mink._registry[settings.name] = mink._registry[settings.name] || [];

      // ### Module Properties and Methods
      // Define namespaces for storing module instance and binding events
      this.queryArguments = [].slice.call(arguments, 3);

      // #### Module Namespace
      // Used to identify the module metada within a namespace
      this.moduleNamespace = namespace;

      // #### Module Event Namespace
      // Used to identify all event handlers the module uses
      this.eventNamespace = '.' + namespace;

      // #### All Modules instances
      // A reference to all modules instances of the same type. This is useful if your module wants to interact with other instances in the page
      this.allModules = mink._registry[settings.name];

      // #### Module ID
      // The module index inside the allModule reference
      // @TODO: Get a better way to handle this
      this.moduleId = this.allModules.push(this) - 1;

      // #### Element
      // The element the module instance is refering to
      this.element = element;

      // #### $element
      // The module element wrapped as an helper API object
      this.$element = $(element);

      // #### Settings
      // A reference to the module settings
      this.settings = settings;

      // #### Attributes
      // Data attributes of the element
      this.attrs = this.$element.data();

      // #### Instance
      // The module instance is stored and retrieved in namespaced DOM metadata
      this.instance = this.$element.data(this.moduleNamespace);

      // #### Performance
      // Called on each debug statement and logs the time since the last debug statement.
      this.performance = {

        log: function (message) {
          var
            currentTime,
            executionTime,
            previousTime;
          if (module.settings.performance) {
            currentTime = new Date().getTime();
            previousTime = module.time || currentTime;
            executionTime = currentTime - previousTime;
            module.time = currentTime;
            performance.push({
              'Element': element,
              'Name': message[0],
              'Arguments': [].slice.call(message, 1)[0] || '',
              'Execution Time': executionTime
            });
          }
          clearTimeout(module.performance.timer);
          module.performance.timer = setTimeout(module.performance.display, 100);
        },

        display: function () {
          var
            title = module.settings.name + ':',
            totalTime = 0;
          module.time = false;
          clearTimeout(module.performance.timer);
          $.each(performance, function (index, data) {
            totalTime += data['Execution Time'];
          });
          title += ' ' + totalTime + 'ms';
          if (this.moduleSelector) {
            title += ' \'' + this.moduleSelector + '\'';
          }
          if ((console.group !== undefined || console.table !== undefined) && performance.length > 0) {
            console.groupCollapsed(title);
            if (console.table) {
              console.table(performance);
            } else {
              $.each(performance, function (index, data) {
                console.log(data['Name'] + ': ' + data['Execution Time'] + 'ms');
              });
            }
            console.groupEnd();
          }
          performance = [];
        }
      };

      // Initialize module if autoInit is set to true
      if(settings.autoInit) {
        this.initialize();
      }

      return this;
    }

    mod.prototype = {

      // #### Initialize Method
      // This method is the first one to be called once a module is instantiated
      // Every module should implement their own method.
      initialize: function () {
        console.warn('Your module is lacking an initialize method');
      },

      // #### Destroy Method
      // Every module should implement their own destroy method
      // This method is responsible to restore the DOM to the same state as it was before the module was instantiated. This includes - but is not limited to - removing the following:
      // * event listeners,
      // * removing CSS classes
      // * generated DOM elements and attributes
      destroy: function () {
        console.warn('Your module is lacking a destroy method');
      },

      // #### Setting Method
      // Get or set setting properties
      setting: function (name, value) {
        if ($.isPlainObject(name)) {
          $.extend(this.settings, name);
        } else if (value !== undefined) {
          this.settings[name] = value;
        } else {
          return this.settings[name];
        }
      },

      // #### Internal Method
      // Module internals can be set or retrieved as well
      internal: function (name, value) {
        if ($.isPlainObject(name)) {
          $.extend(this, name);
        } else if (value !== undefined) {
          this[name] = value;
        } else {
          return this[name];
        }
      },

      // #### Debug Method
      // Debug pushes arguments to the console formatted as a debug statement
      debug: function () {
        if (this.settings.debug) {
          if (this.settings.performance) {
            this.performance.log(arguments);
          } else {
            this.debug = Function.prototype.bind.call(console.info, console, this.settings.name + ':');
            this.debug.apply(console, arguments);
          }
        }
      },

      // #### Verbose Method
      // Calling verbose internally allows for additional data to be logged which can assist in debugging
      verbose: function () {
        if (this.settings.verbose && this.settings.debug) {
          if (this.settings.performance) {
            this.performance.log(arguments);
          } else {
            this.verbose = Function.prototype.bind.call(console.info, console, this.settings.name + ':');
            this.verbose.apply(console, arguments);
          }
        }
      },

      // #### Error Method
      // Error allows for the module to report named error messages, it may be useful to modify this to push error messages to the user. Error messages are defined in the modules settings object.
      error: function () {
        this.error = Function.prototype.bind.call(console.error, console, this.settings.name + ':');
        this.error.apply(console, arguments);
      },

      // #### Invoke Method
      // Invoke is used to match internal functions to string lookups.
      // `$('.foo').example('invoke', 'set text', 'Foo')`
      // Method lookups are lazy, looking for many variations of a search string
      // For example 'set text', will look for both `setText : function(){}`, `set: { text: function(){} }`
      // Invoke attempts to preserve the 'this' chaining unless a value is returned.
      // If multiple values are returned an array of values matching up to the length of the selector is returned
      invoke: function (query, passedArguments, context) {
        var
        maxDepth,
        found,
        response;
        passedArguments = passedArguments || this.queryArguments;
        context = context || this.instance || this;
        var module = this;
        if (typeof query === 'string' && module.instance !== undefined) {
          query = query.split(/[\. ]/);
          maxDepth = query.length - 1;
          $.each(query, function (depth, value) {
            var camelCaseValue = (depth !== maxDepth) ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) : query;
            if ($.isPlainObject(module.instance[value]) && (depth !== maxDepth)) {
              module.instance = module.instance[value];
            } else if ($.isPlainObject(module.instance[camelCaseValue]) && (depth !== maxDepth)) {
              module.instance = module.instance[camelCaseValue];
            } else if (module.instance[value] !== undefined) {
              found = module.instance[value];
              return false;
            } else if (module.instance[camelCaseValue] !== undefined) {
              found = module.instance[camelCaseValue];
              return false;
            } else {
              module.error(error.method, query);
              return false;
            }
          });
        }
        if ( $.isFunction(found) ) {
          response = found.apply(context, [passedArguments]);
        }
        else if (found !== undefined) {
          response = found;
        }

        return response;
      },

      // #### DataAttributes Method
      // Reads and sets the setting object depending on their data-attributes
      dataAttributes: function () {
        this.debug('Setting data attributes settings');
        if(this.settings.metadata){
          var module = this;
          $.each(this.settings.metadata, function (index, value) {
            if (module.attrs[index] !== undefined) {
              module.settings[index] = module.attrs[index];
            }
          });
        }
      },

      // #### Throttling Method
      // Throttles a function to a certain delay.
      throttle: function(func, delay) {
        var timer = null;

        return function () {
          var context = this, args = arguments;

          if (timer == null) {
            timer = setTimeout(function () {
              func.apply(context, args);
              timer = null;
            }, delay);
          }
        };
      }
    };

    return mod;
  };

  // ## Expose Method
  // Expose module in the window, inside the mink object and as a method of the helper API
  mink.expose = function (name, Constructor) {
    // Saves the old module definition
    var old = $.fn[name];

    mink.fn[name] = mink.$.fn[name] = function (parameters) {

      var
      // Store a reference to the module group, this can be useful to refer to other modules inside each module
      $allModules = $(this),

      // Preserve original arguments to determine if a method is being invoked
      query = arguments[0],

      // Check if we've invoked a method
      methodInvoked = (typeof query === 'string'),
      returnedValue;

      // Iterate over all elements to initialize module

      $allModules
        .each(function () {
          var settings = ($.isPlainObject(parameters)) ? parameters : {};

          settings.autoInit = false;

          var module = new Constructor(this, settings);

          if (methodInvoked) {
            if (module.instance === undefined) {
              module.initialize();
            }
            var response = module.invoke(query);

            // ### Invocation response
            // If a user passes in multiple elements invoke will be called for each element and the value will be returned in an array
            // For example ``$('.things').example('has text')`` with two elements might return ``[true, false]`` and for one element ``true``
            if ($.isArray(returnedValue)) {

              returnedValue.push(response);
            } else if (returnedValue !== undefined) {

              returnedValue = [returnedValue, response];
            } else if (response !== undefined) {

              returnedValue = response;
            }
          }
          // if no method call is required we simply initialize the plugin, destroying it if it exists already
          else {
            if (module.instance !== undefined) {
              module.destroy();
            }
            module.initialize();
          }
      });
      if ( returnedValue !== undefined ){

        return returnedValue;
      } else {

        return this;
      }
    };

    // Expose the constructor
    mink.$.fn[name].constructor = Constructor;

    // ## noConflict method for the helper API interface
    mink.$.fn[name].noConflict = function () {
      mink.$.fn[name] = old;
      return this;
    };

  };

  return mink;

}));
<commit_msg>fix: reference to mink.fn<commit_after>// # Mink Base module
// This module defines utility methods and properties used by the framework

// ## UMD Definition
// Every module - even the base - is wrapped in an UMD definition, making it easier to integrate with your development process
(function (factory) {
  if (typeof define === 'function' && define.amd) {
    // ### AMD
    // To use with any AMD loader such as Require or Almond
    define([], function(){
      return (window.mink = factory());
    });
  } else if (typeof exports === 'object') {
    // ### Node/CommonJS
    // To use with Browserify
    window.mink = module.exports = factory();
  } else {
    // ### Browser globals
    // Plain and simple browser globals
    window.mink = factory();
  }
}(function () {
  'use strict';

  // Gets the helper API from the current script element's data attribute. This way, you can define a specific helper without having to create a script tag before mink.
  function currentScript() {
    var cs = document.currentScript;
    if(!cs){
      // @TODO: This approach has a shortcoming with AMD loading.
      var scripts = document.getElementsByTagName('script');
      cs = scripts[scripts.length - 1];
    }
    return window[cs.getAttribute('data-helper')];
  }

  // If mink is previously defined, we use that definition.
  var mink = window.mink || {};

  // ## Helper hierarchy
  // Programmatical definition comes first. Definition in data-attribute comes second. Zepto comes third for mobile first as a default, if present. Ender comes after as our packaged helper. jQuery after that. kInk and $ if all else fails.
  mink.helper = mink.$ = mink.$ || currentScript() || window.Zepto || window.ender || window.jQuery || window.kink || window.$ || false;

  // Warn the user if no helper is defined
  if (!mink.$) {
    console.warn('No helper ($) available!');
  }

  // This property will contain pointers to all mink module constructors
  mink.fn = mink.fn || {};

  // A pointer for mink inside the helper API.
  mink.$.fn.mink = mink;

  // ## Module Defaults
  // mink modules default settings. These sensible defaults will be overriden by module defaults and runtime options
  mink.defaults = mink.defaults || {
    // The name of the module
    name: 'mink',
    // A unique identifier used to namespace events, and preserve the module instance
    namespace: 'minkModule',
    // Whether debug content should be outputted to console
    debug: false,
    // Whether extra debug content should be outputted
    verbose: false,
    // Whether to track performance data
    performance: false,
    // A flag to auto initialize the module
    autoInit: true
  };

  // ## Module registry
  // An internal registry of all the module instances in the page
  mink._registry = mink._registry || {};

  // ## Module factory
  // Method to create module constructors.
  mink.factory = function(defaults) {
    defaults = defaults || {};
    function mod(element, options){
      var
        $ = mink.$,
        // Extend settings to merge run-time settings with defaults
        settings = $.extend({}, $.fn.mink.defaults, defaults, options || {}),

        // Alias settings object for convenience and performance
        namespace = settings.namespace,
        performance = [],
        module = this;

      // Initialize the registry key for the modules if it's not set yets
      mink._registry[settings.name] = mink._registry[settings.name] || [];

      // ### Module Properties and Methods
      // Define namespaces for storing module instance and binding events
      this.queryArguments = [].slice.call(arguments, 3);

      // #### Module Namespace
      // Used to identify the module metada within a namespace
      this.moduleNamespace = namespace;

      // #### Module Event Namespace
      // Used to identify all event handlers the module uses
      this.eventNamespace = '.' + namespace;

      // #### All Modules instances
      // A reference to all modules instances of the same type. This is useful if your module wants to interact with other instances in the page
      this.allModules = mink._registry[settings.name];

      // #### Module ID
      // The module index inside the allModule reference
      // @TODO: Get a better way to handle this
      this.moduleId = this.allModules.push(this) - 1;

      // #### Element
      // The element the module instance is refering to
      this.element = element;

      // #### $element
      // The module element wrapped as an helper API object
      this.$element = $(element);

      // #### Settings
      // A reference to the module settings
      this.settings = settings;

      // #### Attributes
      // Data attributes of the element
      this.attrs = this.$element.data();

      // #### Instance
      // The module instance is stored and retrieved in namespaced DOM metadata
      this.instance = this.$element.data(this.moduleNamespace);

      // #### Performance
      // Called on each debug statement and logs the time since the last debug statement.
      this.performance = {

        log: function (message) {
          var
            currentTime,
            executionTime,
            previousTime;
          if (module.settings.performance) {
            currentTime = new Date().getTime();
            previousTime = module.time || currentTime;
            executionTime = currentTime - previousTime;
            module.time = currentTime;
            performance.push({
              'Element': element,
              'Name': message[0],
              'Arguments': [].slice.call(message, 1)[0] || '',
              'Execution Time': executionTime
            });
          }
          clearTimeout(module.performance.timer);
          module.performance.timer = setTimeout(module.performance.display, 100);
        },

        display: function () {
          var
            title = module.settings.name + ':',
            totalTime = 0;
          module.time = false;
          clearTimeout(module.performance.timer);
          $.each(performance, function (index, data) {
            totalTime += data['Execution Time'];
          });
          title += ' ' + totalTime + 'ms';
          if (this.moduleSelector) {
            title += ' \'' + this.moduleSelector + '\'';
          }
          if ((console.group !== undefined || console.table !== undefined) && performance.length > 0) {
            console.groupCollapsed(title);
            if (console.table) {
              console.table(performance);
            } else {
              $.each(performance, function (index, data) {
                console.log(data['Name'] + ': ' + data['Execution Time'] + 'ms');
              });
            }
            console.groupEnd();
          }
          performance = [];
        }
      };

      // Initialize module if autoInit is set to true
      if(settings.autoInit) {
        this.initialize();
      }

      return this;
    }

    mod.prototype = {

      // #### Initialize Method
      // This method is the first one to be called once a module is instantiated
      // Every module should implement their own method.
      initialize: function () {
        console.warn('Your module is lacking an initialize method');
      },

      // #### Destroy Method
      // Every module should implement their own destroy method
      // This method is responsible to restore the DOM to the same state as it was before the module was instantiated. This includes - but is not limited to - removing the following:
      // * event listeners,
      // * removing CSS classes
      // * generated DOM elements and attributes
      destroy: function () {
        console.warn('Your module is lacking a destroy method');
      },

      // #### Setting Method
      // Get or set setting properties
      setting: function (name, value) {
        if ($.isPlainObject(name)) {
          $.extend(this.settings, name);
        } else if (value !== undefined) {
          this.settings[name] = value;
        } else {
          return this.settings[name];
        }
      },

      // #### Internal Method
      // Module internals can be set or retrieved as well
      internal: function (name, value) {
        if ($.isPlainObject(name)) {
          $.extend(this, name);
        } else if (value !== undefined) {
          this[name] = value;
        } else {
          return this[name];
        }
      },

      // #### Debug Method
      // Debug pushes arguments to the console formatted as a debug statement
      debug: function () {
        if (this.settings.debug) {
          if (this.settings.performance) {
            this.performance.log(arguments);
          } else {
            this.debug = Function.prototype.bind.call(console.info, console, this.settings.name + ':');
            this.debug.apply(console, arguments);
          }
        }
      },

      // #### Verbose Method
      // Calling verbose internally allows for additional data to be logged which can assist in debugging
      verbose: function () {
        if (this.settings.verbose && this.settings.debug) {
          if (this.settings.performance) {
            this.performance.log(arguments);
          } else {
            this.verbose = Function.prototype.bind.call(console.info, console, this.settings.name + ':');
            this.verbose.apply(console, arguments);
          }
        }
      },

      // #### Error Method
      // Error allows for the module to report named error messages, it may be useful to modify this to push error messages to the user. Error messages are defined in the modules settings object.
      error: function () {
        this.error = Function.prototype.bind.call(console.error, console, this.settings.name + ':');
        this.error.apply(console, arguments);
      },

      // #### Invoke Method
      // Invoke is used to match internal functions to string lookups.
      // `$('.foo').example('invoke', 'set text', 'Foo')`
      // Method lookups are lazy, looking for many variations of a search string
      // For example 'set text', will look for both `setText : function(){}`, `set: { text: function(){} }`
      // Invoke attempts to preserve the 'this' chaining unless a value is returned.
      // If multiple values are returned an array of values matching up to the length of the selector is returned
      invoke: function (query, passedArguments, context) {
        var
        maxDepth,
        found,
        response;
        passedArguments = passedArguments || this.queryArguments;
        context = context || this.instance || this;
        var module = this;
        if (typeof query === 'string' && module.instance !== undefined) {
          query = query.split(/[\. ]/);
          maxDepth = query.length - 1;
          $.each(query, function (depth, value) {
            var camelCaseValue = (depth !== maxDepth) ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) : query;
            if ($.isPlainObject(module.instance[value]) && (depth !== maxDepth)) {
              module.instance = module.instance[value];
            } else if ($.isPlainObject(module.instance[camelCaseValue]) && (depth !== maxDepth)) {
              module.instance = module.instance[camelCaseValue];
            } else if (module.instance[value] !== undefined) {
              found = module.instance[value];
              return false;
            } else if (module.instance[camelCaseValue] !== undefined) {
              found = module.instance[camelCaseValue];
              return false;
            } else {
              module.error(error.method, query);
              return false;
            }
          });
        }
        if ( $.isFunction(found) ) {
          response = found.apply(context, [passedArguments]);
        }
        else if (found !== undefined) {
          response = found;
        }

        return response;
      },

      // #### DataAttributes Method
      // Reads and sets the setting object depending on their data-attributes
      dataAttributes: function () {
        this.debug('Setting data attributes settings');
        if(this.settings.metadata){
          var module = this;
          $.each(this.settings.metadata, function (index, value) {
            if (module.attrs[index] !== undefined) {
              module.settings[index] = module.attrs[index];
            }
          });
        }
      },

      // #### Throttling Method
      // Throttles a function to a certain delay.
      throttle: function(func, delay) {
        var timer = null;

        return function () {
          var context = this, args = arguments;

          if (timer == null) {
            timer = setTimeout(function () {
              func.apply(context, args);
              timer = null;
            }, delay);
          }
        };
      }
    };

    return mod;
  };

  // ## Expose Method
  // Expose module in the window, inside the mink object and as a method of the helper API
  mink.expose = function (name, Constructor) {
    // Saves the old module definition
    var old = $.fn[name];

    mink.fn[name] = Constructor;
    mink.$.fn[name] = function (parameters) {

      var
      // Store a reference to the module group, this can be useful to refer to other modules inside each module
      $allModules = $(this),

      // Preserve original arguments to determine if a method is being invoked
      query = arguments[0],

      // Check if we've invoked a method
      methodInvoked = (typeof query === 'string'),
      returnedValue;

      // Iterate over all elements to initialize module

      $allModules
        .each(function () {
          var settings = ($.isPlainObject(parameters)) ? parameters : {};

          settings.autoInit = false;

          var module = new Constructor(this, settings);

          if (methodInvoked) {
            if (module.instance === undefined) {
              module.initialize();
            }
            var response = module.invoke(query);

            // ### Invocation response
            // If a user passes in multiple elements invoke will be called for each element and the value will be returned in an array
            // For example ``$('.things').example('has text')`` with two elements might return ``[true, false]`` and for one element ``true``
            if ($.isArray(returnedValue)) {

              returnedValue.push(response);
            } else if (returnedValue !== undefined) {

              returnedValue = [returnedValue, response];
            } else if (response !== undefined) {

              returnedValue = response;
            }
          }
          // if no method call is required we simply initialize the plugin, destroying it if it exists already
          else {
            if (module.instance !== undefined) {
              module.destroy();
            }
            module.initialize();
          }
      });
      if ( returnedValue !== undefined ){

        return returnedValue;
      } else {

        return this;
      }
    };

    // Expose the constructor
    mink.$.fn[name].constructor = Constructor;

    // ## noConflict method for the helper API interface
    mink.$.fn[name].noConflict = function () {
      mink.$.fn[name] = old;
      return this;
    };

  };

  return mink;

}));
<|endoftext|>


<commit_before>'use strict';

import test from 'tape';
import postcss from 'postcss';
import plugin from '..';
import {name} from '../../package.json';

let tests = [{
    message: 'should order border consistently',
    fixture: 'h1{border:1px solid red;border:1px red solid;border:solid 1px red;border:solid red 1px;border:red solid 1px;border:red 1px solid}',
    expected: 'h1{border:1px solid red;border:1px solid red;border:1px solid red;border:1px solid red;border:1px solid red;border:1px solid red}'
}, {
    message: 'should order border with two properties',
    fixture: 'h1{border:solid 1px}',
    expected: 'h1{border:1px solid}'
}, {
    message: 'should order border with color functions',
    fixture: 'h1{border:rgba(255,255,255,0.5) dashed thick}',
    expected: 'h1{border:thick dashed rgba(255,255,255,0.5)}',
}, {
    message: 'should order border longhand',
    fixture: 'h1{border-left:solid 2px red;border-right:#fff 3px dashed;border-top:dotted #000 1px;border-bottom:4px navy groove}',
    expected: 'h1{border-left:2px solid red;border-right:3px dashed #fff;border-top:1px dotted #000;border-bottom:4px groove navy}',
}, {
    message: 'should skip inherit',
    fixture: 'h1{border:inherit}',
    expected: 'h1{border:inherit}'
}, {
    message: 'should order outline consistently',
    fixture: 'h1{outline:solid red 1px}',
    expected: 'h1{outline:1px solid red}'
}, {
    message: 'should handle -webkit-focus-ring & auto',
    fixture: 'h1{outline:-webkit-focus-ring-color 5px auto}',
    expected: 'h1{outline:5px auto -webkit-focus-ring-color}'
}, {
    message: 'should order flex-flow',
    fixture: 'h1{flex-flow: wrap column}',
    expected: 'h1{flex-flow: column wrap}'
}, {
    message: 'should order flex-flow',
    fixture: 'h1{flex-flow: row-reverse wrap-reverse}',
    expected: 'h1{flex-flow: row-reverse wrap-reverse}'
}];

function process (css, options) {
    return postcss(plugin(options)).process(css).css;
}

test(name, t => {
    t.plan(tests.length);

    tests.forEach(test => {
        var options = test.options || {};
        t.equal(process(test.fixture, options), test.expected, test.message);
    });
});

test('should use the postcss plugin api', t => {
    t.plan(2);
    t.ok(plugin().postcssVersion, 'should be able to access version');
    t.equal(plugin().postcssPlugin, name, 'should be able to access name');
});
<commit_msg>add more test case<commit_after>'use strict';

import test from 'tape';
import postcss from 'postcss';
import plugin from '..';
import {name} from '../../package.json';

let tests = [{
    message: 'should order border consistently',
    fixture: 'h1{border:1px solid red;border:1px red solid;border:solid 1px red;border:solid red 1px;border:red solid 1px;border:red 1px solid}',
    expected: 'h1{border:1px solid red;border:1px solid red;border:1px solid red;border:1px solid red;border:1px solid red;border:1px solid red}'
}, {
    message: 'should order border with two properties',
    fixture: 'h1{border:solid 1px}',
    expected: 'h1{border:1px solid}'
}, {
    message: 'should order border with color functions',
    fixture: 'h1{border:rgba(255,255,255,0.5) dashed thick}',
    expected: 'h1{border:thick dashed rgba(255,255,255,0.5)}',
}, {
    message: 'should order border longhand',
    fixture: 'h1{border-left:solid 2px red;border-right:#fff 3px dashed;border-top:dotted #000 1px;border-bottom:4px navy groove}',
    expected: 'h1{border-left:2px solid red;border-right:3px dashed #fff;border-top:1px dotted #000;border-bottom:4px groove navy}',
}, {
    message: 'should order width currentColor',
    fixture: 'h1{border:solid 2vmin currentColor}',
    expected: 'h1{border:2vmin solid currentColor}'
}, {
    message: 'should skip border:inherit',
    fixture: 'h1{border:inherit}',
    expected: 'h1{border:inherit}'
}, {
    message: 'should skip border:initial',
    fixture: 'h1{border:initial}',
    expected: 'h1{border:initial}'
}, {
    message: 'should skip border:unset',
    fixture: 'h1{border:unset}',
    expected: 'h1{border:unset}'
}, {
    message: 'should order outline consistently',
    fixture: 'h1{outline:solid red .6em}',
    expected: 'h1{outline:.6em solid red}'
}, {
    message: 'should order outline(outline-color is invert)',
    fixture: 'h1{outline:solid invert 1px}',
    expected: 'h1{outline:1px solid invert}'
}, {
    message: 'should handle -webkit-focus-ring & auto',
    fixture: 'h1{outline:-webkit-focus-ring-color 5px auto}',
    expected: 'h1{outline:5px auto -webkit-focus-ring-color}'
}, {
    message: 'should order flex-flow',
    fixture: 'h1{flex-flow: wrap column}',
    expected: 'h1{flex-flow: column wrap}'
}, {
    message: 'should order flex-flow',
    fixture: 'h1{flex-flow: row-reverse wrap-reverse}',
    expected: 'h1{flex-flow: row-reverse wrap-reverse}'
}, {
    message: 'should skip flex-flow:inherit',
    fixture: 'h1{flex-flow:inherit}',
    expected: 'h1{flex-flow:inherit}'
}, {
    message: 'should skip flex-flow:unset',
    fixture: 'h1{flex-flow: unset}',
    expected: 'h1{flex-flow: unset}'
}];

function process (css, options) {
    return postcss(plugin(options)).process(css).css;
}

test(name, t => {
    t.plan(tests.length);

    tests.forEach(test => {
        var options = test.options || {};
        t.equal(process(test.fixture, options), test.expected, test.message);
    });
});

test('should use the postcss plugin api', t => {
    t.plan(2);
    t.ok(plugin().postcssVersion, 'should be able to access version');
    t.equal(plugin().postcssPlugin, name, 'should be able to access name');
});
<|endoftext|>


<commit_before>// @flow

import typeof ReactTestRenderer from 'react-test-renderer';

export function act(callback: Function): void {
  const TestUtils = require('react-dom/test-utils');
  TestUtils.act(() => {
    callback();
  });

  // Flush Bridge operations
  TestUtils.act(() => {
    jest.runAllTimers();
  });
}

export async function actAsync(cb: () => *) : Promise<void> {
  const TestUtils = require('react-dom/test-utils');

  // $FlowFixMe Flow doens't know about "await act()" yet
  await TestUtils.act(async () => {
    await cb();
  });
  while (jest.getTimerCount() > 0) {
    // $FlowFixMe Flow doens't know about "await act()" yet
    await TestUtils.act(async () => {
      jest.runAllTimers();
    });
  }
}

export function beforeEachProfiling(): void {
  // Mock React's timing information so that test runs are predictable.
  jest.mock('scheduler', () =>
    // $FlowFixMe Flow does not konw about requireActual
    require.requireActual('scheduler/unstable_mock')
  );

  // DevTools itself uses performance.now() to offset commit times
  // so they appear relative to when profiling was started in the UI.
  jest.spyOn(performance, 'now').mockImplementation(
    // $FlowFixMe Flow does not konw about requireActual
    require.requireActual('scheduler/unstable_mock').unstable_now
  );
}

export function getRendererID(): number {
  if (global.agent == null) {
    throw Error('Agent unavailable.');
  }
  const ids = Object.keys(global.agent._rendererInterfaces);
  if (ids.length !== 1) {
    throw Error('Multiple renderers attached.');
  }
  return parseInt(ids[0], 10);
}

export function requireTestRenderer(): ReactTestRenderer {
  let hook;
  try {
    // Hide the hook before requiring TestRenderer, so we don't end up with a loop.
    hook = global.__REACT_DEVTOOLS_GLOBAL_HOOK__;
    delete global.__REACT_DEVTOOLS_GLOBAL_HOOK__;

    return require('react-test-renderer');
  } finally {
    global.__REACT_DEVTOOLS_GLOBAL_HOOK__ = hook;
  }
}
<commit_msg>pretty, witty, fine<commit_after>// @flow

import typeof ReactTestRenderer from 'react-test-renderer';

export function act(callback: Function): void {
  const TestUtils = require('react-dom/test-utils');
  TestUtils.act(() => {
    callback();
  });

  // Flush Bridge operations
  TestUtils.act(() => {
    jest.runAllTimers();
  });
}

export async function actAsync(cb: () => *): Promise<void> {
  const TestUtils = require('react-dom/test-utils');

  // $FlowFixMe Flow doens't know about "await act()" yet
  await TestUtils.act(async () => {
    await cb();
  });
  while (jest.getTimerCount() > 0) {
    // $FlowFixMe Flow doens't know about "await act()" yet
    await TestUtils.act(async () => {
      jest.runAllTimers();
    });
  }
}

export function beforeEachProfiling(): void {
  // Mock React's timing information so that test runs are predictable.
  jest.mock('scheduler', () =>
    // $FlowFixMe Flow does not konw about requireActual
    require.requireActual('scheduler/unstable_mock')
  );

  // DevTools itself uses performance.now() to offset commit times
  // so they appear relative to when profiling was started in the UI.
  jest.spyOn(performance, 'now').mockImplementation(
    // $FlowFixMe Flow does not konw about requireActual
    require.requireActual('scheduler/unstable_mock').unstable_now
  );
}

export function getRendererID(): number {
  if (global.agent == null) {
    throw Error('Agent unavailable.');
  }
  const ids = Object.keys(global.agent._rendererInterfaces);
  if (ids.length !== 1) {
    throw Error('Multiple renderers attached.');
  }
  return parseInt(ids[0], 10);
}

export function requireTestRenderer(): ReactTestRenderer {
  let hook;
  try {
    // Hide the hook before requiring TestRenderer, so we don't end up with a loop.
    hook = global.__REACT_DEVTOOLS_GLOBAL_HOOK__;
    delete global.__REACT_DEVTOOLS_GLOBAL_HOOK__;

    return require('react-test-renderer');
  } finally {
    global.__REACT_DEVTOOLS_GLOBAL_HOOK__ = hook;
  }
}
<|endoftext|>


<commit_before>var Constants = require('../constants/Constants');
var TrackModel = require('../models/TrackModel');
var WorldModel = require('../models/WorldModel');
var ProgramModel = require('../models/ProgramModel');

module.exports = {
  loadPrograms: function() {
    this.dispatch(Constants.ActionTypes.LOAD_PROGRAMS);
    var query = new Parse.Query(ProgramModel);
    query.equalTo("owner", Parse.User.current());
    query.include('world');
    query.find({
      success: function(programs) {
        this.dispatch(Constants.ActionTypes.LOAD_PROGRAMS_SUCCESS, {programs:programs});
      }.bind(this),
      error: function(error) {
        this.dispatch(Constants.ActionTypes.LOAD_PROGRAMS_FAIL, {error: error});
      }.bind(this)
    });
  },

  saveProgram: function(data, program, callback) {
    this.dispatch(Constants.ActionTypes.SAVE_PROGRAM);
    program.save(data, {
      success: function(program) {
        this.dispatch(Constants.ActionTypes.SAVE_PROGRAM_SUCCESS, {programs: [program]});
        callback();
      }.bind(this),
      error: function(program, error) {
        this.dispatch(Constants.ActionTypes.SAVE_PROGRAM_FAIL);
        console.error("There was an error while saving the program: "+error.code+" "+error.message);
      }.bind(this)
    });
  },

  loadTracks: function() {
    this.dispatch(Constants.ActionTypes.LOAD_TRACKS);
    var query = new Parse.Query(TrackModel);
    query.ascending("createdAt");
    query.find({
      success: function(tracks) {
        this.dispatch(Constants.ActionTypes.LOAD_TRACKS_SUCCESS, {tracks: tracks});
      }.bind(this),
      error: function(error) {
        this.dispatch(Constants.ActionTypes.LOAD_TRACKS_FAIL, {error: error});
      }.bind(this)
    });
  },

  loadTracksAndWorlds: function() {
    this.dispatch(Constants.ActionTypes.LOAD_TRACKS_AND_WORLDS);
    var query = new Parse.Query(TrackModel);
    query.ascending("createdAt");
    query.find({
      success: function(tracks) {
        var worldQuery = new Parse.Query(WorldModel);
        worldQuery.containedIn("track", tracks);
        worldQuery.include('owner');
        worldQuery.find({
          success: function(worlds) {
            var owners = worlds.map(function(world){
              var owner = world.get('owner');
              // defensively unset nested owner so call sites are forced to use UserStore.
              var ownerPointer = new Parse.User();
              ownerPointer.id = owner.id;
              world.set('owner', ownerPointer);
              return owner;
            });
            this.dispatch(Constants.ActionTypes.LOAD_TRACKS_AND_WORLDS_SUCCESS, {tracks: tracks, worlds:worlds});
            this.dispatch(Constants.ActionTypes.LOAD_USERS_SUCCESS, {users: owners});
          }.bind(this),
          error: function(error) {
            console.error('Failed to get worlds, with error code: ' + error.message);
            this.dispatch(Constants.ActionTypes.LOAD_TRACKS_AND_WORLDS_FAIL, {error: error});
          }.bind(this)
        })
      }.bind(this),
      error: function(error) {
        console.error('Failed to get tracks, with error code: ' + error.message);
        this.dispatch(Constants.ActionTypes.LOAD_TRACKS_FAIL, {error: error});
      }.bind(this)
    });
  },

  loadWorld: function(id) {
    this.dispatch(Constants.ActionTypes.LOAD_WORLDS);
    var query = new Parse.Query(WorldModel);
    query.get(id, {
      success: function(world) {
        this.dispatch(Constants.ActionTypes.LOAD_WORLDS_SUCCESS, {worlds:[world]})
      }.bind(this),
      error: function(object, error) {
        console.error("failed to load: "+error.code+" "+error.message);
        this.dispatch(Constants.ActionTypes.LOAD_WORLDS_FAIL, {error:error});
      }.bind(this)
    });
  },

  addWorld: function(name, trackId) {
    this.dispatch(Constants.ActionTypes.ADD_WORLD);
    var world = new WorldModel();
    world.set('owner', Parse.User.current());
    world.set('name', name);
    if (trackId) {
      var track = new TrackModel();
      track.id = trackId
      world.set('track', track);
    }
    world.save(null, {
      success: function(world) {
        this.dispatch(Constants.ActionTypes.ADD_WORLD_SUCCESS, {world:world});
      }.bind(this),
      error: function(world, error) {
        console.error('Failed to create new world, with error code: ' + error.message);
        this.dispatch(Constants.ActionTypes.ADD_WORLD_FAIL, {error:error});
      }.bind(this)
    });
  },

  destroyWorld: function(world) {
    this.dispatch(Constants.ActionTypes.DESTROY_WORLD);
    world.destroy({
      success: function(world) {
        this.dispatch(Constants.ActionTypes.DESTROY_WORLD_SUCCESS, {world:world});
      }.bind(this),
      error: function(world, error) {
        this.dispatch(Constants.ActionTypes.DESTROY_WORLD_FAIL, {error: error});
        alert("There was an error while deleting the world: "+error.code+" "+error.message);
      }.bind(this)
    });
  },

  saveWorld: function(data, world, callback) {
    this.dispatch(Constants.ActionTypes.SAVE_WORLD);
    world.needsSave = false;
    world.save(data, {
      success: function(world) {
        this.dispatch(Constants.ActionTypes.SAVE_WORLD_SUCCESS, {worlds:[world]});
        callback && callback();
      }.bind(this),
      error: function(world, error) {
        this.dispatch(Constants.ActionTypes.SAVE_WORLD_FAIL, {error:error});
      }.bind(this)
    });
  },

  saveWorldLocal: function(data, world) {
    for (var key in data) {
      if (data[key] !== world.get(key)) {
        world.set(key, data[key]);
      }
    }
    world.needsSave = true;
    this.dispatch(Constants.ActionTypes.SAVE_WORLD_LOCAL, {world:world});
  },

  loadLeaderboard: function() {
    this.dispatch(Constants.ActionTypes.LOAD_LEADERBOARD);
    var query = new Parse.Query(Parse.User);
    query.descending("programsFinished");
    query.limit(20);
    query.find({
      success: function(users) {
        this.dispatch(Constants.ActionTypes.LOAD_LEADERBOARD_SUCCESS, {users:users});
      }.bind(this),
      error: function(error) {
        this.dispatch(Constants.ActionTypes.LOAD_LEADERBOARD_FAIL, {error:error});
      }.bind(this)
    });
  }
};<commit_msg>pass error to SAVE_PROGRAM_FAIL action<commit_after>var Constants = require('../constants/Constants');
var TrackModel = require('../models/TrackModel');
var WorldModel = require('../models/WorldModel');
var ProgramModel = require('../models/ProgramModel');

module.exports = {
  loadPrograms: function() {
    this.dispatch(Constants.ActionTypes.LOAD_PROGRAMS);
    var query = new Parse.Query(ProgramModel);
    query.equalTo("owner", Parse.User.current());
    query.include('world');
    query.find({
      success: function(programs) {
        this.dispatch(Constants.ActionTypes.LOAD_PROGRAMS_SUCCESS, {programs:programs});
      }.bind(this),
      error: function(error) {
        this.dispatch(Constants.ActionTypes.LOAD_PROGRAMS_FAIL, {error: error});
      }.bind(this)
    });
  },

  saveProgram: function(data, program, callback) {
    this.dispatch(Constants.ActionTypes.SAVE_PROGRAM);
    program.save(data, {
      success: function(program) {
        this.dispatch(Constants.ActionTypes.SAVE_PROGRAM_SUCCESS, {programs: [program]});
        callback();
      }.bind(this),
      error: function(program, error) {
        this.dispatch(Constants.ActionTypes.SAVE_PROGRAM_FAIL, {error: error});
        console.error("There was an error while saving the program: "+error.code+" "+error.message);
      }.bind(this)
    });
  },

  loadTracks: function() {
    this.dispatch(Constants.ActionTypes.LOAD_TRACKS);
    var query = new Parse.Query(TrackModel);
    query.ascending("createdAt");
    query.find({
      success: function(tracks) {
        this.dispatch(Constants.ActionTypes.LOAD_TRACKS_SUCCESS, {tracks: tracks});
      }.bind(this),
      error: function(error) {
        this.dispatch(Constants.ActionTypes.LOAD_TRACKS_FAIL, {error: error});
      }.bind(this)
    });
  },

  loadTracksAndWorlds: function() {
    this.dispatch(Constants.ActionTypes.LOAD_TRACKS_AND_WORLDS);
    var query = new Parse.Query(TrackModel);
    query.ascending("createdAt");
    query.find({
      success: function(tracks) {
        var worldQuery = new Parse.Query(WorldModel);
        worldQuery.containedIn("track", tracks);
        worldQuery.include('owner');
        worldQuery.find({
          success: function(worlds) {
            var owners = worlds.map(function(world){
              var owner = world.get('owner');
              // defensively unset nested owner so call sites are forced to use UserStore.
              var ownerPointer = new Parse.User();
              ownerPointer.id = owner.id;
              world.set('owner', ownerPointer);
              return owner;
            });
            this.dispatch(Constants.ActionTypes.LOAD_TRACKS_AND_WORLDS_SUCCESS, {tracks: tracks, worlds:worlds});
            this.dispatch(Constants.ActionTypes.LOAD_USERS_SUCCESS, {users: owners});
          }.bind(this),
          error: function(error) {
            console.error('Failed to get worlds, with error code: ' + error.message);
            this.dispatch(Constants.ActionTypes.LOAD_TRACKS_AND_WORLDS_FAIL, {error: error});
          }.bind(this)
        })
      }.bind(this),
      error: function(error) {
        console.error('Failed to get tracks, with error code: ' + error.message);
        this.dispatch(Constants.ActionTypes.LOAD_TRACKS_FAIL, {error: error});
      }.bind(this)
    });
  },

  loadWorld: function(id) {
    this.dispatch(Constants.ActionTypes.LOAD_WORLDS);
    var query = new Parse.Query(WorldModel);
    query.get(id, {
      success: function(world) {
        this.dispatch(Constants.ActionTypes.LOAD_WORLDS_SUCCESS, {worlds:[world]})
      }.bind(this),
      error: function(object, error) {
        console.error("failed to load: "+error.code+" "+error.message);
        this.dispatch(Constants.ActionTypes.LOAD_WORLDS_FAIL, {error:error});
      }.bind(this)
    });
  },

  addWorld: function(name, trackId) {
    this.dispatch(Constants.ActionTypes.ADD_WORLD);
    var world = new WorldModel();
    world.set('owner', Parse.User.current());
    world.set('name', name);
    if (trackId) {
      var track = new TrackModel();
      track.id = trackId
      world.set('track', track);
    }
    world.save(null, {
      success: function(world) {
        this.dispatch(Constants.ActionTypes.ADD_WORLD_SUCCESS, {world:world});
      }.bind(this),
      error: function(world, error) {
        console.error('Failed to create new world, with error code: ' + error.message);
        this.dispatch(Constants.ActionTypes.ADD_WORLD_FAIL, {error:error});
      }.bind(this)
    });
  },

  destroyWorld: function(world) {
    this.dispatch(Constants.ActionTypes.DESTROY_WORLD);
    world.destroy({
      success: function(world) {
        this.dispatch(Constants.ActionTypes.DESTROY_WORLD_SUCCESS, {world:world});
      }.bind(this),
      error: function(world, error) {
        this.dispatch(Constants.ActionTypes.DESTROY_WORLD_FAIL, {error: error});
        alert("There was an error while deleting the world: "+error.code+" "+error.message);
      }.bind(this)
    });
  },

  saveWorld: function(data, world, callback) {
    this.dispatch(Constants.ActionTypes.SAVE_WORLD);
    world.needsSave = false;
    world.save(data, {
      success: function(world) {
        this.dispatch(Constants.ActionTypes.SAVE_WORLD_SUCCESS, {worlds:[world]});
        callback && callback();
      }.bind(this),
      error: function(world, error) {
        this.dispatch(Constants.ActionTypes.SAVE_WORLD_FAIL, {error:error});
      }.bind(this)
    });
  },

  saveWorldLocal: function(data, world) {
    for (var key in data) {
      if (data[key] !== world.get(key)) {
        world.set(key, data[key]);
      }
    }
    world.needsSave = true;
    this.dispatch(Constants.ActionTypes.SAVE_WORLD_LOCAL, {world:world});
  },

  loadLeaderboard: function() {
    this.dispatch(Constants.ActionTypes.LOAD_LEADERBOARD);
    var query = new Parse.Query(Parse.User);
    query.descending("programsFinished");
    query.limit(20);
    query.find({
      success: function(users) {
        this.dispatch(Constants.ActionTypes.LOAD_LEADERBOARD_SUCCESS, {users:users});
      }.bind(this),
      error: function(error) {
        this.dispatch(Constants.ActionTypes.LOAD_LEADERBOARD_FAIL, {error:error});
      }.bind(this)
    });
  }
};<|endoftext|>


<commit_before>import fetch from 'isomorphic-fetch'

// determine where to send requests
const www = window.location.href.indexOf('www.') !== -1 ? 'www.' : ''
const url = process.env.NODE_ENV === 'production'
  ? `http://${www}amodahl.no/api/public` : `http://${www}local.amodahl.no:3000`

export const requestTokenFromLocalStorage = () => {
  return {
    type: 'REQUEST_TOKEN_FROM_LOCAL_STORAGE'
  }
}

export const requestTokenFromServer = () => {
  return {
    type: 'REQUEST_TOKEN_FROM_SERVER'
  }
}

export const requestTokenFailed = (message, displayMessage) => {
  return {
    message: message,
    displayMessage: displayMessage,
    jwToken: null,
    type: 'REQUEST_TOKEN_FAILED'
  }
}

export const deleteToken = (dispatcher) => {
  return {
    jwToken: null,
    type: '@@' + dispatcher + '/DELETE_TOKEN'
  }
}

export const receiveTokenFromServer = (jwToken, name, email) => {
  return {
    jwToken: jwToken,
    name: name,
    email: email,
    type: 'RECEIVE_TOKEN_FROM_SERVER'
  }
}

export const receiveTokenFromLocalStorage = (jwToken, name, email) => {
  return {
    jwToken: jwToken,
    name: name,
    email: email,
    type: 'RECEIVE_TOKEN_FROM_LOCAL_STORAGE'
  }
}

function fetchTestUserJwtToken (dispatch, name, email, mockFacebookId, scopes, onSuccess) {
  var form = new FormData()
  form.append('requested_scopes', JSON.stringify(scopes))
  form.append('name', name)
  form.append('email', email)
  form.append('mock_facebook_id', mockFacebookId)

  fetch(url + '/token', {
    method: 'POST',
    body: form
  })
  .then(response => { // ensure its json
    let contentType = response.headers.get('content-type')
    let gotJson = contentType && contentType.indexOf('application/json') !== -1
    console.log(response)
    if (!gotJson) {
      throw new Error('Oops, we haven\'t got JSON: ' + JSON.stringify(response))
    }
    return response.json()
  })
  .then(response => { // ensure query was accepted
    let ok = response.status === 'ok'

    if (!ok) {
      throw new Error('Received: ' + JSON.stringify(response))
    }

    // finally got token
    onSuccess(response)
  })
  .catch(error => { // all errors are handled here
    dispatch(requestTokenFailed('Something went wrong: ' + error, true))
  })
}

function fetchJwtToken (dispatch, fbAccessToken, scopes, onSuccess) {
  var form = new FormData()
  form.append('fb_access_token', fbAccessToken)
  form.append('requested_scopes', JSON.stringify(scopes))

  fetch(url + '/token', {
    method: 'POST',
    body: form
  })
  .then(response => { // ensure its json
    let contentType = response.headers.get('content-type')
    let gotJson = contentType && contentType.indexOf('application/json') !== -1

    if (!gotJson) {
      throw new Error('Oops, we haven\'t got JSON: ' + JSON.stringify(response))
    }
    return response.json()
  })
  .then(response => { // ensure query was accepted
    let ok = response.status === 'ok'

    if (!ok) {
      throw new Error('Received: ' + JSON.stringify(response))
    }

    // finally got token
    onSuccess(response)
  })
  .catch(error => { // all errors are handled here
    dispatch(requestTokenFailed('Something went wrong: ' + error, true))
  })
}

function fbLoginCallback (dispatch, response, callback) {
  let fbAccessToken = response.authResponse.accessToken

  if (!response.authResponse) { // ensure facebook login was successful
    dispatch(requestTokenFailed('Failed to log in to facebook: ' + JSON.stringify(response), true))
    return
  }

  fetchJwtToken(dispatch, fbAccessToken, ['user.list', 'user.all'],
    response => {
      let action = receiveTokenFromServer(response.token,
        response.user.name, response.user.email)
      dispatch(action)

      // store user info in browser
      localStorage.setItem('jwToken', response.token)
      localStorage.setItem('name', response.user.name)
      localStorage.setItem('email', response.user.email)
      localStorage.setItem('mockFacebookId', null)
      localStorage.setItem('isTestUser', false)

      if (callback) {
        callback()
      }
    })
}

export const testUserLogin = (local, server, name, email, mockFacebookId, callback) => {
  return (dispatch) => {
    // try to get from local
    if (local) {
      dispatch(requestTokenFromLocalStorage())
      if (localStorage.jwToken && localStorage.name && localStorage.email) {
        let action = receiveTokenFromLocalStorage(localStorage.jwToken,
          localStorage.name, localStorage.email)
        dispatch(action)
        return
      }
      let action = requestTokenFailed('No login info found in local storage', false)
      dispatch(action)
    }

    if (!server) {
      return
    }
    // try to get from server
    dispatch(requestTokenFromServer())
    fetchTestUserJwtToken(dispatch, name, email, mockFacebookId, ['user.list', 'user.all'],
      response => {
        let action = receiveTokenFromServer(response.token,
          response.user.name, response.user.email)
        dispatch(action)

        // store user info in browser
        localStorage.setItem('jwToken', response.token)
        localStorage.setItem('name', response.user.name)
        localStorage.setItem('email', response.user.email)
        localStorage.setItem('mockFacebookId', mockFacebookId)
        localStorage.setItem('isTestUser', true)

        if (callback) {
          callback()
        }
      })
  }
}

export const login = (local, server, callback) => {
  return (dispatch) => {
    // try to get from local
    if (local) {
      dispatch(requestTokenFromLocalStorage())
      if (localStorage.jwToken && localStorage.name && localStorage.email) {
        let action = receiveTokenFromLocalStorage(localStorage.jwToken,
        localStorage.name, localStorage.email)
        dispatch(action)
        if (callback) {
          callback()
        }
        return
      }
      dispatch(requestTokenFailed('No login info found in local storage', false))
    }

    if (!server) {
      return
    }

          // try to get from server
    dispatch(requestTokenFromServer())
          // log in with facebook
    console.info('Begin facebook login')
    window.FB.login(response => {
      fbLoginCallback(dispatch, response, callback)
      console.info('Successfully logged in to facebook', response)
    }, {
      scope: 'public_profile,email'
    })
  }
}

export const myFetch = (jwToken, dispatch, attempts = 0) => {
  return (what, props) => {
    var headers = new Headers()
    headers.append('Authorization', 'Bearer ' + jwToken)

    const properties = {
      headers: headers,
      ...props
    }

    return fetch(url + what, properties)
    .then(response => { // ensure its json
      let contentType = response.headers.get('content-type')
      let gotJson = contentType && contentType.indexOf('application/json') !== -1

      if (!gotJson) {
        throw new Error('Oops, we haven\'t got JSON: ' + JSON.stringify(response))
      }
      return response.json()
    })
    .then(response => { // check if token has expired
      if (response.status === 'error' && response.message === 'Expired token') {
        // try to get new token and then repeat fetch
        if (attempts < 2) {
          let callback = () => myFetch(jwToken, dispatch, attempts++)(what, props)
          if (localStorage.isTestUser === true && localStorage.jwToken
            && localStorage.name && localStorage.email) {
            dispatch(testUserLogin(false, true, localStorage.name, localStorage.email, localStorage.name, callback))
          } else {
            dispatch(login(false, true, callback))
          }

          throw new Error('Token expired')
        }

        throw new Error('Token expired, no more relog attempts')
      }
      return response
    })
    .then(response => { // ensure query was accepted
      if (response.status && response.status !== 'ok') {
        throw new Error('Received: ' + JSON.stringify(response))
      }
      return response
    })
  }
}

export const logout = (dispatcher) => {
  return (dispatch) => {
    dispatch(deleteToken(dispatcher))
    localStorage.clear()

    // log out of facebook
    console.info('Begin facebook logout')
    try {
      window.FB.logout((response) => {
        console.info('Successfully logged out of facebook', response)
      })
    } catch (err) {
      console.info('There was a problem logging out of facebook', err)
    }
  }
}
<commit_msg>Mostly refactoring, some small changes<commit_after>import fetch from 'isomorphic-fetch'

// determine where to send requests
const www = window.location.href.indexOf('www.') !== -1 ? 'www.' : ''
const url = process.env.NODE_ENV === 'production'
  ? `https://${www}amodahl.no/api/public` : `http://${www}local.amodahl.no:3000`

const scopes = [
  'user.all',
  'user.list',
  'chess-game.all',
  'chess-game.list',
  'chess-game.create',
  'chess-move.all',
  'chess-move.list',
  'chess-move.create',
  'update.all',
  'update.list'
]

export const requestTokenFromLocalStorage = () => {
  return {
    type: 'REQUEST_TOKEN_FROM_LOCAL_STORAGE'
  }
}

export const requestTokenFromServer = () => {
  return {
    type: 'REQUEST_TOKEN_FROM_SERVER'
  }
}

export const requestTokenFailed = (message, displayMessage) => {
  return {
    message: message,
    displayMessage: displayMessage,
    jwToken: null,
    type: 'REQUEST_TOKEN_FAILED'
  }
}

export const deleteToken = (dispatcher) => {
  return {
    jwToken: null,
    type: '@@' + dispatcher + '/DELETE_TOKEN'
  }
}

export const receiveTokenFromServer = (jwToken, name, email) => {
  return {
    jwToken: jwToken,
    name: name,
    email: email,
    type: 'RECEIVE_TOKEN_FROM_SERVER'
  }
}

export const receiveTokenFromLocalStorage = (jwToken, name, email) => {
  return {
    jwToken: jwToken,
    name: name,
    email: email,
    type: 'RECEIVE_TOKEN_FROM_LOCAL_STORAGE'
  }
}

function fetchTestUserJwtToken (dispatch, name, email, mockFacebookId, scopes, onSuccess) {
  var form = new FormData()
  form.append('requested_scopes', JSON.stringify(scopes))
  form.append('name', name)
  form.append('email', email)
  form.append('mock_facebook_id', mockFacebookId)

  fetch(url + '/token', {
    method: 'POST',
    body: form
  })
  .then(response => { // ensure its json
    let contentType = response.headers.get('content-type')
    let gotJson = contentType && contentType.indexOf('application/json') !== -1
    console.log(response)
    if (!gotJson) {
      throw new Error('Oops, we haven\'t got JSON: ' + JSON.stringify(response))
    }
    return response.json()
  })
  .then(response => { // ensure query was accepted
    let ok = response.status === 'ok'

    if (!ok) {
      throw new Error('Received: ' + JSON.stringify(response))
    }

    // finally got token
    onSuccess(response)
  })
  .catch(error => { // all errors are handled here
    dispatch(requestTokenFailed('Something went wrong: ' + error, true))
  })
}

function fetchJwtToken (dispatch, fbAccessToken, scopes, onSuccess) {
  var form = new FormData()
  form.append('fb_access_token', fbAccessToken)
  form.append('requested_scopes', JSON.stringify(scopes))

  fetch(url + '/token', {
    method: 'POST',
    body: form
  })
  .then(response => { // ensure its json
    let contentType = response.headers.get('content-type')
    let gotJson = contentType && contentType.indexOf('application/json') !== -1

    if (!gotJson) {
      throw new Error('Oops, we haven\'t got JSON: ' + JSON.stringify(response))
    }
    return response.json()
  })
  .then(response => { // ensure query was accepted
    let ok = response.status === 'ok'

    if (!ok) {
      throw new Error('Received: ' + JSON.stringify(response))
    }

    // finally got token
    onSuccess(response)
  })
  .catch(error => { // all errors are handled here
    dispatch(requestTokenFailed('Something went wrong: ' + error, true))
  })
}

function fbLoginCallback (dispatch, response, callback) {
  let fbAccessToken = response.authResponse.accessToken

  if (!response.authResponse) { // ensure facebook login was successful
    dispatch(requestTokenFailed('Failed to log in to facebook: ' + JSON.stringify(response), true))
    return
  }

  fetchJwtToken(dispatch, fbAccessToken, scopes,
    response => {
      let action = receiveTokenFromServer(response.token,
        response.user.name, response.user.email)
      dispatch(action)

      // store user info in browser
      localStorage.setItem('jwToken', response.token)
      localStorage.setItem('name', response.user.name)
      localStorage.setItem('email', response.user.email)
      localStorage.setItem('mockFacebookId', null)
      localStorage.setItem('isTestUser', false)

      if (callback) {
        callback(response.token)
      }
    })
}

export const testUserLogin = (local, server, name, email, mockFacebookId, callback) => {
  return (dispatch) => {
    // try to get from local
    if (local) {
      dispatch(requestTokenFromLocalStorage())
      if (localStorage.jwToken && localStorage.name && localStorage.email) {
        let action = receiveTokenFromLocalStorage(localStorage.jwToken,
          localStorage.name, localStorage.email)
        dispatch(action)
        return
      }
      let action = requestTokenFailed('No login info found in local storage', false)
      dispatch(action)
    }

    if (!server) {
      return
    }
    // try to get from server
    dispatch(requestTokenFromServer())
    console.log(name, email, mockFacebookId)
    fetchTestUserJwtToken(dispatch, name, email, mockFacebookId, scopes,
      response => {
        let action = receiveTokenFromServer(response.token,
          response.user.name, response.user.email)
        dispatch(action)

        // store user info in browser
        localStorage.setItem('jwToken', response.token)
        localStorage.setItem('name', response.user.name)
        localStorage.setItem('email', response.user.email)
        localStorage.setItem('mockFacebookId', mockFacebookId)
        localStorage.setItem('isTestUser', true)

        if (callback) {
          callback(response.token)
        }
      })
  }
}

export const login = (local, server, callback) => {
  return (dispatch) => {
    // try to get from local
    if (local) {
      dispatch(requestTokenFromLocalStorage())
      if (localStorage.jwToken && localStorage.name && localStorage.email) {
        let action = receiveTokenFromLocalStorage(localStorage.jwToken,
        localStorage.name, localStorage.email)
        dispatch(action)
        if (callback) {
          callback()
        }
        return
      }
      dispatch(requestTokenFailed('No login info found in local storage', false))
    }

    if (!server) {
      return
    }

    // try to get from server
    dispatch(requestTokenFromServer())
          // log in with facebook
    console.info('Begin facebook login')
    window.FB.login(response => {
      fbLoginCallback(dispatch, response, callback)
      console.info('Successfully logged in to facebook', response)
    }, {
      scope: 'public_profile,email'
    })
  }
}

/*
  Uses callback instead of .then because
  I could not figure out how to
  pass both body and headers otherwise.
*/
export const myFetch = (dispatch) => (jwToken, attempts = 0) => {
  return (what, props, callback) => {
    var headers = props.headers ? props.headers : new Headers()
    headers.append('Authorization', 'Bearer ' + jwToken)
    headers.append('pragma', 'no-cache')
    headers.append('cache-control', 'no-store')

    const properties = {
      headers: headers,
      ...props
    }

    return fetch(url + what, properties)
    .then(response => {
      // ensure its json
      let contentType = response.headers.get('content-type')
      let gotJson = contentType && contentType.indexOf('application/json') !== -1
      if (!gotJson) {
        throw new Error('Oops, we haven\'t got JSON: ' + JSON.stringify(response))
      }
      return response.json().then(json => {
        // check if token has expired
        if (json.status === 'error' && json.message === 'Expired token') {
          // try to get new token and then repeat fetch
          if (attempts < 2) {
            let callback = (newToken) =>
              myFetch(newToken, dispatch, attempts + 1)(what, props, callback)

            if (localStorage.isTestUser === true && localStorage.jwToken &&
              localStorage.name && localStorage.email) {
              dispatch(testUserLogin(false, true, localStorage.name,
                localStorage.email, localStorage.name, callback))
            } else {
              dispatch(login(false, true, callback))
            }
            throw new Error('Token expired')
          }
          throw new Error('Token expired, no more relog attempts')
        }

        // ensure query was accepted
        if (json.status && json.status !== 'ok') {
          throw new Error('Received: ' + JSON.stringify(json))
        }
        if (callback) {
          callback(json, response.headers)
        }
      })
    })
  }
}

export const logout = (dispatcher) => {
  return (dispatch) => {
    dispatch(deleteToken(dispatcher))
    localStorage.clear()

    // log out of facebook
    console.info('Begin facebook logout')
    try {
      window.FB.logout((response) => {
        console.info('Successfully logged out of facebook', response)
      })
    } catch (err) {
      console.info('There was a problem logging out of facebook', err)
    }
  }
}
<|endoftext|>


<commit_before>import { REGISTER_ANIMAL } from '../constants/ActionTypes';
import { registerAnimal as ra} from '../api/user';

export const registerAnimal = (user, animal) => (dispatch, ownProps) => {
  return ra(user, animal).then((data) => {
    localStorage.setItem('jwt', data.token)
    return dispatch({
      type: REGISTER_ANIMAL,
      data: {animal, user}
    })
  }).catch(err => { console.info(err); alert('Ooops!, Algo deu errado')})
}<commit_msg>fix how to handle response from server<commit_after>import { REGISTER_ANIMAL } from '../constants/ActionTypes';
import { registerAnimal as ra} from '../api/user';

export const registerAnimal = (user, animal) => (dispatch, ownProps) => {
  return ra(user, animal).then(resp => {
    localStorage.setItem('jwt', resp.data.token)
    return dispatch({
      type: REGISTER_ANIMAL,
      data: {animal, user}
    })
  }).catch(err => { console.info(err); alert('Ooops!, Algo deu errado')})
}<|endoftext|>


<commit_before>utils.extend( KityMinder, function () {
    var _kityminderUI = {},
        _kityminderToolbarUI = {},
        _activeWidget = null,
        _widgetData = {},
        _widgetCallBack = {};
    return {
        registerUI: function ( uiname, fn ) {
            utils.each( uiname.split( /\s+/ ), function ( i, name ) {
                _kityminderUI[ name ] = fn;
            } )
        },
        registerToolbarUI: function ( uiname, fn ) {
            utils.each( uiname.split( /\s+/ ), function ( i, name ) {
                _kityminderToolbarUI[ name ] = fn;
            } )
        },
        loadUI: function ( km ) {
            utils.each( _kityminderUI, function ( i, fn ) {
                fn.call( km )
            } )
        },
        _createUI: function ( id ) {
            var $cont = $( '

' ),
                $toolbar = $.kmuitoolbar(),
                $kmbody = $( '

' ),
                $statusbar = $( '

' );

            $cont.append( $toolbar ).append( $kmbody ).append( $statusbar );
            $( utils.isString( id ) ? '#' + id : id ).append( $cont );

            return {
                '$container': $cont,
                '$toolbar': $toolbar,
                '$body': $kmbody,
                '$statusbar': $statusbar
            };
        },
        _createToolbar: function ( $toolbar, km ) {
            var toolbars = km.getOptions( 'toolbars' );
            if ( toolbars && toolbars.length ) {
                var btns = [];
                $.each( toolbars, function ( i, uiNames ) {
                    $.each( uiNames.split( /\s+/ ), function ( index, name ) {
                        if ( name == '|' ) {
                            $.kmuiseparator && btns.push( $.kmuiseparator() );
                        } else {
                            if ( _kityminderToolbarUI[ name ] ) {
                                var ui = _kityminderToolbarUI[ name ].call( km, name );
                                ui && btns.push( ui );
                            }

                        }

                    } );
                    btns.length && $toolbar.kmui().appendToBtnmenu( btns );
                } );
            }
            $toolbar.append( $( '

' ) );
        },
        _createStatusbar: function ( $statusbar, km ) {

        },
        getKityMinder: function ( id, options ) {
            var containers = this._createUI( id );
            var km = this.getMinder( containers.$body.get( 0 ), options );
            this._createToolbar( containers.$toolbar, km );
            this._createStatusbar( containers.$statusbar, km );
            km.$container = containers.$container;

            this.loadUI( km );
            return km.fire( 'interactchange' );
        },
        registerWidget: function ( name, pro, cb ) {
            _widgetData[ name ] = $.extend2( pro, {
                $root: '',
                _preventDefault: false,
                root: function ( $el ) {
                    return this.$root || ( this.$root = $el );
                },
                preventDefault: function () {
                    this._preventDefault = true;
                },
                clear: false
            } );
            if ( cb ) {
                _widgetCallBack[ name ] = cb;
            }
        },
        getWidgetData: function ( name ) {
            return _widgetData[ name ]
        },
        setWidgetBody: function ( name, $widget, km ) {
            if ( !km._widgetData ) {

                utils.extend( km, {
                    _widgetData: {},
                    getWidgetData: function ( name ) {
                        return this._widgetData[ name ];
                    },
                    getWidgetCallback: function ( widgetName ) {
                        var me = this;
                        return function () {
                            return _widgetCallBack[ widgetName ].apply( me, [ me, $widget ].concat( utils.argsToArray( arguments, 0 ) ) )
                        }
                    }
                } )

            }
            var pro = _widgetData[ name ];
            if ( !pro ) {
                return null;
            }
            pro = km._widgetData[ name ];
            if ( !pro ) {
                pro = _widgetData[ name ];
                pro = km._widgetData[ name ] = $.type( pro ) == 'function' ? pro : utils.clone( pro );
            }

            pro.root( $widget.kmui().getBodyContainer() );

            pro.initContent( km, $widget );
            if ( !pro._preventDefault ) {
                pro.initEvent( km, $widget );
            }

            pro.width && $widget.width( pro.width );
        },
        setActiveWidget: function ( $widget ) {
            _activeWidget = $widget;
        }
    }
}() );<commit_msg>修改在没有按钮时，toolbar还是会显示个原点的问题<commit_after>utils.extend( KityMinder, function () {
    var _kityminderUI = {},
        _kityminderToolbarUI = {},
        _activeWidget = null,
        _widgetData = {},
        _widgetCallBack = {};
    return {
        registerUI: function ( uiname, fn ) {
            utils.each( uiname.split( /\s+/ ), function ( i, name ) {
                _kityminderUI[ name ] = fn;
            } )
        },
        registerToolbarUI: function ( uiname, fn ) {
            utils.each( uiname.split( /\s+/ ), function ( i, name ) {
                _kityminderToolbarUI[ name ] = fn;
            } )
        },
        loadUI: function ( km ) {
            utils.each( _kityminderUI, function ( i, fn ) {
                fn.call( km )
            } )
        },
        _createUI: function ( id ) {
            var $cont = $( '

' ),
                $toolbar = $.kmuitoolbar(),
                $kmbody = $( '

' ),
                $statusbar = $( '

' );

            $cont.append( $toolbar ).append( $kmbody ).append( $statusbar );
            $( utils.isString( id ) ? '#' + id : id ).append( $cont );

            return {
                '$container': $cont,
                '$toolbar': $toolbar,
                '$body': $kmbody,
                '$statusbar': $statusbar
            };
        },
        _createToolbar: function ( $toolbar, km ) {
            var toolbars = km.getOptions( 'toolbars' );
            if ( toolbars && toolbars.length ) {
                var btns = [];
                $.each( toolbars, function ( i, uiNames ) {
                    $.each( uiNames.split( /\s+/ ), function ( index, name ) {
                        if ( name == '|' ) {
                            $.kmuiseparator && btns.push( $.kmuiseparator() );
                        } else {
                            if ( _kityminderToolbarUI[ name ] ) {
                                var ui = _kityminderToolbarUI[ name ].call( km, name );
                                ui && btns.push( ui );
                            }

                        }

                    } );
                    btns.length && $toolbar.kmui().appendToBtnmenu( btns );
                } );
                $toolbar.append( $( '

' ) );
            }else{
                $toolbar.hide()
            }

        },
        _createStatusbar: function ( $statusbar, km ) {

        },
        getKityMinder: function ( id, options ) {
            var containers = this._createUI( id );
            var km = this.getMinder( containers.$body.get( 0 ), options );
            this._createToolbar( containers.$toolbar, km );
            this._createStatusbar( containers.$statusbar, km );
            km.$container = containers.$container;

            this.loadUI( km );
            return km.fire( 'interactchange' );
        },
        registerWidget: function ( name, pro, cb ) {
            _widgetData[ name ] = $.extend2( pro, {
                $root: '',
                _preventDefault: false,
                root: function ( $el ) {
                    return this.$root || ( this.$root = $el );
                },
                preventDefault: function () {
                    this._preventDefault = true;
                },
                clear: false
            } );
            if ( cb ) {
                _widgetCallBack[ name ] = cb;
            }
        },
        getWidgetData: function ( name ) {
            return _widgetData[ name ]
        },
        setWidgetBody: function ( name, $widget, km ) {
            if ( !km._widgetData ) {

                utils.extend( km, {
                    _widgetData: {},
                    getWidgetData: function ( name ) {
                        return this._widgetData[ name ];
                    },
                    getWidgetCallback: function ( widgetName ) {
                        var me = this;
                        return function () {
                            return _widgetCallBack[ widgetName ].apply( me, [ me, $widget ].concat( utils.argsToArray( arguments, 0 ) ) )
                        }
                    }
                } )

            }
            var pro = _widgetData[ name ];
            if ( !pro ) {
                return null;
            }
            pro = km._widgetData[ name ];
            if ( !pro ) {
                pro = _widgetData[ name ];
                pro = km._widgetData[ name ] = $.type( pro ) == 'function' ? pro : utils.clone( pro );
            }

            pro.root( $widget.kmui().getBodyContainer() );

            pro.initContent( km, $widget );
            if ( !pro._preventDefault ) {
                pro.initEvent( km, $widget );
            }

            pro.width && $widget.width( pro.width );
        },
        setActiveWidget: function ( $widget ) {
            _activeWidget = $widget;
        }
    }
}() );<|endoftext|>


<commit_before>/**
 * Qoopido.demand adapter for require.js
 *
 * Adapter for Qoopido.demand to enable loading of require.js compatible modules
 *
 * Copyright (c) 2015 Dirk Lueth
 *
 * Dual licensed under the MIT and GPL licenses.
 *  - http://www.opensource.org/licenses/mit-license.php
 *  - http://www.gnu.org/copyleft/gpl.html
 *
 * @author Dirk Lueth <info@qoopido.com>
 */

;(function(global) {
	'use strict';

	var NULL         = null,
		arrayIsArray = Array.isArray;

	/**
	 * definition of the require.js adapter
	 *
	 * @param {Function} demand
	 * @param {Function} provide
	 *
	 * @returns {{require: require, define: define}}
	 *
	 * @exports /adapter/require
	 */
	function definition(demand, provide) {
		/**
		 * provides require.js require functionality
		 *
		 * @param {...String} dependency
		 * @param {Function} callback
		 */
		function require() {
			var parameter    = arguments,
				dependencies = arrayIsArray(parameter[0]) ? parameter[0] : NULL,
				callback     = arguments[dependencies ? 1 : 0];

			demand
				.apply(NULL, dependencies || [])
				.then(callback);
		}

		/**
		 * provides require.js define functionality
		 *
		 * @param {String} [id]
		 * @param {Object[]} [dependencies]
		 * @param {Function} definition
		 */
		function define() {
			var parameter    = arguments,
				id           = typeof parameter[0] === 'string' ? parameter[0] : NULL,
				dependencies = arrayIsArray(parameter[id ? 1 : 0]) ? parameter[id ? 1 : 0] : NULL,
				definition   = parameter[id ? (dependencies ? 2 : 1) : (dependencies ? 1 : 0)],
				temp         = provide.apply(NULL, id ? [ id, definition ] : [ definition]);

			if(dependencies) {
				temp.when.apply(NULL, dependencies);
			}
		}

		define.amd = 1;

		global.require = require;
		global.define  = define;

		return { require: require, define: define };
	}

	provide(definition)
		.when('/demand', '/provide');
}(this));<commit_msg>[UPDATE] adapter/require<commit_after>/**
 * Qoopido.demand adapter for require.js
 *
 * Adapter for Qoopido.demand to enable loading of require.js compatible modules
 *
 * Copyright (c) 2015 Dirk Lueth
 *
 * Dual licensed under the MIT and GPL licenses.
 *  - http://www.opensource.org/licenses/mit-license.php
 *  - http://www.gnu.org/copyleft/gpl.html
 *
 * @author Dirk Lueth <info@qoopido.com>
 */

;(function(global) {
	'use strict';

	var NULL         = null,
		arrayIsArray = Array.isArray;

	/**
	 * definition of the require.js adapter
	 *
	 * @param {Function} demand
	 * @param {Function} provide
	 *
	 * @returns {{require: require, define: define}}
	 *
	 * @exports /adapter/require
	 */
	function definition() {
		/**
		 * provides require.js require functionality
		 *
		 * @param {...String} dependency
		 * @param {Function} callback
		 */
		function require() {
			var parameter    = arguments,
				dependencies = arrayIsArray(parameter[0]) ? parameter[0] : NULL,
				callback     = arguments[dependencies ? 1 : 0];

			if(dependencies) {
				demand
					.apply(NULL, dependencies)
					.then(callback);
			} else {
				callback();
			}
		}

		/**
		 * provides require.js define functionality
		 *
		 * @param {String} [id]
		 * @param {Object[]} [dependencies]
		 * @param {Function} definition
		 */
		function define() {
			var parameter    = arguments,
				id           = typeof parameter[0] === 'string' ? parameter[0] : NULL,
				dependencies = arrayIsArray(parameter[id ? 1 : 0]) ? parameter[id ? 1 : 0] : NULL,
				definition   = parameter[id ? (dependencies ? 2 : 1) : (dependencies ? 1 : 0)],
				temp         = provide.apply(NULL, id ? [ id, definition ] : [ definition]);

			if(dependencies) {
				temp.when.apply(NULL, dependencies);
			}
		}

		define.amd = 1;

		global.require = require;
		global.define  = define;

		return { require: require, define: define };
	}

	provide(definition);
}(this));<|endoftext|>


<commit_before>/**
 * @license
 * Youbora Plugin Kaltura player
 * Copyright NicePopleAtWork & Kaltura
 * @author Jordi Aguilar & Dan Ziv
 */

var VERSION = '1.0.0';

$YB.plugins.KalturaV2 = function (player, options) {
  try {
    /** Name and platform of the plugin.*/
    this.pluginName = 'kaltura-js';

    /** Version of the plugin. ie: 5.1.0-name */
    this.pluginVersion = '5.4.5-' + VERSION + '-kaltura-js';

    /* Initialize YouboraJS */
    this.startMonitoring(player, options);

    this.bitrate = -1;

    // Start listening
    this.registerListeners();
  } catch (err) {
    $YB.error(err);
  }
};

/** Inherit from generic plugin */
$YB.plugins.KalturaV2.prototype = new $YB.plugins.Generic;

$YB.plugins.KalturaV2.prototype.getPlayhead = function () {
  return this.player.getPlayer().currentTime;
};

$YB.plugins.KalturaV2.prototype.getBitrate = function () {
  if (this.player.getPlayer().isMulticast &&
    $.isFunction(this.player.getPlayer().getMulticastBitrate)
  ) {
    this.bitrate = this.player.getPlayer().getMulticastBitrate();
  }

  var bitrate = this.player.getPlayer().mediaElement.selectedSource.getBitrate();
  if (this.bitrate === -1 && bitrate > 0) {
    this.bitrate = bitrate
  }

  return (this.bitrate !== -1) ? (this.bitrate * 1024) : -1
};

$YB.plugins.KalturaV2.prototype.getMediaDuration = function () {
  return this.player.getPlayer().evaluate("{mediaProxy.entry.duration}");
};

$YB.plugins.KalturaV2.prototype.getTitle = function () {
  return this.player.getPlayer().evaluate("{mediaProxy.entry.name}");
};

$YB.plugins.KalturaV2.prototype.getRendition = function () {
  var source = this.player.getPlayer().mediaElement.selectedSource;
  if (source && source.height && source.width) {
    return $YB.utils.buildRenditionString(source.width, source.height, source.bandwidth)
  }
};

$YB.plugins.KalturaV2.prototype.getResource = function () {
  return this.player.getPlayer().getSrc()
};

$YB.plugins.KalturaV2.prototype.getIsLive = function () {
  return this.player.getPlayer().isLive()
};

$YB.plugins.KalturaV2.prototype.getPlayerVersion = function () {
  return 'kaltura-player-v' + MWEMBED_VERSION;
};

/** Register Listeners */
$YB.plugins.KalturaV2.prototype.registerListeners = function () {
  // save context
  var context = this;

  this.player.bind('onChangeMedia', function () {
    // dispatch stop if changing media during playback in order to close the session at Youbora
    if (context.player.getPlayer().currentState !== 'end') {
      context.endedHandler();
      context.reset();
    }
  });

  this.player.bind('playerReady', function () {
    // Set ContentId
    context.setMetadata();

    // Set bitrate
    var kalturaContextData = context.player.getPlayer().kalturaContextData;
    if (kalturaContextData && kalturaContextData.flavorAssets) {
      if (kalturaContextData.flavorAssets.length === 1) {
        context.bitrate = kalturaContextData.flavorAssets[0].bitrate;
      } else {
        context.bitrate = -1;
      }
    }
  });

  this.player.bind('postEnded', function () {
    context.endedHandler();
    context.reset();
  });

  this.player.bind('playerError', function (e, errorObj) {
    var errorMsg = errorObj ? errorObj.message : context.player.getPlayer().getErrorMessage();
    var errorCode = errorObj && errorObj.key ? errorObj.key : context.player.getPlayer().getErrorCode();
    context.setMetadata();
    context.errorHandler(errorCode, errorMsg);
  });

  this.player.bind('bitrateChange', function (e, newBitrate) {
    context.bitrate = newBitrate;
  });

  this.player.bind('SourceSelected', function (e, source) {
    if (source.getBitrate()) {
      context.bitrate = source.getBitrate();
    }
  });

  this.player.bind('sourceSwitchingEnd', function (e, source) {
    if (source.newBitrate) {
      context.bitrate = source.newBitrate;
    }
  });

  this.player.bind('onpause', function () {
    context.pauseHandler();
  });

  this.player.bind('onplay', function () {
    context.resumeHandler();
  });

  this.player.bind('bufferStartEvent', function () {
    context.bufferingHandler();
  });

  this.player.bind('bufferEndEvent', function () {
    context.bufferedHandler();
  });

  this.player.bind('AdSupport_PreSequence firstPlay replayEvent', function () {
    context.setMetadata();
    context.playHandler();
  });

  this.player.bind('playing', function () {
    if ( context.player.getPlayer().isInSequence ) {
      return;
    }
    context.playingHandler();
  });

  this.player.bind('seeking', function () {
    if (!context.viewManager.isBuffering) {
      context.seekingHandler();
    }
  });

  this.player.bind('seeked', function () {
      context.seekedHandler();
  });

  // Adnalyzer start
  this.adnalyzer = new $YB.adnalyzers.KalturaAds(this)
};

$YB.plugins.KalturaV2.prototype.unregisterListeners = function () {
  this.player.unbind(this.eventSuffix)
};

$YB.plugins.KalturaV2.prototype.reset = function () {
  this.viewManager.comm.view++;
};

$YB.plugins.KalturaV2.prototype.setMetadata = function () {
	this.setOptions({
		properties: {
			kalturaInfo: {
				entryId: this.player.getPlayer().evaluate("{mediaProxy.entry.id}"),
				sessionId: this.player.getPlayer().evaluate("{configProxy.sessionId}"),
				uiConfigId: this.player.getPlayer().evaluate("{configProxy.kw.uiConfId}")
			}
		}
	});
};<commit_msg>fix(FEC-7169): pass youbora config on media change<commit_after>/**
 * @license
 * Youbora Plugin Kaltura player
 * Copyright NicePopleAtWork & Kaltura
 * @author Jordi Aguilar & Dan Ziv
 */

var VERSION = '1.0.0';

$YB.plugins.KalturaV2 = function (player, options) {
  try {
    /** Name and platform of the plugin.*/
    this.pluginName = 'kaltura-js';

    /** Version of the plugin. ie: 5.1.0-name */
    this.pluginVersion = '5.4.5-' + VERSION + '-kaltura-js';

    /* Initialize YouboraJS */
    this.startMonitoring(player, options);

    this.bitrate = -1;

    // Start listening
    this.registerListeners();
  } catch (err) {
    $YB.error(err);
  }
};

/** Inherit from generic plugin */
$YB.plugins.KalturaV2.prototype = new $YB.plugins.Generic;

$YB.plugins.KalturaV2.prototype.getPlayhead = function () {
  return this.player.getPlayer().currentTime;
};

$YB.plugins.KalturaV2.prototype.getBitrate = function () {
  if (this.player.getPlayer().isMulticast &&
    $.isFunction(this.player.getPlayer().getMulticastBitrate)
  ) {
    this.bitrate = this.player.getPlayer().getMulticastBitrate();
  }

  var bitrate = this.player.getPlayer().mediaElement.selectedSource.getBitrate();
  if (this.bitrate === -1 && bitrate > 0) {
    this.bitrate = bitrate
  }

  return (this.bitrate !== -1) ? (this.bitrate * 1024) : -1
};

$YB.plugins.KalturaV2.prototype.getMediaDuration = function () {
  return this.player.getPlayer().evaluate("{mediaProxy.entry.duration}");
};

$YB.plugins.KalturaV2.prototype.getTitle = function () {
  return this.player.getPlayer().evaluate("{mediaProxy.entry.name}");
};

$YB.plugins.KalturaV2.prototype.getRendition = function () {
  var source = this.player.getPlayer().mediaElement.selectedSource;
  if (source && source.height && source.width) {
    return $YB.utils.buildRenditionString(source.width, source.height, source.bandwidth)
  }
};

$YB.plugins.KalturaV2.prototype.getResource = function () {
  return this.player.getPlayer().getSrc()
};

$YB.plugins.KalturaV2.prototype.getIsLive = function () {
  return this.player.getPlayer().isLive()
};

$YB.plugins.KalturaV2.prototype.getPlayerVersion = function () {
  return 'kaltura-player-v' + MWEMBED_VERSION;
};

/** Register Listeners */
$YB.plugins.KalturaV2.prototype.registerListeners = function () {
  // save context
  var context = this;

  this.player.bind('onChangeMedia', function () {
    // dispatch stop if changing media during playback in order to close the session at Youbora
    if (context.player.getPlayer().currentState !== 'end') {
      context.endedHandler();
      context.reset();
    }
  });

  this.player.bind('playerReady', function () {
    // Set ContentId
    context.setMetadata();

    // Set bitrate
    var kalturaContextData = context.player.getPlayer().kalturaContextData;
    if (kalturaContextData && kalturaContextData.flavorAssets) {
      if (kalturaContextData.flavorAssets.length === 1) {
        context.bitrate = kalturaContextData.flavorAssets[0].bitrate;
      } else {
        context.bitrate = -1;
      }
    }
  });

  this.player.bind('postEnded', function () {
    context.endedHandler();
    context.reset();
  });

  this.player.bind('playerError', function (e, errorObj) {
    var errorMsg = errorObj ? errorObj.message : context.player.getPlayer().getErrorMessage();
    var errorCode = errorObj && errorObj.key ? errorObj.key : context.player.getPlayer().getErrorCode();
    context.setMetadata();
    context.errorHandler(errorCode, errorMsg);
  });

  this.player.bind('bitrateChange', function (e, newBitrate) {
    context.bitrate = newBitrate;
  });

  this.player.bind('SourceSelected', function (e, source) {
    if (source.getBitrate()) {
      context.bitrate = source.getBitrate();
    }
  });

  this.player.bind('sourceSwitchingEnd', function (e, source) {
    if (source.newBitrate) {
      context.bitrate = source.newBitrate;
    }
  });

  this.player.bind('onpause', function () {
    context.pauseHandler();
  });

  this.player.bind('onplay', function () {
    context.resumeHandler();
  });

  this.player.bind('bufferStartEvent', function () {
    context.bufferingHandler();
  });

  this.player.bind('bufferEndEvent', function () {
    context.bufferedHandler();
  });

  this.player.bind('AdSupport_PreSequence firstPlay replayEvent', function () {
    context.setMetadata();
    context.playHandler();
  });

  this.player.bind('playing', function () {
    if ( context.player.getPlayer().isInSequence ) {
      return;
    }
    context.playingHandler();
  });

  this.player.bind('seeking', function () {
    if (!context.viewManager.isBuffering) {
      context.seekingHandler();
    }
  });

  this.player.bind('seeked', function () {
      context.seekedHandler();
  });

  // Adnalyzer start
  this.adnalyzer = new $YB.adnalyzers.KalturaAds(this)
};

$YB.plugins.KalturaV2.prototype.unregisterListeners = function () {
  this.player.unbind(this.eventSuffix)
};

$YB.plugins.KalturaV2.prototype.reset = function () {
  this.viewManager.comm.view++;
};

$YB.plugins.KalturaV2.prototype.setMetadata = function () {
    //Set default kaltura properties
	this.setOptions({
		properties: {
			kalturaInfo: {
				entryId: this.player.getPlayer().evaluate("{mediaProxy.entry.id}"),
				sessionId: this.player.getPlayer().evaluate("{configProxy.sessionId}"),
				uiConfigId: this.player.getPlayer().evaluate("{configProxy.kw.uiConfId}")
			}
		}
	});
	//Set new youbora media config
	var player = this.player.getPlayer();
	var config = player.getKalturaConfig("youbora");
	this.setOptions(config);
};<|endoftext|>