<commit_before>import Vue from 'vue'

Vue.filter('ucfirst', function (string) {
	if(string){
		return string.charAt(0).toUpperCase() + string.slice(1);
	}else{
		return '';
	}
});

Vue.filter('strtoupper', function (string) {
	if(string){
    	return string.toUpperCase();
    }else{
    	return '';
    }
});

Vue.filter('strtolower', function (string) {
	if(string){
    	return string.toLowerCase();
    }else{
    	return '';
    }
});

Vue.filter('siret', function (siret) {
	if(siret){
		siret = siret.replace(/\s/g,'');
	    return siret.slice(0, 3) + ' ' + siret.slice(3, 6) + ' ' + siret.slice(6, 9) + ' ' + siret.slice(9);
	}else{
		return '';
	}
});

Vue.filter('pluck', function (items, key) {
    if(items.constructor === Array){
        var results = [];
        _.forEach(items, function(item){
            if(typeof item[key] !== 'undefined'){
                results.push(item[key]);
            }else{
                throw('Missing key ' + key + ' to "pluck" data');
            }
        });
        return results;
    }else{
        throw('Could not "pluck" non-array data');
    }
});

Vue.filter('implode', function (items, separator) {
    if(items.constructor === Array){
        return items.join(separator);
    }else{
        throw('Could not "implode" non-array data');
    }
});

Vue.filter('nl2br', function (str, is_xhtml) {
    var breakTag = (is_xhtml || typeof is_xhtml === 'undefined') ? '
' : '
';
    return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag + '$2');
});
<commit_msg>Phone filter added<commit_after>import Vue from 'vue'

Vue.filter('ucfirst', function (string) {
	if(string){
		return string.charAt(0).toUpperCase() + string.slice(1);
	}else{
		return '';
	}
});

Vue.filter('strtoupper', function (string) {
	if(string){
    	return string.toUpperCase();
    }else{
    	return '';
    }
});

Vue.filter('strtolower', function (string) {
	if(string){
    	return string.toLowerCase();
    }else{
    	return '';
    }
});

Vue.filter('siret', function (siret) {
	if(siret){
		siret = siret.replace(/\s/g,'');
	    return siret.slice(0, 3) + ' ' + siret.slice(3, 6) + ' ' + siret.slice(6, 9) + ' ' + siret.slice(9);
	}else{
		return '';
	}
});

Vue.filter('pluck', function (items, key) {
    if(items.constructor === Array){
        var results = [];
        _.forEach(items, function(item){
            if(typeof item[key] !== 'undefined'){
                results.push(item[key]);
            }else{
                throw('Missing key ' + key + ' to "pluck" data');
            }
        });
        return results;
    }else{
        throw('Could not "pluck" non-array data');
    }
});

Vue.filter('implode', function (items, separator) {
    if(items.constructor === Array){
        return items.join(separator);
    }else{
        throw('Could not "implode" non-array data');
    }
});

Vue.filter('nl2br', function (str, is_xhtml) {
    var breakTag = (is_xhtml || typeof is_xhtml === 'undefined') ? '
' : '
';
    return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag + '$2');
});

Vue.filter('phone', function (string) {

    if(typeof string === 'string' && string && string.length >= 12){
        return string.slice(0, 3)
            + ' ' + string.slice(3, 4)
            + ' ' + string.slice(4, 6)
            + ' ' + string.slice(6, 8)
            + ' ' + string.slice(8, 10)
            + ' ' + string.slice(10);
    }
    return string;
});
<|endoftext|>


<commit_before>var _ = require('lodash');
var uuid = require('node-uuid');

var utils = require('./utils');

function newGame(client, data, userID, callback) {
    data.id = uuid.v4();
    data.created = data.modified = new Date();
    data.status = 'pending';
    data.slug = utils.slugify(data.slug || data.name);

    client.hset('games', data.id, JSON.stringify(data));

    // TODO: enforce slug uniqueness #108
    client.hset('gamesBySlug', data.slug, data.id);
    client.hget('gameIDsByUserID', userID, function(err, resp) {
        if (err) {
            callback('db_error');
        } else if (!resp) {
            resp = JSON.stringify([data.id]);
        } else {
            resp.push(data.id);
        }
        client.hset('gameIDsByUserID', userID, resp);
        callback(null, data);
    });
}
exports.newGame = newGame;

function updateGame(client, gameSlug, updatedGame, callback) {
    getGameFromSlug(client, gameSlug, function(err, game) {
        if (err) {
            callback(err);
        } else if (!game) {
            callback('no_such_game');
        } else {
            // Ensure that we don't change the id of the game, and
            // update the modified timestamp
            updatedGame.id = game.id;
            updatedGame.modified = new Date();

            client.hset('games', game.id, JSON.stringify(updatedGame));

            // TODO: enforce slug uniqueness #108
            if (game.slug !== updatedGame.slug) {
                client.hset('gamesBySlug', updatedGame.slug, game.id);
                client.hdel('gamesBySlug', game.slug);
            }
            callback(null, updatedGame);
        }
    });
}
exports.updateGame = updateGame;

function getGameFromID(client, id, callback) {
    /*
    `callback` is called with an error parameter and a parameter
    containing a JSON blob of game data.
    */
    client.hget('games', id, function(err, resp) {
        if (err) {
            callback('db_error');
        } else if (!resp) {
            callback('no_such_game');
        } else {
            callback(null, JSON.parse(resp));
        }
    });
}
exports.getGameFromID = getGameFromID;

function getGameFromSlug(client, slug, callback) {
    getGameIDFromSlug(client, slug, function(err, id) {
        if (err && err !== 'no_such_game') {
            callback(err);
        } else if (!id) {
            callback(null, null);
        } else {
            getGameFromID(client, id, callback);
        }
    });
}
exports.getGameFromSlug = getGameFromSlug;

function getGameIDFromSlug(client, slug, callback) {
    client.hget('gamesBySlug', slug, function(err, resp) {
        if (err) {
            callback('db_error');
        } else if (!resp) {
            callback('no_such_game');
        } else {
            // `resp` is the game ID.
            callback(null, resp);
        }
    });
}
exports.getGameIDFromSlug = getGameIDFromSlug;

function publicGameObj(full) {
    return _.pick(full, [
        'app_url',
        'appcache_path',
        'created',
        'default_locale',
        'description',
        'developer_name',
        'developer_url',
        'fullscreen',
        'genre',
        'homepage_url',
        'icons',
        'license',
        'locales',
        'name',
        'orientation',
        'privacy',
        'screenshots',
        'slug',
        'status'
    ]);
}
exports.publicGameObj = publicGameObj;

function protectedFields(full) {
    return _.pick(full, [
        'created',
        'id',
        'modified',
        'status'
    ]);
}
exports.protectedFields = protectedFields;

function getPublicGameObj(client, id, callback) {
    // `callback` is called with a single parameter, which is either
    // the public game object or `null`.
    getGameFromID(client, id, function(err, resp) {
        if (err || !resp) {
            callback(null);
            return;
        }
        try {
            callback(null, publicGameObj(resp));
        } catch(e) {
            callback(null);
        }
    });
}
exports.getPublicGameObj = getPublicGameObj;

function getGameList(client, ids, callback) {
    // `callback` is called with a single parameter, which is an
    // array of public game objects. If any result is invalid, it
    // is not included.
    if (!ids) {
        // TODO: We'll definitely need an efficient way to filter results without having
        // to fetch *every* game from the db (probably by creating sets for each property
        // we're interested in frequently filtering by)
        client.hvals('games', handleResults);
    } else {
        client.hmget(['games'].concat(ids), handleResults);
    }
    function handleResults(err, resp) {
        if (err) {
            callback('db_error');
            return;
        }
        if (!resp) {
            callback(null, null);
            return;
        }
        callback(null, resp.map(function(result) {
            if (!result) return;
            try {
                return JSON.parse(result);
            } catch(e) {
            }
        }));
    };
};
exports.getGameList = getGameList;

function getPublicGameObjList(client, ids, callback) {
    getGameList(client, ids, function(err, results) {
        if (err) {
            callback(err);
            return;
        }
        if (!results) {
            callback(null, null);
            return;
        }
        callback(null, results.map(publicGameObj).filter(_.identity));
    });
}
exports.getPublicGameObjList = getPublicGameObjList;
<commit_msg>Fixed bug with JSON parsing gameIDsByUserID<commit_after>var _ = require('lodash');
var uuid = require('node-uuid');

var utils = require('./utils');

function newGame(client, data, userID, callback) {
    data.id = uuid.v4();
    data.created = data.modified = new Date();
    data.status = 'pending';
    data.slug = utils.slugify(data.slug || data.name);

    client.hset('games', data.id, JSON.stringify(data));

    // TODO: enforce slug uniqueness #108
    client.hset('gamesBySlug', data.slug, data.id);
    client.hget('gameIDsByUserID', userID, function(err, resp) {
        if (err) {
            callback('db_error');
        } else if (!resp) {
            resp = JSON.stringify([data.id]);
        } else {
            respData = JSON.parse(resp);
            respData.push(data.id);
            resp = JSON.stringify(respData)
        }
        client.hset('gameIDsByUserID', userID, resp);
        callback(null, data);
    });
}
exports.newGame = newGame;

function updateGame(client, gameSlug, updatedGame, callback) {
    getGameFromSlug(client, gameSlug, function(err, game) {
        if (err) {
            callback(err);
        } else if (!game) {
            callback('no_such_game');
        } else {
            // Ensure that we don't change the id of the game, and
            // update the modified timestamp
            updatedGame.id = game.id;
            updatedGame.modified = new Date();

            client.hset('games', game.id, JSON.stringify(updatedGame));

            // TODO: enforce slug uniqueness #108
            if (game.slug !== updatedGame.slug) {
                client.hset('gamesBySlug', updatedGame.slug, game.id);
                client.hdel('gamesBySlug', game.slug);
            }
            callback(null, updatedGame);
        }
    });
}
exports.updateGame = updateGame;

function getGameFromID(client, id, callback) {
    /*
    `callback` is called with an error parameter and a parameter
    containing a JSON blob of game data.
    */
    client.hget('games', id, function(err, resp) {
        if (err) {
            callback('db_error');
        } else if (!resp) {
            callback('no_such_game');
        } else {
            callback(null, JSON.parse(resp));
        }
    });
}
exports.getGameFromID = getGameFromID;

function getGameFromSlug(client, slug, callback) {
    getGameIDFromSlug(client, slug, function(err, id) {
        if (err && err !== 'no_such_game') {
            callback(err);
        } else if (!id) {
            callback(null, null);
        } else {
            getGameFromID(client, id, callback);
        }
    });
}
exports.getGameFromSlug = getGameFromSlug;

function getGameIDFromSlug(client, slug, callback) {
    client.hget('gamesBySlug', slug, function(err, resp) {
        if (err) {
            callback('db_error');
        } else if (!resp) {
            callback('no_such_game');
        } else {
            // `resp` is the game ID.
            callback(null, resp);
        }
    });
}
exports.getGameIDFromSlug = getGameIDFromSlug;

function publicGameObj(full) {
    return _.pick(full, [
        'app_url',
        'appcache_path',
        'created',
        'default_locale',
        'description',
        'developer_name',
        'developer_url',
        'fullscreen',
        'genre',
        'homepage_url',
        'icons',
        'license',
        'locales',
        'name',
        'orientation',
        'privacy',
        'screenshots',
        'slug',
        'status'
    ]);
}
exports.publicGameObj = publicGameObj;

function protectedFields(full) {
    return _.pick(full, [
        'created',
        'id',
        'modified',
        'status'
    ]);
}
exports.protectedFields = protectedFields;

function getPublicGameObj(client, id, callback) {
    // `callback` is called with a single parameter, which is either
    // the public game object or `null`.
    getGameFromID(client, id, function(err, resp) {
        if (err || !resp) {
            callback(null);
            return;
        }
        try {
            callback(null, publicGameObj(resp));
        } catch(e) {
            callback(null);
        }
    });
}
exports.getPublicGameObj = getPublicGameObj;

function getGameList(client, ids, callback) {
    // `callback` is called with a single parameter, which is an
    // array of public game objects. If any result is invalid, it
    // is not included.
    if (!ids) {
        // TODO: We'll definitely need an efficient way to filter results without having
        // to fetch *every* game from the db (probably by creating sets for each property
        // we're interested in frequently filtering by)
        client.hvals('games', handleResults);
    } else {
        client.hmget(['games'].concat(ids), handleResults);
    }
    function handleResults(err, resp) {
        if (err) {
            callback('db_error');
            return;
        }
        if (!resp) {
            callback(null, null);
            return;
        }
        callback(null, resp.map(function(result) {
            if (!result) return;
            try {
                return JSON.parse(result);
            } catch(e) {
            }
        }));
    };
};
exports.getGameList = getGameList;

function getPublicGameObjList(client, ids, callback) {
    getGameList(client, ids, function(err, results) {
        if (err) {
            callback(err);
            return;
        }
        if (!results) {
            callback(null, null);
            return;
        }
        callback(null, results.map(publicGameObj).filter(_.identity));
    });
}
exports.getPublicGameObjList = getPublicGameObjList;
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2017 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.nanos.auth',
  name: 'Group',

  implements: [ 'foam.nanos.auth.EnabledAware' ],

  requires: [ 'foam.nanos.app.AppConfig' ],

  documentation: 'A Group of Users.',

  tableColumns: [ 'id', 'description', 'defaultMenu', 'parent' ],

  searchColumns: [ ],

  properties: [
    {
      class: 'String',
      name: 'id',
      documentation: 'Unique name of the Group.'
    },
    {
      class: 'Boolean',
      name: 'enabled',
      value: true
    },
    {
      class: 'String',
      name: 'description',
      documentation: 'Description of the Group.'
    },
    {
      class: 'Reference',
      name: 'parent',
      targetDAOKey: 'groupDAO',
      of: 'foam.nanos.auth.Group',
      documentation: 'Parent group to inherit permissions from.'
    },
    {
      class: 'FObjectArray',
      of: 'foam.nanos.auth.Permission',
      name: 'permissions',
      documentation: 'Permissions set on group.'
    },
    {
      class: 'Reference',
      targetDAOKey: 'menuDAO',
      name: 'defaultMenu',
      documentation: 'Menu user redirects to after login.',
      of: 'foam.nanos.menu.Menu'
    },
    {
      class: 'Image',
      name: 'logo',
      documentation: 'Group logo.',
      displayWidth: 60
    },
    {
      class: 'String',
      name: 'topNavigation',
      value: 'foam.nanos.u2.navigation.TopNavigation',
      displayWidth: 45
    },
    {
      class: 'String',
      name: 'footerView',
      value: 'foam.nanos.u2.navigation.FooterView',
      displayWidth: 45
    },
    {
      class: 'String',
      name: 'groupCSS',
      view: { class: 'foam.u2.tag.TextArea', rows: 16, cols: 60 },
    },
    {
      class: 'Color',
      name: 'primaryColor',
      documentation: 'The following color properties can determine the color scheme of the GUI.'
    },
    { class: 'Color', name: 'secondaryColor' },
    { class: 'Color', name: 'accentColor' },
    { class: 'Color', name: 'tableColor' },
    { class: 'Color', name: 'tableHoverColor' },
    {
      class: 'String',
      name: 'url',
      value: null
    }
    /*    {
          class: 'FObjectProperty',
          of: 'foam.nanos.app.AppConfig',
          name: 'appConfig',
          factory: function() { return this.AppConfig.create(); },
          documentation: 'Custom application configuration for group.'
        }
    */
    /*
      FUTURE
    {
      class: 'FObjectProperty',
      of: 'AuthConfig',
      documentation: 'Custom authentication settings for this group.'
    }
    */
  ],

  javaImports: [
    'foam.core.X',
    'foam.dao.DAO',
    'foam.nanos.app.AppConfig',
    'foam.nanos.session.Session',
    'foam.util.SafetyUtil',
    'org.eclipse.jetty.server.Request',
    'javax.servlet.http.HttpServletRequest'
  ],

  methods: [
    {
      name: 'implies',
      javaReturns: 'Boolean',
      args: [
        {
          name: 'permission',
          javaType: 'java.security.Permission'
        }
      ],
      javaCode: `
        if ( getPermissions() == null ) return false;
        for ( int i = 0 ; i < permissions_.length ; i++ ) {
          if ( new javax.security.auth.AuthPermission(permissions_[i].getId()).implies(permission) ) {
            return true;
          }
        }
        return false;`
      ,
      code: function(permissionId) {
        if ( this.permissions == null ) return false;

        for ( var i = 0 ; i < this.permissions.length ; i++ )
          if ( this.permissions[i].implies(permissionId) ) return true;

        return false;
      }
    },
    {
      name: 'getAppConfig',
      javaReturns: 'AppConfig',
      args: [
        {
          name: 'x',
          javaType: 'X'
        }
      ],
      javaCode: `
DAO userDAO         = (DAO) x.get("localUserDAO");
DAO groupDAO        = (DAO) x.get("groupDAO");
AppConfig config    = (AppConfig) ((AppConfig) x.get("appConfig")).fclone();

Session session = x.get(Session.class);
if ( session != null ) {
  User user = (User) userDAO.find(session.getUserId());
  if ( user != null ) {
    Group group    = (Group) groupDAO.find(user.getGroup());
    if ( ! SafetyUtil.isEmpty(group.getUrl()) ) {
      // populate AppConfig url with group url
      config.setUrl(group.getUrl());
    } else {
      // populate AppConfig url with request's RootUrl
      HttpServletRequest req = x.get(HttpServletRequest.class);
      if ( ! SafetyUtil.isEmpty(config.getUrl()) && ! SafetyUtil.isEmpty(req.getRequestURI())) {
        String curConfigUrl = config.getUrl();
        String request = ((Request) req).getRootURL().toString();

        // check it's http or https
        if ( curConfigUrl.startsWith("https") ) {
          config.setUrl("https" + request.substring(4));
        } else {
          config.setUrl(request);
        }
      }
    }
  }
}

return config;
        `
    }
  ]
});
<commit_msg>formatting<commit_after>/**
 * @license
 * Copyright 2017 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.nanos.auth',
  name: 'Group',

  implements: [ 'foam.nanos.auth.EnabledAware' ],

  requires: [ 'foam.nanos.app.AppConfig' ],

  documentation: 'A Group of Users.',

  tableColumns: [ 'id', 'description', 'defaultMenu', 'parent' ],

  searchColumns: [ ],

  properties: [
    {
      class: 'String',
      name: 'id',
      documentation: 'Unique name of the Group.'
    },
    {
      class: 'Boolean',
      name: 'enabled',
      value: true
    },
    {
      class: 'String',
      name: 'description',
      documentation: 'Description of the Group.'
    },
    {
      class: 'Reference',
      name: 'parent',
      targetDAOKey: 'groupDAO',
      of: 'foam.nanos.auth.Group',
      documentation: 'Parent group to inherit permissions from.'
    },
    {
      class: 'FObjectArray',
      of: 'foam.nanos.auth.Permission',
      name: 'permissions',
      documentation: 'Permissions set on group.'
    },
    {
      class: 'StringArray',
      of: 'foam.nanos.auth.Permission',
      name: 'permissions2',
      view: 'foam.u2.view.StringArrayRowView',
      documentation: 'Permissions set on group.'
    },
    {
      class: 'Reference',
      targetDAOKey: 'menuDAO',
      name: 'defaultMenu',
      documentation: 'Menu user redirects to after login.',
      of: 'foam.nanos.menu.Menu'
    },
    {
      class: 'Image',
      name: 'logo',
      documentation: 'Group logo.',
      displayWidth: 60
    },
    {
      class: 'String',
      name: 'topNavigation',
      value: 'foam.nanos.u2.navigation.TopNavigation',
      displayWidth: 45
    },
    {
      class: 'String',
      name: 'footerView',
      value: 'foam.nanos.u2.navigation.FooterView',
      displayWidth: 45
    },
    {
      class: 'String',
      name: 'groupCSS',
      view: { class: 'foam.u2.tag.TextArea', rows: 16, cols: 60 },
    },
    {
      class: 'Color',
      name: 'primaryColor',
      documentation: 'The following color properties can determine the color scheme of the GUI.'
    },
    { class: 'Color', name: 'secondaryColor' },
    { class: 'Color', name: 'accentColor' },
    { class: 'Color', name: 'tableColor' },
    { class: 'Color', name: 'tableHoverColor' },
    {
      class: 'String',
      name: 'url',
      value: null
    }
/*    {
      class: 'FObjectProperty',
      of: 'foam.nanos.app.AppConfig',
      name: 'appConfig',
      factory: function() { return this.AppConfig.create(); },
      documentation: 'Custom application configuration for group.'
    }
*/
    /*
      FUTURE
    {
      class: 'FObjectProperty',
      of: 'AuthConfig',
      documentation: 'Custom authentication settings for this group.'
    }
    */
  ],

  javaImports: [
    'foam.core.X',
    'foam.dao.DAO',
    'foam.nanos.app.AppConfig',
    'foam.nanos.session.Session',
    'foam.util.SafetyUtil',
    'org.eclipse.jetty.server.Request',
    'javax.servlet.http.HttpServletRequest'
  ],

  methods: [
    {
      name: 'implies',
      javaReturns: 'Boolean',
      args: [
        {
          name: 'permission',
          javaType: 'java.security.Permission'
        }
      ],
      javaCode: `
        if ( getPermissions() == null ) return false;
        for ( int i = 0 ; i < permissions_.length ; i++ ) {
          if ( new javax.security.auth.AuthPermission(permissions_[i].getId()).implies(permission) ) {
            return true;
          }
        }
        return false;`
      ,
      code: function(permissionId) {
        if ( this.permissions == null ) return false;

        for ( var i = 0 ; i < this.permissions.length ; i++ )
          if ( this.permissions[i].implies(permissionId) ) return true;

        return false;
      }
    },
    {
      name: 'getAppConfig',
      javaReturns: 'AppConfig',
      args: [
        {
          name: 'x',
          javaType: 'X'
        }
      ],
      javaCode: `
DAO userDAO         = (DAO) x.get("localUserDAO");
DAO groupDAO        = (DAO) x.get("groupDAO");
AppConfig config    = (AppConfig) ((AppConfig) x.get("appConfig")).fclone();

Session session = x.get(Session.class);
if ( session != null ) {
  User user = (User) userDAO.find(session.getUserId());
  if ( user != null ) {
    Group group    = (Group) groupDAO.find(user.getGroup());
    if ( ! SafetyUtil.isEmpty(group.getUrl()) ) {
      // populate AppConfig url with group url
      config.setUrl(group.getUrl());
    } else {
      // populate AppConfig url with request's RootUrl
      HttpServletRequest req = x.get(HttpServletRequest.class);
      if ( ! SafetyUtil.isEmpty(config.getUrl()) && ! SafetyUtil.isEmpty(req.getRequestURI())) {
        String curConfigUrl = config.getUrl();
        String request = ((Request) req).getRootURL().toString();

        // check it's http or https
        if ( curConfigUrl.startsWith("https") ) {
          config.setUrl("https" + request.substring(4));
        } else {
          config.setUrl(request);
        }
      }
    }
  }
}

return config;
        `
    }
  ]
});
<|endoftext|>


<commit_before>const Player      = require('./player');
const Ball        = require('./ball');
const Scorekeeper = require('./scorekeeper');

let keysDown = {};

window.addEventListener("keydown", function (event) {
    keysDown[event.keyCode] = true;
});

window.addEventListener("keyup", function (event) {
    delete keysDown[event.keyCode];
});

let player1Score = document.getElementById("player-1-score");
let player2Score = document.getElementById("player-2-score");

let Game = function (context, canvas, request) {
    this.context = context;
    this.request = request;
    this.width = canvas.width;
    this.height = canvas.height;
    this.player1 = new Player(context, 10, (canvas.height / 2) - 40, this);
    this.player2 = new Player(context, canvas.width - 20, (canvas.height / 2) - 40, this);
    this.ball = new Ball(this.width / 2, this.height / 2, this.context, this);
    this.scorekeeper = new Scorekeeper(this.player1, this.player2);
    this.gameObjects = [this.player1, this.player2];
};

// Game.prototype.collisionDetection = function () {
//     for (let i = 0; i < this.gameObjects.length; i++) {
//         let obj = gameObjects[i]
//         this.checkCollisionWithBall(obj);
//     }
// }

// Game.prototype.checkCollisionWithBall = function (obj) {
//     if obj.
//}

Game.prototype.render = function() {
    this.context.fillStyle = "#AFFFFF";
    this.context.fillRect(0, 0, this.width, this.height);
    this.ball.render();
    this.gameObjects.forEach( (object) => object.render() );
};

Game.prototype.moveTo = function (keysDown) {
    let moveDown = [0, 4];
    let moveUp   = [0,-4];
    let moveRight = [4, 0];
    let moveLeft = [-4, 0];

    for (var key in keysDown) {
        var value = Number(key);
        if (value === 40) {
            this.player2.update(moveDown);
        } else if (value === 38) {
            this.player2.update(moveUp);
        } else if (value === 87) {
            this.player1.update(moveUp);
        } else if (value === 83) {
            this.player1.update(moveDown);
        } else if (value === 39 ) {
            this.player2.update(moveRight);
        } else if (value === 37) {
            this.player2.update(moveLeft);
        } else if (value === 81) {
            this.player1.update(moveLeft);
        } else if (value === 69) {
            this.player1.update(moveRight);
        }
    }
};

Game.prototype.update = function() {
    this.moveTo(keysDown);
    this.ball.update(this.player1.paddle, this.player2.paddle);
};

Game.prototype.score = function(player) {
    this.scorekeeper.increaseScore(player);
    this.renderScore();
    this.serveBall();
};

Game.prototype.over = function() {
    if (this.scorekeeper.scores.player1 > 9) {
        return this.endgame("Player 1");
    } else if (this.scorekeeper.scores.player2 > 9) {
        return this.endgame("Player 2");
    } else {
        return false;
    }
};

Game.prototype.endgame = function(player) {
    this.renderScore();
    alert(`Game over, ${player} won`);
    return true;
};

Game.prototype.renderScore = function() {
    let p1 = this.scorekeeper.scores.player1;
    let p2 = this.scorekeeper.scores.player2;
    player1Score.innerHTML = p1;
    player2Score.innerHTML = p2;
};

Game.prototype.serveBall = function() {
    this.ball.x = this.width / 2;
    this.ball.y = this.height / 2;
    this.ball.x_speed = 5;
    this.ball.y_speed = 0.7;
};

module.exports = Game;
<commit_msg>Removed comments from game.js<commit_after>const Player      = require('./player');
const Ball        = require('./ball');
const Scorekeeper = require('./scorekeeper');

let keysDown = {};

window.addEventListener("keydown", function (event) {
    keysDown[event.keyCode] = true;
});

window.addEventListener("keyup", function (event) {
    delete keysDown[event.keyCode];
});

let player1Score = document.getElementById("player-1-score");
let player2Score = document.getElementById("player-2-score");

let Game = function (context, canvas, request) {
    this.context = context;
    this.request = request;
    this.width = canvas.width;
    this.height = canvas.height;
    this.player1 = new Player(context, 10, (canvas.height / 2) - 40, this);
    this.player2 = new Player(context, canvas.width - 20, (canvas.height / 2) - 40, this);
    this.ball = new Ball(this.width / 2, this.height / 2, this.context, this);
    this.scorekeeper = new Scorekeeper(this.player1, this.player2);
    this.gameObjects = [this.player1, this.player2];
};

Game.prototype.render = function() {
    this.context.fillStyle = "#AFFFFF";
    this.context.fillRect(0, 0, this.width, this.height);
    this.ball.render();
    this.gameObjects.forEach( (object) => object.render() );
};

Game.prototype.moveTo = function (keysDown) {
    let moveDown = [0, 4];
    let moveUp   = [0,-4];
    let moveRight = [4, 0];
    let moveLeft = [-4, 0];

    for (var key in keysDown) {
        var value = Number(key);
        if (value === 40) {
            this.player2.update(moveDown);
        } else if (value === 38) {
            this.player2.update(moveUp);
        } else if (value === 87) {
            this.player1.update(moveUp);
        } else if (value === 83) {
            this.player1.update(moveDown);
        } else if (value === 39 ) {
            this.player2.update(moveRight);
        } else if (value === 37) {
            this.player2.update(moveLeft);
        } else if (value === 81) {
            this.player1.update(moveLeft);
        } else if (value === 69) {
            this.player1.update(moveRight);
        }
    }
};

Game.prototype.update = function() {
    this.moveTo(keysDown);
    this.ball.update(this.player1.paddle, this.player2.paddle);
};

Game.prototype.score = function(player) {
    this.scorekeeper.increaseScore(player);
    this.renderScore();
    this.serveBall();
};

Game.prototype.over = function() {
    if (this.scorekeeper.scores.player1 > 9) {
        return this.endgame("Player 1");
    } else if (this.scorekeeper.scores.player2 > 9) {
        return this.endgame("Player 2");
    } else {
        return false;
    }
};

Game.prototype.endgame = function(player) {
    this.renderScore();
    alert(`Game over, ${player} won`);
    return true;
};

Game.prototype.renderScore = function() {
    let p1 = this.scorekeeper.scores.player1;
    let p2 = this.scorekeeper.scores.player2;
    player1Score.innerHTML = p1;
    player2Score.innerHTML = p2;
};

Game.prototype.serveBall = function() {
    this.ball.x = this.width / 2;
    this.ball.y = this.height / 2;
    this.ball.x_speed = 5;
    this.ball.y_speed = 0.7;
};

module.exports = Game;
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2017 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */
foam.CLASS({
  package: 'foam.nanos.boot',
  name: 'NSpec',

  requires: [
    {
      path: 'foam.comics.BrowserView',
      flags: ['web'],
    },
  ],

  javaImports: [
    'bsh.EvalError',
    'bsh.Interpreter',
    'foam.dao.DAO',
    'foam.core.FObject'
  ],

  ids: [ 'name' ],

  tableColumns: [ 'name', 'lazy', 'serve', 'authenticate', /*'serviceClass',*/ 'configure' ],

  properties: [
    {
      class: 'String',
      name: 'name',
      tableWidth: 460
    },
    {
      class: 'String',
      name: 'description',
      width: 80
    },
    {
      class: 'Boolean',
      name: 'lazy',
      tableWidth: 65,
      value: true,
      tableCellFormatter: function(value, obj, property) {
        this
          .start()
            .call(function() {
              if ( value ) { this.style({color: 'green'}); }
            })
            .add(value ? ' Y' : '-')
          .end();
      },
    },
    {
      class: 'Boolean',
      name: 'serve',
      tableWidth: 72,
      tableCellFormatter: function(value, obj, property) {
        this
          .start()
            .call(function() {
              if ( value ) { this.style({color: 'green'}); }
            })
            .add(value ? ' Y' : '-')
          .end();
      },
      documentation: 'If true, this service is served over the network.'
    },
    {
      class: 'Boolean',
      name: 'authenticate',
      value: true,
      tableCellFormatter: function(value, obj, property) {
        this
          .start()
            .call(function() {
              if ( value ) { this.style({color: 'green'}); }
            })
            .add(value ? ' Y' : '-')
          .end();
      }
    },
    {
      class: 'Boolean',
      name: 'parameters',
      value: false,
      tableCellFormatter: function(value, obj, property) {
        this
          .start()
            .call(function() {
              if ( value ) { this.style({color: 'green'}); }
            })
            .add(value ? ' Y' : '-')
          .end();
      }
    },
    {
      class: 'Boolean',
      name: 'pm',
      value: true,
      tableCellFormatter: function(value, obj, property) {
        this
          .start()
            .call(function() {
              if ( value ) { this.style({color: 'green'}); }
            })
            .add(value ? ' Y' : '-')
          .end();
      }
    },
    {
      class: 'String',
      name: 'serviceClass',
      displayWidth: 80
    },
    {
      class: 'String',
      name: 'boxClass',
      displayWidth: 80
    },
    {
      class: 'String',
      name: 'serviceScript',
      view: { class: 'foam.u2.tag.TextArea', rows: 12, cols: 120 },
      permissionRequired: true
    },
    {
      class: 'String',
      name: 'client',
      value: '{}',
      view: { class: 'foam.u2.tag.TextArea', rows: 12, cols: 120 }
    },
    {
      class: 'FObjectProperty',
      name: 'service',
      view: { class: 'foam.u2.view.FObjectView' },
      permissionRequired: true
    },
    {
      class: 'String',
      name: 'documentation',
      view: { class: 'foam.u2.tag.TextArea', rows: 12, cols: 120 },
      permissionRequired: true
    }
    // TODO: permissions, keywords, lazy, parent
  ],

  methods: [
    {
      name: 'saveService',
      args: [
        { name: 'x', type: 'Context' },
        { name: 'service', type: 'Any' }
      ],
      javaCode: `
      /*
        System.err.println("saveService: " + this.getName());
        if ( service instanceof FObject ) {
          setService((FObject) service);
          DAO dao = (DAO) x.get("nSpecDAO");
          dao.put(this);
        }
        */
      `
    },
    {
      name: 'createService',
      args: [
        { name: 'x', type: 'Context' }
      ],
      javaType: 'java.lang.Object',
      javaCode: `
        if ( getService() != null ) return getService();

        if ( getServiceClass().length() > 0 ) {
          Object service = Class.forName(getServiceClass()).newInstance();
          // TODO: doesn't work with DAO's, fix
          // saveService(x, service);
          return service;
        }

        Interpreter shell = new Interpreter();
        try {
          shell.set("x", x);
          Object service = shell.eval(getServiceScript());
          saveService(x, service);
          return service;
        } catch (EvalError e) {
          System.err.println("NSpec serviceScript error: " + getServiceScript());
          e.printStackTrace();
        }

        return null;
      `,
      javaThrows: [
        'java.lang.ClassNotFoundException',
        'java.lang.InstantiationException',
        'java.lang.IllegalAccessException'
      ],
    }
  ],

  actions: [
    {
      // Let user configure this service. Is hard-coded to work with DAO's
      // for now, but should get the config object from the NSpec itself
      // to be extensible.
      name: 'configure',
      isAvailable: function(boxClass, serve) {
        return serve && ! boxClass;
//        return foam.dao.DAO.isInstance(this.__context__[this.name]);
      },
      code: function() {
        var service = this.__context__[this.name];
        if ( foam.dao.DAO.isInstance(service) ) {
          this.__context__.stack.push({
            class: 'foam.comics.BrowserView',
            createEnabled: true,
            editEnabled: true,
            exportEnabled: true,
            data: service
          });
        }
      }
    }
  ]
});
<commit_msg>Make NSpec serviceScript and client use the code editor view.<commit_after>/**
 * @license
 * Copyright 2017 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */
foam.CLASS({
  package: 'foam.nanos.boot',
  name: 'NSpec',

  requires: [
    {
      path: 'foam.comics.BrowserView',
      flags: ['web'],
    },
  ],

  javaImports: [
    'bsh.EvalError',
    'bsh.Interpreter',
    'foam.dao.DAO',
    'foam.core.FObject'
  ],

  ids: [ 'name' ],

  tableColumns: [ 'name', 'lazy', 'serve', 'authenticate', /*'serviceClass',*/ 'configure' ],

  properties: [
    {
      class: 'String',
      name: 'name',
      tableWidth: 460
    },
    {
      class: 'String',
      name: 'description',
      width: 80
    },
    {
      class: 'Boolean',
      name: 'lazy',
      tableWidth: 65,
      value: true,
      tableCellFormatter: function(value, obj, property) {
        this
          .start()
            .call(function() {
              if ( value ) { this.style({color: 'green'}); }
            })
            .add(value ? ' Y' : '-')
          .end();
      },
    },
    {
      class: 'Boolean',
      name: 'serve',
      tableWidth: 72,
      tableCellFormatter: function(value, obj, property) {
        this
          .start()
            .call(function() {
              if ( value ) { this.style({color: 'green'}); }
            })
            .add(value ? ' Y' : '-')
          .end();
      },
      documentation: 'If true, this service is served over the network.'
    },
    {
      class: 'Boolean',
      name: 'authenticate',
      value: true,
      tableCellFormatter: function(value, obj, property) {
        this
          .start()
            .call(function() {
              if ( value ) { this.style({color: 'green'}); }
            })
            .add(value ? ' Y' : '-')
          .end();
      }
    },
    {
      class: 'Boolean',
      name: 'parameters',
      value: false,
      tableCellFormatter: function(value, obj, property) {
        this
          .start()
            .call(function() {
              if ( value ) { this.style({color: 'green'}); }
            })
            .add(value ? ' Y' : '-')
          .end();
      }
    },
    {
      class: 'Boolean',
      name: 'pm',
      value: true,
      tableCellFormatter: function(value, obj, property) {
        this
          .start()
            .call(function() {
              if ( value ) { this.style({color: 'green'}); }
            })
            .add(value ? ' Y' : '-')
          .end();
      }
    },
    {
      class: 'String',
      name: 'serviceClass',
      displayWidth: 80
    },
    {
      class: 'String',
      name: 'boxClass',
      displayWidth: 80
    },
    {
      class: 'String',
      name: 'serviceScript',
      view: { class: 'io.c9.ace.Editor' },
      permissionRequired: true
    },
    {
      class: 'String',
      name: 'client',
      value: '{}',
      view: { class: 'io.c9.ace.Editor' }
    },
    {
      class: 'FObjectProperty',
      name: 'service',
      view: { class: 'foam.u2.view.FObjectView' },
      permissionRequired: true
    },
    {
      class: 'String',
      name: 'documentation',
      view: { class: 'foam.u2.tag.TextArea', rows: 12, cols: 120 },
      permissionRequired: true
    }
    // TODO: permissions, keywords, lazy, parent
  ],

  methods: [
    {
      name: 'saveService',
      args: [
        { name: 'x', type: 'Context' },
        { name: 'service', type: 'Any' }
      ],
      javaCode: `
      /*
        System.err.println("saveService: " + this.getName());
        if ( service instanceof FObject ) {
          setService((FObject) service);
          DAO dao = (DAO) x.get("nSpecDAO");
          dao.put(this);
        }
        */
      `
    },
    {
      name: 'createService',
      args: [
        { name: 'x', type: 'Context' }
      ],
      javaType: 'java.lang.Object',
      javaCode: `
        if ( getService() != null ) return getService();

        if ( getServiceClass().length() > 0 ) {
          Object service = Class.forName(getServiceClass()).newInstance();
          // TODO: doesn't work with DAO's, fix
          // saveService(x, service);
          return service;
        }

        Interpreter shell = new Interpreter();
        try {
          shell.set("x", x);
          Object service = shell.eval(getServiceScript());
          saveService(x, service);
          return service;
        } catch (EvalError e) {
          System.err.println("NSpec serviceScript error: " + getServiceScript());
          e.printStackTrace();
        }

        return null;
      `,
      javaThrows: [
        'java.lang.ClassNotFoundException',
        'java.lang.InstantiationException',
        'java.lang.IllegalAccessException'
      ],
    }
  ],

  actions: [
    {
      // Let user configure this service. Is hard-coded to work with DAO's
      // for now, but should get the config object from the NSpec itself
      // to be extensible.
      name: 'configure',
      isAvailable: function(boxClass, serve) {
        return serve && ! boxClass;
//        return foam.dao.DAO.isInstance(this.__context__[this.name]);
      },
      code: function() {
        var service = this.__context__[this.name];
        if ( foam.dao.DAO.isInstance(service) ) {
          this.__context__.stack.push({
            class: 'foam.comics.BrowserView',
            createEnabled: true,
            editEnabled: true,
            exportEnabled: true,
            data: service
          });
        }
      }
    }
  ]
});
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2019 The FOAM Authors. All Rights Reserved.
 *     http://www.apache.org/licenses/LICENSE-2.0
 */

 foam.CLASS({
  package: 'foam.nanos.ruler',
  name: 'Rule',

  documentation: 'Rule model represents rules(actions) that need to be applied in case passed object satisfies provided predicate.',

  javaImports: [
    'foam.core.FObject',
    'foam.core.X'
  ],

  properties: [
    {
      class: 'Long',
      name: 'id',
      documentation: 'Sequence number.'
    },
    {
      class: 'String',
      name: 'name',
      documentation: 'Rule name for human readability.'
    },
    {
      class: 'Int',
      name: 'priority',
      documentation: 'Priority defines the order in which rules are to be applied.'+
      'Rules with a higher priority are to be applied first.'+
      'The convention for values is ints that are multiple of 10.'
    },
    {
      class: 'String',
      name: 'ruleGroup',
      documentation: 'ruleGroup defines sets of rules related to the same action.'
    },
    {
      class: 'String',
      name: 'documentation',
      view: {
        class: 'foam.u2.tag.TextArea',
        rows: 12, cols: 80
      }
    },
    {
      class: 'Reference',
      of: 'foam.nanos.boot.NSpec',
      name: 'daoKey',
      documentation: 'dao name that the rule is applied on.',
      view: function(_, X) {
        var E = foam.mlang.Expressions.create();
        return foam.u2.view.ChoiceView.create({
          dao: X.nSpecDAO
            .where(E.ENDS_WITH(foam.nanos.boot.NSpec.ID, 'DAO'))
            .orderBy(foam.nanos.boot.NSpec.ID),
          objToChoice: function(nspec) {
            return [nspec.id, nspec.id];
          }
        });
      }
    },
    {
      class: 'Enum',
      of: 'foam.nanos.ruler.Operations',
      name: 'operation',
      documentation: 'Defines when the rules is to be applied: put/removed'
    },
    {
      class: 'Boolean',
      name: 'after',
      documentation: 'Defines if the rule needs to be applied before or after operation is completed'+
      'E.g. on dao.put: before object was stored in a dao or after.'
    },
    {
      class: 'FObjectProperty',
      of: 'foam.mlang.predicate.Predicate',
      name: 'predicate',
      javaFactory: `
      return foam.mlang.MLang.TRUE;
      `,
      documentation: 'predicate is checked against an object; if returns true, the action is executed.'+
      'Defaults to return true.'
    },
    {
      class: 'FObjectProperty',
      of: 'foam.nanos.ruler.RuleAction',
      name: 'action',
      javaFactory: `
      return new RuleAction() {
        @Override
        public void applyAction(X x, FObject obj, FObject oldObj, RuleEngine ruler) { /*noop*/ }
      };`,
      documentation: 'The action to be executed if predicates returns true for passed object.'
    },
    {
      class: 'FObjectProperty',
      of: 'foam.nanos.ruler.RuleAction',
      name: 'asyncAction',
      javaFactory: `
      return new RuleAction() {
        @Override
        public void applyAction(X x, FObject obj, FObject oldObj, RuleEngine ruler) { /*noop*/ }
      };`,
      documentation: 'The action to be executed asynchronously if predicates returns true for passed object.'
    },
    {
      class: 'Boolean',
      name: 'enabled',
      value: true,
      documentation: 'Enables the rule.'
    },
    {
      class: 'Boolean',
      name: 'saveHistory',
      value: false,
      documentation: 'Determines if history of rule execution should be saved.',
      help: 'Automatically sets to true when validity is greater than zero.',
      adapt: function(_, nu) {
        return nu || this.validity > 0;
      }
    },
    {
      class: 'Int',
      name: 'validity',
      documentation: 'Validity of the rule (in days) for automatic rescheduling.',
      postSet: function(_, nu) {
        if ( nu > 0
          && ! this.saveHistory
        ) {
          this.saveHistory = true;
        }
      }
    },
    {
      class: 'Object',
      name: 'cmd',
      transient: true,
      hidden: true,
      javaFactory: `
        if ( Operations.CREATE == getOperation()
          || Operations.UPDATE == getOperation()
          || Operations.CREATE_OR_UPDATE == getOperation()
          || Operations.REMOVE == getOperation()
        ) {
          return RulerDAO.PUT_CMD;
        }
        return null;
      `
    }
  ],

  methods: [
    {
      name: 'f',
      type: 'Boolean',
      args: [
        {
          name: 'x',
          type: 'Context'
        },
        {
          name: 'obj',
          type: 'FObject'
        },
        {
          name: 'oldObj',
          type: 'FObject'
        }
      ],
      javaCode: `
        return getEnabled()
          && getPredicate().f(
            x.put("NEW", obj).put("OLD", oldObj)
          );
      `
    },
    {
      name: 'apply',
      args: [
        {
          name: 'x',
          type: 'Context'
        },
        {
          name: 'obj',
          type: 'FObject'
        },
        {
          name: 'oldObj',
          type: 'FObject'
        },
        {
          name: 'ruler',
          type: 'foam.nanos.ruler.RuleEngine'
        }
      ],
      javaCode: `
        getAction().applyAction(x, obj, oldObj, ruler);
        if ( ! getAfter() ) {
          ruler.getDelegate().cmd_(x.put("OBJ", obj), getCmd());
        }
      `
    },
    {
      name: 'asyncApply',
      args: [
        {
          name: 'x',
          type: 'Context'
        },
        {
          name: 'obj',
          type: 'FObject'
        },
        {
          name: 'oldObj',
          type: 'FObject'
        },
        {
          name: 'ruler',
          type: 'foam.nanos.ruler.RuleEngine'
        }
      ],
      javaCode: `
        getAsyncAction().applyAction(x, obj, oldObj, ruler);
        if ( ! getAfter() ) {
          ruler.getDelegate().cmd_(x.put("OBJ", obj), getCmd());
        }
      `
    }
  ]
});
<commit_msg>ignore put_cmd during remove operation<commit_after>/**
 * @license
 * Copyright 2019 The FOAM Authors. All Rights Reserved.
 *     http://www.apache.org/licenses/LICENSE-2.0
 */

 foam.CLASS({
  package: 'foam.nanos.ruler',
  name: 'Rule',

  documentation: 'Rule model represents rules(actions) that need to be applied in case passed object satisfies provided predicate.',

  javaImports: [
    'foam.core.FObject',
    'foam.core.X'
  ],

  properties: [
    {
      class: 'Long',
      name: 'id',
      documentation: 'Sequence number.'
    },
    {
      class: 'String',
      name: 'name',
      documentation: 'Rule name for human readability.'
    },
    {
      class: 'Int',
      name: 'priority',
      documentation: 'Priority defines the order in which rules are to be applied.'+
      'Rules with a higher priority are to be applied first.'+
      'The convention for values is ints that are multiple of 10.'
    },
    {
      class: 'String',
      name: 'ruleGroup',
      documentation: 'ruleGroup defines sets of rules related to the same action.'
    },
    {
      class: 'String',
      name: 'documentation',
      view: {
        class: 'foam.u2.tag.TextArea',
        rows: 12, cols: 80
      }
    },
    {
      class: 'Reference',
      of: 'foam.nanos.boot.NSpec',
      name: 'daoKey',
      documentation: 'dao name that the rule is applied on.',
      view: function(_, X) {
        var E = foam.mlang.Expressions.create();
        return foam.u2.view.ChoiceView.create({
          dao: X.nSpecDAO
            .where(E.ENDS_WITH(foam.nanos.boot.NSpec.ID, 'DAO'))
            .orderBy(foam.nanos.boot.NSpec.ID),
          objToChoice: function(nspec) {
            return [nspec.id, nspec.id];
          }
        });
      }
    },
    {
      class: 'Enum',
      of: 'foam.nanos.ruler.Operations',
      name: 'operation',
      documentation: 'Defines when the rules is to be applied: put/removed'
    },
    {
      class: 'Boolean',
      name: 'after',
      documentation: 'Defines if the rule needs to be applied before or after operation is completed'+
      'E.g. on dao.put: before object was stored in a dao or after.'
    },
    {
      class: 'FObjectProperty',
      of: 'foam.mlang.predicate.Predicate',
      name: 'predicate',
      javaFactory: `
      return foam.mlang.MLang.TRUE;
      `,
      documentation: 'predicate is checked against an object; if returns true, the action is executed.'+
      'Defaults to return true.'
    },
    {
      class: 'FObjectProperty',
      of: 'foam.nanos.ruler.RuleAction',
      name: 'action',
      javaFactory: `
      return new RuleAction() {
        @Override
        public void applyAction(X x, FObject obj, FObject oldObj, RuleEngine ruler) { /*noop*/ }
      };`,
      documentation: 'The action to be executed if predicates returns true for passed object.'
    },
    {
      class: 'FObjectProperty',
      of: 'foam.nanos.ruler.RuleAction',
      name: 'asyncAction',
      javaFactory: `
      return new RuleAction() {
        @Override
        public void applyAction(X x, FObject obj, FObject oldObj, RuleEngine ruler) { /*noop*/ }
      };`,
      documentation: 'The action to be executed asynchronously if predicates returns true for passed object.'
    },
    {
      class: 'Boolean',
      name: 'enabled',
      value: true,
      documentation: 'Enables the rule.'
    },
    {
      class: 'Boolean',
      name: 'saveHistory',
      value: false,
      documentation: 'Determines if history of rule execution should be saved.',
      help: 'Automatically sets to true when validity is greater than zero.',
      adapt: function(_, nu) {
        return nu || this.validity > 0;
      }
    },
    {
      class: 'Int',
      name: 'validity',
      documentation: 'Validity of the rule (in days) for automatic rescheduling.',
      postSet: function(_, nu) {
        if ( nu > 0
          && ! this.saveHistory
        ) {
          this.saveHistory = true;
        }
      }
    },
    {
      class: 'Object',
      name: 'cmd',
      transient: true,
      hidden: true,
      javaFactory: `
        if ( Operations.CREATE == getOperation()
          || Operations.UPDATE == getOperation()
          || Operations.CREATE_OR_UPDATE == getOperation()
        ) {
          return RulerDAO.PUT_CMD;
        }
        return null;
      `
    }
  ],

  methods: [
    {
      name: 'f',
      type: 'Boolean',
      args: [
        {
          name: 'x',
          type: 'Context'
        },
        {
          name: 'obj',
          type: 'FObject'
        },
        {
          name: 'oldObj',
          type: 'FObject'
        }
      ],
      javaCode: `
        return getEnabled()
          && getPredicate().f(
            x.put("NEW", obj).put("OLD", oldObj)
          );
      `
    },
    {
      name: 'apply',
      args: [
        {
          name: 'x',
          type: 'Context'
        },
        {
          name: 'obj',
          type: 'FObject'
        },
        {
          name: 'oldObj',
          type: 'FObject'
        },
        {
          name: 'ruler',
          type: 'foam.nanos.ruler.RuleEngine'
        }
      ],
      javaCode: `
        getAction().applyAction(x, obj, oldObj, ruler);
        if ( ! getAfter() && getCmd() != null ) {
          ruler.getDelegate().cmd_(x.put("OBJ", obj), getCmd());
        }
      `
    },
    {
      name: 'asyncApply',
      args: [
        {
          name: 'x',
          type: 'Context'
        },
        {
          name: 'obj',
          type: 'FObject'
        },
        {
          name: 'oldObj',
          type: 'FObject'
        },
        {
          name: 'ruler',
          type: 'foam.nanos.ruler.RuleEngine'
        }
      ],
      javaCode: `
        getAsyncAction().applyAction(x, obj, oldObj, ruler);
        if ( ! getAfter() && getCmd() != null ) {
          ruler.getDelegate().cmd_(x.put("OBJ", obj), getCmd());
        }
      `
    }
  ]
});
<|endoftext|>


<commit_before>/*
 * Some handy utility functions to handle data coming off the blockchain.
 */

var util = require('util');
var EventEmitter = require('events');
var eris = require(__libs+'/eris/eris-wrapper');

var chainUtils = {

    /**
     * createContractEventHandler - Creates an event handler
     * for `contract` to log any `ActionEvent` events triggered
     * within the contract.
     *
     * @param  {Object} contract description
     * @param  {Object} log      description
     * @return {null}          description
     */
    createContractEventHandler: function (contract, log) {
        // Set up event emitter
        function ChainEventEmitter () {
            EventEmitter.call(this);
        }
        util.inherits(ChainEventEmitter, EventEmitter);
        var chainEvents = new ChainEventEmitter();

        contract.ActionEvent(
            function (error, eventSub) {
                if (error)
                    throw error;
            },
            function (error, event) {
                if (event) {
                    var eventString = eris.hex2str(event.args.actionType);

                    log.info("***CONTRACT EVENT:***\n", eventString);
                    chainEvents.emit(eventString, event.args);
                }
            });
    },

    /**
     * extractInt - Extracts an integer from a `uint`/`int` Solidity type value.
     *
     * @param  {Object} bcObject The blockchain object to be extracted from.
     * @return {int}             The extracted integer.
     */
    extractInt: function (bcObject) {
        return bcObject['c'][0];
    },

    /**
     * extractIntFromArray - Extracts an integer from a `uint`/`int` Solidity
     * type value nested inside an array.
     *
     * @param  {Object} bcObject The blockchain object to be extracted from.
     * @param  {int} index    Index position of the int in the array.
     * @return {int}          The extracted integer.
     */
    extractIntFromArray: function (bcObject, index) {
        return bcObject[index]['c'][0];
    },

    /**
     * marshalForChain - description
     *
     * @param  {type} obj description
     * @return {type}     description
     */
    marshalForChain: function (obj) {
        var hexObj = {};

        for (var prop in obj) {
            if ({}.hasOwnProperty.call(obj, prop)) {
                var val = obj[prop];

                if (Number.isInteger(val)) {
                    val = String(val);
                } else if (Array.isArray(val)) {
                    val = JSON.stringify(val);
                } else if (typeof val !== "string") {
                    throw new Error("Error at marshalForChain: " + prop + ":" + val + " is not a string.");
                }
                hexObj[prop] = eris.str2hex(val);
            }
        }

        return hexObj;
    }
};

module.exports = chainUtils;
<commit_msg>Ignore chainUtils for coverage reports<commit_after>/*
 * Some handy utility functions to handle data coming off the blockchain.
 */

var util = require('util');
var EventEmitter = require('events');
var eris = require(__libs+'/eris/eris-wrapper');

/* istanbul ignore next */
var chainUtils = {

    /**
     * createContractEventHandler - Creates an event handler
     * for `contract` to log any `ActionEvent` events triggered
     * within the contract.
     *
     * @param  {Object} contract description
     * @param  {Object} log      description
     * @return {null}          description
     */
    createContractEventHandler: function (contract, log) {
        // Set up event emitter
        function ChainEventEmitter () {
            EventEmitter.call(this);
        }
        util.inherits(ChainEventEmitter, EventEmitter);
        var chainEvents = new ChainEventEmitter();

        contract.ActionEvent(
            function (error, eventSub) {
                if (error)
                    throw error;
            },
            function (error, event) {
                if (event) {
                    var eventString = eris.hex2str(event.args.actionType);

                    log.info("***CONTRACT EVENT:***\n", eventString);
                    chainEvents.emit(eventString, event.args);
                }
            });
    },

    /**
     * extractInt - Extracts an integer from a `uint`/`int` Solidity type value.
     *
     * @param  {Object} bcObject The blockchain object to be extracted from.
     * @return {int}             The extracted integer.
     */
    extractInt: function (bcObject) {
        return bcObject['c'][0];
    },

    /**
     * extractIntFromArray - Extracts an integer from a `uint`/`int` Solidity
     * type value nested inside an array.
     *
     * @param  {Object} bcObject The blockchain object to be extracted from.
     * @param  {int} index    Index position of the int in the array.
     * @return {int}          The extracted integer.
     */
    extractIntFromArray: function (bcObject, index) {
        return bcObject[index]['c'][0];
    },

    /**
     * marshalForChain - description
     *
     * @param  {type} obj description
     * @return {type}     description
     */
    marshalForChain: function (obj) {
        var hexObj = {};

        for (var prop in obj) {
            if ({}.hasOwnProperty.call(obj, prop)) {
                var val = obj[prop];

                if (Number.isInteger(val)) {
                    val = String(val);
                } else if (Array.isArray(val)) {
                    val = JSON.stringify(val);
                } else if (typeof val !== "string") {
                    throw new Error("Error at marshalForChain: " + prop + ":" + val + " is not a string.");
                }
                hexObj[prop] = eris.str2hex(val);
            }
        }

        return hexObj;
    }
};

module.exports = chainUtils;
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import styled from 'react-emotion';
import { inject } from 'mobx-react';
import LazyLoad from '@frontity/lazyload';

class LazyIframe extends Component {
  static propTypes = {
    name: PropTypes.string.isRequired,
    src: PropTypes.string.isRequired,
    className: PropTypes.string,
    width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
    height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
    isSsr: PropTypes.bool.isRequired,
  };

  static defaultProps = {
    className: '',
  };

  constructor(props) {
    super(props);
    const { isSsr } = props;
    this.state = { isSsr, loaded: isSsr };
    this.onLoad = this.onLoad.bind(this);
  }

  onLoad() {
    this.setState({ loaded: true });
  }

  render() {
    const { name, src, className, width, height } = this.props;
    const { isSsr, loaded } = this.state;

    if (isSsr)
      return (
        <Iframe
          title={name}
          src={src}
          className={className}
          width={0}
          height={0}
          minWidth={width}
          minHeight={height}
        />
      );

    return (
      <Container className={className}>
        <StyledLazy
          width={width}
          height={height}
          offsetHorizontal={-50}
          throttle={50}
          loaded={loaded}
          debounce={false}
          className={className}
        >
          <Iframe
            title={name}
            src={src}
            className={className}
            width={0}
            height={0}
            minWidth={width}
            minHeight={height}
            onLoad={this.onLoad}
          />
        </StyledLazy>
        {/* {!loaded && <SpinnerContainer>{Spinner && <Spinner />}</SpinnerContainer>} */}
      </Container>
    );
  }
}

export default inject(({ stores: { build } }) => ({
  isSsr: build.isSsr,
}))(LazyIframe);

const StyledLazy = styled(LazyLoad)`
  filter: ${({ loaded }) => (loaded ? 'opacity(100%)' : 'opacity(0)')};
  transition: filter 100ms ease-in;
`;

const Container = styled.div`
  display: block;
  position: relative;
  width: 100%;
  height: 100%;
`;

const Iframe = styled.iframe`
  min-width: ${({ minWidth }) => (typeof minWidth === 'number' ? `${minWidth}px` : minWidth)};
  min-height: ${({ minHeight }) => (typeof minHeight === 'number' ? `${minHeight}px` : minHeight)};
  margin: 0 auto;
  display: block;
  border: none;
`;
<commit_msg>fix(iframe): changes styles in custom iframes<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import styled from 'react-emotion';
import { inject } from 'mobx-react';
import LazyLoad from '@frontity/lazyload';

class LazyIframe extends Component {
  static propTypes = {
    name: PropTypes.string.isRequired,
    src: PropTypes.string.isRequired,
    className: PropTypes.string,
    width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
    height: PropTypes.oneOfType([PropTypes.number, PropTypes.string])
      .isRequired,
    isSsr: PropTypes.bool.isRequired,
  };

  static defaultProps = {
    className: '',
  };

  constructor(props) {
    super(props);
    const { isSsr } = props;
    this.state = { isSsr, loaded: isSsr };
    this.onLoad = this.onLoad.bind(this);
  }

  onLoad() {
    this.setState({ loaded: true });
  }

  render() {
    const { name, src, className, width, height } = this.props;
    const { isSsr, loaded } = this.state;

    if (isSsr)
      return (
        <Container className={className}>
          <Iframe
            title={name}
            src={src}
            className={className}
            width={0}
            height={0}
            minWidth={width}
            minHeight={height}
          />
        </Container>
      );

    return (
      <Container className={className}>
        <StyledLazy
          width={width}
          height={height}
          offsetHorizontal={-50}
          throttle={50}
          loaded={loaded}
          debounce={false}
          className={className}
        >
          <Iframe
            title={name}
            src={src}
            className={className}
            width={0}
            height={0}
            minWidth={width}
            minHeight={height}
            onLoad={this.onLoad}
          />
        </StyledLazy>
        {/* {!loaded && <SpinnerContainer>{Spinner && <Spinner />}</SpinnerContainer>} */}
      </Container>
    );
  }
}

export default inject(({ stores: { build } }) => ({
  isSsr: build.isSsr,
}))(LazyIframe);

const StyledLazy = styled(LazyLoad)`
  filter: ${({ loaded }) => (loaded ? 'opacity(100%)' : 'opacity(0)')};
  transition: filter 100ms ease-in;
`;

const Container = styled.div`
  display: block;
  position: relative;
  width: calc(100% - 30px);
  height: 100%;
  padding: 15px;
`;

const Iframe = styled.iframe`
  min-width: ${({ minWidth }) =>
    typeof minWidth === 'number' ? `${minWidth}px` : minWidth};
  min-height: ${({ minHeight }) =>
    typeof minHeight === 'number' ? `${minHeight}px` : minHeight};
  margin: 0 auto;
  display: block;
  border: none;
`;
<|endoftext|>


<commit_before>var jsdom = require('jsdom')
var dual_xhr  = require("./xhr/dual_xhr.js");
var Q = require('q');

module.exports.create_dom = function (url) {
  /*
   * Setup a bare window ready for dom manipulations
   */
  var document = jsdom.jsdom("", null, {url:url});
  var window = document.createWindow()

  // Monkey-patch createRange support to JSDOM.
  document.createRange = function() {
    return {
      selectNode: function() {},
      createContextualFragment: jsdom.jsdom
    };
  };

  // taken from d3 npm module. index.js
  var CSSStyleDeclaration_prototype = window.CSSStyleDeclaration.prototype,
      CSSStyleDeclaration_setProperty = CSSStyleDeclaration_prototype.setProperty;
  CSSStyleDeclaration_prototype.setProperty = function(name, value, priority) {
    return CSSStyleDeclaration_setProperty.call(this, name + "", value == null ? null : value + "", priority == null ? null : priority + "");
  };

  // attach special xhr object
  window.XMLHttpRequest = dual_xhr.XMLHttpRequest;

  window.console = global.console;
  window.alert = global.console.log;
  window.WebSocket = require('ws');
  return window
}

module.exports.window_loaded = function(window, default_keys) {
  var deferred = Q.defer();
  module.exports.window_vars(window, default_keys, deferred);
  return deferred.promise;
}

module.exports.window_vars = function (window, default_keys, deferred) {
  // checks for the inode_sentinel value added to each html run
  if (!('_inode_sentinel' in window)) {
    setTimeout(module.exports.window_vars, 100, window, default_keys, deferred);
  } else {
    var inode_deferred = window._inode_loads;
    if (inode_deferred) {
      inode_deferred.promise.then(function() {
        console.log('_inode_load');
        deferred.resolve();
      });
    } else {
      deferred.resolve();
    }
  }
}

module.exports.stripScripts = function(html) {
  // Remove scripts from html output
  // When outputting a rendered html page, the jsdom
  // has already run the scripts and including them will only
  // make the script run again.
  // TODO: ability to specify which scripts to run?
  var window = module.exports.create_dom();
  var div = window.document.createElement('div');
  div.innerHTML = html;

  var scripts = div.getElementsByTagName('script');
  var i = scripts.length;
  while (i--) {
    var script = scripts[i];
    if (!(script.getAttribute('inode-keep') == 'true')) {
      scripts[i].parentNode.removeChild(scripts[i]);
    }
  }
  return div.innerHTML;
}
<commit_msg>timeout html run, this also has hoists partial html runs, #27 granted only after a timeout<commit_after>var jsdom = require('jsdom')
var dual_xhr  = require("./xhr/dual_xhr.js");
var Q = require('q');

module.exports.create_dom = function (url) {
  /*
   * Setup a bare window ready for dom manipulations
   */
  var document = jsdom.jsdom("", null, {url:url});
  var window = document.createWindow()

  // Monkey-patch createRange support to JSDOM.
  document.createRange = function() {
    return {
      selectNode: function() {},
      createContextualFragment: jsdom.jsdom
    };
  };

  // taken from d3 npm module. index.js
  var CSSStyleDeclaration_prototype = window.CSSStyleDeclaration.prototype,
      CSSStyleDeclaration_setProperty = CSSStyleDeclaration_prototype.setProperty;
  CSSStyleDeclaration_prototype.setProperty = function(name, value, priority) {
    return CSSStyleDeclaration_setProperty.call(this, name + "", value == null ? null : value + "", priority == null ? null : priority + "");
  };

  // attach special xhr object
  window.XMLHttpRequest = dual_xhr.XMLHttpRequest;

  window.console = global.console;
  window.alert = global.console.log;
  window.WebSocket = require('ws');
  return window
}

module.exports.window_loaded = function(window, default_keys) {
  var deferred = Q.defer();
  module.exports.window_vars(window, default_keys, deferred);
  return deferred.promise;
}

module.exports.window_vars = function (window, default_keys, deferred) {
  // checks for the inode_sentinel value added to each html run
  if (!('_inode_sentinel' in window)) {
    setTimeout(module.exports.window_vars, 100, window, default_keys, deferred);
  } else {
    var inode_deferred = window._inode_load;
    if (inode_deferred) {
      inode_deferred.promise.timeout(5000, 'Page load timeout')
        .then(function() {
          deferred.resolve();})
        .fail(function() {
          console.log('html_run error. Still hoisting availabel variabels');
          deferred.resolve();});
    } else {
      deferred.resolve();
    }
  }
}

module.exports.stripScripts = function(html) {
  // Remove scripts from html output
  // When outputting a rendered html page, the jsdom
  // has already run the scripts and including them will only
  // make the script run again.
  // TODO: ability to specify which scripts to run?
  var window = module.exports.create_dom();
  var div = window.document.createElement('div');
  div.innerHTML = html;

  var scripts = div.getElementsByTagName('script');
  var i = scripts.length;
  while (i--) {
    var script = scripts[i];
    if (!(script.getAttribute('inode-keep') == 'true')) {
      scripts[i].parentNode.removeChild(scripts[i]);
    }
  }
  return div.innerHTML;
}
<|endoftext|>


<commit_before>var argv = require('./argv');
var base = require('./base');
var re = require('./re');

var Formatter = require('./formatter_base');

var iterateLines = base.iterateLines;
var sub = base.sub;

var jspLintStubs = base.jspLintStubs;

var iterateRules = re.iterateRules;

var VERBOSE = argv.v;

var scriptletBlockOpen = '/* scriptlet block ';
var scriptletBlockClose = ' */';

var token = String.fromCharCode(-1);
var nsToken = String.fromCharCode(-2);

var getScriptletBlockReplacement = function(length) {
	return scriptletBlockOpen + (new Array(length).join('\nvoid 0;')) + scriptletBlockClose;
};

require('./js');

Formatter.HTML = Formatter.create(
	{
		extensions: '*.+(jsp*|htm*|vm|ftl|tpl|tmpl)',
		id: 'html',
		prototype: {
			extractJs: function(contents) {
				var filePath = this.file.path;

				var scriptBlocks = [];

				var hasJs = (re.REGEX_AUI_SCRIPT).test(contents);

				if (hasJs) {
					var reAUIScriptGlobal = new RegExp(re.REGEX_AUI_SCRIPT.source, 'g');

					var newContents = contents.replace(/<%.*?%>/gim, jspLintStubs.scriptlet)
										.replace(/<%=[^>]+>/g, jspLintStubs.echoScriptlet)
										.replace(/<portlet:namespace \/>/g, jspLintStubs.namespace);

					newContents.replace(
						reAUIScriptGlobal,
						function(m, tagNamespace, scriptAttrs, body, index) {
							if (!body) {
								return;
							}

							var lines = newContents.substring(0, index).split('\n').length;

							scriptBlocks.push(
								{
									contents: body,
									file: filePath,
									match: m,
									scriptAttrs: scriptAttrs,
									startLine: lines,
									tagNamespace: tagNamespace
								}
							);
						}
					);
				}

				return scriptBlocks;
			},

			format: function(contents) {
				var instance = this;

				instance._attrMap = {};

				instance.parseJs(contents);

				var filePath = instance.file.path;

				var logger = instance.log.bind(instance);

				return iterateLines(
					contents,
					function(item, index, collection) {
						var fullItem = item;

						item = item.trim();

						re.hasExtraNewLines(item, index, collection, logger);

						var lineNum = index + 1;

						var filteredItem = fullItem;

						filteredItem = instance._attrRemoveScriptlets(filteredItem, lineNum);
						filteredItem = instance._attrRemoveTags(filteredItem, lineNum);

						filteredItem = instance._processAttrs(filteredItem, lineNum);

						fullItem = filteredItem;

						fullItem = instance._attrRestoreScriptlets(fullItem, lineNum);
						fullItem = instance._attrRestoreTags(fullItem, lineNum);

						var context = {
							file: filePath,
							item: item,
							logger: logger,
							lineNum: lineNum
						};

						fullItem = iterateRules('html', fullItem, context);

						return fullItem;
					}
				);
			},

			formatJs: function(scriptBlocks) {
				var jsFormatter = new Formatter.JS(this.file.path, this.logger);
				var esLintConfig = require('./eslint_config_jsp');

				return scriptBlocks.map(
					function(item, index) {
						return jsFormatter.format(item.contents, esLintConfig);
					}
				);
			},

			parseJs: function(contents) {
				var scriptBlocks = this.extractJs(contents);

				scriptBlocks = this.sanitizeScriptBlocks(scriptBlocks);
				scriptBlocks = this.formatJs(scriptBlocks);

				return scriptBlocks;
			},

			sanitizeScriptBlocks: function(scriptBlocks) {
				var instance = this;

				scriptBlocks = scriptBlocks.map(
					function(item, index) {
						var contents = item.contents;

						item = instance._jsIterateRules(item);
						item = instance._jsRemoveScriptletBlocks(item);
						item = instance._jsHandleScriptletWhitespace(item);
						item = instance._jsPadLines(item);

						return item;
					}
				);

				return scriptBlocks;
			},

			_attrCheckOrder: function(attrName, lastAttr, line, lineNum) {
				if (lastAttr > attrName) {
					var filePath = this.file.path;

					var regex = new RegExp('\\b' + lastAttr + '\\b.*?> ?<.*?' + attrName);

					var note = '';

					if (regex.test(line)) {
						note = '**';
					}

					if (!note || note && VERBOSE) {
						this.log(lineNum, sub('Sort attributes{2}: {0} {1}', lastAttr, attrName, note));
					}
				}
			},

			_attrGetMapEntry: function(lineNum) {
				var attrMapEntry = this._attrMap[lineNum];

				if (!attrMapEntry) {
					attrMapEntry = {};

					this._attrMap[lineNum] = attrMapEntry;
				}

				return attrMapEntry;
			},

			_attrRemoveScriptlets: function(line, lineNum) {
				var m = line.match(/<%.*?%>/g);

				var matches = m && m.map(
					function(item, index, collection) {
						line = line.replace(item, token + index + token);

						return item;
					}
				);

				var attrMapEntry = this._attrGetMapEntry(lineNum);

				attrMapEntry.matches = matches;

				return line;
			},

			_attrRemoveTags: function(line, lineNum) {
				var nsm = line.match(/<portlet:namespace \/>/);

				var nsMatches = nsm && nsm.map(
					function(item, index) {
						line = line.replace(item, nsToken + index + nsToken);

						return item;
					}
				);

				var attrMapEntry = this._attrGetMapEntry(lineNum);

				attrMapEntry.nsMatches = nsMatches;

				return line;
			},

			_attrRestoreScriptlets: function(line, lineNum) {
				var attrMapEntry = this._attrGetMapEntry(lineNum);

				var matches = attrMapEntry.matches;

				if (matches) {
					line = line.replace(
						new RegExp(token + '(\\d+)' + token, 'g'),
						function(str, id) {
							return matches[id];
						}
					);
				}

				return line;
			},

			_attrRestoreTags: function(line, lineNum) {
				var attrMapEntry = this._attrGetMapEntry(lineNum);

				var nsMatches = attrMapEntry.nsMatches;

				if (nsMatches) {
					line = line.replace(
						new RegExp(nsToken + '(\\d+)' + nsToken, 'g'),
						function(str, id) {
							return nsMatches[id];
						}
					);
				}

				return line;
			},

			_attrSortValues: function(attrName, attrValue, item, line, lineNum) {
				var instance = this;

				var styleAttr = (attrName == 'style');
				var onAttr = (attrName.indexOf('on') === 0);
				var labelAttr = (attrName.indexOf('label') === 0);

				var attrSep = ' ';

				if (styleAttr) {
					attrSep = /\s?;\s?/;
				}

				var attrValuePieces = attrValue.split(attrSep);

				var lastAttrPiece = -1;

				var sort = false;

				var filePath = this.file.path;

				attrValuePieces.forEach(
					function(item, index, collection) {
						item = item.trim();
						if (/^[A-Za-z]/.test(item)) {
							// Skip event handlers like onClick, etc since they will have
							// complex values that probably shouldn't be sorted
							if (!onAttr && !labelAttr && lastAttrPiece > item) {
								instance.log(lineNum, sub('Sort attribute values: {0} {1}',  lastAttrPiece, item));

								sort = true;
							}

							lastAttrPiece = item;
						}
					}
				);

				var newAttrValue;

				if (sort) {
					attrValuePieces = attrValuePieces.filter(
						function(item, index, collection) {
							return !!item.trim();
						}
					);

					attrValuePieces.sort();

					if (styleAttr) {
						newAttrValue = attrValuePieces.join('; ') + ';';
					}
					else {
						newAttrValue = attrValuePieces.join(' ');
					}

					item = item.replace(attrValue, newAttrValue);
				}

				return item;
			},

			_jsHandleScriptletWhitespace: function(scriptBlock) {
				var contents = scriptBlock.contents;

				// Let's check to see if we have new new lines at the start
				// or end of a script block due to scriptlet blocks, ie:
				// <aui:script>
				//
				//  <% if() { %>
				// ...
				// <% } %>
				//
				// </aui:script>
				//
				// We should ignore those lines as they're valid for this case

				var lines = contents.split('\n');
				var numLines = lines.length;

				if (numLines >= 3) {
					if (lines[1] === '' && lines[2].indexOf(scriptletBlockOpen) > -1) {
						lines[1] = 'void 0;';
					}

					if (lines[numLines - 2] === '' && lines[numLines - 3].indexOf('void 0; */') > -1) {
						lines[numLines - 2] = 'void 0;';
					}
				}

				// If we have something like:
				// <%= obj.getJavaScript() %>
				// go ahead and assume it's okay to exist
				// on it's own line

				contents = lines.map(
					function(item, index) {
						if (re.REGEX_SCRIPTLET_STUB.test(item)) {
							item = '//' + item;
						}

						return item;
					}
				).join('\n');

				scriptBlock.contents = contents;

				return scriptBlock;
			},

			_jsIterateRules: function(scriptBlock) {
				var instance = this;

				var contents = scriptBlock.contents;
				var file = scriptBlock.file;
				var match = scriptBlock.match;
				var scriptAttrs = scriptBlock.scriptAttrs;
				var startLine = scriptBlock.startLine;
				var tagNamespace = scriptBlock.tagNamespace;

				var asyncAUIScript = tagNamespace && tagNamespace.indexOf('aui:') === 0 && scriptAttrs.indexOf('use="') > -1;

				iterateLines(
					contents,
					function(item, index) {
						var fullItem = item;
						var lineNum = startLine + index;

						item = item.trim();

						var context = {
							asyncAUIScript: asyncAUIScript,
							body: contents,
							file: file,
							fullMatch: match,
							item: item,
							lineNum: lineNum,
							scriptAttrs: scriptAttrs,
							tagNamespace: tagNamespace
						};

						fullItem = iterateRules('htmlJS', fullItem, context);
					}
				);

				return scriptBlock;
			},

			_jsPadLines: function(scriptBlock) {
				var prefix = new Array(scriptBlock.startLine).join('void 0;\n');

				scriptBlock.contents = prefix + scriptBlock.contents;

				return scriptBlock;
			},

			_jsRemoveScriptletBlocks: function(scriptBlock) {
				var rescanBlocks = [];

				var contents = scriptBlock.contents;

				contents = contents.replace(/\$\{.*?\}/g, jspLintStubs.elExpression)
							.replace(
								/<%[^>]+>/g,
								function(m, index) {
									var len = m.length;
									var retVal = m;

									// If the last portion of this block is not the closing
									// scriptlet, let's keep track that we should rescan this
									// eg. when we hit cases like:
									// <% List<String> foo = null; %>
									// the regex will stop at String>

									if (m.substr(len - 2, len - 1) === '%>') {
										retVal = getScriptletBlockReplacement(m.split('\n').length);
									}
									else {
										rescanBlocks.push(true);
									}

									return retVal;
								}
							).replace(/<\/?[A-Za-z0-9-_]+:[^>]+>/g, '/* jsp tag */');

				if (rescanBlocks.length) {
					var scriptBlockRe = /<%/g;
					var match;

					// We didn't find the closing %>, so let's iterate
					// over all of the characters from the start of the
					// remaining scriptlet blocks until we get to %>

					while (match = scriptBlockRe.exec(contents)) {
						var matchIndex = match.index;

						for (var i = matchIndex; i < contents.length; i++) {
							var item = contents.charAt(i);

							if (item && item == '>' && contents.charAt(i - 1) == '%') {
								var block = contents.substring(matchIndex, i + 1);

								contents = contents.replace(block, getScriptletBlockReplacement(block.split('\n').length));

								break;
							}
						}
					}
				}

				scriptBlock.contents = contents;

				return scriptBlock;
			},

			_processAttrs: function(line, lineNum) {
				var instance = this;

				var filePath = this.file.path;

				line = line.replace(
					/<[^>]+>/g,
					function(m, mi, str) {
						var attrs = m.match(/(?: )?([A-Za-z0-9-]+=(["']).*?\2)/g);

						if (attrs) {
							var lastAttr = -1;

							attrs.forEach(
								function(item, index, collection) {
									var oldItem = item;

									var pieces = item.trim().match(/^([^=]+)=(["'])(.*)\2$/);

									var attrName = pieces[1];
									var attrValue = pieces[3];

									instance._attrCheckOrder(attrName, lastAttr, line, lineNum);

									item = instance._attrSortValues(attrName, attrValue, item, line, lineNum);

									lastAttr = attrName;

									m = m.replace(oldItem, item);
								}
							);
						}

						return m;
					}
				);

				return line;
			}
		}
	}
);

module.exports = Formatter.HTML;<commit_msg>Run the common rules against HTML<commit_after>var argv = require('./argv');
var base = require('./base');
var re = require('./re');

var Formatter = require('./formatter_base');

var iterateLines = base.iterateLines;
var sub = base.sub;

var jspLintStubs = base.jspLintStubs;

var iterateRules = re.iterateRules;

var VERBOSE = argv.v;

var scriptletBlockOpen = '/* scriptlet block ';
var scriptletBlockClose = ' */';

var token = String.fromCharCode(-1);
var nsToken = String.fromCharCode(-2);

var getScriptletBlockReplacement = function(length) {
	return scriptletBlockOpen + (new Array(length).join('\nvoid 0;')) + scriptletBlockClose;
};

require('./js');

Formatter.HTML = Formatter.create(
	{
		extensions: '*.+(jsp*|htm*|vm|ftl|tpl|tmpl)',
		id: 'html',
		prototype: {
			extractJs: function(contents) {
				var filePath = this.file.path;

				var scriptBlocks = [];

				var hasJs = (re.REGEX_AUI_SCRIPT).test(contents);

				if (hasJs) {
					var reAUIScriptGlobal = new RegExp(re.REGEX_AUI_SCRIPT.source, 'g');

					var newContents = contents.replace(/<%.*?%>/gim, jspLintStubs.scriptlet)
										.replace(/<%=[^>]+>/g, jspLintStubs.echoScriptlet)
										.replace(/<portlet:namespace \/>/g, jspLintStubs.namespace);

					newContents.replace(
						reAUIScriptGlobal,
						function(m, tagNamespace, scriptAttrs, body, index) {
							if (!body) {
								return;
							}

							var lines = newContents.substring(0, index).split('\n').length;

							scriptBlocks.push(
								{
									contents: body,
									file: filePath,
									match: m,
									scriptAttrs: scriptAttrs,
									startLine: lines,
									tagNamespace: tagNamespace
								}
							);
						}
					);
				}

				return scriptBlocks;
			},

			format: function(contents) {
				var instance = this;

				instance._attrMap = {};

				instance.parseJs(contents);

				var filePath = instance.file.path;

				var logger = instance.log.bind(instance);

				return iterateLines(
					contents,
					function(item, index, collection) {
						var fullItem = item;

						item = item.trim();

						re.hasExtraNewLines(item, index, collection, logger);

						var lineNum = index + 1;

						var filteredItem = fullItem;

						filteredItem = instance._attrRemoveScriptlets(filteredItem, lineNum);
						filteredItem = instance._attrRemoveTags(filteredItem, lineNum);

						filteredItem = instance._processAttrs(filteredItem, lineNum);

						fullItem = filteredItem;

						fullItem = instance._attrRestoreScriptlets(fullItem, lineNum);
						fullItem = instance._attrRestoreTags(fullItem, lineNum);

						var context = {
							file: filePath,
							item: item,
							logger: logger,
							lineNum: lineNum
						};

						fullItem = iterateRules('common', fullItem, context);

						fullItem = iterateRules('html', fullItem, context);

						return fullItem;
					}
				);
			},

			formatJs: function(scriptBlocks) {
				var jsFormatter = new Formatter.JS(this.file.path, this.logger);
				var esLintConfig = require('./eslint_config_jsp');

				return scriptBlocks.map(
					function(item, index) {
						return jsFormatter.format(item.contents, esLintConfig);
					}
				);
			},

			parseJs: function(contents) {
				var scriptBlocks = this.extractJs(contents);

				scriptBlocks = this.sanitizeScriptBlocks(scriptBlocks);
				scriptBlocks = this.formatJs(scriptBlocks);

				return scriptBlocks;
			},

			sanitizeScriptBlocks: function(scriptBlocks) {
				var instance = this;

				scriptBlocks = scriptBlocks.map(
					function(item, index) {
						var contents = item.contents;

						item = instance._jsIterateRules(item);
						item = instance._jsRemoveScriptletBlocks(item);
						item = instance._jsHandleScriptletWhitespace(item);
						item = instance._jsPadLines(item);

						return item;
					}
				);

				return scriptBlocks;
			},

			_attrCheckOrder: function(attrName, lastAttr, line, lineNum) {
				if (lastAttr > attrName) {
					var filePath = this.file.path;

					var regex = new RegExp('\\b' + lastAttr + '\\b.*?> ?<.*?' + attrName);

					var note = '';

					if (regex.test(line)) {
						note = '**';
					}

					if (!note || note && VERBOSE) {
						this.log(lineNum, sub('Sort attributes{2}: {0} {1}', lastAttr, attrName, note));
					}
				}
			},

			_attrGetMapEntry: function(lineNum) {
				var attrMapEntry = this._attrMap[lineNum];

				if (!attrMapEntry) {
					attrMapEntry = {};

					this._attrMap[lineNum] = attrMapEntry;
				}

				return attrMapEntry;
			},

			_attrRemoveScriptlets: function(line, lineNum) {
				var m = line.match(/<%.*?%>/g);

				var matches = m && m.map(
					function(item, index, collection) {
						line = line.replace(item, token + index + token);

						return item;
					}
				);

				var attrMapEntry = this._attrGetMapEntry(lineNum);

				attrMapEntry.matches = matches;

				return line;
			},

			_attrRemoveTags: function(line, lineNum) {
				var nsm = line.match(/<portlet:namespace \/>/);

				var nsMatches = nsm && nsm.map(
					function(item, index) {
						line = line.replace(item, nsToken + index + nsToken);

						return item;
					}
				);

				var attrMapEntry = this._attrGetMapEntry(lineNum);

				attrMapEntry.nsMatches = nsMatches;

				return line;
			},

			_attrRestoreScriptlets: function(line, lineNum) {
				var attrMapEntry = this._attrGetMapEntry(lineNum);

				var matches = attrMapEntry.matches;

				if (matches) {
					line = line.replace(
						new RegExp(token + '(\\d+)' + token, 'g'),
						function(str, id) {
							return matches[id];
						}
					);
				}

				return line;
			},

			_attrRestoreTags: function(line, lineNum) {
				var attrMapEntry = this._attrGetMapEntry(lineNum);

				var nsMatches = attrMapEntry.nsMatches;

				if (nsMatches) {
					line = line.replace(
						new RegExp(nsToken + '(\\d+)' + nsToken, 'g'),
						function(str, id) {
							return nsMatches[id];
						}
					);
				}

				return line;
			},

			_attrSortValues: function(attrName, attrValue, item, line, lineNum) {
				var instance = this;

				var styleAttr = (attrName == 'style');
				var onAttr = (attrName.indexOf('on') === 0);
				var labelAttr = (attrName.indexOf('label') === 0);

				var attrSep = ' ';

				if (styleAttr) {
					attrSep = /\s?;\s?/;
				}

				var attrValuePieces = attrValue.split(attrSep);

				var lastAttrPiece = -1;

				var sort = false;

				var filePath = this.file.path;

				attrValuePieces.forEach(
					function(item, index, collection) {
						item = item.trim();
						if (/^[A-Za-z]/.test(item)) {
							// Skip event handlers like onClick, etc since they will have
							// complex values that probably shouldn't be sorted
							if (!onAttr && !labelAttr && lastAttrPiece > item) {
								instance.log(lineNum, sub('Sort attribute values: {0} {1}',  lastAttrPiece, item));

								sort = true;
							}

							lastAttrPiece = item;
						}
					}
				);

				var newAttrValue;

				if (sort) {
					attrValuePieces = attrValuePieces.filter(
						function(item, index, collection) {
							return !!item.trim();
						}
					);

					attrValuePieces.sort();

					if (styleAttr) {
						newAttrValue = attrValuePieces.join('; ') + ';';
					}
					else {
						newAttrValue = attrValuePieces.join(' ');
					}

					item = item.replace(attrValue, newAttrValue);
				}

				return item;
			},

			_jsHandleScriptletWhitespace: function(scriptBlock) {
				var contents = scriptBlock.contents;

				// Let's check to see if we have new new lines at the start
				// or end of a script block due to scriptlet blocks, ie:
				// <aui:script>
				//
				//  <% if() { %>
				// ...
				// <% } %>
				//
				// </aui:script>
				//
				// We should ignore those lines as they're valid for this case

				var lines = contents.split('\n');
				var numLines = lines.length;

				if (numLines >= 3) {
					if (lines[1] === '' && lines[2].indexOf(scriptletBlockOpen) > -1) {
						lines[1] = 'void 0;';
					}

					if (lines[numLines - 2] === '' && lines[numLines - 3].indexOf('void 0; */') > -1) {
						lines[numLines - 2] = 'void 0;';
					}
				}

				// If we have something like:
				// <%= obj.getJavaScript() %>
				// go ahead and assume it's okay to exist
				// on it's own line

				contents = lines.map(
					function(item, index) {
						if (re.REGEX_SCRIPTLET_STUB.test(item)) {
							item = '//' + item;
						}

						return item;
					}
				).join('\n');

				scriptBlock.contents = contents;

				return scriptBlock;
			},

			_jsIterateRules: function(scriptBlock) {
				var instance = this;

				var contents = scriptBlock.contents;
				var file = scriptBlock.file;
				var match = scriptBlock.match;
				var scriptAttrs = scriptBlock.scriptAttrs;
				var startLine = scriptBlock.startLine;
				var tagNamespace = scriptBlock.tagNamespace;

				var asyncAUIScript = tagNamespace && tagNamespace.indexOf('aui:') === 0 && scriptAttrs.indexOf('use="') > -1;

				iterateLines(
					contents,
					function(item, index) {
						var fullItem = item;
						var lineNum = startLine + index;

						item = item.trim();

						var context = {
							asyncAUIScript: asyncAUIScript,
							body: contents,
							file: file,
							fullMatch: match,
							item: item,
							lineNum: lineNum,
							scriptAttrs: scriptAttrs,
							tagNamespace: tagNamespace
						};

						fullItem = iterateRules('htmlJS', fullItem, context);
					}
				);

				return scriptBlock;
			},

			_jsPadLines: function(scriptBlock) {
				var prefix = new Array(scriptBlock.startLine).join('void 0;\n');

				scriptBlock.contents = prefix + scriptBlock.contents;

				return scriptBlock;
			},

			_jsRemoveScriptletBlocks: function(scriptBlock) {
				var rescanBlocks = [];

				var contents = scriptBlock.contents;

				contents = contents.replace(/\$\{.*?\}/g, jspLintStubs.elExpression)
							.replace(
								/<%[^>]+>/g,
								function(m, index) {
									var len = m.length;
									var retVal = m;

									// If the last portion of this block is not the closing
									// scriptlet, let's keep track that we should rescan this
									// eg. when we hit cases like:
									// <% List<String> foo = null; %>
									// the regex will stop at String>

									if (m.substr(len - 2, len - 1) === '%>') {
										retVal = getScriptletBlockReplacement(m.split('\n').length);
									}
									else {
										rescanBlocks.push(true);
									}

									return retVal;
								}
							).replace(/<\/?[A-Za-z0-9-_]+:[^>]+>/g, '/* jsp tag */');

				if (rescanBlocks.length) {
					var scriptBlockRe = /<%/g;
					var match;

					// We didn't find the closing %>, so let's iterate
					// over all of the characters from the start of the
					// remaining scriptlet blocks until we get to %>

					while (match = scriptBlockRe.exec(contents)) {
						var matchIndex = match.index;

						for (var i = matchIndex; i < contents.length; i++) {
							var item = contents.charAt(i);

							if (item && item == '>' && contents.charAt(i - 1) == '%') {
								var block = contents.substring(matchIndex, i + 1);

								contents = contents.replace(block, getScriptletBlockReplacement(block.split('\n').length));

								break;
							}
						}
					}
				}

				scriptBlock.contents = contents;

				return scriptBlock;
			},

			_processAttrs: function(line, lineNum) {
				var instance = this;

				var filePath = this.file.path;

				line = line.replace(
					/<[^>]+>/g,
					function(m, mi, str) {
						var attrs = m.match(/(?: )?([A-Za-z0-9-]+=(["']).*?\2)/g);

						if (attrs) {
							var lastAttr = -1;

							attrs.forEach(
								function(item, index, collection) {
									var oldItem = item;

									var pieces = item.trim().match(/^([^=]+)=(["'])(.*)\2$/);

									var attrName = pieces[1];
									var attrValue = pieces[3];

									instance._attrCheckOrder(attrName, lastAttr, line, lineNum);

									item = instance._attrSortValues(attrName, attrValue, item, line, lineNum);

									lastAttr = attrName;

									m = m.replace(oldItem, item);
								}
							);
						}

						return m;
					}
				);

				return line;
			}
		}
	}
);

module.exports = Formatter.HTML;<|endoftext|>