<commit_before>'use strict';

import * as PublicGameStates from './states/public_game.server.controller';
import * as PrivateGameStates from './states/private_game.server.controller';

// Set min and max players
export var min_players = 3;
export var max_players = 7;

export default class GameRoom {

    constructor(players, is_public_room, game_id) {
        // Set players prop, return error if not array
        if (Array.isArray(players)) this.players = players;
        else throw 'Attempted to create game without correct players param';
        // Set the game_id generated from the game_rooms controller
        this._id = game_id;
        // Is game public, if not then game is private
        this.is_public_room = is_public_room;
        // Set to true if judge leaves
        this.no_winner = false;
        this.State = is_public_room ? new PublicGameStates.Establishing(this) : new PrivateGameStates.Establishing(this);
    }

    set CurrState(State) {
        this.State = State;
    }

    get CurrState() {
        return this.State;
    }

    getStateName() {
        return this.State.state_name;
    }

    isFull() {
        return this.players.length === max_players;
    }

    // When a player presses leave game
    playerExits(player) {
        // Delete player from players array
        this.players.splice(this.players.indexOf(player), 1);

        // If theres not enough players to continue, terminate game
        if (this.players.length < min_players) {
            this.CurrState = this.is_public_room ? new PublicGameStates.Terminating(this).state_name : new PrivateGameStates.Terminating(this).state_name;
        }
        // Enough players to keep game open
        else {
            // The judge left the game, no winner can be determined
            // TODO: Flag judge for leaving mid-game!
            if (player === this.judge) this.no_winner = true;
        }
    }

    // Add a player to the game
    addPlayer(player) {
        var index = getRandomIntInclusive(0, this.players.length-1);
        this.players.splice(index, 0, player);
    }

    // TODO: Add a cleanup function that unregisters all callbacks (methods of the Game object) that were registered on socket events.
}

// Returns a random integer between min (included) and max (included)
// Using Math.round() will give you a non-uniform distribution!
function getRandomIntInclusive(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}<commit_msg>renamed states controllers<commit_after>'use strict';

import * as PublicGameStates from './states/public_game.states.server.controller';
import * as PrivateGameStates from './states/private_game.states.server.controller';

// Set min and max players
export var min_players = 3;
export var max_players = 7;

export default class GameRoom {

    constructor(players, is_public_room, game_id) {
        // Set players prop, return error if not array
        if (Array.isArray(players)) this.players = players;
        else throw 'Attempted to create game without correct players param';
        // Set the game_id generated from the game_rooms controller
        this._id = game_id;
        // Is game public, if not then game is private
        this.is_public_room = is_public_room;
        // Set to true if judge leaves
        this.no_winner = false;
        this.State = is_public_room ? new PublicGameStates.Establishing(this) : new PrivateGameStates.Establishing(this);
    }

    set CurrState(State) {
        this.State = State;
    }

    get CurrState() {
        return this.State;
    }

    getStateName() {
        return this.State.state_name;
    }

    isFull() {
        return this.players.length === max_players;
    }

    // When a player presses leave game
    playerExits(player) {
        // Delete player from players array
        this.players.splice(this.players.indexOf(player), 1);

        // If theres not enough players to continue, terminate game
        if (this.players.length < min_players) {
            this.CurrState = this.is_public_room ? new PublicGameStates.Terminating(this).state_name : new PrivateGameStates.Terminating(this).state_name;
        }
        // Enough players to keep game open
        else {
            // The judge left the game, no winner can be determined
            // TODO: Flag judge for leaving mid-game!
            if (player === this.judge) this.no_winner = true;
        }
    }

    // Add a player to the game
    addPlayer(player) {
        var index = getRandomIntInclusive(0, this.players.length-1);
        this.players.splice(index, 0, player);
    }

    // TODO: Add a cleanup function that unregisters all callbacks (methods of the Game object) that were registered on socket events.
}

// Returns a random integer between min (included) and max (included)
// Using Math.round() will give you a non-uniform distribution!
function getRandomIntInclusive(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}<|endoftext|>


<commit_before>function drawPage() {
    console.log(json);
    var output = "";
    var body = "
\n" +
        "        <input type=\"hidden\" name=\"appName\" value=\"\" />\n" +
        "
\n" +
        "
\n" +
        "
\n" +
        "                    Authorized Applications	\n" +
        "                    Application Developer	\n" +
        "                    Actions	\n" +
        "
\n" +
        "
\n" +
        "
\n";
    if (json != null) {

        if (isArray(json.return)) {
            for (var i in json.return) {
                body = body + "
\n" +
                    "                    " + json.return[i].applicationName + "	\n" +
                    "                    " + json.return[i].username + "	\n" +
                    "                     Remove Application	\n" +
                    "
\n";
            }
        }
        else {
            body = body + "
\n" +
                "                    " + json.return.applicationName + "	\n" +
                "                    " + json.return.username + "	\n" +
                "                     Remove Application	\n" +
                "
\n";
        }
    }
    body = body + "
\n" +
        "
\n" +
        "\n" +
        "
";

    output = body;
    $("#gadgetBody").empty();
    $("#gadgetBody").append(output);
}

function itemRemove(appName) {
    var str = PROXY_CONTEXT_PATH + "/portal/gadgets/user_auth_apps/controllers/my_auth_apps/my_authorized_app_remove.jag";
    $.ajax({
        url:str,
        type:"POST",
        data:"appName=" + appName + "&cookie=" + cookie + "&user=" + userName
    })
        .done(function (data) {
            cancel();

        })
        .fail(function () {
            message({content:'Error while removing Application ', type:'error', cbk:function () {
            } });
            console.log('error');

        })
        .always(function () {
            console.log('completed');
        });

}

function isArray(element) {
    return Object.prototype.toString.call(element) === '[object Array]';
}

function cancel() {
    gadgets.Hub.publish('org.wso2.is.dashboard', {
        msg:'A message from User profile',
        id:"user_auth_apps .shrink-widget"
    });

}

function validate(appName) {
    var element = "
\n" +
        "
\n" +
        "
\n" +
        "
\n" +
        "        <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\">×</button>\n" +
        "
Modal title
\n" +
        "
\n" +
        "
\n" +
        "
One fine body…
\n" +
        "
\n" +
        "
\n" +
        "
\n" +
        "
\n" +
        "
\n" +
        "
";
    $("#message").append(element);
    itemRemoveValidate(appName);
}

function itemRemoveValidate(appName) {
    var msg = "You are about to remove " + appName + ". Do you want to proceed?";
    message({content:msg, type:'confirm', okCallback:function () {
        itemRemove(appName);
    }, cancelCallback:function () {
    }});
}

<commit_msg>Fixing - IDENTITY-4064<commit_after>function drawPage() {
    console.log(json);
    var output = "";
    var body = "
\n" +
        "        <input type=\"hidden\" name=\"appName\" value=\"\" />\n" +
        "
\n" +
        "
\n" +
        "
\n" +
        "                    Authorized Applications	\n" +
        "                    Application Developer	\n" +
        "                    Actions	\n" +
        "
\n" +
        "
\n" +
        "
\n";
    if (json != null) {

        if (isArray(json.return)) {

            for (var i in json.return) {

                var username = json.return[i].username;

                if (username.indexOf("carbon.super") > -1) {
                    username = username.substring(0, username.indexOf("carbon.super") - 1);
                }

                body = body + "
\n" +
                    "                    " + json.return[i].applicationName + "	\n" +
                    "                    " + username + "	\n" +
                    "                     Remove Application	\n" +
                    "
\n";
            }
        }
        else {

            var username = json.return.username;

            if (username.indexOf("carbon.super") > -1) {
                username = username.substring(0, username.indexOf("carbon.super") - 1);
            }

            body = body + "
\n" +
                "                    " + json.return.applicationName + "	\n" +
                "                    " + username + "	\n" +
                "                     Remove Application	\n" +
                "
\n";
        }
    }
    body = body + "
\n" +
        "
\n" +
        "\n" +
        "
";

    output = body;
    $("#gadgetBody").empty();
    $("#gadgetBody").append(output);
}

function itemRemove(appName) {
    var str = PROXY_CONTEXT_PATH + "/portal/gadgets/user_auth_apps/controllers/my_auth_apps/my_authorized_app_remove.jag";
    $.ajax({
        url:str,
        type:"POST",
        data:"appName=" + appName + "&cookie=" + cookie + "&user=" + userName
    })
        .done(function (data) {
            cancel();

        })
        .fail(function () {
            message({content:'Error while removing Application ', type:'error', cbk:function () {
            } });
            console.log('error');

        })
        .always(function () {
            console.log('completed');
        });

}

function isArray(element) {
    return Object.prototype.toString.call(element) === '[object Array]';
}

function cancel() {
    gadgets.Hub.publish('org.wso2.is.dashboard', {
        msg:'A message from User profile',
        id:"user_auth_apps .shrink-widget"
    });

}

function validate(appName) {
    var element = "
\n" +
        "
\n" +
        "
\n" +
        "
\n" +
        "        <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\">×</button>\n" +
        "
Modal title
\n" +
        "
\n" +
        "
\n" +
        "
One fine body…
\n" +
        "
\n" +
        "
\n" +
        "
\n" +
        "
\n" +
        "
\n" +
        "
";
    $("#message").append(element);
    itemRemoveValidate(appName);
}

function itemRemoveValidate(appName) {
    var msg = "You are about to remove " + appName + ". Do you want to proceed?";
    message({content:msg, type:'confirm', okCallback:function () {
        itemRemove(appName);
    }, cancelCallback:function () {
    }});
}

<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var path = require('path'),
    errorHandler = require(path.resolve('./modules/core/server/controllers/errors.server.controller')),
    textProcessor = require(path.resolve('./modules/core/server/controllers/text-processor.server.controller')),
    config = require(path.resolve('./config/config')),
    nodemailer = require('nodemailer'),
    validator = require('validator'),
    async = require('async');

// Replace mailer with Stub mailer transporter
// Stub transport does not send anything, it builds the mail stream into a single Buffer and returns
// it with the sendMail callback. This is useful for testing the emails before actually sending anything.
// @link https://github.com/andris9/nodemailer-stub-transport
if (process.env.NODE_ENV === 'test') {
  var stubTransport = require('nodemailer-stub-transport');
  config.mailer.options = stubTransport();
}

/**
 * Send support request to our support systems
 */
exports.supportRequest = function(req, res) {
  async.waterfall([

    // Prepare TEXT email
    function(done) {

      var renderVars = {
        message:       (req.body.message) ? textProcessor.plainText(req.body.message) : '—',
        username:      (req.user) ? req.user.username : textProcessor.plainText(req.body.username),
        email:         (req.user) ? req.user.email : textProcessor.plainText(req.body.email),
        displayName:   (req.user) ? req.user.displayName : '-',
        userId:        (req.user) ? req.user._id.toString() : '-',
        userAgent:     (req.headers['user-agent']) ? textProcessor.plainText(req.headers['user-agent']) : '—',
        authenticated: (req.user) ? 'yes' : 'no',
      };

      res.render(
        path.resolve('./modules/core/server/views/email-templates-text/support-request'),
        renderVars,
        function(err, emailPlain) {
          done(err, emailPlain, renderVars);
        });
    },

    // If valid email, send reset email using service
    function(emailPlain, renderVars, done) {
      var smtpTransport = nodemailer.createTransport(config.mailer.options);

      var fromMail = {
        // Trust registered user's email, otherwise validate it
        // Default to TO-support email
        address: (req.user || validator.isEmail(renderVars.email)) ? renderVars.email : config.supportEmail
      };

      // Add name to sender if we have it
      if(req.user) {
        fromMail.name = req.user.displayName;
      }

      var mailOptions = {
        from: fromMail,
        to: 'Trustroots <' + config.supportEmail + '>',
        subject: 'Support request',
        text: emailPlain
      };

      smtpTransport.sendMail(mailOptions, function(err) {
        smtpTransport.close(); // close the connection pool
        if (!err) {
          return res.json({message: 'Support request sent.'});
        } else {
          return res.status(400).send({
            message: 'Failure while sending your support request. Please try again.'
          });
        }
      });
    }
  ], function(err) {
    if(err) {
      console.error('Support request error:');
      console.error(err);
      return res.status(400).send({
        message: 'Failure while sending your support request. Please try again.'
      });
    }
  });
};
<commit_msg>Fix support requests "Unconfigured Sending Domain"<commit_after>'use strict';

/**
 * Module dependencies.
 */
var path = require('path'),
    errorHandler = require(path.resolve('./modules/core/server/controllers/errors.server.controller')),
    textProcessor = require(path.resolve('./modules/core/server/controllers/text-processor.server.controller')),
    config = require(path.resolve('./config/config')),
    nodemailer = require('nodemailer'),
    validator = require('validator'),
    async = require('async');

// Replace mailer with Stub mailer transporter
// Stub transport does not send anything, it builds the mail stream into a single Buffer and returns
// it with the sendMail callback. This is useful for testing the emails before actually sending anything.
// @link https://github.com/andris9/nodemailer-stub-transport
if (process.env.NODE_ENV === 'test') {
  var stubTransport = require('nodemailer-stub-transport');
  config.mailer.options = stubTransport();
}

/**
 * Send support request to our support systems
 */
exports.supportRequest = function(req, res) {
  async.waterfall([

    // Prepare TEXT email
    function(done) {

      var renderVars = {
        message:       (req.body.message) ? textProcessor.plainText(req.body.message) : '—',
        username:      (req.user) ? req.user.username : textProcessor.plainText(req.body.username),
        email:         (req.user) ? req.user.email : textProcessor.plainText(req.body.email),
        displayName:   (req.user) ? req.user.displayName : '-',
        userId:        (req.user) ? req.user._id.toString() : '-',
        userAgent:     (req.headers['user-agent']) ? textProcessor.plainText(req.headers['user-agent']) : '—',
        authenticated: (req.user) ? 'yes' : 'no',
      };

      res.render(
        path.resolve('./modules/core/server/views/email-templates-text/support-request'),
        renderVars,
        function(err, emailPlain) {
          done(err, emailPlain, renderVars);
        });
    },

    // If valid email, send reset email using service
    function(emailPlain, renderVars, done) {
      var smtpTransport = nodemailer.createTransport(config.mailer.options);

      var fromMail = {
        // Trust registered user's email, otherwise validate it
        // Default to TO-support email
        address: (req.user || validator.isEmail(renderVars.email)) ? renderVars.email : config.supportEmail
      };

      // Add name to sender if we have it
      if(req.user) {
        fromMail.name = req.user.displayName;
      }

      var mailOptions = {
        from: 'Trustroots Support <' + config.supportEmail + '>',
        to: 'Trustroots Support <' + config.supportEmail + '>',
        replyTo: fromMail,
        subject: 'Support request',
        subject: 'Support request',
        text: emailPlain
      };

      smtpTransport.sendMail(mailOptions, function(err) {
        smtpTransport.close(); // close the connection pool
        if (!err) {
          return res.json({message: 'Support request sent.'});
        } else {
          return res.status(400).send({
            message: 'Failure while sending your support request. Please try again.'
          });
        }
      });
    }
  ], function(err) {
    if(err) {
      console.error('Support request error:');
      console.error(err);
      return res.status(400).send({
        message: 'Failure while sending your support request. Please try again.'
      });
    }
  });
};
<|endoftext|>


<commit_before>import bcrypt from 'bcrypt'
import { OAuthClientName, isURL } from '../classes/Validators'

const CLIENT_SECRET_MAX_LENGTH = 1024
const MIN_SECRET_LENGTH = 32
const MAX_SECRET_LENGTH = 512

module.exports = function (sequelize, DataTypes) {
  let client = sequelize.define('Client', {
    id: {
      type: DataTypes.UUID,
      primaryKey: true,
      defaultValue: DataTypes.UUIDV4,
      validate: {
        isUUID: 4
      }
    },
    name: {
      type: DataTypes.STRING,
      allowNull: false,
      validate: {
        is: OAuthClientName
      }
    },
    secret: {
      type: DataTypes.STRING(CLIENT_SECRET_MAX_LENGTH),
      allowNull: false,
      validate: {
        len: [MIN_SECRET_LENGTH, MAX_SECRET_LENGTH]
      }
    },
    redirectUri: {
      type: DataTypes.STRING,
      allowNull: true,
      validate: {
        isURL
      }
    },
    userId: {
      type: DataTypes.UUID,
      allowNull: true,
      validate: {
        isUUID: 4
      }
    }
  })

  let hashPasswordHook = async function (instance) {
    if (!instance.changed('secret')) {
      return
    }
    let hash = await bcrypt.hash(instance.get('secret'), global.BCRYPT_ROUNDS_COUNT)
    instance.set('secret', hash)
  }
  client.beforeCreate(hashPasswordHook)
  client.beforeUpdate(hashPasswordHook)

  client.prototype.toJSON = function () {
    let values = this.get()
    delete values.secret
    return values
  }

  client.associate = function (models) {
    models.Client.belongsTo(models.User, { foreignKey: 'userId', as: 'user' })

    models.Client.addScope('defaultScope', {
      include:  [
        {
          model: models.User,
          as: 'user',
          required: true
        }
      ]
    }, {
      override: true
    })
  }

  return client
}
<commit_msg>Fix API failing to find users without registered oauth clients<commit_after>import bcrypt from 'bcrypt'
import { OAuthClientName, isURL } from '../classes/Validators'

const CLIENT_SECRET_MAX_LENGTH = 1024
const MIN_SECRET_LENGTH = 32
const MAX_SECRET_LENGTH = 512

module.exports = function (sequelize, DataTypes) {
  let client = sequelize.define('Client', {
    id: {
      type: DataTypes.UUID,
      primaryKey: true,
      defaultValue: DataTypes.UUIDV4,
      validate: {
        isUUID: 4
      }
    },
    name: {
      type: DataTypes.STRING,
      allowNull: false,
      validate: {
        is: OAuthClientName
      }
    },
    secret: {
      type: DataTypes.STRING(CLIENT_SECRET_MAX_LENGTH),
      allowNull: false,
      validate: {
        len: [MIN_SECRET_LENGTH, MAX_SECRET_LENGTH]
      }
    },
    redirectUri: {
      type: DataTypes.STRING,
      allowNull: true,
      validate: {
        isURL
      }
    },
    userId: {
      type: DataTypes.UUID,
      allowNull: true,
      validate: {
        isUUID: 4
      }
    }
  })

  let hashPasswordHook = async function (instance) {
    if (!instance.changed('secret')) {
      return
    }
    let hash = await bcrypt.hash(instance.get('secret'), global.BCRYPT_ROUNDS_COUNT)
    instance.set('secret', hash)
  }
  client.beforeCreate(hashPasswordHook)
  client.beforeUpdate(hashPasswordHook)

  client.prototype.toJSON = function () {
    let values = this.get()
    delete values.secret
    return values
  }

  client.associate = function (models) {
    models.Client.belongsTo(models.User, { foreignKey: 'userId', as: 'user' })

    models.Client.addScope('defaultScope', {
      include:  [
        {
          model: models.User,
          as: 'user',
          required: false
        }
      ]
    }, {
      override: true
    })
  }

  return client
}
<|endoftext|>


<commit_before>(function(){
  'use strict';

  angular
    .module('platanus.prettyLoad')
    .directive('prettyLoad', prettyLoad);

  /* ngInject */
  function prettyLoad() {
    var ALWAYS_CLASS = 'pretty-loader';
    var LOADING_CLASS = 'pretty-loading';
    var LOADED_CLASS = 'pretty-loaded';

    var checkLoaded = function(_image) {
      if (!_image.complete) return false;
      if (_image.naturalWidth === 0) return false;
      return true;
    };

    var monitorLoadState = function(_parent, _image) {
      var checkInterval = setInterval(function(){
        if ( checkLoaded(_image) ) {
          _parent.removeClass(LOADING_CLASS);
          _parent.addClass(LOADED_CLASS);
          clearInterval(checkInterval);
        }
      }, 200);
      _parent.addClass(LOADING_CLASS);
    };

    var setupOverlay = function(_parent) {
      var overlay = angular.element('

');
      _parent.append(overlay);

      overlay.css({
        position: 'absolute',
        backgroundColor: 'white'
      });

      return overlay;
    }

    var resizeImage = function(_image, _originalWidth, _originalHeight) {
      var ratio = _originalWidth / _originalHeight;

      if ( _image.width === 0 && _image.height === 0 ) {
        _image.width = _originalWidth;
        _image.height = _originalHeight;
      } else if ( _image.clientWidth > 0 ) {
        _image.height = _image.clientWidth / ratio;
      } else {
        _image.width = _image.clientHeight * ratio;
      }
    };

    var positionOverlay = function(_parent, _target, _overlay) {
      if(!_overlay) return;

      var parentRect = _parent.getBoundingClientRect(),
          targetRect = _target.getBoundingClientRect(),
          offsetTop = targetRect.top - parentRect.top,
          offsetLeft = targetRect.left - parentRect.left;

      _overlay.css({
        top: offsetTop + 'px',
        left: offsetLeft + 'px',
        width: _target.clientWidth + 'px',
        height: _target.clientHeight + 'px'
      });
    }

    return {
      restrict: 'A',
      scope: {
        prettyLoadWidth: '@',
        prettyLoadHeight: '@'
      },
      link: function(_scope, _element, _attributes) {
        var image = _element.find('img')[0];
        if ( !image ) return false;

        _element.addClass(ALWAYS_CLASS);

        monitorLoadState(_element, image);
        var overlay = setupOverlay(_element);

        _attributes.$observe('prettyLoadColor', function(color){
          overlay.css({
            backgroundColor: color
          });
        });

        var recalculateDimensions = function(){
          resizeImage(image, _scope.prettyLoadWidth, _scope.prettyLoadHeight);
          positionOverlay(_element[0], image, overlay);
        };

        _scope.$watch(function() {
          if ( _scope.prettyLoadWidth && _scope.prettyLoadHeight ) {
            return _scope.prettyLoadWidth / _scope.prettyLoadHeight;
          } else return 0;
        }, function(_ratio) {
          if ( _ratio == 0 ) return;
          recalculateDimensions();
        });

        window.addEventListener('resize', recalculateDimensions);

        _scope.$on('$destroy', function() {
          window.removeEventListener('resize', recalculateDimensions)
        });
      }
    }
  }

})();
<commit_msg>feat(refactor): the directive creates the wrapper<commit_after>(function(){
  'use strict';

  var INIT_CLASS = 'pretty-load-init';
  var LOADING_CLASS = 'pretty-load-loading';
  var COMPLETED_CLASS = 'pretty-load-completed';

  angular
    .module('platanus.prettyLoad')
    .directive('prettyLoad', prettyLoad);

  /* ngInject */
  function prettyLoad() {

    return {
      restrict: 'A',

      scope: {
        prettyLoadWidth: '@',
        prettyLoadHeight: '@'
      },

      link: function(_scope, _element, _attributes) {
        var settings = {
          referenceWidth: _scope.prettyLoadWidth,
          referenceHeight: _scope.prettyLoadHeight,
          referenceColor: _attributes.prettyLoadColor || "white",
          shouldSetImageWidth: _element[0].width == 0,
          shouldSetImageHeight: _element[0].height == 0
        };

        var image = _element;
        var wrapper = createWrapper(image);
        var overlay = createOverlay(wrapper, settings.referenceColor);

        setImageSize(image, settings);
        setOverlayPositionAndSize(overlay, image);

        monitorLoading(wrapper, image);
        watchResizeEvent(_scope, image, overlay, settings);
      }
    }
  }

  //// Private Methods

  function createWrapper(_image) {
    var html = "

";
    _image.wrap(html);

    var wrapper = _image.parent();

    wrapper.css({
      position: "relative"
    });

    return wrapper;
  }

  function createOverlay(_wrapper, _referenceColor) {
    var html = '

';
    var overlay = angular.element(html);

    _wrapper.append(overlay);

    overlay.css({
      position: 'absolute',
      backgroundColor: _referenceColor
    });

    return overlay;
  }

  function monitorLoading(wrapper, image) {
    setTimeout(function() {
      wrapper.addClass(LOADING_CLASS);

      whenImageIsLoaded(image, function() {
        wrapper.removeClass(LOADING_CLASS);
        wrapper.addClass(COMPLETED_CLASS);
      });
    }, 0);
  }

  function watchResizeEvent(_scope, _image, _overlay, _settings) {
    var callback = function() {
      setImageSize(_image, _settings);
      setOverlayPositionAndSize(_overlay, _image);
    }

    window.addEventListener('resize', callback);

    _scope.$on('$destroy', function() {
      window.removeEventListener('resize', callback)
    });
  }

  function setImageSize(_image, _settings) {
    var imageNode = _image[0];
    if(_settings.shouldSetImageWidth && _settings.shouldSetImageHeight) {
      imageNode.width = _settings.referenceWidth;
      imageNode.height = _settings.referenceHeight;
    }
    else {
      var ratio = _settings.referenceWidth / _settings.referenceHeight;

      if(_settings.shouldSetImageWidth)   imageNode.width = imageNode.clientHeight * ratio;
      if(_settings.shouldSetImageHeight)  imageNode.height = imageNode.clientWidth / ratio;
    }
  };

  function setOverlayPositionAndSize(_overlay, _image) {
    _overlay.css({
      top: '0px',
      left: '0px',
      width: _image[0].clientWidth + 'px',
      height: _image[0].clientHeight + 'px'
    });
  }

  function checkLoaded(_image) {
    if (!_image.complete) return false;
    if (_image.naturalWidth === 0) return false;
    return true;
  };

  function whenImageIsLoaded(_image, _callback) {
    var checkInterval = setInterval(function(){
      if ( checkLoaded(_image[0]) ) {
        clearInterval(checkInterval);
        _callback.call();
      }
    }, 200);
  };

})();
<|endoftext|>


<commit_before>import React from 'react'
import {reduxForm, Field} from 'redux-form'
import _get from 'lodash/get'
import {intlShape, FormattedRelative, FormattedMessage} from 'react-intl'

import {Button, LayoutBox} from 'tocco-ui'
import LabeledField from './LabeledField'
import ErrorBox from './ErrorBox'
import {getFieldId, selectTypes} from '../../util/detailView/helpers'
import {getForm} from '../../util/detailView/formBuilder'
import formErrorsUtil from '../../util/detailView/formErrors'

export class DetailForm extends React.Component {
  createLayoutComponent = (field, type, key, traverser) => {
    if (type === 'HorizontalBox' || type === 'VerticalBox') {
      const alignment = type === 'HorizontalBox' ? 'horizontal' : 'vertical'
      const label = field.useLabel ? field.label : undefined
      return (
        <LayoutBox key={key} label={label} alignment={alignment}>
          {traverser()}
        </LayoutBox>
      )
    }
  }

  createField = (field, key) => {
    const entityField = this.props.entity.paths[field.name]

    let fieldProps = {}

    if (selectTypes.includes(entityField.type)) {
      fieldProps.type = entityField.type === 'entity' ? 'single-select' : 'multi-select'
      const store = this.props.selectBoxStores[field.name] ? this.props.selectBoxStores[field.name].data : []
      fieldProps.options = {store}
    } else {
      fieldProps.type = entityField.value.type
    }

    const isMandatoryField = _get(this.props.entityModel, `${field.name}.validation.mandatory`, false)
    const isWritableField = _get(entityField, 'value.writable', true)

    const handleFocus = (type, fieldName) => {
      if (selectTypes.includes(type)) {
        this.props.loadRelationEntities(fieldName)
      }
    }

    return (

 (handleFocus(entityField.type, field.name))}>
        <Field
          id={getFieldId(this.props.form, field.name)}
          name={field.name}
          key={key}
          label={field.label}
          component={LabeledField}
          mandatory={isMandatoryField}
          readOnly={!isWritableField}
          {...fieldProps}
        />

    )
  }

  isEntityLoaded = () => (this.props.entity && this.props.entity.paths)

  touchFieldsWithError = () => {
    Object.keys(formErrorsUtil.getFieldErrors(this.props.formErrors)).forEach(f => this.props.touch(f))
  }

  focusErrorFields = () => {
    const firstErrorField = formErrorsUtil.getFirstErrorField(this.props.formErrors)
    if (firstErrorField) {
      document.getElementById(getFieldId(this.props.form, firstErrorField)).focus()
    }
  }

  save = () => {
    if (this.props.valid) {
      this.props.submitForm()
    } else if (this.props.formErrors) {
      this.touchFieldsWithError()
    }
  }

  handleSubmit = event => {
    event.preventDefault()
    this.save()
  }

  handleKeyPress = event => {
    console.log('event.target', event.target.tagName)
    if (event.ctrlKey && event.key === 's') {
      event.preventDefault()
      this.save()
    }

    if (event.key === 'Enter' && event.target.tagName !== 'TEXTAREA') {
      event.preventDefault()
    }
  }

  showErrors = () => {
    this.touchFieldsWithError()
    this.focusErrorFields()
  }

  msg = id => (this.props.intl.formatMessage({id}))

  render() {
    const props = this.props

    if (!this.isEntityLoaded()) {
      return

    }

    return (
      <form tabIndex="0" onSubmit={this.handleSubmit} className="form-horizontal" onKeyDown={this.handleKeyPress}>
        {getForm(props.formDefinition, this.createField, this.createLayoutComponent)}
        {!props.valid && props.anyTouched && <ErrorBox formErrors={props.formErrors} showErrors={this.showErrors}/>}
        <Button
          type="submit"
          label={this.msg('client.entity-browser.save')}
          icon="glyphicon-floppy-save"
          pending={props.submitting}
          disabled={props.submitting || (props.anyTouched && !props.valid)}
          primary
        />
        {props.lastSave
        &&

          <FormattedMessage id="client.entity-browser.lastSave"/>: <FormattedRelative value={props.lastSave}/>

        }
      </form>
    )
  }
}

DetailForm.propTypes = {
  intl: intlShape.isRequired,
  entityModel: React.PropTypes.object.isRequired,
  submitForm: React.PropTypes.func.isRequired,
  formDefinition: React.PropTypes.object.isRequired,
  entity: React.PropTypes.object.isRequired,
  loadRelationEntities: React.PropTypes.func.isRequired,
  selectBoxStores: React.PropTypes.shape({
    entityName: React.PropTypes.shape({
      loaded: React.PropTypes.bool,
      data: React.PropTypes.arrayOf(
        React.PropTypes.shape({
          value: React.PropTypes.string,
          label: React.PropTypes.string
        })
      )
    })
  }).isRequired,
  form: React.PropTypes.string.isRequired,
  touch: React.PropTypes.func.isRequired,
  submitting: React.PropTypes.bool,
  anyTouched: React.PropTypes.bool,
  formErrors: React.PropTypes.objectOf(
    React.PropTypes.objectOf(React.PropTypes.arrayOf(
      React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.object])))
  ),
  valid: React.PropTypes.bool,
  lastSave: React.PropTypes.number
}

export default reduxForm({
  form: 'detailForm',
  destroyOnUnmount: false
})(DetailForm)

<commit_msg>refactor(tocco-theme): remove console.log<commit_after>import React from 'react'
import {reduxForm, Field} from 'redux-form'
import _get from 'lodash/get'
import {intlShape, FormattedRelative, FormattedMessage} from 'react-intl'

import {Button, LayoutBox} from 'tocco-ui'
import LabeledField from './LabeledField'
import ErrorBox from './ErrorBox'
import {getFieldId, selectTypes} from '../../util/detailView/helpers'
import {getForm} from '../../util/detailView/formBuilder'
import formErrorsUtil from '../../util/detailView/formErrors'

export class DetailForm extends React.Component {
  createLayoutComponent = (field, type, key, traverser) => {
    if (type === 'HorizontalBox' || type === 'VerticalBox') {
      const alignment = type === 'HorizontalBox' ? 'horizontal' : 'vertical'
      const label = field.useLabel ? field.label : undefined
      return (
        <LayoutBox key={key} label={label} alignment={alignment}>
          {traverser()}
        </LayoutBox>
      )
    }
  }

  createField = (field, key) => {
    const entityField = this.props.entity.paths[field.name]

    let fieldProps = {}

    if (selectTypes.includes(entityField.type)) {
      fieldProps.type = entityField.type === 'entity' ? 'single-select' : 'multi-select'
      const store = this.props.selectBoxStores[field.name] ? this.props.selectBoxStores[field.name].data : []
      fieldProps.options = {store}
    } else {
      fieldProps.type = entityField.value.type
    }

    const isMandatoryField = _get(this.props.entityModel, `${field.name}.validation.mandatory`, false)
    const isWritableField = _get(entityField, 'value.writable', true)

    const handleFocus = (type, fieldName) => {
      if (selectTypes.includes(type)) {
        this.props.loadRelationEntities(fieldName)
      }
    }

    return (

 (handleFocus(entityField.type, field.name))}>
        <Field
          id={getFieldId(this.props.form, field.name)}
          name={field.name}
          key={key}
          label={field.label}
          component={LabeledField}
          mandatory={isMandatoryField}
          readOnly={!isWritableField}
          {...fieldProps}
        />

    )
  }

  isEntityLoaded = () => (this.props.entity && this.props.entity.paths)

  touchFieldsWithError = () => {
    Object.keys(formErrorsUtil.getFieldErrors(this.props.formErrors)).forEach(f => this.props.touch(f))
  }

  focusErrorFields = () => {
    const firstErrorField = formErrorsUtil.getFirstErrorField(this.props.formErrors)
    if (firstErrorField) {
      document.getElementById(getFieldId(this.props.form, firstErrorField)).focus()
    }
  }

  save = () => {
    if (this.props.valid) {
      this.props.submitForm()
    } else if (this.props.formErrors) {
      this.touchFieldsWithError()
    }
  }

  handleSubmit = event => {
    event.preventDefault()
    this.save()
  }

  handleKeyPress = event => {
    if (event.ctrlKey && event.key === 's') {
      event.preventDefault()
      this.save()
    }

    if (event.key === 'Enter' && event.target.tagName !== 'TEXTAREA') {
      event.preventDefault()
    }
  }

  showErrors = () => {
    this.touchFieldsWithError()
    this.focusErrorFields()
  }

  msg = id => (this.props.intl.formatMessage({id}))

  render() {
    const props = this.props

    if (!this.isEntityLoaded()) {
      return

    }

    return (
      <form tabIndex="0" onSubmit={this.handleSubmit} className="form-horizontal" onKeyDown={this.handleKeyPress}>
        {getForm(props.formDefinition, this.createField, this.createLayoutComponent)}
        {!props.valid && props.anyTouched && <ErrorBox formErrors={props.formErrors} showErrors={this.showErrors}/>}
        <Button
          type="submit"
          label={this.msg('client.entity-browser.save')}
          icon="glyphicon-floppy-save"
          pending={props.submitting}
          disabled={props.submitting || (props.anyTouched && !props.valid)}
          primary
        />
        {props.lastSave
        &&

          <FormattedMessage id="client.entity-browser.lastSave"/>: <FormattedRelative value={props.lastSave}/>

        }
      </form>
    )
  }
}

DetailForm.propTypes = {
  intl: intlShape.isRequired,
  entityModel: React.PropTypes.object.isRequired,
  submitForm: React.PropTypes.func.isRequired,
  formDefinition: React.PropTypes.object.isRequired,
  entity: React.PropTypes.object.isRequired,
  loadRelationEntities: React.PropTypes.func.isRequired,
  selectBoxStores: React.PropTypes.shape({
    entityName: React.PropTypes.shape({
      loaded: React.PropTypes.bool,
      data: React.PropTypes.arrayOf(
        React.PropTypes.shape({
          value: React.PropTypes.string,
          label: React.PropTypes.string
        })
      )
    })
  }).isRequired,
  form: React.PropTypes.string.isRequired,
  touch: React.PropTypes.func.isRequired,
  submitting: React.PropTypes.bool,
  anyTouched: React.PropTypes.bool,
  formErrors: React.PropTypes.objectOf(
    React.PropTypes.objectOf(React.PropTypes.arrayOf(
      React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.object])))
  ),
  valid: React.PropTypes.bool,
  lastSave: React.PropTypes.number
}

export default reduxForm({
  form: 'detailForm',
  destroyOnUnmount: false
})(DetailForm)

<|endoftext|>


<commit_before>
import { Stream } from 'most';

// domEvent :: (EventTarget t, Event e) => String -> t -> boolean=false -> Stream e
export const domEvent = (event, node, capture = false) =>
    new Stream(new DomEvent(event, node, capture));

export const blur         = (node, capture = false) => domEvent('blur', node, capture);
export const focus        = (node, capture = false) => domEvent('focus', node, capture);
export const focusin      = (node, capture = false) => domEvent('focusin', node, capture);
export const focusout     = (node, capture = false) => domEvent('focusout', node, capture);
export const click        = (node, capture = false) => domEvent('click', node, capture);
export const dblclick     = (node, capture = false) => domEvent('dblclick', node, capture);
export const mousedown    = (node, capture = false) => domEvent('mousedown', node, capture);
export const mouseup      = (node, capture = false) => domEvent('mouseup', node, capture);
export const mousemove    = (node, capture = false) => domEvent('mousemove', node, capture);
export const mouseover    = (node, capture = false) => domEvent('mouseover', node, capture);
export const mouseenter   = (node, capture = false) => domEvent('mouseenter', node, capture);
export const mouseout     = (node, capture = false) => domEvent('mouseout', node, capture);
export const mouseleave   = (node, capture = false) => domEvent('mouseleave', node, capture);
export const change       = (node, capture = false) => domEvent('change', node, capture);
export const select       = (node, capture = false) => domEvent('select', node, capture);
export const submit       = (node, capture = false) => domEvent('submit', node, capture);
export const keydown      = (node, capture = false) => domEvent('keydown', node, capture);
export const keypress     = (node, capture = false) => domEvent('keypress', node, capture);
export const keyup        = (node, capture = false) => domEvent('keyup', node, capture);
export const input        = (node, capture = false) => domEvent('input', node, capture);
export const contextmenu  = (node, capture = false) => domEvent('contextmenu', node, capture);
export const resize       = (node, capture = false) => domEvent('resize', node, capture);
export const scroll       = (node, capture = false) => domEvent('scroll', node, capture);
export const error        = (node, capture = false) => domEvent('error', node, capture);

export const hashchange   = (node, capture = false) => domEvent('hashchange', node, capture);
export const popstate     = (node, capture = false) => domEvent('popstate', node, capture);
export const load         = (node, capture = false) => domEvent('load', node, capture);
export const unload       = (node, capture = false) => domEvent('unload', node, capture);

export const pointerdown  = (node, capture = false) => domEvent('pointerdown', node, capture);
export const pointerup    = (node, capture = false) => domEvent('pointerup', node, capture);
export const pointermove  = (node, capture = false) => domEvent('pointermove', node, capture);
export const pointerover  = (node, capture = false) => domEvent('pointerover', node, capture);
export const pointerenter = (node, capture = false) => domEvent('pointerenter', node, capture);
export const pointerout   = (node, capture = false) => domEvent('pointerout', node, capture);
export const pointerleave = (node, capture = false) => domEvent('pointerleave', node, capture);

export const touchstart   = (node, capture = false) => domEvent('touchstart', node, capture);
export const touchend     = (node, capture = false) => domEvent('touchend', node, capture);
export const touchmove    = (node, capture = false) => domEvent('touchmove', node, capture);
export const touchcancel  = (node, capture = false) => domEvent('touchcancel', node, capture);

class DomEvent {
    constructor(event, node, capture) {
        this.event = event;
        this.node = node;
        this.capture = capture;
    }

    run(sink, scheduler) {
        const send = e => tryEvent(scheduler.now(), e, sink);
        const dispose = () => this.node.removeEventListener(this.event, send, this.capture);

        this.node.addEventListener(this.event, send, this.capture);

        return { dispose };
    }
}

function tryEvent(t, x, sink) {
    try {
        sink.event(t, x);
    } catch (e) {
        sink.error(t, e);
    }
}
<commit_msg>Add copyright<commit_after>/** @license MIT License (c) copyright 2015-2016 original author or authors */
/** @author Brian Cavalier */
'use strict';

import { Stream } from 'most';

// domEvent :: (EventTarget t, Event e) => String -> t -> boolean=false -> Stream e
export const domEvent = (event, node, capture = false) =>
    new Stream(new DomEvent(event, node, capture));

export const blur         = (node, capture = false) => domEvent('blur', node, capture);
export const focus        = (node, capture = false) => domEvent('focus', node, capture);
export const focusin      = (node, capture = false) => domEvent('focusin', node, capture);
export const focusout     = (node, capture = false) => domEvent('focusout', node, capture);
export const click        = (node, capture = false) => domEvent('click', node, capture);
export const dblclick     = (node, capture = false) => domEvent('dblclick', node, capture);
export const mousedown    = (node, capture = false) => domEvent('mousedown', node, capture);
export const mouseup      = (node, capture = false) => domEvent('mouseup', node, capture);
export const mousemove    = (node, capture = false) => domEvent('mousemove', node, capture);
export const mouseover    = (node, capture = false) => domEvent('mouseover', node, capture);
export const mouseenter   = (node, capture = false) => domEvent('mouseenter', node, capture);
export const mouseout     = (node, capture = false) => domEvent('mouseout', node, capture);
export const mouseleave   = (node, capture = false) => domEvent('mouseleave', node, capture);
export const change       = (node, capture = false) => domEvent('change', node, capture);
export const select       = (node, capture = false) => domEvent('select', node, capture);
export const submit       = (node, capture = false) => domEvent('submit', node, capture);
export const keydown      = (node, capture = false) => domEvent('keydown', node, capture);
export const keypress     = (node, capture = false) => domEvent('keypress', node, capture);
export const keyup        = (node, capture = false) => domEvent('keyup', node, capture);
export const input        = (node, capture = false) => domEvent('input', node, capture);
export const contextmenu  = (node, capture = false) => domEvent('contextmenu', node, capture);
export const resize       = (node, capture = false) => domEvent('resize', node, capture);
export const scroll       = (node, capture = false) => domEvent('scroll', node, capture);
export const error        = (node, capture = false) => domEvent('error', node, capture);

export const hashchange   = (node, capture = false) => domEvent('hashchange', node, capture);
export const popstate     = (node, capture = false) => domEvent('popstate', node, capture);
export const load         = (node, capture = false) => domEvent('load', node, capture);
export const unload       = (node, capture = false) => domEvent('unload', node, capture);

export const pointerdown  = (node, capture = false) => domEvent('pointerdown', node, capture);
export const pointerup    = (node, capture = false) => domEvent('pointerup', node, capture);
export const pointermove  = (node, capture = false) => domEvent('pointermove', node, capture);
export const pointerover  = (node, capture = false) => domEvent('pointerover', node, capture);
export const pointerenter = (node, capture = false) => domEvent('pointerenter', node, capture);
export const pointerout   = (node, capture = false) => domEvent('pointerout', node, capture);
export const pointerleave = (node, capture = false) => domEvent('pointerleave', node, capture);

export const touchstart   = (node, capture = false) => domEvent('touchstart', node, capture);
export const touchend     = (node, capture = false) => domEvent('touchend', node, capture);
export const touchmove    = (node, capture = false) => domEvent('touchmove', node, capture);
export const touchcancel  = (node, capture = false) => domEvent('touchcancel', node, capture);

class DomEvent {
    constructor(event, node, capture) {
        this.event = event;
        this.node = node;
        this.capture = capture;
    }

    run(sink, scheduler) {
        const send = e => tryEvent(scheduler.now(), e, sink);
        const dispose = () => this.node.removeEventListener(this.event, send, this.capture);

        this.node.addEventListener(this.event, send, this.capture);

        return { dispose };
    }
}

function tryEvent(t, x, sink) {
    try {
        sink.event(t, x);
    } catch (e) {
        sink.error(t, e);
    }
}
<|endoftext|>


<commit_before>import { ATTR_KEY, EMPTY } from '../constants';
import { hasOwnProperty, memoize } from '../util';
import { optionsHook } from '../hooks';

export function ensureNodeData(node) {
	return node[ATTR_KEY] || (node[ATTR_KEY] = {});
}

/** Append multiple children to a Node.
 *	Uses a Document Fragment to batch when appending 2 or more children
 *	@private
 */
export function appendChildren(parent, children) {
	let len = children.length,
		many = len>2,
		into = many ? document.createDocumentFragment() : parent;
	for (let i=0; i<len; i++) into.appendChild(children[i]);
	if (many) parent.appendChild(into);
}

/** Retrieve the value of a rendered attribute
 *	@private
 */
export function getAccessor(node, name, value, cache) {
	if (name!=='type' && name!=='style' && name in node) return node[name];
	let attrs = node[ATTR_KEY];
	if (cache!==false && attrs && hasOwnProperty.call(attrs, name)) return attrs[name];
	if (name==='class') return node.className;
	if (name==='style') return node.style.cssText;
	return value;
}

/** Set a named attribute on the given Node, with special behavior for some names and event handlers.
 *	If `value` is `null`, the attribute/handler will be removed.
 *	@param {Element} node	An element to mutate
 *	@param {string} name	The name/key to set, such as an event or attribute name
 *	@param {any} value		An attribute value, such as a function to be used as an event handler
 *	@param {any} previousValue	The last value that was set for this name/node pair
 *	@private
 */
export function setAccessor(node, name, value) {
	if (name==='class') {
		node.className = value;
	}
	else if (name==='style') {
		node.style.cssText = value;
	}
	else if (name==='dangerouslySetInnerHTML') {
		node.innerHTML = value.__html;
	}
	else if (name==='key' || (name in node && name!=='type')) {
		node[name] = value;
	}
	else {
		setComplexAccessor(node, name, value);
	}

	ensureNodeData(node)[name] = value;
}

/** For props without explicit behavior, apply to a Node as event handlers or attributes.
 *	@private
 */
function setComplexAccessor(node, name, value) {
	if (name.substring(0,2)==='on') {
		let type = normalizeEventName(name),
			l = node._listeners || (node._listeners = {}),
			fn = !l[type] ? 'add' : !value ? 'remove' : null;
		if (fn) node[fn+'EventListener'](type, eventProxy);
		l[type] = value;
		return;
	}

	let type = typeof value;
	if (value===null) {
		node.removeAttribute(name);
	}
	else if (type!=='function' && type!=='object') {
		node.setAttribute(name, value);
	}
}

/** Proxy an event to hooked event handlers
 *	@private
 */
function eventProxy(e) {
	let fn = this._listeners[normalizeEventName(e.type)];
	if (fn) return fn.call(this, optionsHook('event', e) || e);
}

/** Convert an Event name/type to lowercase and strip any "on*" prefix.
 *	@function
 *	@private
 */
let normalizeEventName = memoize(t => t.replace(/^on/i,'').toLowerCase());

/** Get a hashmap of node properties, preferring preact's cached property values over the DOM's
 *	@private
 */
export function getNodeAttributes(node) {
	return node[ATTR_KEY] || getRawNodeAttributes(node) || EMPTY;
	// let list = getRawNodeAttributes(node),
	// 	l = node[ATTR_KEY];
	// return l && list ? extend(list, l) : (l || list || EMPTY);
}

/** Get a node's attributes as a hashmap, regardless of type.
 *	@private
 */
function getRawNodeAttributes(node) {
	let list = node.attributes;
	if (!list || !list.getNamedItem) return list;
	if (list.length) return getAttributesAsObject(list);
}

/** Convert a DOM `.attributes` NamedNodeMap to a hashmap.
 *	@private
 */
function getAttributesAsObject(list) {
	let attrs;
	for (let i=list.length; i--; ) {
		let item = list[i];
		if (!attrs) attrs = {};
		attrs[item.name] = item.value;
	}
	return attrs;
}
<commit_msg>Coerce falsey `className` and `style` values to an empty string to avoid `class="null"` and `style="null"`.<commit_after>import { ATTR_KEY, EMPTY } from '../constants';
import { hasOwnProperty, memoize } from '../util';
import { optionsHook } from '../hooks';

export function ensureNodeData(node) {
	return node[ATTR_KEY] || (node[ATTR_KEY] = {});
}

/** Append multiple children to a Node.
 *	Uses a Document Fragment to batch when appending 2 or more children
 *	@private
 */
export function appendChildren(parent, children) {
	let len = children.length,
		many = len>2,
		into = many ? document.createDocumentFragment() : parent;
	for (let i=0; i<len; i++) into.appendChild(children[i]);
	if (many) parent.appendChild(into);
}

/** Retrieve the value of a rendered attribute
 *	@private
 */
export function getAccessor(node, name, value, cache) {
	if (name!=='type' && name!=='style' && name in node) return node[name];
	let attrs = node[ATTR_KEY];
	if (cache!==false && attrs && hasOwnProperty.call(attrs, name)) return attrs[name];
	if (name==='class') return node.className;
	if (name==='style') return node.style.cssText;
	return value;
}

/** Set a named attribute on the given Node, with special behavior for some names and event handlers.
 *	If `value` is `null`, the attribute/handler will be removed.
 *	@param {Element} node	An element to mutate
 *	@param {string} name	The name/key to set, such as an event or attribute name
 *	@param {any} value		An attribute value, such as a function to be used as an event handler
 *	@param {any} previousValue	The last value that was set for this name/node pair
 *	@private
 */
export function setAccessor(node, name, value) {
	if (name==='class') {
		node.className = value || '';
	}
	else if (name==='style') {
		node.style.cssText = value || '';
	}
	else if (name==='dangerouslySetInnerHTML') {
		node.innerHTML = value.__html;
	}
	else if (name==='key' || (name in node && name!=='type')) {
		node[name] = value;
	}
	else {
		setComplexAccessor(node, name, value);
	}

	ensureNodeData(node)[name] = value;
}

/** For props without explicit behavior, apply to a Node as event handlers or attributes.
 *	@private
 */
function setComplexAccessor(node, name, value) {
	if (name.substring(0,2)==='on') {
		let type = normalizeEventName(name),
			l = node._listeners || (node._listeners = {}),
			fn = !l[type] ? 'add' : !value ? 'remove' : null;
		if (fn) node[fn+'EventListener'](type, eventProxy);
		l[type] = value;
		return;
	}

	let type = typeof value;
	if (value===null) {
		node.removeAttribute(name);
	}
	else if (type!=='function' && type!=='object') {
		node.setAttribute(name, value);
	}
}

/** Proxy an event to hooked event handlers
 *	@private
 */
function eventProxy(e) {
	let fn = this._listeners[normalizeEventName(e.type)];
	if (fn) return fn.call(this, optionsHook('event', e) || e);
}

/** Convert an Event name/type to lowercase and strip any "on*" prefix.
 *	@function
 *	@private
 */
let normalizeEventName = memoize(t => t.replace(/^on/i,'').toLowerCase());

/** Get a hashmap of node properties, preferring preact's cached property values over the DOM's
 *	@private
 */
export function getNodeAttributes(node) {
	return node[ATTR_KEY] || getRawNodeAttributes(node) || EMPTY;
	// let list = getRawNodeAttributes(node),
	// 	l = node[ATTR_KEY];
	// return l && list ? extend(list, l) : (l || list || EMPTY);
}

/** Get a node's attributes as a hashmap, regardless of type.
 *	@private
 */
function getRawNodeAttributes(node) {
	let list = node.attributes;
	if (!list || !list.getNamedItem) return list;
	if (list.length) return getAttributesAsObject(list);
}

/** Convert a DOM `.attributes` NamedNodeMap to a hashmap.
 *	@private
 */
function getAttributesAsObject(list) {
	let attrs;
	for (let i=list.length; i--; ) {
		let item = list[i];
		if (!attrs) attrs = {};
		attrs[item.name] = item.value;
	}
	return attrs;
}
<|endoftext|>


<commit_before>import fs from 'fs';
import os from 'os';
import path from 'path';
import readline from 'readline';
import { performance } from 'perf_hooks';

import JSDOMDomProvider from './JSDOMDomProvider';
import Logger from './Logger';
import MultipleErrors from './MultipleErrors';
import constructReport from './constructReport';
import createStaticPackage from './createStaticPackage';
import createDynamicEntryPoint from './createDynamicEntryPoint';
import createWebpackBundle from './createWebpackBundle';
import loadCSSFile from './loadCSSFile';
import prepareAssetsPackage from './prepareAssetsPackage';
import processSnapsInBundle from './processSnapsInBundle';

const { VERBOSE = 'false' } = process.env;

function logTargetResults({ name, globalCSS, snapPayloads }) {
  const cssPath = path.join(os.tmpdir(), `happo-verbose-${name}.css`);
  const snippetsPath = path.join(os.tmpdir(), `happo-snippets-${name}.json`);
  fs.writeFileSync(cssPath, JSON.stringify(globalCSS));
  fs.writeFileSync(snippetsPath, JSON.stringify(snapPayloads));
  console.log(`Recorded CSS for target "${name}" can be found in ${cssPath}`);
  console.log(
    `Recorded HTML snippets for target "${name}" can be found in ${snippetsPath}`,
  );
}

function waitForAnyKey() {
  readline.emitKeypressEvents(process.stdin);
  process.stdin.setRawMode(true);
  process.stdin.resume();

  return new Promise((resolve) => {
    process.stdin.once('keypress', (_, key) => {
      if (key.ctrl && key.name === 'c') {
        process.exit();
      } else {
        process.stdin.setRawMode(false);
        process.stdin.pause();
        resolve();
      }
    });
  });
}

function resolveDomProvider({ plugins, jsdomOptions }) {
  const pluginWithProvider = plugins.find(({ DomProvider }) => !!DomProvider);
  if (pluginWithProvider) {
    return pluginWithProvider.DomProvider;
  }
  return JSDOMDomProvider.bind(JSDOMDomProvider, jsdomOptions);
}

async function executeTargetWithPrerender({
  name,
  targets,
  css,
  snapPayloads,
  publicFolders,
  cssBlocks,
  apiKey,
  apiSecret,
  endpoint,
  isAsync,
}) {
  if (!snapPayloads.length) {
    console.warn(`No examples found for target ${name}, skipping`);
    return [];
  }
  const errors = snapPayloads.filter((p) => p.isError);
  if (errors.length === 1) {
    throw errors[0];
  }
  if (errors.length > 1) {
    throw new MultipleErrors(errors);
  }

  const globalCSS = cssBlocks.concat([{ css }]);

  if (VERBOSE === 'true') {
    logTargetResults({ name, globalCSS, snapPayloads });
  }

  const assetsPackage = await prepareAssetsPackage({
    globalCSS,
    snapPayloads,
    publicFolders,
  });
  snapPayloads.forEach((item) => {
    delete item.assetPaths;
  });

  const result = await targets[name].execute({
    asyncResults: isAsync,
    targetName: name,
    assetsPackage,
    globalCSS,
    snapPayloads,
    apiKey,
    apiSecret,
    endpoint,
  });
  return result;
}

async function generateScreenshots(
  {
    apiKey,
    apiSecret,
    stylesheets,
    endpoint,
    targets,
    publicFolders,
    jsdomOptions,
    plugins,
    prerender,
    tmpdir,
    isAsync,
  },
  bundleFile,
  logger,
) {
  const cssBlocks = await Promise.all(
    stylesheets.map(async (sheet) => {
      const { source, id, conditional } =
        typeof sheet === 'string' ? { source: sheet } : sheet;
      const result = {
        source,
        css: await loadCSSFile(source),
      };
      if (id) result.id = id;
      if (conditional) result.conditional = conditional;
      return result;
    }),
  );
  plugins.forEach(({ css }) => {
    if (css) {
      cssBlocks.push({ css });
    }
  });

  const targetNames = Object.keys(targets);
  const tl = targetNames.length;
  const DomProvider = resolveDomProvider({ plugins, jsdomOptions });
  logger.info(`Generating screenshots in ${tl} target${tl > 1 ? 's' : ''}...`);
  try {
    const staticPackage = prerender
      ? undefined
      : await createStaticPackage({
        tmpdir,
        publicFolders,
      });

    let results;
    if (prerender) {
      const processedSnaps = {};
      for (const name of targetNames) {
        // These tasks are CPU-bound, and we need to be careful about how much
        // memory we are using at one time, so we want to run them serially.
        // eslint-disable-next-line no-await-in-loop
        const { css, snapPayloads } = await processSnapsInBundle(bundleFile, {
          targetName: name,
          publicFolders,
          viewport: targets[name].viewport,
          DomProvider,
        });
        processedSnaps[name] = { css, snapPayloads };
      }

      results = await Promise.all(
        targetNames.map(async (name) => {
          const startTime = performance.now();
          const { css, snapPayloads } = processedSnaps[name];
          const result = await executeTargetWithPrerender({
            name,
            css,
            snapPayloads,
            targets,
            publicFolders,
            viewport: targets[name].viewport,
            cssBlocks,
            apiKey,
            apiSecret,
            endpoint,
            logger,
            isAsync,
          });
          logger.start(`  - ${name}`, { startTime });
          logger.success();
          return { name, result };
        }),
      );
    } else {
      results = await Promise.all(
        targetNames.map(async (name) => {
          const startTime = performance.now();
          const result = await targets[name].execute({
            asyncResults: isAsync,
            targetName: name,
            staticPackage,
            globalCSS: cssBlocks,
            apiKey,
            apiSecret,
            endpoint,
          });
          logger.start(`  - ${name}`, { startTime });
          logger.success();
          return { name, result };
        }),
      );
    }
    if (isAsync) {
      return results;
    }
    return constructReport(results);
  } catch (e) {
    logger.fail();
    throw e;
  }
}

export default async function domRunner(
  {
    apiKey,
    apiSecret,
    setupScript,
    customizeWebpackConfig,
    stylesheets,
    include,
    endpoint,
    targets,
    publicFolders,
    rootElementSelector,
    renderWrapperModule,
    prerender,
    type,
    plugins,
    tmpdir,
    jsdomOptions,
    asyncTimeout,
  },
  { only, isAsync, onReady },
) {
  const boundGenerateScreenshots = generateScreenshots.bind(null, {
    apiKey,
    apiSecret,
    stylesheets,
    endpoint,
    targets,
    publicFolders,
    prerender,
    only,
    isAsync,
    jsdomOptions,
    plugins,
    tmpdir,
  });
  const logger = new Logger();
  logger.start('Searching for happo test files...');
  let entryFile;
  try {
    const entryPointResult = await createDynamicEntryPoint({
      setupScript,
      include,
      only,
      type,
      plugins,
      tmpdir,
      rootElementSelector,
      renderWrapperModule,
      asyncTimeout,
    });
    entryFile = entryPointResult.entryFile;
    logger.success(`${entryPointResult.numberOfFilesProcessed} found`);
  } catch (e) {
    logger.fail(e);
    throw e;
  }

  const debugIndexHtml = fs.readFileSync(path.resolve(__dirname, 'debug.html'));
  fs.writeFileSync(path.resolve(tmpdir, 'index.html'), debugIndexHtml);

  logger.start('Creating bundle...');

  if (onReady) {
    let currentBuildPromise;
    let currentLogger;
    let currentWaitPromise;
    // We're in dev/watch mode
    createWebpackBundle(
      entryFile,
      { type, customizeWebpackConfig, plugins, tmpdir },
      {
        onBuildReady: async (bundleFile) => {
          if (currentBuildPromise) {
            currentBuildPromise.cancelled = true;
            currentLogger.mute();
            if (currentWaitPromise) {
              currentWaitPromise.cancelled = true;
            } else {
              logger.divider();
              logger.info('Changes detected. Press any key to continue.');
            }
            const waitPromise = waitForAnyKey();
            currentWaitPromise = waitPromise;
            await waitPromise;
            if (waitPromise.cancelled) {
              return;
            }
            logger.divider();
          } else {
            logger.success();
          }
          currentWaitPromise = undefined;
          const mutableLogger = new Logger();
          const buildPromise = boundGenerateScreenshots(bundleFile, mutableLogger);
          currentLogger = mutableLogger;
          currentBuildPromise = buildPromise;
          try {
            const report = await buildPromise;
            if (!buildPromise.cancelled) {
              onReady(report);
            }
          } catch (e) {
            logger.error(e);
          }
        },
      },
    );
    return;
  }

  const bundleFile = await createWebpackBundle(
    entryFile,
    { type, customizeWebpackConfig, plugins, tmpdir },
    {},
  );
  logger.success();
  return boundGenerateScreenshots(bundleFile, logger);
}
<commit_msg>Send pre-rendered payloads to happo.io earlier<commit_after>import fs from 'fs';
import os from 'os';
import path from 'path';
import readline from 'readline';
import { performance } from 'perf_hooks';

import JSDOMDomProvider from './JSDOMDomProvider';
import Logger from './Logger';
import MultipleErrors from './MultipleErrors';
import constructReport from './constructReport';
import createStaticPackage from './createStaticPackage';
import createDynamicEntryPoint from './createDynamicEntryPoint';
import createWebpackBundle from './createWebpackBundle';
import loadCSSFile from './loadCSSFile';
import prepareAssetsPackage from './prepareAssetsPackage';
import processSnapsInBundle from './processSnapsInBundle';

const { VERBOSE = 'false' } = process.env;

function logTargetResults({ name, globalCSS, snapPayloads }) {
  const cssPath = path.join(os.tmpdir(), `happo-verbose-${name}.css`);
  const snippetsPath = path.join(os.tmpdir(), `happo-snippets-${name}.json`);
  fs.writeFileSync(cssPath, JSON.stringify(globalCSS));
  fs.writeFileSync(snippetsPath, JSON.stringify(snapPayloads));
  console.log(`Recorded CSS for target "${name}" can be found in ${cssPath}`);
  console.log(
    `Recorded HTML snippets for target "${name}" can be found in ${snippetsPath}`,
  );
}

function waitForAnyKey() {
  readline.emitKeypressEvents(process.stdin);
  process.stdin.setRawMode(true);
  process.stdin.resume();

  return new Promise((resolve) => {
    process.stdin.once('keypress', (_, key) => {
      if (key.ctrl && key.name === 'c') {
        process.exit();
      } else {
        process.stdin.setRawMode(false);
        process.stdin.pause();
        resolve();
      }
    });
  });
}

function resolveDomProvider({ plugins, jsdomOptions }) {
  const pluginWithProvider = plugins.find(({ DomProvider }) => !!DomProvider);
  if (pluginWithProvider) {
    return pluginWithProvider.DomProvider;
  }
  return JSDOMDomProvider.bind(JSDOMDomProvider, jsdomOptions);
}

async function executeTargetWithPrerender({
  name,
  targets,
  css,
  snapPayloads,
  publicFolders,
  cssBlocks,
  apiKey,
  apiSecret,
  endpoint,
  isAsync,
}) {
  if (!snapPayloads.length) {
    console.warn(`No examples found for target ${name}, skipping`);
    return [];
  }
  const errors = snapPayloads.filter((p) => p.isError);
  if (errors.length === 1) {
    throw errors[0];
  }
  if (errors.length > 1) {
    throw new MultipleErrors(errors);
  }

  const globalCSS = cssBlocks.concat([{ css }]);

  if (VERBOSE === 'true') {
    logTargetResults({ name, globalCSS, snapPayloads });
  }

  const assetsPackage = await prepareAssetsPackage({
    globalCSS,
    snapPayloads,
    publicFolders,
  });
  snapPayloads.forEach((item) => {
    delete item.assetPaths;
  });

  const result = await targets[name].execute({
    asyncResults: isAsync,
    targetName: name,
    assetsPackage,
    globalCSS,
    snapPayloads,
    apiKey,
    apiSecret,
    endpoint,
  });
  return result;
}

async function generateScreenshots(
  {
    apiKey,
    apiSecret,
    stylesheets,
    endpoint,
    targets,
    publicFolders,
    jsdomOptions,
    plugins,
    prerender,
    tmpdir,
    isAsync,
  },
  bundleFile,
  logger,
) {
  const cssBlocks = await Promise.all(
    stylesheets.map(async (sheet) => {
      const { source, id, conditional } =
        typeof sheet === 'string' ? { source: sheet } : sheet;
      const result = {
        source,
        css: await loadCSSFile(source),
      };
      if (id) result.id = id;
      if (conditional) result.conditional = conditional;
      return result;
    }),
  );
  plugins.forEach(({ css }) => {
    if (css) {
      cssBlocks.push({ css });
    }
  });

  const targetNames = Object.keys(targets);
  const tl = targetNames.length;
  const DomProvider = resolveDomProvider({ plugins, jsdomOptions });
  logger.info(`Generating screenshots in ${tl} target${tl > 1 ? 's' : ''}...`);
  try {
    const staticPackage = prerender
      ? undefined
      : await createStaticPackage({
        tmpdir,
        publicFolders,
      });

    let results;
    if (prerender) {
      const prerenderPromises = [];
      for (const name of targetNames) {
        // These tasks are CPU-bound, and we need to be careful about how much
        // memory we are using at one time, so we want to run them serially.
        // eslint-disable-next-line no-await-in-loop
        const { css, snapPayloads } = await processSnapsInBundle(bundleFile, {
          targetName: name,
          publicFolders,
          viewport: targets[name].viewport,
          DomProvider,
        });
        prerenderPromises.push((async () => {
          const startTime = performance.now();
          const result = await executeTargetWithPrerender({
            name,
            css,
            snapPayloads,
            targets,
            publicFolders,
            viewport: targets[name].viewport,
            cssBlocks,
            apiKey,
            apiSecret,
            endpoint,
            logger,
            isAsync,
          });
          logger.start(`  - ${name}`, { startTime });
          logger.success();
          return { name, result };
        })());
      }

      results = await Promise.all(prerenderPromises);
    } else {
      results = await Promise.all(
        targetNames.map(async (name) => {
          const startTime = performance.now();
          const result = await targets[name].execute({
            asyncResults: isAsync,
            targetName: name,
            staticPackage,
            globalCSS: cssBlocks,
            apiKey,
            apiSecret,
            endpoint,
          });
          logger.start(`  - ${name}`, { startTime });
          logger.success();
          return { name, result };
        }),
      );
    }
    if (isAsync) {
      return results;
    }
    return constructReport(results);
  } catch (e) {
    logger.fail();
    throw e;
  }
}

export default async function domRunner(
  {
    apiKey,
    apiSecret,
    setupScript,
    customizeWebpackConfig,
    stylesheets,
    include,
    endpoint,
    targets,
    publicFolders,
    rootElementSelector,
    renderWrapperModule,
    prerender,
    type,
    plugins,
    tmpdir,
    jsdomOptions,
    asyncTimeout,
  },
  { only, isAsync, onReady },
) {
  const boundGenerateScreenshots = generateScreenshots.bind(null, {
    apiKey,
    apiSecret,
    stylesheets,
    endpoint,
    targets,
    publicFolders,
    prerender,
    only,
    isAsync,
    jsdomOptions,
    plugins,
    tmpdir,
  });
  const logger = new Logger();
  logger.start('Searching for happo test files...');
  let entryFile;
  try {
    const entryPointResult = await createDynamicEntryPoint({
      setupScript,
      include,
      only,
      type,
      plugins,
      tmpdir,
      rootElementSelector,
      renderWrapperModule,
      asyncTimeout,
    });
    entryFile = entryPointResult.entryFile;
    logger.success(`${entryPointResult.numberOfFilesProcessed} found`);
  } catch (e) {
    logger.fail(e);
    throw e;
  }

  const debugIndexHtml = fs.readFileSync(path.resolve(__dirname, 'debug.html'));
  fs.writeFileSync(path.resolve(tmpdir, 'index.html'), debugIndexHtml);

  logger.start('Creating bundle...');

  if (onReady) {
    let currentBuildPromise;
    let currentLogger;
    let currentWaitPromise;
    // We're in dev/watch mode
    createWebpackBundle(
      entryFile,
      { type, customizeWebpackConfig, plugins, tmpdir },
      {
        onBuildReady: async (bundleFile) => {
          if (currentBuildPromise) {
            currentBuildPromise.cancelled = true;
            currentLogger.mute();
            if (currentWaitPromise) {
              currentWaitPromise.cancelled = true;
            } else {
              logger.divider();
              logger.info('Changes detected. Press any key to continue.');
            }
            const waitPromise = waitForAnyKey();
            currentWaitPromise = waitPromise;
            await waitPromise;
            if (waitPromise.cancelled) {
              return;
            }
            logger.divider();
          } else {
            logger.success();
          }
          currentWaitPromise = undefined;
          const mutableLogger = new Logger();
          const buildPromise = boundGenerateScreenshots(bundleFile, mutableLogger);
          currentLogger = mutableLogger;
          currentBuildPromise = buildPromise;
          try {
            const report = await buildPromise;
            if (!buildPromise.cancelled) {
              onReady(report);
            }
          } catch (e) {
            logger.error(e);
          }
        },
      },
    );
    return;
  }

  const bundleFile = await createWebpackBundle(
    entryFile,
    { type, customizeWebpackConfig, plugins, tmpdir },
    {},
  );
  logger.success();
  return boundGenerateScreenshots(bundleFile, logger);
}
<|endoftext|>


<commit_before>var React = require('react');
var f1Chief = require('f1/chief');
var merge = require('deep-extend');

const TARGET_PROP_NAME = 'data-f1';

class Chief extends React.Component {

  constructor(props) {
    super(props);

    this.handleUpdate = this.handleUpdate.bind(this);
    this.handleTargetInState = this.handleTargetInState.bind(this);

    this.state = {};
    this.chiefTargets = {};
  }

  componentWillMount() {

    var chief = f1Chief({
      transitions: this.props.transitions,
      states: this.props.states,
      onUpdate: this.handleUpdate
    });

    this.setState({
      chief: chief
    });
  }

  handleUpdate(state) {

    // added this check just to ensure kimi doesnt throw one final update
    if(this.isMounted()) {
      this.setState({
        chiefState: state
      });
    }
  }

  handleTargetInState() {
    this.countTargetsIn++;

    if(this.countTargetsIn === this.countTargets) {
      this.props.onComplete();
    }
  }

  componentDidMount() {
    this.state.chief.targets(this.chiefTargets);

    this.setState({
      chief: this.state.chief
    });

    this.state.chief.init(this.props.state);
  }

  componentWillReceiveProps(nextProps) {

    if(
      nextProps.state &&
      (this.state.propsState !== nextProps.state || this.state.propsOnComplete !== nextProps.onComplete)
    ) {
      this.state.chief.go(nextProps.state, nextProps.onComplete);

      this.countTargetsIn = 0;
      this.countTargets = Object.keys(nextProps.states[nextProps.state]).length;

      this.setState({
        propsState: nextProps.state,
        propsOnComplete: nextProps.onComplete
      })
    }
  }

  getChildrenWithTargetName(chiefState) {
    return React.Children.map(this.props.children, (child) => {

      var f1Target = child.props[ TARGET_PROP_NAME ];
      var childProps = merge(
        {},
        child.props,
        {
          state: chiefState[ f1Target ],
          onComplete: this.handleTargetInState
        }
      );

      if(f1Target) {
        return React.cloneElement(
          child,
          childProps
        );
      } else {
        return child;
      }
    });
  }

  getChildrenFromFunction(chiefState) {
    var state = {};

    for(var i in chiefState) {
      state[ i ] = {
        state: chiefState[ i ],
        onComplete: this.handleTargetInState
      };
    }

    return this.props.children(state);
  }

  render() {

    var chiefState = this.state.chiefState;
    var children;

    if(chiefState) {

      if(typeof this.props.children === 'function') {
        children = this.getChildrenFromFunction(chiefState);
      } else {
        children = this.getChildrenWithTargetName(chiefState);
      }
    } else {
      children = this.props.children;
    }

    return <div
      {...this.props}
    >
      { children }
    </div>;
  }
};

Chief.defaultProps = {
  onComplete: function() {}
};

module.exports = Chief;<commit_msg>Added a destroy function to Chief<commit_after>var React = require('react');
var f1Chief = require('f1/chief');
var merge = require('deep-extend');

const TARGET_PROP_NAME = 'data-f1';

class Chief extends React.Component {

  constructor(props) {
    super(props);

    this.handleUpdate = this.handleUpdate.bind(this);
    this.handleTargetInState = this.handleTargetInState.bind(this);

    this.state = {};
    this.chiefTargets = {};
  }

  componentWillMount() {

    var chief = f1Chief({
      transitions: this.props.transitions,
      states: this.props.states,
      onUpdate: this.handleUpdate
    });

    this.setState({
      chief: chief
    });
  }

  componentWillUnMount() {
    if(this.state.chief) {
      this.state.chief.destroy();
    }
  }

  handleUpdate(state) {
    this.setState({
      chiefState: state
    });
  }

  handleTargetInState() {
    this.countTargetsIn++;

    if(this.countTargetsIn === this.countTargets) {
      this.props.onComplete();
    }
  }

  componentDidMount() {
    this.state.chief.targets(this.chiefTargets);

    this.setState({
      chief: this.state.chief
    });

    this.state.chief.init(this.props.state);
  }

  componentWillReceiveProps(nextProps) {

    if(
      nextProps.state &&
      (this.state.propsState !== nextProps.state || this.state.propsOnComplete !== nextProps.onComplete)
    ) {
      this.state.chief.go(nextProps.state, nextProps.onComplete);

      this.countTargetsIn = 0;
      this.countTargets = Object.keys(nextProps.states[nextProps.state]).length;

      this.setState({
        propsState: nextProps.state,
        propsOnComplete: nextProps.onComplete
      })
    }
  }

  getChildrenWithTargetName(chiefState) {
    return React.Children.map(this.props.children, (child) => {

      var f1Target = child.props[ TARGET_PROP_NAME ];
      var childProps = merge(
        {},
        child.props,
        {
          state: chiefState[ f1Target ],
          onComplete: this.handleTargetInState
        }
      );

      if(f1Target) {
        return React.cloneElement(
          child,
          childProps
        );
      } else {
        return child;
      }
    });
  }

  getChildrenFromFunction(chiefState) {
    var state = {};

    for(var i in chiefState) {
      state[ i ] = {
        state: chiefState[ i ],
        onComplete: this.handleTargetInState
      };
    }

    return this.props.children(state);
  }

  render() {

    var chiefState = this.state.chiefState;
    var children;

    if(chiefState) {

      if(typeof this.props.children === 'function') {
        children = this.getChildrenFromFunction(chiefState);
      } else {
        children = this.getChildrenWithTargetName(chiefState);
      }
    } else {
      children = this.props.children;
    }

    return <div
      {...this.props}
    >
      { children }
    </div>;
  }
};

Chief.defaultProps = {
  onComplete: function() {}
};

module.exports = Chief;<|endoftext|>


<commit_before>'use strict';

var util = require( './util' );
var define = require( './define' );
var Collection = require( './collection' );
var Core = require( './core' );
var incExts = require( './extensions' );
var is = require( './is' );

// registered extensions to cytoscape, indexed by name
var extensions = {};

// registered modules for extensions, indexed by name
var modules = {};

function setExtension( type, name, registrant ){

  var ext = registrant;

  var overrideErr = function( field ){
    util.error( 'Can not register `' + name + '` for `' + type + '` since `' + field + '` already exists in the prototype and can not be overridden' );
  };

  if( type === 'core' ){
    if( Core.prototype[ name ] ){
      return overrideErr( name );
    } else {
      Core.prototype[ name ] = registrant;
    }

  } else if( type === 'collection' ){
    if( Collection.prototype[ name ] ){
      return overrideErr( name );
    } else {
      Collection.prototype[ name ] = registrant;
    }

  } else if( type === 'layout' ){
    // fill in missing layout functions in the prototype

    var Layout = function( options ){
      this.options = options;

      registrant.call( this, options );

      // make sure layout has _private for use w/ std apis like .on()
      if( !is.plainObject( this._private ) ){
        this._private = {};
      }

      this._private.cy = options.cy;
      this._private.listeners = [];
    };

    var layoutProto = Layout.prototype = Object.create( registrant.prototype );

    var optLayoutFns = [];

    for( var i = 0; i < optLayoutFns.length; i++ ){
      var fnName = optLayoutFns[ i ];

      layoutProto[ fnName ] = layoutProto[ fnName ] || function(){ return this; };
    }

    // either .start() or .run() is defined, so autogen the other
    if( layoutProto.start && !layoutProto.run ){
      layoutProto.run = function(){ this.start(); return this; };
    } else if( !layoutProto.start && layoutProto.run ){
      layoutProto.start = function(){ this.run(); return this; };
    }

    if( !layoutProto.stop ){
      layoutProto.stop = function(){
        var opts = this.options;

        if( opts && opts.animate ){
          var anis = this.animations;
          for( var i = 0; i < anis.length; i++ ){
            anis[ i ].stop();
          }
        }

        this.trigger( 'layoutstop' );

        return this;
      };
    }

    if( !layoutProto.destroy ){
      layoutProto.destroy = function(){
        return this;
      };
    }

    layoutProto.on = define.on( { layout: true } );
    layoutProto.one = define.on( { layout: true, unbindSelfOnTrigger: true } );
    layoutProto.once = define.on( { layout: true, unbindAllBindersOnTrigger: true } );
    layoutProto.off = define.off( { layout: true } );
    layoutProto.trigger = define.trigger( { layout: true } );

    define.eventAliasesOn( layoutProto );

    ext = Layout; // replace with our wrapped layout

  } else if( type === 'renderer' && name !== 'null' && name !== 'base' ){
    // user registered renderers inherit from base

    var BaseRenderer = getExtension( 'renderer', 'base' );
    var bProto = BaseRenderer.prototype;
    var RegistrantRenderer = registrant;
    var rProto = registrant.prototype;

    var Renderer = function(){
      BaseRenderer.apply( this, arguments );
      RegistrantRenderer.apply( this, arguments );
    };

    var proto = Renderer.prototype;

    for( var pName in bProto ){
      var pVal = bProto[ pName ];
      var existsInR = rProto[ pName ] != null;

      if( existsInR ){
        return overrideErr( pName );
      }

      proto[ pName ] = pVal; // take impl from base
    }

    for( var pName in rProto ){
      proto[ pName ] = rProto[ pName ]; // take impl from registrant
    }

    bProto.clientFunctions.forEach( function( name ){
      proto[ name ] = proto[ name ] || function(){
        util.error( 'Renderer does not implement `renderer.' + name + '()` on its prototype' );
      };
    } );

    ext = Renderer;

  }

  return util.setMap( {
    map: extensions,
    keys: [ type, name ],
    value: ext
  } );
}

function getExtension( type, name ){
  return util.getMap( {
    map: extensions,
    keys: [ type, name ]
  } );
}

function setModule( type, name, moduleType, moduleName, registrant ){
  return util.setMap( {
    map: modules,
    keys: [ type, name, moduleType, moduleName ],
    value: registrant
  } );
}

function getModule( type, name, moduleType, moduleName ){
  return util.getMap( {
    map: modules,
    keys: [ type, name, moduleType, moduleName ]
  } );
}

var extension = function(){
  // e.g. extension('renderer', 'svg')
  if( arguments.length === 2 ){
    return getExtension.apply( null, arguments );
  }

  // e.g. extension('renderer', 'svg', { ... })
  else if( arguments.length === 3 ){
    return setExtension.apply( null, arguments );
  }

  // e.g. extension('renderer', 'svg', 'nodeShape', 'ellipse')
  else if( arguments.length === 4 ){
    return getModule.apply( null, arguments );
  }

  // e.g. extension('renderer', 'svg', 'nodeShape', 'ellipse', { ... })
  else if( arguments.length === 5 ){
    return setModule.apply( null, arguments );
  }

  else {
    util.error( 'Invalid extension access syntax' );
  }

};

// allows a core instance to access extensions internally
Core.prototype.extension = extension;

// included extensions
incExts.forEach( function( group ){
  group.extensions.forEach( function( ext ){
    setExtension( group.type, ext.name, ext.impl );
  } );
} );

module.exports = extension;
<commit_msg>Automatic layout function impls should be complemented by the specified impls, not replaced #1648<commit_after>'use strict';

var util = require( './util' );
var define = require( './define' );
var Collection = require( './collection' );
var Core = require( './core' );
var incExts = require( './extensions' );
var is = require( './is' );

// registered extensions to cytoscape, indexed by name
var extensions = {};

// registered modules for extensions, indexed by name
var modules = {};

function setExtension( type, name, registrant ){

  var ext = registrant;

  var overrideErr = function( field ){
    util.error( 'Can not register `' + name + '` for `' + type + '` since `' + field + '` already exists in the prototype and can not be overridden' );
  };

  if( type === 'core' ){
    if( Core.prototype[ name ] ){
      return overrideErr( name );
    } else {
      Core.prototype[ name ] = registrant;
    }

  } else if( type === 'collection' ){
    if( Collection.prototype[ name ] ){
      return overrideErr( name );
    } else {
      Collection.prototype[ name ] = registrant;
    }

  } else if( type === 'layout' ){
    // fill in missing layout functions in the prototype

    var Layout = function( options ){
      this.options = options;

      registrant.call( this, options );

      // make sure layout has _private for use w/ std apis like .on()
      if( !is.plainObject( this._private ) ){
        this._private = {};
      }

      this._private.cy = options.cy;
      this._private.listeners = [];
    };

    var layoutProto = Layout.prototype = Object.create( registrant.prototype );

    var optLayoutFns = [];

    for( var i = 0; i < optLayoutFns.length; i++ ){
      var fnName = optLayoutFns[ i ];

      layoutProto[ fnName ] = layoutProto[ fnName ] || function(){ return this; };
    }

    // either .start() or .run() is defined, so autogen the other
    if( layoutProto.start && !layoutProto.run ){
      layoutProto.run = function(){ this.start(); return this; };
    } else if( !layoutProto.start && layoutProto.run ){
      layoutProto.start = function(){ this.run(); return this; };
    }

    var regStop = registrant.prototype.stop;
    layoutProto.stop = function(){
      var opts = this.options;

      if( opts && opts.animate ){
        var anis = this.animations;

        if( anis ){
          for( var i = 0; i < anis.length; i++ ){
            anis[ i ].stop();
          }
        }
      }

      if( regStop ){
        regStop.call( this );
      } else {
        this.trigger( 'layoutstop' );
      }

      return this;
    };

    if( !layoutProto.destroy ){
      layoutProto.destroy = function(){
        return this;
      };
    }

    layoutProto.on = define.on( { layout: true } );
    layoutProto.one = define.on( { layout: true, unbindSelfOnTrigger: true } );
    layoutProto.once = define.on( { layout: true, unbindAllBindersOnTrigger: true } );
    layoutProto.off = define.off( { layout: true } );
    layoutProto.trigger = define.trigger( { layout: true } );

    define.eventAliasesOn( layoutProto );

    ext = Layout; // replace with our wrapped layout

  } else if( type === 'renderer' && name !== 'null' && name !== 'base' ){
    // user registered renderers inherit from base

    var BaseRenderer = getExtension( 'renderer', 'base' );
    var bProto = BaseRenderer.prototype;
    var RegistrantRenderer = registrant;
    var rProto = registrant.prototype;

    var Renderer = function(){
      BaseRenderer.apply( this, arguments );
      RegistrantRenderer.apply( this, arguments );
    };

    var proto = Renderer.prototype;

    for( var pName in bProto ){
      var pVal = bProto[ pName ];
      var existsInR = rProto[ pName ] != null;

      if( existsInR ){
        return overrideErr( pName );
      }

      proto[ pName ] = pVal; // take impl from base
    }

    for( var pName in rProto ){
      proto[ pName ] = rProto[ pName ]; // take impl from registrant
    }

    bProto.clientFunctions.forEach( function( name ){
      proto[ name ] = proto[ name ] || function(){
        util.error( 'Renderer does not implement `renderer.' + name + '()` on its prototype' );
      };
    } );

    ext = Renderer;

  }

  return util.setMap( {
    map: extensions,
    keys: [ type, name ],
    value: ext
  } );
}

function getExtension( type, name ){
  return util.getMap( {
    map: extensions,
    keys: [ type, name ]
  } );
}

function setModule( type, name, moduleType, moduleName, registrant ){
  return util.setMap( {
    map: modules,
    keys: [ type, name, moduleType, moduleName ],
    value: registrant
  } );
}

function getModule( type, name, moduleType, moduleName ){
  return util.getMap( {
    map: modules,
    keys: [ type, name, moduleType, moduleName ]
  } );
}

var extension = function(){
  // e.g. extension('renderer', 'svg')
  if( arguments.length === 2 ){
    return getExtension.apply( null, arguments );
  }

  // e.g. extension('renderer', 'svg', { ... })
  else if( arguments.length === 3 ){
    return setExtension.apply( null, arguments );
  }

  // e.g. extension('renderer', 'svg', 'nodeShape', 'ellipse')
  else if( arguments.length === 4 ){
    return getModule.apply( null, arguments );
  }

  // e.g. extension('renderer', 'svg', 'nodeShape', 'ellipse', { ... })
  else if( arguments.length === 5 ){
    return setModule.apply( null, arguments );
  }

  else {
    util.error( 'Invalid extension access syntax' );
  }

};

// allows a core instance to access extensions internally
Core.prototype.extension = extension;

// included extensions
incExts.forEach( function( group ){
  group.extensions.forEach( function( ext ){
    setExtension( group.type, ext.name, ext.impl );
  } );
} );

module.exports = extension;
<|endoftext|>


<commit_before>// taken from script.aculo.us and modified to break it

var JSJaC = {
  Version: '0.6.1',
  require: function(libraryName) {
    // inserting via DOM fails in Safari 2.0, so brute force approach
    document.write('<script type="text/javascript" src="'+libraryName+'"></script>');
  },
  load: function() {
    var includes = ['xmlextras','JSJaCPacket','crypt','json','qm_cookie','JSJaCConnection','JSJaCHttpPollingConnection','JSJaCHttpBindingConnection'];
    var scripts = document.getElementsByTagName("script");
    var path = './';
    for (var i=0; i<scripts.length; i++) {
      if (scripts.item(i).src && scripts.item(i).src.match(/JSJaC\.js$/)) {
				path = scripts.item(i).src.replace(/JSJaC.js$/,'');
				break;
			}
		}
    for (var i=0; i<includes.length; i++)
      this.require(path+includes[i]+'.js');
  }
}

JSJaC.load();
<commit_msg>proset 'Revision'<commit_after>// taken from script.aculo.us and modified to break it

var JSJaC = {
  Version: '$Rev$',
  require: function(libraryName) {
    // inserting via DOM fails in Safari 2.0, so brute force approach
    document.write('<script type="text/javascript" src="'+libraryName+'"></script>');
  },
  load: function() {
    var includes = ['xmlextras','JSJaCPacket','crypt','json','qm_cookie','JSJaCConnection','JSJaCHttpPollingConnection','JSJaCHttpBindingConnection'];
    var scripts = document.getElementsByTagName("script");
    var path = './';
    for (var i=0; i<scripts.length; i++) {
      if (scripts.item(i).src && scripts.item(i).src.match(/JSJaC\.js$/)) {
				path = scripts.item(i).src.replace(/JSJaC.js$/,'');
				break;
			}
		}
    for (var i=0; i<includes.length; i++)
      this.require(path+includes[i]+'.js');
  }
}

JSJaC.load();
<|endoftext|>