<commit_before>const connector = require('./Connector')

let _where = ''
let _select = ''
let _from = ''
let _orderBy = ''
let _groupBy = ''
let _limit = ''
let _skip = ''
let _join = ''
let _insert = ''
let _delete = ''
let _update = ''
let _command = ''
let _table = ''
let _option = ''
let _params = []

/**
 * [Generate ? symbol for sql query for every parameter]
 * @param  {Array} columns [List of all parameters on sql query]
 * @return {String}        [Correct syntax for query builder of parameters]
 */
function returnSymbolParamsCount (columns) {
  let length = columns.length
  let symbols = Array(length).join('?, ')
  return symbols.slice(0, -2)
}

module.exports = {

  /**
   * [Select clause of sql query which select the columns (properties) of records]
   * @param  {Array} columns [Array or String All selected columns from table]
   * @return {QueryBuilder}  [Query Builder Creator of sql queries and connect to database]
   */
  select: function (columns) {
    if (Array.isArray(columns)) {
      _select = `SELECT ${columns.join(', ')}`
    } else if (columns.length > 0) {
      _select = `SELECT ${columns}`
    } else {
      throw new Error('The columns is not available in correct format!')
    }

    _option = 'select'
    return this
  },

  /**
   * [From clause of sql query which select the database table]
   * @param  {String} table [The name of database table]
   * @return {QueryBuilder} [Query Builder Creator of sql queries and connect to database]
   */
  from: function (table) {
    if (table.length > 0 && !Array.isArray(table)) {
      _from = ` FROM ${table}`
      _table = table
      return this
    } else {
      throw new Error('The table variable is required to be string!')
    }
  },

  /**
   * [Set the name of database table]
   * @param  {String} table [The name of database table]
   * @return {QueryBuilder} [Query Builder Creator of sql queries and connect to database]
   */
  table: function (table) {
    if (table.length > 0 && !Array.isArray(table)) {
      _table = table
      return this
    } else {
      throw new Error('The table variable is required to be string!')
    }
  },

  /**
   * [Add few more columns on select caluse of sql query]
   * @param  {String} columns [Array or String All selected columns from table]
   * @return {QueryBuilder}  [Query Builder Creator of sql queries and connect to database]
   */
  addSelect: function (columns) {
    if (!_select) {
      throw new Error('Please first use SELECT method before add new column on select method!')
    } else if (Array.isArray(columns)) {
      _select += ` ${columns.join(', ')}`
    } else if (columns.length > 0) {
      _select += ` ${columns}`
    } else {
      throw new Error('The columns is not available in correct format!')
    }

    return this
  },

  /**
   * [Insert clause on sql query which is create to add new record on database]
   * @param  {Array} columns [All columns which is to add on database]
   * @return {QueryBuilder} [Query Builder Creator of sql queries and connect to database]
   */
  add: function (columns) {
    if (Array.isArray(columns)) {
      let symbols = returnSymbolParamsCount(columns)

      if (symbols.length > 0) {
        _insert = 'INSERT INTO `' + _table + '` ( ' + symbols + ' ) VALUES ( ' + symbols + ' )'
        _option = 'insert'
        return this
      } else {
        throw new Error('The columns is empty!')
      }
    } else {
      throw new Error('The columns is required to be array!')
    }
  },

  /**
   * [Delete clause on sql query which is delete record from database]
   * @return {QueryBuilder} [Query Builder Creator of sql queries and connect to database]
   */
  delete: function () {
    if (_table) {
      _delete = `DELETE FROM ${_table}`
      _option = 'delete'
      return this
    } else {
      throw new Error('Is need to enter in which table is need to delete record!')
    }
  },

  /**
   * [Update clause on sql query which is update current record on database]
   * @param  {Array} columns [All columns which is update on databse]
   * @return {QueryBuilder} [Query Builder Creator of sql queries and connect to database]
   */
  update: function (columns) {
    if (!Array.isArray(columns)) {
      throw new Error('The columns variable is required to be array!')
    }

    if (!_table) {
      throw new Error('Is need to enter in which table is need to delete record!')
    }

    let cl = columns.map((cl) => { return cl + ' = ?, ' })
    _update = `UPDATE ${_table} SET ${cl.join('').slice(0, -2)}`
    _option = 'update'
    return this
  },

  /**
   * [Join clause on sql query which is just join another table on sql query]
   * @param  {String} table [The database table which is need to join]
   * @param  {String} equal [The columns ids equals on both databases]
   * @param  {String} type  [Type of join clause (left, inner, outer etc)]
   * @return {QueryBuilder} [Query Builder Creator of sql queries and connect to database]
   */
  join: function (table, equal, type) {
    if (typeof table === 'string' && table.length > 1 &&
    typeof equal === 'string' && equal.length > 1) {
      _join += ` ${type} JOIN ${table} ON ${equal}`
      return this
    } else {
      throw new Error('The table and equal variable is required to be string!')
    }
  },

  /**
   * [Take clause on sql query which is set how many records to take from database table]
   * @param  {Number} limit [How many items to take]
   * @return {QueryBuilder} [Query Builder Creator of sql queries and connect to database]
   */
  take: function (limit) {
    limit = parseInt(limit)

    if (isNaN(limit)) {
      throw new Error('The limit variable is required to be Integer!')
    }

    _limit = ` LIMIT ${limit}`
    return this
  },

  /**
   * [Skip clause on sql query which is set how many records to skip from database table]
   * @param  {Number} count [How many items to skip]
   * @return {QueryBuilder} [Query Builder Creator of sql queries and connect to database]
   */
  skip: function (count) {
    count = parseInt(count)

    if (isNaN(count)) {
      throw new Error('The count variable is required to be Integer!')
    }

    _skip = ` OFFSET ${count}`
    return this
  },

  /**
   * [Top clause on sql query which is set how many records to get from database table]
   * @param  {Number} count [How many items to show]
   * @return {QueryBuilder} [Query Builder Creator of sql queries and connect to database]
   */
  top: function (count) {
    if (_select) {
      throw new Error('Is need to not have select!')
    }

    count = parseInt(count)

    if (isNaN(count)) {
      throw new Error('The count variable is required to be Integer!')
    }

    _select = `SELECT TOP ${count} `
    _option = 'select'
    return this
  },

  /**
   * [Order clause on sql query which is order by one column]
   * @param  {String}  column         [The column on table with which is to be ordered]
   * @param  {Boolean} [isDesc=false] [Do is DESC or ASC]
   * @return {QueryBuilder}           [Query Builder Creator of sql queries and connect to database]
   */
  orderBy: function (column, isDesc = false) {
    if (typeof column !== 'string') {
      throw new Error('The column variable is required to be string!')
    }

    _orderBy = ` ORDER BY ${column} `

    if (isDesc) {
      _orderBy += ' DESC '
    }

    return this
  },

  /**
   * [Group clause on sql query which is set the grouped by column]
   * @param  {String}  column         [The column on table with which is to be grouped]
   * @param  {Boolean} [isDesc=false] [Do is DESC or ASC]
   * @return {QueryBuilder}           [Query Builder Creator of sql queries and connect to database]
   */
  groupBy: function (column, isDesc = false) {
    if (typeof column !== 'string') {
      throw new Error('The column variable is required to be string!')
    }

    _groupBy = ` GROUP BY ${column} `

    if (isDesc) {
      _groupBy += ' DESC '
    }

    return this
  },

  /**
   * [Where clause on sql query which is check do column is some equal with param]
   * @param  {String} column         [Column from database table to check do is some equal with param]
   * @param  {String} [operator='='] [Operator for comparison the column and parameter]
   * @param  {String} [param=null]   [Value to check do column from database table is some equal with value]
   * @return {QueryBuilder}          [Query Builder Creator of sql queries and connect to database]
   */
  where: function (column, operator = '=', param = null) {
    if (typeof column === 'string' && typeof operator === 'string') {
      _where = ` WHERE ${column} ${operator.replace(/'"/g, '')} ?`

      if (param && !Array.isArray(param)) {
        _params.push(param)
      }

      return this
    } else {
      throw new Error('The column and operator variable is required to be string!')
    }
  },

  /**
   * [If is used the where clause then that is next where clause if is need both to be true]
   * @param  {String} column         [Column from database table to check do is some equal with param]
   * @param  {String} [operator='='] [Operator for comparison the column and parameter]
   * @param  {String} [param=null]   [Value to check do column from database table is some equal with value]
   * @return {QueryBuilder}          [Query Builder Creator of sql queries and connect to database]
   */
  andWhere: function (column, operator = '=', param = null) {
    return this
  },

  orWhere: function (column, operator = '=', param = null) {

  },

  /**
   * [Get all sql query parameters]
   * @return {Array} [SQL Query parameters]
   */
  getParameters: () => {
    return _params
  },

  /**
   * [Set parameters for created sql query]
   * @param  {Array} values [SQL query parameres only values]
   * @return {QueryBuilder} [Query Builder Creator of sql queries and connect to database]
   */
  setParameters: function (values) {
    let len = values.length

    if (len > 0) {
      for (let i = 0; i < len; i++) {
        _params.push(values[i])
      }

      return this
    } else {
      throw new Error('The values variable is required to be array!')
    }
  },

  /**
   * [Get the created sql query]
   * @return {String} [SQL Query]
   */
  getCommand: () => {
    return _command
  },

  /**
   * [Set Your own SQL Query]
   * @param  {String} command [SQL Query]
   * @return {QueryBuilder}   [Query Builder Creator of sql queries and connect to database]
   */
  setCommand: function (command) {
    if (typeof command !== 'string') {
      throw new Error('The command variable is required to be string!')
    }
    _command = command
    return this
  },

  /**
   * [Prepare the sql query and set what kind of query is will used]
   * @return {QueryBuilder} [Query Builder Creator of sql queries and connect to database]
   */
  prepare: function () {
    if (_option === 'select') {
      _command = _select + _from + _join + _groupBy + _where + _orderBy + _limit + _skip
    } else if (_option === 'insert') {
      _command = _insert
    } else if (_option === 'update') {
      _command = _update + _where
    } else if (_option === 'delete') {
      _command = _delete + _where
    } else {
      _command = _where + _limit + _skip
    }

    _select = ''
    _from = ''
    _join = ''
    _groupBy = ''
    _where = ''
    _orderBy = ''
    _limit = ''
    _skip = ''
    _insert = ''
    _update = ''
    _delete = ''

    return this
  },

  /**
   * [Execute the created sql query]
   * @return {Boolean} [Do is executed correct]
   */
  execute: function () {
    return true
  },

  /**
   * [Get the result from created sql query]
   * @return {[type]} [SQL Query result]
   */
  get: () => {

  }
}
<commit_msg>Delete the get and execute functions<commit_after>const connector = require('./Connector')

let _where = ''
let _select = ''
let _from = ''
let _orderBy = ''
let _groupBy = ''
let _limit = ''
let _skip = ''
let _join = ''
let _insert = ''
let _delete = ''
let _update = ''
let _command = ''
let _table = ''
let _option = ''
let _params = []

/**
 * [Generate ? symbol for sql query for every parameter]
 * @param  {Array} columns [List of all parameters on sql query]
 * @return {String}        [Correct syntax for query builder of parameters]
 */
function returnSymbolParamsCount (columns) {
  let length = columns.length
  let symbols = Array(length).join('?, ')
  return symbols.slice(0, -2)
}

module.exports = {

  /**
   * [Select clause of sql query which select the columns (properties) of records]
   * @param  {Array} columns [Array or String All selected columns from table]
   * @return {QueryBuilder}  [Query Builder Creator of sql queries and connect to database]
   */
  select: function (columns) {
    if (Array.isArray(columns)) {
      _select = `SELECT ${columns.join(', ')}`
    } else if (columns.length > 0) {
      _select = `SELECT ${columns}`
    } else {
      throw new Error('The columns is not available in correct format!')
    }

    _option = 'select'
    return this
  },

  /**
   * [From clause of sql query which select the database table]
   * @param  {String} table [The name of database table]
   * @return {QueryBuilder} [Query Builder Creator of sql queries and connect to database]
   */
  from: function (table) {
    if (table.length > 0 && !Array.isArray(table)) {
      _from = ` FROM ${table}`
      _table = table
      return this
    } else {
      throw new Error('The table variable is required to be string!')
    }
  },

  /**
   * [Set the name of database table]
   * @param  {String} table [The name of database table]
   * @return {QueryBuilder} [Query Builder Creator of sql queries and connect to database]
   */
  table: function (table) {
    if (table.length > 0 && !Array.isArray(table)) {
      _table = table
      return this
    } else {
      throw new Error('The table variable is required to be string!')
    }
  },

  /**
   * [Add few more columns on select caluse of sql query]
   * @param  {String} columns [Array or String All selected columns from table]
   * @return {QueryBuilder}  [Query Builder Creator of sql queries and connect to database]
   */
  addSelect: function (columns) {
    if (!_select) {
      throw new Error('Please first use SELECT method before add new column on select method!')
    } else if (Array.isArray(columns)) {
      _select += ` ${columns.join(', ')}`
    } else if (columns.length > 0) {
      _select += ` ${columns}`
    } else {
      throw new Error('The columns is not available in correct format!')
    }

    return this
  },

  /**
   * [Insert clause on sql query which is create to add new record on database]
   * @param  {Array} columns [All columns which is to add on database]
   * @return {QueryBuilder} [Query Builder Creator of sql queries and connect to database]
   */
  add: function (columns) {
    if (Array.isArray(columns)) {
      let symbols = returnSymbolParamsCount(columns)

      if (symbols.length > 0) {
        _insert = 'INSERT INTO `' + _table + '` ( ' + symbols + ' ) VALUES ( ' + symbols + ' )'
        _option = 'insert'
        return this
      } else {
        throw new Error('The columns is empty!')
      }
    } else {
      throw new Error('The columns is required to be array!')
    }
  },

  /**
   * [Delete clause on sql query which is delete record from database]
   * @return {QueryBuilder} [Query Builder Creator of sql queries and connect to database]
   */
  delete: function () {
    if (_table) {
      _delete = `DELETE FROM ${_table}`
      _option = 'delete'
      return this
    } else {
      throw new Error('Is need to enter in which table is need to delete record!')
    }
  },

  /**
   * [Update clause on sql query which is update current record on database]
   * @param  {Array} columns [All columns which is update on databse]
   * @return {QueryBuilder} [Query Builder Creator of sql queries and connect to database]
   */
  update: function (columns) {
    if (!Array.isArray(columns)) {
      throw new Error('The columns variable is required to be array!')
    }

    if (!_table) {
      throw new Error('Is need to enter in which table is need to delete record!')
    }

    let cl = columns.map((cl) => { return cl + ' = ?, ' })
    _update = `UPDATE ${_table} SET ${cl.join('').slice(0, -2)}`
    _option = 'update'
    return this
  },

  /**
   * [Join clause on sql query which is just join another table on sql query]
   * @param  {String} table [The database table which is need to join]
   * @param  {String} equal [The columns ids equals on both databases]
   * @param  {String} type  [Type of join clause (left, inner, outer etc)]
   * @return {QueryBuilder} [Query Builder Creator of sql queries and connect to database]
   */
  join: function (table, equal, type) {
    if (typeof table === 'string' && table.length > 1 &&
    typeof equal === 'string' && equal.length > 1) {
      _join += ` ${type} JOIN ${table} ON ${equal}`
      return this
    } else {
      throw new Error('The table and equal variable is required to be string!')
    }
  },

  /**
   * [Take clause on sql query which is set how many records to take from database table]
   * @param  {Number} limit [How many items to take]
   * @return {QueryBuilder} [Query Builder Creator of sql queries and connect to database]
   */
  take: function (limit) {
    limit = parseInt(limit)

    if (isNaN(limit)) {
      throw new Error('The limit variable is required to be Integer!')
    }

    _limit = ` LIMIT ${limit}`
    return this
  },

  /**
   * [Skip clause on sql query which is set how many records to skip from database table]
   * @param  {Number} count [How many items to skip]
   * @return {QueryBuilder} [Query Builder Creator of sql queries and connect to database]
   */
  skip: function (count) {
    count = parseInt(count)

    if (isNaN(count)) {
      throw new Error('The count variable is required to be Integer!')
    }

    _skip = ` OFFSET ${count}`
    return this
  },

  /**
   * [Top clause on sql query which is set how many records to get from database table]
   * @param  {Number} count [How many items to show]
   * @return {QueryBuilder} [Query Builder Creator of sql queries and connect to database]
   */
  top: function (count) {
    if (_select) {
      throw new Error('Is need to not have select!')
    }

    count = parseInt(count)

    if (isNaN(count)) {
      throw new Error('The count variable is required to be Integer!')
    }

    _select = `SELECT TOP ${count} `
    _option = 'select'
    return this
  },

  /**
   * [Order clause on sql query which is order by one column]
   * @param  {String}  column         [The column on table with which is to be ordered]
   * @param  {Boolean} [isDesc=false] [Do is DESC or ASC]
   * @return {QueryBuilder}           [Query Builder Creator of sql queries and connect to database]
   */
  orderBy: function (column, isDesc = false) {
    if (typeof column !== 'string') {
      throw new Error('The column variable is required to be string!')
    }

    _orderBy = ` ORDER BY ${column} `

    if (isDesc) {
      _orderBy += ' DESC '
    }

    return this
  },

  /**
   * [Group clause on sql query which is set the grouped by column]
   * @param  {String}  column         [The column on table with which is to be grouped]
   * @param  {Boolean} [isDesc=false] [Do is DESC or ASC]
   * @return {QueryBuilder}           [Query Builder Creator of sql queries and connect to database]
   */
  groupBy: function (column, isDesc = false) {
    if (typeof column !== 'string') {
      throw new Error('The column variable is required to be string!')
    }

    _groupBy = ` GROUP BY ${column} `

    if (isDesc) {
      _groupBy += ' DESC '
    }

    return this
  },

  /**
   * [Where clause on sql query which is check do column is some equal with param]
   * @param  {String} column         [Column from database table to check do is some equal with param]
   * @param  {String} [operator='='] [Operator for comparison the column and parameter]
   * @param  {String} [param=null]   [Value to check do column from database table is some equal with value]
   * @return {QueryBuilder}          [Query Builder Creator of sql queries and connect to database]
   */
  where: function (column, operator = '=', param = null) {
    if (typeof column === 'string' && typeof operator === 'string') {
      _where = ` WHERE ${column} ${operator.replace(/'"/g, '')} ?`

      if (param && !Array.isArray(param)) {
        _params.push(param)
      }

      return this
    } else {
      throw new Error('The column and operator variable is required to be string!')
    }
  },

  /**
   * [If is used the where clause then that is next where clause if is need both to be true]
   * @param  {String} column         [Column from database table to check do is some equal with param]
   * @param  {String} [operator='='] [Operator for comparison the column and parameter]
   * @param  {String} [param=null]   [Value to check do column from database table is some equal with value]
   * @return {QueryBuilder}          [Query Builder Creator of sql queries and connect to database]
   */
  andWhere: function (column, operator = '=', param = null) {
    return this
  },

  orWhere: function (column, operator = '=', param = null) {

  },

  /**
   * [Get all sql query parameters]
   * @return {Array} [SQL Query parameters]
   */
  getParameters: () => {
    return _params
  },

  /**
   * [Set parameters for created sql query]
   * @param  {Array} values [SQL query parameres only values]
   * @return {QueryBuilder} [Query Builder Creator of sql queries and connect to database]
   */
  setParameters: function (values) {
    let len = values.length

    if (len > 0) {
      for (let i = 0; i < len; i++) {
        _params.push(values[i])
      }

      return this
    } else {
      throw new Error('The values variable is required to be array!')
    }
  },

  /**
   * [Get the created sql query]
   * @return {String} [SQL Query]
   */
  getCommand: () => {
    return _command
  },

  /**
   * [Set Your own SQL Query]
   * @param  {String} command [SQL Query]
   * @return {QueryBuilder}   [Query Builder Creator of sql queries and connect to database]
   */
  setCommand: function (command) {
    if (typeof command !== 'string') {
      throw new Error('The command variable is required to be string!')
    }
    _command = command
    return this
  },

  /**
   * [Prepare the sql query and set what kind of query is will used]
   * @return {QueryBuilder} [Query Builder Creator of sql queries and connect to database]
   */
  prepare: function () {
    if (_option === 'select') {
      _command = _select + _from + _join + _groupBy + _where + _orderBy + _limit + _skip
    } else if (_option === 'insert') {
      _command = _insert
    } else if (_option === 'update') {
      _command = _update + _where
    } else if (_option === 'delete') {
      _command = _delete + _where
    } else {
      _command = _where + _limit + _skip
    }

    _select = ''
    _from = ''
    _join = ''
    _groupBy = ''
    _where = ''
    _orderBy = ''
    _limit = ''
    _skip = ''
    _insert = ''
    _update = ''
    _delete = ''

    return _command
  }
}
<|endoftext|>


<commit_before>/*
 Copyright, 2013, by Tomas Korcak. <korczis@gmail.com>

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 */

(function () {
    'use strict';

    var deferred = require('deferred'),
        mongodb = require('mongodb'),
        mongoose = require('mongoose');

    /**
     * Mongo wrapper
     * @type {Mongo}
     */
    var exports = module.exports = function Mongo(config) {
        this.config = config;
        this.collections = {};
    };

    /**
     * Config to be used
     * @type {object}
     */
    exports.prototype.config = null;

    /**
     * Active MongoDB database
     * @type {object}
     */
    exports.prototype.db = null;

    /**
     * Preloaded collections
     * @type {array}
     */
    exports.prototype.collections = null;

    /**
     * Connects to mongo
     * @returns {*} Promise
     */
    exports.prototype.connect = function () {
        var d = deferred();

        var MongoClient = require('mongodb').MongoClient;

        var self = this;

        MongoClient.connect(this.config.mongo.uri, function (err, db) {
            if (err) {
                d.reject(new Error("Cannot connect to DB '" + self.config.mongo.uri + "'"));
                return;
            }

            if (self.config.verbose) {
                console.log("Connected to DB '" + self.config.mongo.uri + "'");
            }

            self.db = db;
            d.resolve(self.db);
        });

        return d.promise();
    };

    /**
     * Loads collection by name and caches it (do not use for BIG collections!)
     * @param collectionName {string} Name of the collection to be loaded
     * @returns {*} Promise
     */
    exports.prototype.loadCollection = function (collectionName) {
        var d = deferred();

        if (this.config.verbose) {
            console.log("Loading collection '" + collectionName + "'");
        }

        var collection = this.db.collection(collectionName);

        var self = this;
        collection.find().toArray(function (err, data) {
            if (err) {
                d.reject(new Error(err));
                return;
            }

            self.collections[collectionName] = data;

            d.resolve(data);
        });

        return d.promise();
    };

    /**
     * Returns loaded collection by name as promise
     * @param collectionName
     * @returns {*}
     */
    exports.prototype.getCollection = function(collectionName) {
        if (this.config.verbose) {
            console.log("Loading collection '" + collectionName + "'");
        }

        var collection = this.db.collection(collectionName);

        return deferred(collection);
    };

    /**
     * Initializes Mongo wrapper
     * @returns {*} Promise
     */
    exports.prototype.initialize = function () {
        var d = deferred();

        var self = this;
        this.connect().then(function (res) {
            var opt = self.config.mongo.watcher;

            if(opt !== null && opt !== undefined && opt.toString() === "true" || opt.toString() === "1") {
                var Watcher = require('./watcher.js');
                self.watcher = new Watcher(self);

                return self.watcher.initialize();
            } else {
                d.resolve(self);
            }
        });

        return d.promise();
    };

}());<commit_msg>Removed copied & pasted code ..<commit_after>/*
 Copyright, 2013, by Tomas Korcak. <korczis@gmail.com>

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 */

(function () {
    'use strict';

    /**
     * Core Module
     * @type {CoreModule}
     */
    var exports = module.exports = function CoreModule() {
    };

}());<|endoftext|>


<commit_before>/* globals Scope */

var view = Scope.import('galaxy/view');
var inputs = Scope.import('galaxy/inputs');
console.info(inputs);
inputs.__onChange__.when('items', function (value, oldValue) {
  console.info('Text has changed from `' + oldValue + '` to `' + value + '`');
});

view.init({
  class: 'card big',
  animation: {
    ':enter': {
      sequence: 'card',
      from: {
        y: 100,
        opacity: 0
      },
      to: {
        y: 0,
        opacity: 1
      },
      duration: .5
    },
    ':leave': {
      sequence: 'card',
      order: 1,
      to: {
        y: 100,
        opacity: 0
      },
      duration: .5
    }
  },
  children: [
    {
      class: 'content',
      tag: 'section',
      children: [
        {
          tag: 'h1',
          text: 'Guide Page',
          // animation: {
          //   ':leave': {
          //     sequence: 'card',
          //     group: 'h1',
          //     order: 10,
          //     to: {
          //       color: 'green'
          //     },
          //     duration: 1
          //   }
          // }
        },
        {
          tag: 'div',
          class: 'field',
          children: [
            {
              tag: 'label',
              text: 'Text'
            },
            {
              tag: 'input',
              value: '[inputs.text]'
            }
          ]
        },
        {
          tag: 'h3',
          text: '[inputs.text]',
          // animation: {
          //   ':leave': {
          //     sequence: 'card',
          //     group: 'h3',
          //     order: 5,
          //     to: {
          //       color: 'red'
          //     },
          //     duration: 1
          //   }
          // }
        },
        {
          content: '*'
        },
        {
          tag: 'blockquote',
          children: [
            {
              $for: 'item in inputs.items',
              animation: {
                ':enter': {
                  sequence: 'card',
                  group: 'items',
                  from: {
                    x: 100,
                    opacity: 0
                  },
                  position: '-=.25',
                  duration: .4
                },
                ':leave': {
                  sequence: 'card',
                  group: 'items',
                  order: 10,
                  to: {
                    x: 100,
                    opacity: 0
                  },
                  position: '-=.25',
                  duration: .4
                },
                '.done': {
                  sequence: 'card',
                  group: 'items',
                  order: 1,
                  duration: .3
                }
              },
              tag: 'p',
              class: {
                done: '[item.done]'
              },
              text: '[item.title]',
              children: [
                {
                  tag: 'input',
                  type: 'checkbox',
                  checked: '[item.done]'
                }
              ]
            }
          ]
        }
      ]
    }
  ]
});
<commit_msg>WIP V3<commit_after>/* globals Scope */

var view = Scope.import('galaxy/view');
var inputs = Scope.import('galaxy/inputs');
console.info(Scope);
// inputs.__onChange__.when('items', function (value, oldValue) {
//   console.info('Text has changed from `' + oldValue + '` to `' + value + '`');
// });

view.init({
  class: 'card big',
  animation: {
    ':enter': {
      sequence: 'card',
      from: {
        y: 100,
        opacity: 0
      },
      to: {
        y: 0,
        opacity: 1
      },
      duration: .5
    },
    ':leave': {
      sequence: 'card',
      order: 1,
      to: {
        y: 100,
        opacity: 0
      },
      duration: .5
    }
  },
  children: [
    {
      class: 'content',
      tag: 'section',
      children: [
        {
          tag: 'h1',
          text: 'Guide Page',
          // animation: {
          //   ':leave': {
          //     sequence: 'card',
          //     group: 'h1',
          //     order: 10,
          //     to: {
          //       color: 'green'
          //     },
          //     duration: 1
          //   }
          // }
        },
        {
          tag: 'div',
          class: 'field',
          children: [
            {
              tag: 'label',
              text: 'Text'
            },
            {
              tag: 'input',
              value: '[inputs.text]'
            }
          ]
        },
        {
          tag: 'h3',
          text: '[inputs.text]',
          // animation: {
          //   ':leave': {
          //     sequence: 'card',
          //     group: 'h3',
          //     order: 5,
          //     to: {
          //       color: 'red'
          //     },
          //     duration: 1
          //   }
          // }
        },
        {
          content: '*'
        },
        {
          tag: 'blockquote',
          children: [
            {
              $for: 'item in inputs.items',
              animation: {
                ':enter': {
                  sequence: 'card',
                  group: 'items',
                  from: {
                    x: 100,
                    opacity: 0
                  },
                  position: '-=.25',
                  duration: .4
                },
                ':leave': {
                  sequence: 'card',
                  group: 'items',
                  order: 10,
                  to: {
                    x: 100,
                    opacity: 0
                  },
                  position: '-=.25',
                  duration: .4
                },
                '.done': {
                  sequence: 'card',
                  group: 'items',
                  order: 1,
                  duration: .3
                }
              },
              tag: 'p',
              class: {
                done: '[item.done]'
              },
              text: '[item.title]',
              children: [
                {
                  tag: 'input',
                  type: 'checkbox',
                  checked: '[item.done]'
                }
              ]
            }
          ]
        }
      ]
    }
  ]
});
<|endoftext|>


<commit_before>/*
 * ------------------------------------------
 * 日历算法实现文件
 * @version  1.0
 * @author   genify(caijf@corp.netease.com)
 * ------------------------------------------
 */
/** @module util/calendar/calendar */
NEJ.define([
    'base/global',
    'base/klass',
    'base/element',
    'base/event',
    'base/util',
    'util/event'
],function(NEJ,_k,_e,_v,_u,_t,_p,_o,_f,_r){
    var _pro;
    /**
     * 日历算法
     *
     * 日期范围说明
     *
     * | 范围 | 说明 |
     * | :--- | :--- |
     * | [0,0]                                   | 全部日期可选【默认】 |
     * | [0,new Date]                            | 可选当前日期之前的 |
     * | [new Date,0]                            | 可选当前日期之后的 |
     * | [new Date(1997,1,1),new Date(2000,1,1)] | 可选指定范围的日期 |
     *
     * 结构举例
     * ```html
     * <div id="datepick-box">
     *   <div id="days"></div>
     *   <div id="year"></div>
     *   <div id="month"></div>
     *   <div id="yprv">前一年</div>
     *   <div id="mprv">前一月</div>
     *   <div id="ynxt">后一年</div>
     *   <div id="mnxt">后一月</div>
     * </div>
     * ```
     *
     * 脚本举例
     * ```javascript
     * NEJ.define([
     *     'util/calendar/calendar'
     * ],function(_t){
     *     // 构建日期列表
     *     var _days = _e._$get('days');
     *     _html = _e._$add('{list 1..2 as x}<div>{list 1..6 as y}<p class="z-day"></p>{/list}</div>{/list}');
     *     _days.innerHTML = _e._$get(_html);
     *     // 分配日历功能
     *     var _calendar = _t._$$Calendar._$allocate({
     *         parent:'datepick-box',
     *         list:_e._$getByClassName(_days,"z-day"),
     *         offset:1,
     *         year:'year',
     *         month:'month',
     *         yprv:'yprv',
     *         mprv:'mprv',
     *         ynxt:'ynxt',
     *         mnxt:'mnxt',
     *         // 日期的范围，超过范围不可选
     *         range:[new Date(2011,7,9),new Date(2013,7,9)],
     *         onchange:function(_date){
     *             // 日期列表变化
     *         },
     *         onselect:function(_date){
     *             // 选择了一个日期，返回此日期
     *         }
     *     });
     *
     * });
     * ```
     *
     * @class    module:util/calendar/calendar._$$Calendar
     * @extends  module:util/event._$$EventTarget
     *
     * @param    {Object}      config   - 可选配置参数
     * @property {Number}      offset   - 开始星期偏移，默认为0，0-星期天、1-星期一 ...
     * @property {Array}       list     - 日期显示节点列表
     * @property {Number}      year     - 年份显示节点
     * @property {Number}      month    - 月份显示节点
     * @property {String|Node} mprv     - 上一月按钮节点
     * @property {String|Node} mnxt     - 下一月按钮节点
     * @property {String|Node} yprv     - 上一年按钮节点
     * @property {String|Node} ynxt     - 下一年按钮节点
     * @property {String|Node} wprv     - 上一星期按钮节点
     * @property {String|Node} wnxt     - 下一星期按钮节点
     * @property {String|Node} dprv     - 上一天按钮节点
     * @property {String|Node} dnxt     - 下一天按钮节点
     * @property {Array}       range    - 日期可选范围，默认全部可选
     * @property {String}      selected - 当前项样式，默认为js-selected
     * @property {String}      extended - 扩展项样式，默认为js-extended
     * @property {String}      disabled - 禁用项样式，默认为js-disabled
     * @property {Date}        date     - 显示日期，默认为当前时间
     */
    /**
     * 日期变化事件
     *
     * @event module:util/calendar/calendar._$$Calendar#onchange
     * @param {Date} date - 当前日期
     */
    /**
     * 日期选中事件
     *
     * @event module:util/calendar/calendar._$$Calendar#onselect
     * @param {Date} date - 选中日期
     */
    _p._$$Calendar = _k._$klass();
    _pro = _p._$$Calendar._$extend(_t._$$EventTarget);
    /**
     * 控件重置
     *
     * @protected
     * @method module:util/calendar/calendar._$$Calendar#__reset
     * @param  {Object} arg0 - 可选配置参数
     * @return {Void}
     */
    _pro.__reset = function(_options){
        this.__super(_options);
        // init event
        // TODO delegate event
        this.__doInitDomEvent([[
            _options.mprv,'click',
            this.__onMonthChange._$bind(this,-1)
        ],[
            _options.mnxt,'click',
            this.__onMonthChange._$bind(this, 1)
        ],[
            _options.yprv,'click',
            this.__onYearChange._$bind(this,-1)
        ],[
            _options.ynxt,'click',
            this.__onYearChange._$bind(this, 1)
        ],[
            _options.wprv,'click',
            this.__onWeekChange._$bind(this,-1)
        ],[
            _options.wnxt,'click',
            this.__onWeekChange._$bind(this, 1)
        ],[
            _options.wprv,'click',
            this.__onDayChange._$bind(this,-1)
        ],[
            _options.wnxt,'click',
            this.__onDayChange._$bind(this, 1)
        ]]);
        this.__offset = _options.offset||0;
        this.__nyear  = _e._$get(_options.year);
        this.__nmonth = _e._$get(_options.month);
        this.__selected = _options.selected||'js-selected';
        this.__extended = _options.extended||'js-extended';
        this.__disabled = _options.disabled||'js-disabled';
        this.__doRangeCheck(_options.range);
        this.__doDateListCheck(_options.list);
        this._$setDate(_options.date||(new Date()));
    };
    /**
     * 控件销毁
     *
     * @protected
     * @method module:util/calendar/calendar._$$Calendar#__destroy
     * @return {Void}
     */
    _pro.__destroy = function(){
        this.__super();
        delete this.__list;
        delete this.__range;
        delete this.__nyear;
        delete this.__nmonth;
    };
    /**
     * 可选范围检测
     *
     * @protected
     * @method module:util/calendar/calendar._$$Calendar#__doRangeCheck
     * @param  {Array} arg0 - 可选择范围
     * @return {Void}
     */
    _pro.__doRangeCheck = function(_range){
        this.__range = _range||[];
        var _value = this.__range[0];
        this.__range[0] = _u._$isDate(_value)?(+_value):(_value||0);
        var _value = this.__range[1];
        this.__range[1] = _u._$isDate(_value)?(+_value):(_value||0);
    };
    /**
     * 检查日期列表
     *
     * @protected
     * @method module:util/calendar/calendar._$$Calendar#__doDateListCheck
     * @param  {Array} arg0 - 日期显示列表
     * @return {Void}
     */
    _pro.__doDateListCheck = (function(){
        var _doCheck = function(_node){
            this.__list.push(_node);
            this.__doInitDomEvent([[
                _node,'click',
                this.__onDateChange._$bind(this)
            ]]);
        };
        return function(_list){
            this.__list = [];
            _u._$forEach(_list,_doCheck,this);
        };
    })();
    /**
     * 保存日期信息
     *
     * @protected
     * @method module:util/calendar/calendar._$$Calendar#__doSaveDateInfo
     * @param  {Node}   arg0 - 节点
     * @param  {Number} arg1 - 年份
     * @param  {Number} arg2 - 月份
     * @param  {Number} arg3 - 日期
     * @return {Void}
     */
    _pro.__doSaveDateInfo = (function(){
        var _isDisabled = function(_range,_time){
            var _min = _range[0],
                _max = _range[1];
            return _time<_min||(!!_max&&_time>_max);
        };
        return function(_node,_year,_month,_date){
            _e._$dataset(_node,'y',_year);
            _e._$dataset(_node,'m',_month);
            _e._$dataset(_node,'d',_date);
            _node.innerText = _date;
            if (_year==this.__year&&
                _month==this.__month&&
                _date==this.__date){
                _e._$addClassName(_node,this.__selected);
            }else{
                _e._$delClassName(_node,this.__selected);
            }
            _isDisabled(this.__range,+new Date(_year,_month-1,_date))
                ? _e._$addClassName(_node,this.__disabled)
                : _e._$delClassName(_node,this.__disabled);
        };
    })();
    /**
     * 同步日历显示
     *
     * @protected
     * @method module:util/calendar/calendar._$$Calendar#__doSyncDateShow
     * @return {Void}
     */
    _pro.__doSyncDateShow = (function(){
        var _days = [31,28,31,30,31,30,31,31,30,31,30,31];
        var _isLeap = function(_year){
            return !(_year%400)||!(_year%4)&&!!(_year%100);
        };
        var _getMonthDay = function(_year,_month){
            return _month==2&&_isLeap(_year)?29:_days[_month-1];
        };
        return function(){
            var _year  = this.__year,
                _month = this.__month,
                _date  = new Date(_year,_month-1,1),
                _beg = ((7+_date.getDay())-this.__offset)%7,
                _end = Math.min(this.__list.length,
                      _beg+_getMonthDay(_year,_month));
            // sync year and month
            if (!!this.__nyear)
                this.__nyear.innerText = this.__year;
            if (!!this.__nmonth)
                this.__nmonth.innerText = this.__month;
            // offset with limit
            for(var i=_beg,_node;i<_end;i++){
                _node = this.__list[i];
                this.__doSaveDateInfo(
                      _node,_year,_month,i-_beg+1);
                _e._$delClassName(_node,this.__extended);
            }
            // 0 -> begin
            if (_beg>0){
                _date.setMonth(_month-2||0);
                _year  = _date.getFullYear();
                var _monthTemp = _date.getMonth()+1;
                var _limit = _getMonthDay(_year,_monthTemp);
                for(var i=_beg-1,_node;i>=0;i--){
                    _node = this.__list[i];
                    this.__doSaveDateInfo(
                          _node,_year,_monthTemp,_limit--);
                    _e._$addClassName(_node,this.__extended);
                }
            }
            // end -> length
            var _length = this.__list.length;
            if (_end<_length-1){
                _date.setMonth(_month==12?0:_month);
                _year  = _date.getFullYear();
                _month = _date.getMonth()+1;
                for(var i=_end,k=1;i<_length;i++){
                    _node = this.__list[i];
                    this.__doSaveDateInfo(
                          _node,_year,_month,k++);
                    _e._$addClassName(_node,this.__extended);
                }
            }
        };
    })();
    /**
     * 调整年份
     *
     * @protected
     * @method module:util/calendar/calendar._$$Calendar#__onYearChange
     * @param  {Number} arg0 - 步进
     * @return {Void}
     */
    _pro.__onYearChange = function(_flag){
        this.__year += _flag;
        this.__doSyncDateShow();
        this._$dispatchEvent('onchange',this._$getDate());
    };
    /**
     * 调整月份
     *
     * @protected
     * @method module:util/calendar/calendar._$$Calendar#__onMonthChange
     * @param  {Number} arg0 - 步进
     * @return {Void}
     */
    _pro.__onMonthChange = function(_flag){
        this.__month += _flag;
        if (this.__month<1){
            this.__year--;
            this.__month += 12;
        }
        if (this.__month>12){
            this.__year += Math.floor(this.__month/12);
            this.__month = (this.__month-1)%12+1;
        }
        this.__doSyncDateShow();
        this._$dispatchEvent('onchange',this._$getDate());
    };
    /**
     * 日期选择触发事件
     *
     * @protected
     * @method module:util/calendar/calendar._$$Calendar#__onDateChange
     * @param  {Event} arg0 - 事件对象
     * @return {Void}
     */
    _pro.__onDateChange = function(_event){
        var _element = _v._$getElement(_event);
        if (_e._$hasClassName(
            _element,this.__disabled))
            return;
        this.__year  = parseInt(_e._$dataset(_element,'y'));
        this.__month = parseInt(_e._$dataset(_element,'m'));
        this.__date  = parseInt(_e._$dataset(_element,'d'));
        this.__doSyncDateShow();
        this._$dispatchEvent('onselect',this._$getDate());
    };
    /**
     * 周变化触发事件
     *
     * @protected
     * @method module:util/calendar/calendar._$$Calendar#__onWeekChange
     * @param  {Number} arg0 - 上下周标识
     * @return {Void}
     */
    _pro.__onWeekChange = function(_flag){
        // TODO something
    };
    /**
     * 日变化触发事件
     *
     * @protected
     * @method module:util/calendar/calendar._$$Calendar#__onDayChange
     * @param  {Number} arg0 - 上下日标识
     * @return {Void}
     */
    _pro.__onDayChange = function(_flag){
        // TODO something
    };
    /**
     * 设置日期
     *
     * 脚本举例
     * ```javascript
     * _calendar._$setDate('1998-09-28');
     * ```
     *
     * @method module:util/calendar/calendar._$$Calendar#_$setDate
     * @param  {String|Number|Date} arg0 - 日期
     * @return {Void}
     */
    _pro._$setDate = function(_date){
        _date = _u._$var2date(_date);
        this.__year  = _date.getFullYear();
        this.__month = _date.getMonth()+1;
        this.__date  = _date.getDate();
        this.__doSyncDateShow();
    };
    /**
     * 取当前选择时间
     *
     * 脚本举例
     * ```javascript
     * _calendar._$getDate();
     * ```
     *
     * @method module:util/calendar/calendar._$$Calendar#_$getDate
     * @return {Date} 当前选择时间
     */
    _pro._$getDate = function(){
        return new Date(this.__year,this.__month-1,this.__date);
    };

    if (CMPT){
        NEJ.copy(NEJ.P('nej.ut'),_p);
    }

    return _p;
});<commit_msg>bugfix：error year number for calendar when cross year date select<commit_after>/*
 * ------------------------------------------
 * 日历算法实现文件
 * @version  1.0
 * @author   genify(caijf@corp.netease.com)
 * ------------------------------------------
 */
/** @module util/calendar/calendar */
NEJ.define([
    'base/global',
    'base/klass',
    'base/element',
    'base/event',
    'base/util',
    'util/event'
],function(NEJ,_k,_e,_v,_u,_t,_p,_o,_f,_r){
    var _pro;
    /**
     * 日历算法
     *
     * 日期范围说明
     *
     * | 范围 | 说明 |
     * | :--- | :--- |
     * | [0,0]                                   | 全部日期可选【默认】 |
     * | [0,new Date]                            | 可选当前日期之前的 |
     * | [new Date,0]                            | 可选当前日期之后的 |
     * | [new Date(1997,1,1),new Date(2000,1,1)] | 可选指定范围的日期 |
     *
     * 结构举例
     * ```html
     * <div id="datepick-box">
     *   <div id="days"></div>
     *   <div id="year"></div>
     *   <div id="month"></div>
     *   <div id="yprv">前一年</div>
     *   <div id="mprv">前一月</div>
     *   <div id="ynxt">后一年</div>
     *   <div id="mnxt">后一月</div>
     * </div>
     * ```
     *
     * 脚本举例
     * ```javascript
     * NEJ.define([
     *     'util/calendar/calendar'
     * ],function(_t){
     *     // 构建日期列表
     *     var _days = _e._$get('days');
     *     _html = _e._$add('{list 1..2 as x}<div>{list 1..6 as y}<p class="z-day"></p>{/list}</div>{/list}');
     *     _days.innerHTML = _e._$get(_html);
     *     // 分配日历功能
     *     var _calendar = _t._$$Calendar._$allocate({
     *         parent:'datepick-box',
     *         list:_e._$getByClassName(_days,"z-day"),
     *         offset:1,
     *         year:'year',
     *         month:'month',
     *         yprv:'yprv',
     *         mprv:'mprv',
     *         ynxt:'ynxt',
     *         mnxt:'mnxt',
     *         // 日期的范围，超过范围不可选
     *         range:[new Date(2011,7,9),new Date(2013,7,9)],
     *         onchange:function(_date){
     *             // 日期列表变化
     *         },
     *         onselect:function(_date){
     *             // 选择了一个日期，返回此日期
     *         }
     *     });
     *
     * });
     * ```
     *
     * @class    module:util/calendar/calendar._$$Calendar
     * @extends  module:util/event._$$EventTarget
     *
     * @param    {Object}      config   - 可选配置参数
     * @property {Number}      offset   - 开始星期偏移，默认为0，0-星期天、1-星期一 ...
     * @property {Array}       list     - 日期显示节点列表
     * @property {Number}      year     - 年份显示节点
     * @property {Number}      month    - 月份显示节点
     * @property {String|Node} mprv     - 上一月按钮节点
     * @property {String|Node} mnxt     - 下一月按钮节点
     * @property {String|Node} yprv     - 上一年按钮节点
     * @property {String|Node} ynxt     - 下一年按钮节点
     * @property {String|Node} wprv     - 上一星期按钮节点
     * @property {String|Node} wnxt     - 下一星期按钮节点
     * @property {String|Node} dprv     - 上一天按钮节点
     * @property {String|Node} dnxt     - 下一天按钮节点
     * @property {Array}       range    - 日期可选范围，默认全部可选
     * @property {String}      selected - 当前项样式，默认为js-selected
     * @property {String}      extended - 扩展项样式，默认为js-extended
     * @property {String}      disabled - 禁用项样式，默认为js-disabled
     * @property {Date}        date     - 显示日期，默认为当前时间
     */
    /**
     * 日期变化事件
     *
     * @event module:util/calendar/calendar._$$Calendar#onchange
     * @param {Date} date - 当前日期
     */
    /**
     * 日期选中事件
     *
     * @event module:util/calendar/calendar._$$Calendar#onselect
     * @param {Date} date - 选中日期
     */
    _p._$$Calendar = _k._$klass();
    _pro = _p._$$Calendar._$extend(_t._$$EventTarget);
    /**
     * 控件重置
     *
     * @protected
     * @method module:util/calendar/calendar._$$Calendar#__reset
     * @param  {Object} arg0 - 可选配置参数
     * @return {Void}
     */
    _pro.__reset = function(_options){
        this.__super(_options);
        // init event
        // TODO delegate event
        this.__doInitDomEvent([[
            _options.mprv,'click',
            this.__onMonthChange._$bind(this,-1)
        ],[
            _options.mnxt,'click',
            this.__onMonthChange._$bind(this, 1)
        ],[
            _options.yprv,'click',
            this.__onYearChange._$bind(this,-1)
        ],[
            _options.ynxt,'click',
            this.__onYearChange._$bind(this, 1)
        ],[
            _options.wprv,'click',
            this.__onWeekChange._$bind(this,-1)
        ],[
            _options.wnxt,'click',
            this.__onWeekChange._$bind(this, 1)
        ],[
            _options.wprv,'click',
            this.__onDayChange._$bind(this,-1)
        ],[
            _options.wnxt,'click',
            this.__onDayChange._$bind(this, 1)
        ]]);
        this.__offset = _options.offset||0;
        this.__nyear  = _e._$get(_options.year);
        this.__nmonth = _e._$get(_options.month);
        this.__selected = _options.selected||'js-selected';
        this.__extended = _options.extended||'js-extended';
        this.__disabled = _options.disabled||'js-disabled';
        this.__doRangeCheck(_options.range);
        this.__doDateListCheck(_options.list);
        this._$setDate(_options.date||(new Date()));
    };
    /**
     * 控件销毁
     *
     * @protected
     * @method module:util/calendar/calendar._$$Calendar#__destroy
     * @return {Void}
     */
    _pro.__destroy = function(){
        this.__super();
        delete this.__list;
        delete this.__range;
        delete this.__nyear;
        delete this.__nmonth;
    };
    /**
     * 可选范围检测
     *
     * @protected
     * @method module:util/calendar/calendar._$$Calendar#__doRangeCheck
     * @param  {Array} arg0 - 可选择范围
     * @return {Void}
     */
    _pro.__doRangeCheck = function(_range){
        this.__range = _range||[];
        var _value = this.__range[0];
        this.__range[0] = _u._$isDate(_value)?(+_value):(_value||0);
        var _value = this.__range[1];
        this.__range[1] = _u._$isDate(_value)?(+_value):(_value||0);
    };
    /**
     * 检查日期列表
     *
     * @protected
     * @method module:util/calendar/calendar._$$Calendar#__doDateListCheck
     * @param  {Array} arg0 - 日期显示列表
     * @return {Void}
     */
    _pro.__doDateListCheck = (function(){
        var _doCheck = function(_node){
            this.__list.push(_node);
            this.__doInitDomEvent([[
                _node,'click',
                this.__onDateChange._$bind(this)
            ]]);
        };
        return function(_list){
            this.__list = [];
            _u._$forEach(_list,_doCheck,this);
        };
    })();
    /**
     * 保存日期信息
     *
     * @protected
     * @method module:util/calendar/calendar._$$Calendar#__doSaveDateInfo
     * @param  {Node}   arg0 - 节点
     * @param  {Number} arg1 - 年份
     * @param  {Number} arg2 - 月份
     * @param  {Number} arg3 - 日期
     * @return {Void}
     */
    _pro.__doSaveDateInfo = (function(){
        var _isDisabled = function(_range,_time){
            var _min = _range[0],
                _max = _range[1];
            return _time<_min||(!!_max&&_time>_max);
        };
        return function(_node,_year,_month,_date){
            _e._$dataset(_node,'y',_year);
            _e._$dataset(_node,'m',_month);
            _e._$dataset(_node,'d',_date);
            _node.innerText = _date;
            if (_year==this.__year&&
                _month==this.__month&&
                _date==this.__date){
                _e._$addClassName(_node,this.__selected);
            }else{
                _e._$delClassName(_node,this.__selected);
            }
            _isDisabled(this.__range,+new Date(_year,_month-1,_date))
                ? _e._$addClassName(_node,this.__disabled)
                : _e._$delClassName(_node,this.__disabled);
        };
    })();
    /**
     * 同步日历显示
     *
     * @protected
     * @method module:util/calendar/calendar._$$Calendar#__doSyncDateShow
     * @return {Void}
     */
    _pro.__doSyncDateShow = (function(){
        var _days = [31,28,31,30,31,30,31,31,30,31,30,31];
        var _isLeap = function(_year){
            return !(_year%400)||!(_year%4)&&!!(_year%100);
        };
        var _getMonthDay = function(_year,_month){
            return _month==2&&_isLeap(_year)?29:_days[_month-1];
        };
        return function(){
            var _year  = this.__year,
                _month = this.__month,
                _date  = new Date(_year,_month-1,1),
                _beg = ((7+_date.getDay())-this.__offset)%7,
                _end = Math.min(this.__list.length,
                      _beg+_getMonthDay(_year,_month));
            // sync year and month
            if (!!this.__nyear)
                this.__nyear.innerText = this.__year;
            if (!!this.__nmonth)
                this.__nmonth.innerText = this.__month;
            // offset with limit
            for(var i=_beg,_node;i<_end;i++){
                _node = this.__list[i];
                this.__doSaveDateInfo(
                      _node,_year,_month,i-_beg+1);
                _e._$delClassName(_node,this.__extended);
            }
            // 0 -> begin
            if (_beg>0){
                _date.setMonth(_month-2||0);
                _year  = _date.getFullYear();
                var _monthTemp = _date.getMonth()+1;
                var _limit = _getMonthDay(_year,_monthTemp);
                for(var i=_beg-1,_node;i>=0;i--){
                    _node = this.__list[i];
                    this.__doSaveDateInfo(
                          _node,_year,_monthTemp,_limit--);
                    _e._$addClassName(_node,this.__extended);
                }
            }
            // end -> length
            var _length = this.__list.length;
            if (_end<_length-1){
                _date.setMonth(_month);
                _year  = _date.getFullYear();
                _month = _date.getMonth()+1;
                for(var i=_end,k=1;i<_length;i++){
                    _node = this.__list[i];
                    this.__doSaveDateInfo(
                          _node,_year,_month,k++);
                    _e._$addClassName(_node,this.__extended);
                }
            }
        };
    })();
    /**
     * 调整年份
     *
     * @protected
     * @method module:util/calendar/calendar._$$Calendar#__onYearChange
     * @param  {Number} arg0 - 步进
     * @return {Void}
     */
    _pro.__onYearChange = function(_flag){
        this.__year += _flag;
        this.__doSyncDateShow();
        this._$dispatchEvent('onchange',this._$getDate());
    };
    /**
     * 调整月份
     *
     * @protected
     * @method module:util/calendar/calendar._$$Calendar#__onMonthChange
     * @param  {Number} arg0 - 步进
     * @return {Void}
     */
    _pro.__onMonthChange = function(_flag){
        this.__month += _flag;
        if (this.__month<1){
            this.__year--;
            this.__month += 12;
        }
        if (this.__month>12){
            this.__year += Math.floor(this.__month/12);
            this.__month = (this.__month-1)%12+1;
        }
        this.__doSyncDateShow();
        this._$dispatchEvent('onchange',this._$getDate());
    };
    /**
     * 日期选择触发事件
     *
     * @protected
     * @method module:util/calendar/calendar._$$Calendar#__onDateChange
     * @param  {Event} arg0 - 事件对象
     * @return {Void}
     */
    _pro.__onDateChange = function(_event){
        var _element = _v._$getElement(_event);
        if (_e._$hasClassName(
            _element,this.__disabled))
            return;
        this.__year  = parseInt(_e._$dataset(_element,'y'));
        this.__month = parseInt(_e._$dataset(_element,'m'));
        this.__date  = parseInt(_e._$dataset(_element,'d'));
        this.__doSyncDateShow();
        this._$dispatchEvent('onselect',this._$getDate());
    };
    /**
     * 周变化触发事件
     *
     * @protected
     * @method module:util/calendar/calendar._$$Calendar#__onWeekChange
     * @param  {Number} arg0 - 上下周标识
     * @return {Void}
     */
    _pro.__onWeekChange = function(_flag){
        // TODO something
    };
    /**
     * 日变化触发事件
     *
     * @protected
     * @method module:util/calendar/calendar._$$Calendar#__onDayChange
     * @param  {Number} arg0 - 上下日标识
     * @return {Void}
     */
    _pro.__onDayChange = function(_flag){
        // TODO something
    };
    /**
     * 设置日期
     *
     * 脚本举例
     * ```javascript
     * _calendar._$setDate('1998-09-28');
     * ```
     *
     * @method module:util/calendar/calendar._$$Calendar#_$setDate
     * @param  {String|Number|Date} arg0 - 日期
     * @return {Void}
     */
    _pro._$setDate = function(_date){
        _date = _u._$var2date(_date);
        this.__year  = _date.getFullYear();
        this.__month = _date.getMonth()+1;
        this.__date  = _date.getDate();
        this.__doSyncDateShow();
    };
    /**
     * 取当前选择时间
     *
     * 脚本举例
     * ```javascript
     * _calendar._$getDate();
     * ```
     *
     * @method module:util/calendar/calendar._$$Calendar#_$getDate
     * @return {Date} 当前选择时间
     */
    _pro._$getDate = function(){
        return new Date(this.__year,this.__month-1,this.__date);
    };

    if (CMPT){
        NEJ.copy(NEJ.P('nej.ut'),_p);
    }

    return _p;
});<|endoftext|>


<commit_before>export default function addEventListener(node, eventName, handler, options) {
    node.addEventListener(eventName, handler, options);
    return {
        removeEventListener: () => {
            node.removeEventListener(eventName, handler, options);
        }
    };
}<commit_msg>addEventListener add newline at end<commit_after>export default function addEventListener(node, eventName, handler, options) {
    node.addEventListener(eventName, handler, options);
    return {
        removeEventListener: () => {
            node.removeEventListener(eventName, handler, options);
        }
    };
}
<|endoftext|>


<commit_before>/*!
 * Module dependencies.
 */
var _ = require('underscore');
var di = require('asyncdi');
var marked = require('marked');
var Path = require('../../lib/path');
var utils = require('keystone-utils');
var evalDependsOn = require('../utils/evalDependsOn.js');
var debug = require('debug')('keystone:fields:types:Type');

var DEFAULT_OPTION_KEYS = [
	'path',
	'paths',
	'type',
	'label',
	'note',
	'size',
	'initial',
	'required',
	'col',
	'noedit',
	'nocol',
	'nosort',
	'nofilter',
	'indent',
	'hidden',
	'collapse',
	'dependsOn',
];

/**
 * Field Constructor
 * =================
 *
 * Extended by fieldType Classes, should not be used directly.
 *
 * @api public
 */
function Field (list, path, options) {

	// Set field properties and options
	this.list = list;
	this._path = new Path(path);
	this.path = path;

	this.type = this.constructor.name;
	this.options = utils.options(this.defaults, options);
	this.label = options.label || utils.keyToLabel(this.path);
	this.typeDescription = options.typeDescription || this.typeDescription || this.type;

	this.list.automap(this);

	// Warn on required fields that aren't initial
	if (this.options.required
		&& this.options.initial === undefined
		&& this.options.default === undefined
		&& !this.options.value
		&& !this.list.get('nocreate')
		&& this.path !== this.list.mappings.name
	) {
		console.error('\nError: Invalid Configuration\n\n'
		+ 'Field (' + list.key + '.' + path + ') is required but not initial, and has no default or generated value.\n'
		+ 'Please provide a default, remove the required setting, or set initial: false to override this error.\n');
		process.exit(1);
	}

	// if dependsOn and required, set required to a function for validation
	if (this.options.dependsOn && this.options.required === true) {
		var opts = this.options;
		this.options.required = function () {
			// `this` refers to the validating document
			debug('validate dependsOn required', evalDependsOn(opts.dependsOn, this.toObject()));
			return evalDependsOn(opts.dependsOn, this.toObject());
		};
	}

	// Add the field to the schema
	this.addToSchema();

	// Add pre-save handler to the list if this field watches others
	if (this.options.watch) {
		this.list.schema.pre('save', this.getPreSaveWatcher());
	}

	// Convert notes from markdown to html
	var note = null;
	Object.defineProperty(this, 'note', {
		get: function () {
			return (note === null) ? (note = (this.options.note) ? marked(this.options.note) : '') : note;
		},
	});

}

/**
 * Gets the options for the Field, as used by the React components
 */
Field.prototype.getOptions = function () {
	if (!this.__options) {
		this.__options = {};
		var optionKeys = DEFAULT_OPTION_KEYS;
		if (_.isArray(this._properties)) {
			optionKeys = optionKeys.concat(this._properties);
		}
		optionKeys.forEach(function (key) {
			if (this[key]) {
				this.__options[key] = this[key];
			} else if (this.options[key]) {
				this.__options[key] = this.options[key];
			}
		}, this);
		if (this.getProperties) {
			Object.assign(this.__options, this.getProperties());
		}
		this.__options.hasFilterMethod = this.addFilterToQuery ? true : false;
		this.__options.defaultValue = this.getDefaultValue();
	}
	return this.__options;
};

/**
 * Validates and returns the size of the field.
 * Defaults to deprecated 'width' option.
 */
Field.prototype.getSize = function () {
	if (!this.__size) {
		var size = this._fixedSize || this.options.size || this.options.width;
		if (size !== 'small' && size !== 'medium' && size !== 'large' && size !== 'full') {
			size = this._defaultSize || 'full';
		}
		this.__size = size;
	}
	return this.__size;
};

/**
 * Gets default value for the field, based on the option or default for the type
 */
Field.prototype.getDefaultValue = function () {
	return this.options.default || '';
};

/**
 * Gets the field's data from an Item, as used by the React components
 */
Field.prototype.getData = function (item) {
	return item.get(this.path);
};

/**
 * Field watching implementation
 */
Field.prototype.getPreSaveWatcher = function () {
	var field = this;
	var applyValue;

	if (this.options.watch === true) {
		// watch == true means always apply the value method
		applyValue = function () { return true; };
	} else {
		// if watch is a string, convert it to a list of paths to watch
		if (_.isString(this.options.watch)) {
			this.options.watch = this.options.watch.split(' ');
		}
		if (_.isFunction(this.options.watch)) {
			applyValue = this.options.watch;
		} else if (_.isArray(this.options.watch)) {
			applyValue = function (item) {
				var pass = false;
				field.options.watch.forEach(function (path) {
					if (item.isModified(path)) pass = true;
				});
				return pass;
			};
		} else if (_.isObject(this.options.watch)) {
			applyValue = function (item) {
				var pass = false;
				_.each(field.options.watch, function (value, path) {
					if (item.isModified(path) && item.get(path) === value) pass = true;
				});
				return pass;
			};
		}
	}

	if (!applyValue) {
		console.error('\nError: Invalid Configuration\n\n'
		+ 'Invalid watch value (' + this.options.watch + ') provided for ' + this.list.key + '.' + this.path + ' (' + this.type + ')');
		process.exit(1);
	}

	if (!_.isFunction(this.options.value)) {
		console.error('\nError: Invalid Configuration\n\n'
		+ 'Watch set with no value method provided for ' + this.list.key + '.' + this.path + ' (' + this.type + ')');
		process.exit(1);
	}

	return function (next) {
		if (!applyValue(this)) {
			return next();
		}
		di(field.options.value).call(this, function (err, val) {
			if (err) {
				console.error('\nError: '
				+ 'Watch set with value method for ' + field.list.key + '.' + field.path + ' (' + field.type + ') throws error:' + err);
			} else {
				this.set(field.path, val);
			}
			next();
		}.bind(this));
	};

};
module.exports = Field;

/** Getter properties for the Field prototype */
Object.defineProperty(Field.prototype, 'size', { get: function () { return this.getSize(); } });
Object.defineProperty(Field.prototype, 'initial', { get: function () { return this.options.initial || false; } });
Object.defineProperty(Field.prototype, 'required', { get: function () { return this.options.required || false; } });
Object.defineProperty(Field.prototype, 'note', { get: function () { return this.options.note || ''; } });
Object.defineProperty(Field.prototype, 'col', { get: function () { return this.options.col || false; } });
Object.defineProperty(Field.prototype, 'noedit', { get: function () { return this.options.noedit || false; } });
Object.defineProperty(Field.prototype, 'nocol', { get: function () { return this.options.nocol || false; } });
Object.defineProperty(Field.prototype, 'nosort', { get: function () { return this.options.nosort || false; } });
Object.defineProperty(Field.prototype, 'nofilter', { get: function () { return this.options.nofilter || false; } });
Object.defineProperty(Field.prototype, 'collapse', { get: function () { return this.options.collapse || false; } });
Object.defineProperty(Field.prototype, 'hidden', { get: function () { return this.options.hidden || false; } });
Object.defineProperty(Field.prototype, 'dependsOn', { get: function () { return this.options.dependsOn || false; } });

/**
 * Default method to register the field on the List's Mongoose Schema.
 * Overridden by some fieldType Classes
 *
 * @api public
 */
Field.prototype.addToSchema = function () {
	var ops = (this._nativeType) ? _.defaults({ type: this._nativeType }, this.options) : this.options;
	this.list.schema.path(this.path, ops);
	this.bindUnderscoreMethods();
};

Field.prototype.bindUnderscoreMethods = function (methods) {
	var field = this;
	// automatically bind underscore methods specified by the _underscoreMethods property
	// always include the 'update' method
	(this._underscoreMethods || []).concat({ fn: 'updateItem', as: 'update' }, (methods || [])).forEach(function (method) {
		if (typeof method === 'string') {
			method = { fn: method, as: method };
		}
		if (typeof field[method.fn] !== 'function') {
			throw new Error('Invalid underscore method (' + method.fn + ') applied to ' + field.list.key + '.' + field.path + ' (' + field.type + ')');
		}
		field.underscoreMethod(method.as, function () {
			var args = [this].concat(Array.prototype.slice.call(arguments));
			return field[method.fn].apply(field, args);
		});
	});
};

/**
 * Adds a method to the underscoreMethods collection on the field's list,
 * with a path prefix to match this field's path and bound to the document
 *
 * @api public
 */
Field.prototype.underscoreMethod = function (path, fn) {
	this.list.underscoreMethod(this.path + '.' + path, function () {
		return fn.apply(this, arguments);
	});
};

/**
 * Default method to format the field value for display
 * Overridden by some fieldType Classes
 *
 * @api public
 */
Field.prototype.format = function (item) {
	return item.get(this.path);
};

/**
 * Default method to detect whether the field has been modified in an item
 * Overridden by some fieldType Classes
 *
 * @api public
 */
Field.prototype.isModified = function (item) {
	return item.isModified(this.path);
};

/**
 * Checks whether a provided value for the field is in a valid format
 * Overridden by some fieldType Classes
 *
 * @api public
 */
Field.prototype.validateInput = function (data, callback) {
	utils.defer(callback, this.inputIsValid(data));
};

/**
 * Validates that a value for this field has been provided in a data object,
 * taking into account existing data in an item
 * Overridden by some fieldType Classes
 *
 * @api public
 */
Field.prototype.validateRequiredInput = function (item, data, callback) {
	utils.defer(callback, this.inputIsValid(data, true, item));
};

/**
 * Validates that a value for this field has been provided in a data object
 * Overridden by some fieldType Classes
 *
 * Not a reliable public API; use inputIsValid, which is async, instead
 */
Field.prototype.inputIsValid = function (data, required, item) {
	if (!required) return true;
	var value = this.getValueFromData(data);
	if (value === undefined && item && item.get(this.path)) return true;
	if (typeof data[this.path] === 'string') {
		return (data[this.path].trim()) ? true : false;
	} else {
		return (data[this.path]) ? true : false;
	}
};

/**
 * Updates the value for this field in the item from a data object
 * Overridden by some fieldType Classes
 *
 * @api public
 */
Field.prototype.updateItem = function (item, data, callback) {
	var value = this.getValueFromData(data);
	// This is a deliberate type coercion so that numbers from forms play nice
	if (value !== undefined && value != item.get(this.path)) { // eslint-disable-line eqeqeq
		item.set(this.path, value);
	}
	process.nextTick(callback);
};

/**
 * Retrieves the value from an object, whether the path is nested or flattened
 *
 * @api public
 */
Field.prototype.getValueFromData = function (data) {
	return this.path in data ? data[this.path] : this._path.get(data);
};
<commit_msg>Cleaning up docs in the base field Type<commit_after>/*!
 * Module dependencies.
 */
var _ = require('underscore');
var di = require('asyncdi');
var marked = require('marked');
var Path = require('../../lib/path');
var utils = require('keystone-utils');
var evalDependsOn = require('../utils/evalDependsOn.js');
var debug = require('debug')('keystone:fields:types:Type');

var DEFAULT_OPTION_KEYS = [
	'path',
	'paths',
	'type',
	'label',
	'note',
	'size',
	'initial',
	'required',
	'col',
	'noedit',
	'nocol',
	'nosort',
	'nofilter',
	'indent',
	'hidden',
	'collapse',
	'dependsOn',
];

/**
 * Field Constructor
 * =================
 *
 * Extended by fieldType Classes, should not be used directly.
 *
 * @api public
 */
function Field (list, path, options) {

	// Set field properties and options
	this.list = list;
	this._path = new Path(path);
	this.path = path;

	this.type = this.constructor.name;
	this.options = utils.options(this.defaults, options);
	this.label = options.label || utils.keyToLabel(this.path);
	this.typeDescription = options.typeDescription || this.typeDescription || this.type;

	this.list.automap(this);

	// Warn on required fields that aren't initial
	if (this.options.required
		&& this.options.initial === undefined
		&& this.options.default === undefined
		&& !this.options.value
		&& !this.list.get('nocreate')
		&& this.path !== this.list.mappings.name
	) {
		console.error('\nError: Invalid Configuration\n\n'
		+ 'Field (' + list.key + '.' + path + ') is required but not initial, and has no default or generated value.\n'
		+ 'Please provide a default, remove the required setting, or set initial: false to override this error.\n');
		process.exit(1);
	}

	// if dependsOn and required, set required to a function for validation
	if (this.options.dependsOn && this.options.required === true) {
		var opts = this.options;
		this.options.required = function () {
			// `this` refers to the validating document
			debug('validate dependsOn required', evalDependsOn(opts.dependsOn, this.toObject()));
			return evalDependsOn(opts.dependsOn, this.toObject());
		};
	}

	// Add the field to the schema
	this.addToSchema();

	// Add pre-save handler to the list if this field watches others
	if (this.options.watch) {
		this.list.schema.pre('save', this.getPreSaveWatcher());
	}

	// Convert notes from markdown to html
	var note = null;
	Object.defineProperty(this, 'note', {
		get: function () {
			return (note === null) ? (note = (this.options.note) ? marked(this.options.note) : '') : note;
		},
	});

}

/**
 * Gets the options for the Field, as used by the React components
 */
Field.prototype.getOptions = function () {
	if (!this.__options) {
		this.__options = {};
		var optionKeys = DEFAULT_OPTION_KEYS;
		if (_.isArray(this._properties)) {
			optionKeys = optionKeys.concat(this._properties);
		}
		optionKeys.forEach(function (key) {
			if (this[key]) {
				this.__options[key] = this[key];
			} else if (this.options[key]) {
				this.__options[key] = this.options[key];
			}
		}, this);
		if (this.getProperties) {
			Object.assign(this.__options, this.getProperties());
		}
		this.__options.hasFilterMethod = this.addFilterToQuery ? true : false;
		this.__options.defaultValue = this.getDefaultValue();
	}
	return this.__options;
};

/**
 * Validates and returns the size of the field.
 * Defaults to deprecated 'width' option.
 */
Field.prototype.getSize = function () {
	if (!this.__size) {
		var size = this._fixedSize || this.options.size || this.options.width;
		if (size !== 'small' && size !== 'medium' && size !== 'large' && size !== 'full') {
			size = this._defaultSize || 'full';
		}
		this.__size = size;
	}
	return this.__size;
};

/**
 * Gets default value for the field, based on the option or default for the type
 */
Field.prototype.getDefaultValue = function () {
	return this.options.default || '';
};

/**
 * Gets the field's data from an Item, as used by the React components
 */
Field.prototype.getData = function (item) {
	return item.get(this.path);
};

/**
 * Field watching implementation
 */
Field.prototype.getPreSaveWatcher = function () {
	var field = this;
	var applyValue;

	if (this.options.watch === true) {
		// watch == true means always apply the value method
		applyValue = function () { return true; };
	} else {
		// if watch is a string, convert it to a list of paths to watch
		if (_.isString(this.options.watch)) {
			this.options.watch = this.options.watch.split(' ');
		}
		if (_.isFunction(this.options.watch)) {
			applyValue = this.options.watch;
		} else if (_.isArray(this.options.watch)) {
			applyValue = function (item) {
				var pass = false;
				field.options.watch.forEach(function (path) {
					if (item.isModified(path)) pass = true;
				});
				return pass;
			};
		} else if (_.isObject(this.options.watch)) {
			applyValue = function (item) {
				var pass = false;
				_.each(field.options.watch, function (value, path) {
					if (item.isModified(path) && item.get(path) === value) pass = true;
				});
				return pass;
			};
		}
	}

	if (!applyValue) {
		console.error('\nError: Invalid Configuration\n\n'
		+ 'Invalid watch value (' + this.options.watch + ') provided for ' + this.list.key + '.' + this.path + ' (' + this.type + ')');
		process.exit(1);
	}

	if (!_.isFunction(this.options.value)) {
		console.error('\nError: Invalid Configuration\n\n'
		+ 'Watch set with no value method provided for ' + this.list.key + '.' + this.path + ' (' + this.type + ')');
		process.exit(1);
	}

	return function (next) {
		if (!applyValue(this)) {
			return next();
		}
		di(field.options.value).call(this, function (err, val) {
			if (err) {
				console.error('\nError: '
				+ 'Watch set with value method for ' + field.list.key + '.' + field.path + ' (' + field.type + ') throws error:' + err);
			} else {
				this.set(field.path, val);
			}
			next();
		}.bind(this));
	};

};
module.exports = Field;

/** Getter properties for the Field prototype */
Object.defineProperty(Field.prototype, 'size', { get: function () { return this.getSize(); } });
Object.defineProperty(Field.prototype, 'initial', { get: function () { return this.options.initial || false; } });
Object.defineProperty(Field.prototype, 'required', { get: function () { return this.options.required || false; } });
Object.defineProperty(Field.prototype, 'note', { get: function () { return this.options.note || ''; } });
Object.defineProperty(Field.prototype, 'col', { get: function () { return this.options.col || false; } });
Object.defineProperty(Field.prototype, 'noedit', { get: function () { return this.options.noedit || false; } });
Object.defineProperty(Field.prototype, 'nocol', { get: function () { return this.options.nocol || false; } });
Object.defineProperty(Field.prototype, 'nosort', { get: function () { return this.options.nosort || false; } });
Object.defineProperty(Field.prototype, 'nofilter', { get: function () { return this.options.nofilter || false; } });
Object.defineProperty(Field.prototype, 'collapse', { get: function () { return this.options.collapse || false; } });
Object.defineProperty(Field.prototype, 'hidden', { get: function () { return this.options.hidden || false; } });
Object.defineProperty(Field.prototype, 'dependsOn', { get: function () { return this.options.dependsOn || false; } });

/**
 * Default method to register the field on the List's Mongoose Schema.
 * Overridden by some fieldType Classes
 */
Field.prototype.addToSchema = function () {
	var ops = (this._nativeType) ? _.defaults({ type: this._nativeType }, this.options) : this.options;
	this.list.schema.path(this.path, ops);
	this.bindUnderscoreMethods();
};

/**
 * Binds the methods specified by the _underscoreMethods property
 * Must be called by the field type's `addToSchema` method
 * Always includes the `update` method
 */
Field.prototype.bindUnderscoreMethods = function (methods) {
	var field = this;
	(this._underscoreMethods || []).concat({ fn: 'updateItem', as: 'update' }, (methods || [])).forEach(function (method) {
		if (typeof method === 'string') {
			method = { fn: method, as: method };
		}
		if (typeof field[method.fn] !== 'function') {
			throw new Error('Invalid underscore method (' + method.fn + ') applied to ' + field.list.key + '.' + field.path + ' (' + field.type + ')');
		}
		field.underscoreMethod(method.as, function () {
			var args = [this].concat(Array.prototype.slice.call(arguments));
			return field[method.fn].apply(field, args);
		});
	});
};

/**
 * Adds a method to the underscoreMethods collection on the field's list,
 * with a path prefix to match this field's path and bound to the document
 */
Field.prototype.underscoreMethod = function (path, fn) {
	this.list.underscoreMethod(this.path + '.' + path, function () {
		return fn.apply(this, arguments);
	});
};

/**
 * Default method to format the field value for display
 * Overridden by some fieldType Classes
 *
 * @api public
 */
Field.prototype.format = function (item) {
	return item.get(this.path);
};

/**
 * Default method to detect whether the field has been modified in an item
 * Overridden by some fieldType Classes
 *
 * @api public
 */
Field.prototype.isModified = function (item) {
	return item.isModified(this.path);
};

/**
 * Checks whether a provided value for the field is in a valid format
 * Overridden by some fieldType Classes
 *
 * @api public
 */
Field.prototype.validateInput = function (data, callback) {
	utils.defer(callback, this.inputIsValid(data));
};

/**
 * Validates that a value for this field has been provided in a data object,
 * taking into account existing data in an item
 * Overridden by some fieldType Classes
 *
 * @api public
 */
Field.prototype.validateRequiredInput = function (item, data, callback) {
	utils.defer(callback, this.inputIsValid(data, true, item));
};

/**
 * Validates that a value for this field has been provided in a data object
 * Overridden by some fieldType Classes
 *
 * Not a reliable public API; use inputIsValid, which is async, instead
 */
Field.prototype.inputIsValid = function (data, required, item) {
	if (!required) return true;
	var value = this.getValueFromData(data);
	if (value === undefined && item && item.get(this.path)) return true;
	if (typeof data[this.path] === 'string') {
		return (data[this.path].trim()) ? true : false;
	} else {
		return (data[this.path]) ? true : false;
	}
};

/**
 * Updates the value for this field in the item from a data object
 * Overridden by some fieldType Classes
 *
 * @api public
 */
Field.prototype.updateItem = function (item, data, callback) {
	var value = this.getValueFromData(data);
	// This is a deliberate type coercion so that numbers from forms play nice
	if (value !== undefined && value != item.get(this.path)) { // eslint-disable-line eqeqeq
		item.set(this.path, value);
	}
	process.nextTick(callback);
};

/**
 * Retrieves the value from an object, whether the path is nested or flattened
 *
 * @api public
 */
Field.prototype.getValueFromData = function (data) {
	return this.path in data ? data[this.path] : this._path.get(data);
};
<|endoftext|>


<commit_before>'use strict';

angular.module('yapp')
    .controller('pythonInterpreterCtrl', function (Database, $window, $location, User, $scope, $state, $sce) {

    $scope.$state = $state;
    var Sk = $window.Sk;

    var aceHl;

    $scope.frameURL = $sce.trustAsResourceUrl("http://pythontutor.com/iframe-embed.html#code=%23%20this%20is%20the%20debugger&cumulative=false&py=3&curInstr=0");

    $scope.aceLoaded = function(_editor) {
   // Options
       _editor.setReadOnly(false);
       _editor.setValue("print 10", 1);// change to different value acc exercise
       aceHl = _editor;
       //$scope.detailFrame = $sce.trustAsResourceUrl("http://pythontutor.com/iframe-embed.html#code=x+%3D+5&cumulative=false&py=3&curInstr=0");
     };

     $scope.aceChanged = function(e) {
       clearAll();
       //var placeHere = document.getElementById("frameHere");
       //placeHere.innerHTML="";
     };

      function outf(text) {
          var mypre = document.getElementById("output");
          mypre.innerHTML = mypre.innerHTML + text;
      }

     function builtinRead(x) {
          if (Sk.builtinFiles === undefined || Sk.builtinFiles["files"][x] === undefined)
              throw "File not found: '" + x + "'";
          return Sk.builtinFiles["files"][x];
      }

      $scope.debugit = function() {
        // must run program to check that there are no syntax errors before debugging
        var prog = aceHl.getValue();
        var mypre = document.getElementById("output");

        mypre.innerHTML = '';
        Sk.pre = "output";
        Sk.configure({ output: outf, read: builtinRead });
        (Sk.TurtleGraphics || (Sk.TurtleGraphics = {})).target = 'mycanvas';
        var myPromise = Sk.misceval.asyncToPromise(function () {
            return Sk.importMainWithBody("<stdin>", false, prog, true);
        });

        myPromise.then(function (mod) {
          clearAll();
          document.getElementById("debHd").style.visibility="visible";
          var placeHere = document.getElementById("frameHere");
          var iframe = document.createElement('iframe');
          iframe.style.display = "inline";
          iframe.id ="debugger";
          iframe.width="90%";
          iframe.height="600px";
          var url = "http://pythontutor.com/iframe-embed.html#code=" + encodeURIComponent(aceHl.getValue())+ "&codeDivHeight=400&codeDivWidth=550&cumulative=false&curInstr=0&heapPrimitives=false&origin=opt-frontend.js&py=2&rawInputLstJSON=%5B%5D&textReferences=false";
          iframe.src = url;
          placeHere.appendChild(iframe);
        },
            function (err) {
              var mypre = document.getElementById("output");
              mypre.innerHTML = "Cannot debug with syntax errors: \n" +mypre.innerHTML + err.toString();
            });
          console.log("debugging");
      }

      $scope.runit = function() {
          clearAll();
          var prog = aceHl.getValue();
          var mypre = document.getElementById("output");

          mypre.innerHTML = '';
          Sk.pre = "output";
          Sk.configure({ output: outf, read: builtinRead });
          (Sk.TurtleGraphics || (Sk.TurtleGraphics = {})).target = 'mycanvas';
          var myPromise = Sk.misceval.asyncToPromise(function () {
              return Sk.importMainWithBody("<stdin>", false, prog, true);
          });
          myPromise.then(function (mod) {
              console.log('success');
          },
              function (err) {
                  var mypre = document.getElementById("output");
                  mypre.innerHTML = mypre.innerHTML + err.toString();
              });
          console.log('+1 to number of runs for analytics');
      }

      $scope.mark = function() {
          console.log("Submit for automatic marking");
          // analytics: record user ID, timestamp, marking was inititated, success/failure?
      }

      function clearAll()
      {
        var placeHere = document.getElementById("frameHere");
        placeHere.innerHTML=""; // clear previous debugging console
        document.getElementById("debHd").style.visibility="hidden";
        var mypre = document.getElementById("output");
        mypre.innerHTML = "";
      }

    });
<commit_msg>fix brackets<commit_after>'use strict';

angular.module('yapp')
    .controller('pythonInterpreterCtrl', function (Database, $window, $location, User, $scope, $state, $sce) {

    $scope.$state = $state;
    var Sk = $window.Sk;

    var aceHl;

    $scope.frameURL = $sce.trustAsResourceUrl("http://pythontutor.com/iframe-embed.html#code=%23%20this%20is%20the%20debugger&cumulative=false&py=3&curInstr=0");

    $scope.aceLoaded = function(_editor) {
   // Options
       _editor.setReadOnly(false);
       _editor.setValue("print 10", 1);// change to different value acc exercise
       aceHl = _editor;
       //$scope.detailFrame = $sce.trustAsResourceUrl("http://pythontutor.com/iframe-embed.html#code=x+%3D+5&cumulative=false&py=3&curInstr=0");
     };

     $scope.aceChanged = function(e) {
       clearAll();
       //var placeHere = document.getElementById("frameHere");
       //placeHere.innerHTML="";
     };

      function outf(text) {
          var mypre = document.getElementById("output");
          mypre.innerHTML = mypre.innerHTML + text;
      }

     function builtinRead(x) {
          if (Sk.builtinFiles === undefined || Sk.builtinFiles["files"][x] === undefined)
              throw "File not found: '" + x + "'";
          return Sk.builtinFiles["files"][x];
      }

      $scope.debugit = function() {
        // must run program to check that there are no syntax errors before debugging
        var prog = aceHl.getValue();
        var mypre = document.getElementById("output");

        mypre.innerHTML = '';
        Sk.pre = "output";
        Sk.configure({ output: outf, read: builtinRead });
        (Sk.TurtleGraphics || (Sk.TurtleGraphics = {})).target = 'mycanvas';
        var myPromise = Sk.misceval.asyncToPromise(function () {
            return Sk.importMainWithBody("<stdin>", false, prog, true);
        });

        myPromise.then(function (mod) {
          clearAll();
          document.getElementById("debHd").style.visibility="visible";
          var placeHere = document.getElementById("frameHere");
          var iframe = document.createElement('iframe');
          iframe.style.display = "inline";
          iframe.id ="debugger";
          iframe.width="90%";
          iframe.height="600px";
          var url = "http://pythontutor.com/iframe-embed.html#code=" + encodeURIComponent(aceHl.getValue())+ "&codeDivHeight=400&codeDivWidth=550&cumulative=false&curInstr=0&heapPrimitives=false&origin=opt-frontend.js&py=2&rawInputLstJSON=%5B%5D&textReferences=false";
          iframe.src = url;
          placeHere.appendChild(iframe);
        },
            function (err) {
              var mypre = document.getElementById("output");
              mypre.innerHTML = "Cannot debug with syntax errors: \n" +mypre.innerHTML + err.toString();
            });
          console.log("debugging");
      };

      $scope.runit = function() {
          clearAll();
          var prog = aceHl.getValue();
          var mypre = document.getElementById("output");

          mypre.innerHTML = '';
          Sk.pre = "output";
          Sk.configure({ output: outf, read: builtinRead });
          (Sk.TurtleGraphics || (Sk.TurtleGraphics = {})).target = 'mycanvas';
          var myPromise = Sk.misceval.asyncToPromise(function () {
              return Sk.importMainWithBody("<stdin>", false, prog, true);
          });
          myPromise.then(function (mod) {
              console.log('success');
          },
              function (err) {
                  var mypre = document.getElementById("output");
                  mypre.innerHTML = mypre.innerHTML + err.toString();
              });
          console.log('+1 to number of runs for analytics');
      };

      $scope.mark = function() {
          console.log("Submit for automatic marking");
          // analytics: record user ID, timestamp, marking was inititated, success/failure?
      };

      function clearAll()
      {
        var placeHere = document.getElementById("frameHere");
        placeHere.innerHTML=""; // clear previous debugging console
        document.getElementById("debHd").style.visibility="hidden";
        var mypre = document.getElementById("output");
        mypre.innerHTML = "";
      }

    });
<|endoftext|>


<commit_before>'use strict';

angular.module('confRegistrationWebApp')
  .directive('formElements', function () {
    return {
      restrict: 'A',
      link: function dragAndDropInterface(scope) {
        scope.toolbarTreeConfig = {
          accept: function(sourceNodeScope, destNodesScope) {
            return sourceNodeScope.$treeScope === destNodesScope.$treeScope;
          },
          beforeDrop: function(event) {
            //cancel regular drop action
            event.source.nodeScope.$$apply = false;
            //insert block
            if(event.dest.nodesScope.$nodeScope){ //prevents error from dropping on source tree
              var block = event.source.nodeScope.$modelValue;
              var pageId = event.dest.nodesScope.$nodeScope.$modelValue.id;
              scope.insertBlock(block.id, pageId, event.dest.index, block.defaultTitle);
            }
          }
        };
        scope.pageTreeConfig = {
          accept: function (sourceNode, destNodes) {
            var sourceType = sourceNode.$modelValue.pageId || sourceNode.$modelValue.defaultTitle ? 'block' : 'page';
            var destType = destNodes.$element.attr('drop-type');
            return (sourceType === destType); // only accept the same type
          }
        };

        //Debouncing plugin for jQuery from http://www.paulirish.com/2009/throttled-smartresize-jquery-event-handler/
        (function($,sr){
          // debouncing function from John Hann
          // http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
          var debounce = function (func, threshold, execAsap) {
            var timeout;

            return function debounced () {
              var obj = this, args = arguments;
              function delayed () {
                if (!execAsap) {
                  func.apply(obj, args);
                }
                timeout = null;
              }

              if (timeout) {
                clearTimeout(timeout);
              }else if (execAsap) {
                func.apply(obj, args);
              }
              timeout = setTimeout(delayed, threshold || 500);
            };
          };
          // smartresize
          jQuery.fn[sr] = function(fn){  return fn ? this.bind('resize', debounce(fn)) : this.trigger(sr); };

        })(jQuery,'smartresize');

        //keep placeholder the same size when the toolbar is affixed
        function setQuestionToolbarSize(){
          var container = $('.questions-toolbar-container');
          $('.questions-toolbar').data('bs.affix').options.offset.top = container.offset().top;
          container.css('min-height', function(){
            return $('.questions-toolbar').height();
          });
        }
        $(document).ready(function () {
          $('.questions-toolbar').affix({
            offset: {
              top: function () {
                return (this.top = $('.questions-toolbar-container').offset().top)
              }
            }
          });
          setQuestionToolbarSize();
          $(window).smartresize(function(){
            setQuestionToolbarSize();
          });
        });
      }
    };
  });
<commit_msg>Fix jshint error: missing semicolon<commit_after>'use strict';

angular.module('confRegistrationWebApp')
  .directive('formElements', function () {
    return {
      restrict: 'A',
      link: function dragAndDropInterface(scope) {
        scope.toolbarTreeConfig = {
          accept: function(sourceNodeScope, destNodesScope) {
            return sourceNodeScope.$treeScope === destNodesScope.$treeScope;
          },
          beforeDrop: function(event) {
            //cancel regular drop action
            event.source.nodeScope.$$apply = false;
            //insert block
            if(event.dest.nodesScope.$nodeScope){ //prevents error from dropping on source tree
              var block = event.source.nodeScope.$modelValue;
              var pageId = event.dest.nodesScope.$nodeScope.$modelValue.id;
              scope.insertBlock(block.id, pageId, event.dest.index, block.defaultTitle);
            }
          }
        };
        scope.pageTreeConfig = {
          accept: function (sourceNode, destNodes) {
            var sourceType = sourceNode.$modelValue.pageId || sourceNode.$modelValue.defaultTitle ? 'block' : 'page';
            var destType = destNodes.$element.attr('drop-type');
            return (sourceType === destType); // only accept the same type
          }
        };

        //Debouncing plugin for jQuery from http://www.paulirish.com/2009/throttled-smartresize-jquery-event-handler/
        (function($,sr){
          // debouncing function from John Hann
          // http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
          var debounce = function (func, threshold, execAsap) {
            var timeout;

            return function debounced () {
              var obj = this, args = arguments;
              function delayed () {
                if (!execAsap) {
                  func.apply(obj, args);
                }
                timeout = null;
              }

              if (timeout) {
                clearTimeout(timeout);
              }else if (execAsap) {
                func.apply(obj, args);
              }
              timeout = setTimeout(delayed, threshold || 500);
            };
          };
          // smartresize
          jQuery.fn[sr] = function(fn){  return fn ? this.bind('resize', debounce(fn)) : this.trigger(sr); };

        })(jQuery,'smartresize');

        //keep placeholder the same size when the toolbar is affixed
        function setQuestionToolbarSize(){
          var container = $('.questions-toolbar-container');
          $('.questions-toolbar').data('bs.affix').options.offset.top = container.offset().top;
          container.css('min-height', function(){
            return $('.questions-toolbar').height();
          });
        }
        $(document).ready(function () {
          $('.questions-toolbar').affix({
            offset: {
              top: function () {
                return (this.top = $('.questions-toolbar-container').offset().top);
              }
            }
          });
          setQuestionToolbarSize();
          $(window).smartresize(function(){
            setQuestionToolbarSize();
          });
        });
      }
    };
  });
<|endoftext|>