<commit_before>
const https       = require('https');
const fs          = require('fs');
const _           = require('lodash');
const async       = require('async');
const csvWriter   = require('csv-write-stream');

const config      = require('../src/config');

const readJson = (path, callback) => {
  fs.readFile(path, (err, data) => {
    callback(err, JSON.parse(data));
  });
};

//
const parseJson = (json) => {
  const translations = {};
  // parse
  json.feed.entry.forEach(entry => {
    const key = _.get(entry, 'gsx$key.$t');
    config.i18n.whitelist.forEach((lang) => {
      const value = _.get(entry, `gsx$${lang}.$t`);
      if (value) {
        _.setWith(translations, `${lang}.${key}`, value, Object);
      }
    });
  });
  return translations;
};

const writeTranslationFiles = (translations) => {
  // write translation files
  config.i18n.whitelist.forEach((lang) => {
    const dir = `./locales/${lang}`;
    if (!fs.existsSync(dir)) {
      console.warn('Missing directory: ' + dir);
      return;
    }
    translations[lang]._meta = {
      generated_at: new Date(),
      lang
    };
    const data = JSON.stringify(translations[lang], null, 2);
    const filename = `${dir}/translation.json`;
    console.log(`Writing ${filename}`);

    fs.writeFileSync(filename, data );
  });
}

// verbs
const verbs   = {

  // igo i18n update
  update: function(args, callback) {
    if (!config.i18n.spreadsheet_id) {
      return callback('Missing config.i18n.spreadsheet_id');
    }
    const url = `https://spreadsheets.google.com/feeds/list/${config.i18n.spreadsheet_id}/default/public/values?alt=json`;

    // request json data
    https.get(url, (resp) => {
      let body = '';

      resp.on('data', (chunk) => {
        body += chunk;
      });

      resp.on('end', () => {
        const json = JSON.parse(body);
        //console.dir(json);

        const translations = parseJson(json);
        writeTranslationFiles(translations);

        callback();
      })

    }).on('error', callback);
  },

  // igo i18n csv
  csv: function(args, callback) {
    const langs = config.i18n.whitelist;
    async.mapSeries(langs, (lang, callback) => {
      readJson(`./locales/${lang}/translation.json`, callback);
    }, (err, translations) => {
      const keys    = [];

      // build keys
      const traverse = (obj, parents) => {
        for (const key in obj) {
          const val = obj[key];
          if (_.isObject(val)) {
            traverse(obj[key], parents.concat([key]));
          } else if (_.isString(val)) {
            keys.push(parents.concat([key]).join('.'));
          }
        }
      };
      traverse(translations[0], []);

      // build csv
      const writer = csvWriter({ headers: [ 'key' ].concat(langs) });

      writer.pipe(fs.createWriteStream('./translations.csv'))
      keys.forEach(key => {
        const row =  _.map(translations, translation => _.get(translation, key))
        writer.write([ key ].concat(row))
      });

      writer.end()
      console.log(keys.length + ' lines written');
      callback();
    });
  }

};

// igo i18n
module.exports = function(argv) {
  var args = argv._;
  config.init();

  if (args.length > 1 && verbs[args[1]]) {
    verbs[args[1]](args, function(err) {
      console.log(err || 'Done.');
      // process.exit(0);
    });
  } else {
    console.error('ERROR: Wrong options');
    console.error('Usage: igo i18n [update|csv]')
  }

};
<commit_msg>Cli : fix igo i18n<commit_after>
const https       = require('https');
const fs          = require('fs');
const _           = require('lodash');
const async       = require('async');
const csvWriter   = require('csv-write-stream');

const config      = require('../src/config');

const readJson = (path, callback) => {
  fs.readFile(path, (err, data) => {
    callback(err, JSON.parse(data));
  });
};

//
const parseJson = (json) => {
  const translations = {};
  // parse
  json.feed.entry.forEach(entry => {
    const key = _.get(entry, 'gsx$key.$t');
    config.i18n.whitelist.forEach((lang) => {
      const value = _.get(entry, `gsx$${lang}.$t`);
      if (value !== '') {
        _.setWith(translations, `${lang}.${key}`, value, Object);
      }
    });
  });
  return translations;
};

const writeTranslationFiles = (translations) => {
  // write translation files
  config.i18n.whitelist.forEach((lang) => {
    const dir = `./locales/${lang}`;
    if (!fs.existsSync(dir)) {
      console.warn('Missing directory: ' + dir);
      return;
    }
    translations[lang]._meta = {
      generated_at: new Date(),
      lang
    };
    const data = JSON.stringify(translations[lang], null, 2);
    const filename = `${dir}/translation.json`;
    console.log(`Writing ${filename}`);

    fs.writeFileSync(filename, data );
  });
}

// verbs
const verbs   = {

  // igo i18n update
  update: function(args, callback) {
    if (!config.i18n.spreadsheet_id) {
      return callback('Missing config.i18n.spreadsheet_id');
    }
    const url = `https://spreadsheets.google.com/feeds/list/${config.i18n.spreadsheet_id}/default/public/values?alt=json`;
    console.log(`Loading: ${url}`);

    // request json data
    https.get(url, (resp) => {
      let body = [];

      resp.on('data', (chunk) => {
        body.push(chunk);
      });

      resp.on('end', () => {
        const buffer = Buffer.concat(body);
        const json = JSON.parse(buffer.toString());

        const translations = parseJson(json);
        writeTranslationFiles(translations);

        callback();
      })

    }).on('error', callback);
  },

  // igo i18n csv
  csv: function(args, callback) {
    const langs = config.i18n.whitelist;
    async.mapSeries(langs, (lang, callback) => {
      readJson(`./locales/${lang}/translation.json`, callback);
    }, (err, translations) => {
      const keys    = [];

      // build keys
      const traverse = (obj, parents) => {
        for (const key in obj) {
          const val = obj[key];
          if (_.isObject(val)) {
            traverse(obj[key], parents.concat([key]));
          } else if (_.isString(val)) {
            keys.push(parents.concat([key]).join('.'));
          }
        }
      };
      translations.forEach(translation => {
        traverse(translation, []);
      });

      // build csv
      const writer = csvWriter({ headers: [ 'key' ].concat(langs) });

      const file = './translations.csv';
      writer.pipe(fs.createWriteStream(file))
      _.uniq(keys).forEach(key => {
        const row =  _.map(translations, translation => _.get(translation, key))
        writer.write([ key ].concat(row))
      });

      writer.end()
      console.log(keys.length + ' lines written in ' + file);
      callback();
    });
  }

};

// igo i18n
module.exports = function(argv) {
  var args = argv._;
  config.init();

  if (args.length > 1 && verbs[args[1]]) {
    verbs[args[1]](args, function(err) {
      console.log(err || 'Done.');
      // process.exit(0);
    });
  } else {
    console.error('ERROR: Wrong options');
    console.error('Usage: igo i18n [update|csv]')
  }

};
<|endoftext|>


<commit_before>/**
 * Database file
 * To easily switch between different database using a common API.
 *
 *
 * methods.read(key, username, callback)
 *	 Reads a key in the database.
 *
 *	 @param {String} key
 *	 @param {String} user
 *	 @param {Function} callback(err, value)
 *
 * methods.write(key, value, user, callback)
 *	 Writes a key to value in the database.
 *
 *	 @param {String} key
 *	 @param {*} value
 *	 @param {String} user
 *	 @param {Function} callback(err, value)
 *
 * methods.total(key, callback)
 *	 Combined value from all rows.
 *
 *	 @param {String} key
 *	 @param {Function} callback(err, total)
 *
 * methods.countUsers(callback)
 *	 Gets how many users there are.
 *
 *	 @param {Function} callback(err, size)
 *
 * methods.sortDesc(key, amount, callback)
 *	 Sort by a key in descending order.
 *
 *	 @param {String} key
 *	 @param {Number} amount
 *	 @param {Function} callback(err, array)
 *
 * methods.get(key, callback)
 *	 Get a key in the database.
 *
 *	 @param {String} key
 *	 @param {Function} callback(err, key)
 *
 * methods.set(key, value, callback)
 *	 Set a key in the database.
 *
 *	 @param {String} key
 *	 @param {Number} value
 *	 @param {Function} callback(err, newKey)
 *
 * methods.users(callback)
 *	 Get the users array in the database.
 *
 *	 @param {Function} callback(err, users)
 *
 * @license MIT license
 */

var low = require('lowdb');
var mysql = require('mysql');
var path = require('path');

var lowFile = path.join(__dirname, 'config/db.json');

var databases = {};

databases.lowdb = function () {
	var db = low(lowFile);
	var methods = {};

	methods.read = function (key, username, callback) {
		var user = db('users').find({username: username});
		if (!user) return callback(null);
		callback(null, user[key]);
	};

	methods.write = function (key, value, username, callback) {
		var user = db('users').find({username: username});
		if (!user) db('users').push({username: username});
		var obj = {};
		obj[key] = value;
		var val = db('users')
					.chain()
					.find({username: username})
					.assign(obj)
					.value();

		callback(null, val[key]);
	};

	methods.total = function (key, callback) {
		var total = db('users').reduce(function (acc, user) {
			if (!acc[key] || !user[key]) return {money: acc[key]};
			return {money: acc[key] + user[key]};
		});
		callback(null, total.money);
	};

	methods.countUsers = function (callback) {
		return callback(null, db('users').size());
	};

	methods.sortDesc = function (key, amount, callback) {
		var value = db('users')
						.chain()
						.filter(function (user) {
							return user.money >= 0;
						})
						.sortByOrder('money', ['desc'])
						.take(amount)
						.value();

		callback(null, value);
	};

	methods.get = function (key, callback) {
		if (key === 'users') return callback(new Error('Cannot overwrite users'));
		callback(null, db.object[key]);
	};

	methods.set = function (key, value, callback) {
		if (key === 'users') return callback(new Error('Cannot overwrite users'));
		db.object[key] = value;
		callback(null, db.object[key]);
	};

	methods.users = function (callback) {
		callback(null, db('users').value());
	};

	return methods;
};

databases.mysql = function () {
	var methods = {};
	var connection = mysql.createConnection(Config.mysql);
	connection.connect();

	return methods;
};

function Database (database) {
	return databases[database]();
}

module.exports = Database;
<commit_msg>Support mysql read and write<commit_after>/**
 * Database file
 * To easily switch between different database using a common API.
 *
 *
 * methods.read(key, username, callback)
 *	 Reads a key in the database.
 *
 *	 @param {String} key
 *	 @param {String} user
 *	 @param {Function} callback(err, value)
 *
 * methods.write(key, value, user, callback)
 *	 Writes a key to value in the database.
 *
 *	 @param {String} key
 *	 @param {*} value
 *	 @param {String} user
 *	 @param {Function} callback(err, value)
 *
 * methods.total(key, callback)
 *	 Combined value from all rows.
 *
 *	 @param {String} key
 *	 @param {Function} callback(err, total)
 *
 * methods.countUsers(callback)
 *	 Gets how many users there are.
 *
 *	 @param {Function} callback(err, size)
 *
 * methods.sortDesc(key, amount, callback)
 *	 Sort by a key in descending order.
 *
 *	 @param {String} key
 *	 @param {Number} amount
 *	 @param {Function} callback(err, array)
 *
 * methods.get(key, callback)
 *	 Get a key in the database.
 *
 *	 @param {String} key
 *	 @param {Function} callback(err, key)
 *
 * methods.set(key, value, callback)
 *	 Set a key in the database.
 *
 *	 @param {String} key
 *	 @param {Number} value
 *	 @param {Function} callback(err, newKey)
 *
 * methods.users(callback)
 *	 Get the users array in the database.
 *
 *	 @param {Function} callback(err, users)
 *
 * @license MIT license
 */

var low = require('lowdb');
var mysql = require('mysql');
var path = require('path');

var lowFile = path.join(__dirname, 'config/db.json');

var databases = {};

databases.lowdb = function () {
	var db = low(lowFile);
	var methods = {};

	methods.read = function (key, username, callback) {
		var user = db('users').find({username: username});
		if (!user) return callback(null);
		callback(null, user[key]);
	};

	methods.write = function (key, value, username, callback) {
		var user = db('users').find({username: username});
		if (!user) db('users').push({username: username});
		var obj = {};
		obj[key] = value;
		var val = db('users')
					.chain()
					.find({username: username})
					.assign(obj)
					.value();

		callback(null, val[key]);
	};

	methods.total = function (key, callback) {
		var total = db('users').reduce(function (acc, user) {
			if (!acc[key] || !user[key]) return {money: acc[key]};
			return {money: acc[key] + user[key]};
		});
		callback(null, total.money);
	};

	methods.countUsers = function (callback) {
		return callback(null, db('users').size());
	};

	methods.sortDesc = function (key, amount, callback) {
		var value = db('users')
						.chain()
						.filter(function (user) {
							return user.money >= 0;
						})
						.sortByOrder('money', ['desc'])
						.take(amount)
						.value();

		callback(null, value);
	};

	methods.get = function (key, callback) {
		if (key === 'users') return callback(new Error('Cannot overwrite users'));
		callback(null, db.object[key]);
	};

	methods.set = function (key, value, callback) {
		if (key === 'users') return callback(new Error('Cannot overwrite users'));
		db.object[key] = value;
		callback(null, db.object[key]);
	};

	methods.users = function (callback) {
		callback(null, db('users').value());
	};

	return methods;
};

databases.mysql = function () {
	var methods = {};
	var connection = mysql.createConnection(Config.mysql);
	connection.connect(function (err) {
		if (err) return console.error('error connecting: ' + err.stack);
		console.log('connected as id ' + connection.threadId);
	});

	var creationStr = "CREATE TABLE IF NOT EXISTS users (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT," +
							"username VARCHAR(20)," +
							"money INTEGER," +
							"tickets TEXT);";

	connection.query(creationStr, function (err) {
		if (err) throw err;
	});

	methods.read = function (key, username, callback) {
		connection.query("SELECT " + key + " from users WHERE username=\"" + username + "\";", function (err, rows) {
			if (err) return callback(new Error(err));
			if (!rows.length) return callback(null);
			callback(null, rows[0][key]);
		});
	};

	methods.write = function (key, value, username, callback) {
		connection.query("DELETE FROM users WHERE username=\"" + username + "\";", function (err) {
			if (err) return callback(new Error(err));
			connection.query("INSERT INTO users (username, " + key + ") VALUES (\"" + username + "\", " + value + ");", function (err) {
				if (err) return callback(new Error(err));
				callback(null, value);
			});
		});
	};

	return methods;
};

function Database (database) {
	return databases[database]();
}

module.exports = Database;
<|endoftext|>


<commit_before>/*
 * chesterGL - Simple 2D WebGL demo/library
 *
 * Copyright (c) 2010-2012 Rolando Abarca
 *
 * 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.
 *
 */

goog.provide("chesterGL.BlockGroup");

goog.require("goog.vec.Mat4");
goog.require("chesterGL.Block");

/**
 * creates a new block group
 *
 * @constructor
 * @param {string} texture An optional texture that will be shared with all children
 * @param {number=} noChildren The optional initial number of maxChidlren. Defaults to 10
 * @extends {chesterGL.Block}
 */
chesterGL.BlockGroup = function (texture, noChildren) {
	if (!chesterGL.webglMode) {
		throw "BlockGroup only works on WebGL mode";
	}
	// call "super"
	chesterGL.Block.call(this, null, chesterGL.Block.TYPE['BLOCKGROUP']);
	if (texture) {
		this.texture = texture;
		this.program = chesterGL.Block.PROGRAM['TEXTURE'];
	} else {
		this.program = chesterGL.Block.PROGRAM['DEFAULT'];
	}
	this.maxChildren = noChildren || 10;

	// create the buffers for the children
	this.createBuffers();
};
goog.inherits(chesterGL.BlockGroup, chesterGL.Block);

/**
 * The max number of children this blockgroup can hold (this is here for the buffer data)
 * @type {number}
 * @ignore
 */
chesterGL.BlockGroup.prototype.maxChildren = 0;

/**
 * @type {boolean}
 * @ignore
 */
chesterGL.BlockGroup.prototype.isChildDirty = false;

/**
 * @type {?WebGLBuffer}
 * @ignore
 */
chesterGL.BlockGroup.prototype.indexBuffer = null;

/**
 * @type {?Uint16Array}
 * @ignore
 */
chesterGL.BlockGroup.prototype.indexBufferData = null;

/**
 * Creates the buffers for the current maxChildren size
 * @param {Array|Float32Array=} oldBufferData
 * @param {Array|Uint16Array=} oldIndexData
 * @ignore
 */
chesterGL.BlockGroup.prototype.createBuffers = function (oldBufferData, oldIndexData) {
	var gl = chesterGL.gl;
	if (!this.glBuffer)
		this.glBuffer = gl.createBuffer();
	if (!this.indexBuffer)
		this.indexBuffer = gl.createBuffer();

	var glBufferData    = new Float32Array(chesterGL.Block.QUAD_SIZE * this.maxChildren);
	var indexBufferData = new Uint16Array(6 * this.maxChildren);
	if (oldBufferData) {
		glBufferData.set(oldBufferData);
	}
	if (oldIndexData) {
		indexBufferData.set(oldIndexData);
	}
	this.glBufferData = glBufferData;
	this.indexBufferData = indexBufferData;
};

/**
 * creates a block that can be added to this block group
 * @param {goog.vec.Vec4.Type} rect
 */
chesterGL.BlockGroup.prototype.createBlock = function (rect) {
	var b = new chesterGL.Block(rect, chesterGL.Block.TYPE['STANDALONE'], this);
	if (this.texture) {
		b.setTexture(this.texture);
	}
	return b;
};

/**
 * adds a child
 * @param {chesterGL.Block} block
 */
chesterGL.BlockGroup.prototype.addChild = function (block) {
	if (this.children.length >= this.maxChildren) {
		// should resize the buffers
		this.maxChildren *= 2;
		console.log("resize " + this.maxChildren);
		this.createBuffers(this.glBufferData, this.indexBufferData);
	}
	if (block.parent != this) {
		throw "Invalid child: can only add children created with BlockGroup.create";
	}
	if (!this.texture) {
		this.texture = block.texture;
	} else {
		if (this.texture != block.texture) {
			throw "Invalid child: only can add child with the same texture";
		}
	}
	this.children.push(block);

	var length = this.children.length;

	// just point the buffer data on the child and set the baseIndex
	block.baseBufferIndex = length-1;
	block.glBufferData    = this.glBufferData;
	this.isChildDirty = true;
};

/**
 * removes a block from the group
 * @param {chesterGL.Block} b
 */
chesterGL.BlockGroup.prototype.removeChild = function (b) {
	if (b.parent != this) {
		throw "Invalid child";
	}
	if (this._inVisit) {
		this._scheduledRemove.push(b);
	} else {
		var idx = this.children.indexOf(b);
		if (idx > 0) {
			this.children.splice(idx, 1);
			// for the rest of the children, mark them as dirty and reduce the baseBufferIndex
			for (var i=idx; i < this.totalChildren; i++) {
				var _b = this.children[i];
				_b.baseBufferIndex = i;
				_b.isTransformDirty = true;
				_b.isColorDirty = true;
			}
		}
		this.isChildDirty = true;
	}
};

/**
 * when the block list changes, the indices array must be recreated
 * @param {number} startIdx
 */
chesterGL.BlockGroup.prototype.recreateIndices = function (startIdx) {
	var lastIdx = (this.indexBufferData[startIdx*6 - 1] || -1) + 1;
	var total = Math.max(this.children.length, 1);
	for (var i = startIdx; i < total; i ++) {
		var idx = i*6;
		this.indexBufferData[idx + 0] = lastIdx    ; this.indexBufferData[idx + 1] = lastIdx + 1; this.indexBufferData[idx + 2] = lastIdx + 2;
		this.indexBufferData[idx + 3] = lastIdx + 2; this.indexBufferData[idx + 4] = lastIdx + 1; this.indexBufferData[idx + 5] = lastIdx + 3;
		lastIdx += 4;
	}
	var gl = chesterGL.gl;
	gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
	gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indexBufferData, gl.STATIC_DRAW);
};

/**
 * where the fun begins
 * @ignore
 */
chesterGL.BlockGroup.prototype.visit = function () {
	this._inVisit = true;
	if (this.update) {
		this.update(chesterGL.delta);
	}
	if (!this.visible) {
		this._inVisit = false;
		return;
	}
	this.transform();

	// this should be more like cocos2d: preserve the z-ordering
	var children = this.children;
	var len = children.length;
	for (var i=0; i < len; i++) {
		children[i].visit();
	}

	// re-bind the glBuffer (might have changed in the children visit)
	var gl = chesterGL.gl;
	gl.bindBuffer(gl.ARRAY_BUFFER, this.glBuffer);
	gl.bufferData(gl.ARRAY_BUFFER, this.glBufferData, gl.STATIC_DRAW);

	if (this.isChildDirty) {
		this.recreateIndices(0);
		this.isChildDirty = false;
	}
	// render this block group
	this.render();

	// reset our dirty markers
	this.isFrameDirty = this.isColorDirty = this.isTransformDirty = false;
	this._inVisit = false;

	var b;
	while (b = this._scheduledRemove.shift()) {
		this.removeChild(b);
	}
};

/**
 * actually render the block group
 * @ignore
 */
chesterGL.BlockGroup.prototype.render = function () {
	var gl = chesterGL.gl;

	// select current shader
	var program = chesterGL.selectProgram(chesterGL.Block.PROGRAM_NAME[this.program]);
	var totalChildren = this.children.length;
	var texOff = 3 * 4,
		colorOff = texOff + 2 * 4,
		stride = chesterGL.Block.QUAD_SIZE;

	gl.bindBuffer(gl.ARRAY_BUFFER, this.glBuffer);

	gl.vertexAttribPointer(program.attribs['vertexPositionAttribute'], 3, gl.FLOAT, false, stride, 0);
	if (this.program == chesterGL.Block.PROGRAM['DEFAULT']) {
		// no extra attributes for the shader
	} else if (this.program == chesterGL.Block.PROGRAM['TEXTURE']) {
		var texture = chesterGL.getAsset('texture', this.texture);

		// pass the texture attributes
		gl.vertexAttribPointer(program.attribs['textureCoordAttribute'], 2, gl.FLOAT, false, stride, texOff);

		gl.activeTexture(gl.TEXTURE0);
		gl.bindTexture(gl.TEXTURE_2D, texture.tex);
		gl.uniform1i(program.samplerUniform, 0);
	}
	gl.vertexAttribPointer(program.attribs['vertexColorAttribute'], 4, gl.FLOAT, false, stride, colorOff);

	gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);

	// set the matrix uniform (the multiplied model view projection matrix)
	goog.vec.Mat4.multMat(chesterGL.pMatrix, this.mvMatrix, this.mvpMatrix);
	gl.uniformMatrix4fv(program.mvpMatrixUniform, false, this.mvpMatrix);
	// gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4 * this.children.length);
	gl.drawElements(gl.TRIANGLES, totalChildren * 6, gl.UNSIGNED_SHORT, 0);
};

// export the symbol
goog.exportSymbol('chesterGL.BlockGroup', chesterGL.BlockGroup);
// instance methods
goog.exportProperty(chesterGL.BlockGroup.prototype, 'createBlock', chesterGL.BlockGroup.prototype.createBlock);
goog.exportProperty(chesterGL.BlockGroup.prototype, 'addChild', chesterGL.BlockGroup.prototype.addChild);
goog.exportProperty(chesterGL.BlockGroup.prototype, 'removeChild', chesterGL.BlockGroup.prototype.removeChild);
<commit_msg>reorder parent test in addChild<commit_after>/*
 * chesterGL - Simple 2D WebGL demo/library
 *
 * Copyright (c) 2010-2012 Rolando Abarca
 *
 * 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.
 *
 */

goog.provide("chesterGL.BlockGroup");

goog.require("goog.vec.Mat4");
goog.require("chesterGL.Block");

/**
 * creates a new block group
 *
 * @constructor
 * @param {string} texture An optional texture that will be shared with all children
 * @param {number=} noChildren The optional initial number of maxChidlren. Defaults to 10
 * @extends {chesterGL.Block}
 */
chesterGL.BlockGroup = function (texture, noChildren) {
	if (!chesterGL.webglMode) {
		throw "BlockGroup only works on WebGL mode";
	}
	// call "super"
	chesterGL.Block.call(this, null, chesterGL.Block.TYPE['BLOCKGROUP']);
	if (texture) {
		this.texture = texture;
		this.program = chesterGL.Block.PROGRAM['TEXTURE'];
	} else {
		this.program = chesterGL.Block.PROGRAM['DEFAULT'];
	}
	this.maxChildren = noChildren || 10;

	// create the buffers for the children
	this.createBuffers();
};
goog.inherits(chesterGL.BlockGroup, chesterGL.Block);

/**
 * The max number of children this blockgroup can hold (this is here for the buffer data)
 * @type {number}
 * @ignore
 */
chesterGL.BlockGroup.prototype.maxChildren = 0;

/**
 * @type {boolean}
 * @ignore
 */
chesterGL.BlockGroup.prototype.isChildDirty = false;

/**
 * @type {?WebGLBuffer}
 * @ignore
 */
chesterGL.BlockGroup.prototype.indexBuffer = null;

/**
 * @type {?Uint16Array}
 * @ignore
 */
chesterGL.BlockGroup.prototype.indexBufferData = null;

/**
 * Creates the buffers for the current maxChildren size
 * @param {Array|Float32Array=} oldBufferData
 * @param {Array|Uint16Array=} oldIndexData
 * @ignore
 */
chesterGL.BlockGroup.prototype.createBuffers = function (oldBufferData, oldIndexData) {
	var gl = chesterGL.gl;
	if (!this.glBuffer)
		this.glBuffer = gl.createBuffer();
	if (!this.indexBuffer)
		this.indexBuffer = gl.createBuffer();

	var glBufferData    = new Float32Array(chesterGL.Block.QUAD_SIZE * this.maxChildren);
	var indexBufferData = new Uint16Array(6 * this.maxChildren);
	if (oldBufferData) {
		glBufferData.set(oldBufferData);
	}
	if (oldIndexData) {
		indexBufferData.set(oldIndexData);
	}
	this.glBufferData = glBufferData;
	this.indexBufferData = indexBufferData;
};

/**
 * creates a block that can be added to this block group
 * @param {goog.vec.Vec4.Type} rect
 */
chesterGL.BlockGroup.prototype.createBlock = function (rect) {
	var b = new chesterGL.Block(rect, chesterGL.Block.TYPE['STANDALONE'], this);
	if (this.texture) {
		b.setTexture(this.texture);
	}
	return b;
};

/**
 * adds a child
 * @param {chesterGL.Block} block
 */
chesterGL.BlockGroup.prototype.addChild = function (block) {
	if (block.parent != this) {
		throw "Invalid child: can only add children created with BlockGroup.create";
	}
	if (this.children.length >= this.maxChildren) {
		// should resize the buffers
		this.maxChildren *= 2;
		this.createBuffers(this.glBufferData, this.indexBufferData);
	}
	if (!this.texture) {
		this.texture = block.texture;
	} else {
		if (this.texture != block.texture) {
			throw "Invalid child: only can add child with the same texture";
		}
	}
	this.children.push(block);

	var length = this.children.length;

	// just point the buffer data on the child and set the baseIndex
	block.baseBufferIndex = length-1;
	block.glBufferData    = this.glBufferData;
	this.isChildDirty = true;
};

/**
 * removes a block from the group
 * @param {chesterGL.Block} b
 */
chesterGL.BlockGroup.prototype.removeChild = function (b) {
	if (b.parent != this) {
		throw "Invalid child";
	}
	if (this._inVisit) {
		this._scheduledRemove.push(b);
	} else {
		var idx = this.children.indexOf(b);
		if (idx > 0) {
			this.children.splice(idx, 1);
			// for the rest of the children, mark them as dirty and reduce the baseBufferIndex
			for (var i=idx; i < this.totalChildren; i++) {
				var _b = this.children[i];
				_b.baseBufferIndex = i;
				_b.isTransformDirty = true;
				_b.isColorDirty = true;
			}
		}
		this.isChildDirty = true;
	}
};

/**
 * when the block list changes, the indices array must be recreated
 * @param {number} startIdx
 */
chesterGL.BlockGroup.prototype.recreateIndices = function (startIdx) {
	var lastIdx = (this.indexBufferData[startIdx*6 - 1] || -1) + 1;
	var total = Math.max(this.children.length, 1);
	for (var i = startIdx; i < total; i ++) {
		var idx = i*6;
		this.indexBufferData[idx + 0] = lastIdx    ; this.indexBufferData[idx + 1] = lastIdx + 1; this.indexBufferData[idx + 2] = lastIdx + 2;
		this.indexBufferData[idx + 3] = lastIdx + 2; this.indexBufferData[idx + 4] = lastIdx + 1; this.indexBufferData[idx + 5] = lastIdx + 3;
		lastIdx += 4;
	}
	var gl = chesterGL.gl;
	gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
	gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indexBufferData, gl.STATIC_DRAW);
};

/**
 * where the fun begins
 * @ignore
 */
chesterGL.BlockGroup.prototype.visit = function () {
	this._inVisit = true;
	if (this.update) {
		this.update(chesterGL.delta);
	}
	if (!this.visible) {
		this._inVisit = false;
		return;
	}
	this.transform();

	// this should be more like cocos2d: preserve the z-ordering
	var children = this.children;
	var len = children.length;
	for (var i=0; i < len; i++) {
		children[i].visit();
	}

	// re-bind the glBuffer (might have changed in the children visit)
	var gl = chesterGL.gl;
	gl.bindBuffer(gl.ARRAY_BUFFER, this.glBuffer);
	gl.bufferData(gl.ARRAY_BUFFER, this.glBufferData, gl.STATIC_DRAW);

	if (this.isChildDirty) {
		this.recreateIndices(0);
		this.isChildDirty = false;
	}
	// render this block group
	this.render();

	// reset our dirty markers
	this.isFrameDirty = this.isColorDirty = this.isTransformDirty = false;
	this._inVisit = false;

	var b;
	while (b = this._scheduledRemove.shift()) {
		this.removeChild(b);
	}
};

/**
 * actually render the block group
 * @ignore
 */
chesterGL.BlockGroup.prototype.render = function () {
	var gl = chesterGL.gl;

	// select current shader
	var program = chesterGL.selectProgram(chesterGL.Block.PROGRAM_NAME[this.program]);
	var totalChildren = this.children.length;
	var texOff = 3 * 4,
		colorOff = texOff + 2 * 4,
		stride = chesterGL.Block.QUAD_SIZE;

	gl.bindBuffer(gl.ARRAY_BUFFER, this.glBuffer);

	gl.vertexAttribPointer(program.attribs['vertexPositionAttribute'], 3, gl.FLOAT, false, stride, 0);
	if (this.program == chesterGL.Block.PROGRAM['DEFAULT']) {
		// no extra attributes for the shader
	} else if (this.program == chesterGL.Block.PROGRAM['TEXTURE']) {
		var texture = chesterGL.getAsset('texture', this.texture);

		// pass the texture attributes
		gl.vertexAttribPointer(program.attribs['textureCoordAttribute'], 2, gl.FLOAT, false, stride, texOff);

		gl.activeTexture(gl.TEXTURE0);
		gl.bindTexture(gl.TEXTURE_2D, texture.tex);
		gl.uniform1i(program.samplerUniform, 0);
	}
	gl.vertexAttribPointer(program.attribs['vertexColorAttribute'], 4, gl.FLOAT, false, stride, colorOff);

	gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);

	// set the matrix uniform (the multiplied model view projection matrix)
	goog.vec.Mat4.multMat(chesterGL.pMatrix, this.mvMatrix, this.mvpMatrix);
	gl.uniformMatrix4fv(program.mvpMatrixUniform, false, this.mvpMatrix);
	// gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4 * this.children.length);
	gl.drawElements(gl.TRIANGLES, totalChildren * 6, gl.UNSIGNED_SHORT, 0);
};

// export the symbol
goog.exportSymbol('chesterGL.BlockGroup', chesterGL.BlockGroup);
// instance methods
goog.exportProperty(chesterGL.BlockGroup.prototype, 'createBlock', chesterGL.BlockGroup.prototype.createBlock);
goog.exportProperty(chesterGL.BlockGroup.prototype, 'addChild', chesterGL.BlockGroup.prototype.addChild);
goog.exportProperty(chesterGL.BlockGroup.prototype, 'removeChild', chesterGL.BlockGroup.prototype.removeChild);
<|endoftext|>


<commit_before>dojo.provide("dijit._Calendar");

dojo.require("dojo.cldr.supplemental");
dojo.require("dojo.date");
dojo.require("dojo.date.locale");

dojo.require("dijit._Widget");
dojo.require("dijit._Templated");

dojo.declare(
	"dijit._Calendar",
	[dijit._Widget, dijit._Templated],
	{
	//
	//	summary:
	//		A simple GUI for choosing a date in the context of a monthly calendar.
	//
	//	description:
	//		A simple GUI for choosing a date in the context of a monthly calendar.
	//		This widget is used internally by other widgets and is not accessible
	//		as a standalone widget.
	//		This widget can't be used in a form because it doesn't serialize the date to an
	//		`<input>` field.  For a form element, use dijit.form.DateTextBox instead.
	//
	//		Note that the parser takes all dates attributes passed in the
	//		[RFC 3339 format](http://www.faqs.org/rfcs/rfc3339.html), e.g. `2005-06-30T08:05:00-07:00`
	//		so that they are serializable and locale-independent.
	//
	//	example:
	//	|	var calendar = new dijit._Calendar({}, dojo.byId("calendarNode"));
	//
	//	example:
	//	|

	//
		templatePath: dojo.moduleUrl("dijit", "templates/Calendar.html"),

		// value: Date
		// 	the currently selected Date
		value: new Date(),

		// dayWidth: String
		// 	How to represent the days of the week in the calendar header. See dojo.date.locale
		dayWidth: "narrow",

		setValue: function(/*Date*/ value){
			dojo.deprecated("dijit.Calendar:setValue() is deprecated.  Use attr('value', ...) instead.", "", "2.0");
			this.attr('value', value);
		},
		_setValueAttr: function(/*Date*/ value){
			// summary:
			//		Hook to make attr("value", ...) work.
			// description:
			// 		Set the current date and update the UI.  If the date is disabled, the selection will
			//		not change, but the display will change to the corresponding month.
			if(!this.value || dojo.date.compare(value, this.value)){
				value = new Date(value);
				this.displayMonth = new Date(value);
				if(!this.isDisabledDate(value, this.lang)){
					this.value = value;
					this.value.setHours(0,0,0,0);
					this.onChange(this.value);
				}
				this._populateGrid();
			}
		},

		_setText: function(node, text){
			while(node.firstChild){
				node.removeChild(node.firstChild);
			}
			node.appendChild(dojo.doc.createTextNode(text));
		},

		_populateGrid: function(){
			var month = this.displayMonth;
			month.setDate(1);
			var firstDay = month.getDay();
			var daysInMonth = dojo.date.getDaysInMonth(month);
			var daysInPreviousMonth = dojo.date.getDaysInMonth(dojo.date.add(month, "month", -1));
			var today = new Date();
			var selected = this.value;

			var dayOffset = dojo.cldr.supplemental.getFirstDayOfWeek(this.lang);
			if(dayOffset > firstDay){ dayOffset -= 7; }

			// Iterate through dates in the calendar and fill in date numbers and style info
			dojo.query(".dijitCalendarDateTemplate", this.domNode).forEach(function(template, i){
				i += dayOffset;
				var date = new Date(month);
				var number, clazz = "dijitCalendar", adj = 0;

				if(i < firstDay){
					number = daysInPreviousMonth - firstDay + i + 1;
					adj = -1;
					clazz += "Previous";
				}else if(i >= (firstDay + daysInMonth)){
					number = i - firstDay - daysInMonth + 1;
					adj = 1;
					clazz += "Next";
				}else{
					number = i - firstDay + 1;
					clazz += "Current";
				}

				if(adj){
					date = dojo.date.add(date, "month", adj);
				}
				date.setDate(number);

				if(!dojo.date.compare(date, today, "date")){
					clazz = "dijitCalendarCurrentDate " + clazz;
				}

				if(!dojo.date.compare(date, selected, "date")){
					clazz = "dijitCalendarSelectedDate " + clazz;
				}

				if(this.isDisabledDate(date, this.lang)){
					clazz = "dijitCalendarDisabledDate " + clazz;
				}

				var clazz2 = this.getClassForDate(date, this.lang);
				if(clazz2){
					clazz = clazz2 + " " + clazz;
				}

				template.className =  clazz + "Month dijitCalendarDateTemplate";
				template.dijitDateValue = date.valueOf();
				var label = dojo.query(".dijitCalendarDateLabel", template)[0];
				this._setText(label, date.getDate());
			}, this);

			// Fill in localized month name
			var monthNames = dojo.date.locale.getNames('months', 'wide', 'standAlone', this.lang);
			this._setText(this.monthLabelNode, monthNames[month.getMonth()]);

			// Fill in localized prev/current/next years
			var y = month.getFullYear() - 1;
			var d = new Date();
			dojo.forEach(["previous", "current", "next"], function(name){
				d.setFullYear(y++);
				this._setText(this[name+"YearLabelNode"],
					dojo.date.locale.format(d, {selector:'year', locale:this.lang}));
			}, this);

			// Set up repeating mouse behavior
			var _this = this;
			var typematic = function(nodeProp, dateProp, adj){
				_this._connects.push(
					dijit.typematic.addMouseListener(_this[nodeProp], _this, function(count){
						if(count >= 0){ _this._adjustDisplay(dateProp, adj); }
					}, 0.8, 500)
				);
			};
			typematic("incrementMonth", "month", 1);
			typematic("decrementMonth", "month", -1);
			typematic("nextYearLabelNode", "year", 1);
			typematic("previousYearLabelNode", "year", -1);
		},

		goToToday: function(){
			this.attr('value', new Date());
		},

		postCreate: function(){
			this.inherited(arguments);

			var cloneClass = dojo.hitch(this, function(clazz, n){
				var template = dojo.query(clazz, this.domNode)[0];
	 			for(var i=0; i<n; i++){
					template.parentNode.appendChild(template.cloneNode(true));
				}
			});

			// clone the day label and calendar day templates 6 times to make 7 columns
			cloneClass(".dijitCalendarDayLabelTemplate", 6);
			cloneClass(".dijitCalendarDateTemplate", 6);

			// now make 6 week rows
			cloneClass(".dijitCalendarWeekTemplate", 5);

			// insert localized day names in the header
			var dayNames = dojo.date.locale.getNames('days', this.dayWidth, 'standAlone', this.lang);
			var dayOffset = dojo.cldr.supplemental.getFirstDayOfWeek(this.lang);
			dojo.query(".dijitCalendarDayLabel", this.domNode).forEach(function(label, i){
				this._setText(label, dayNames[(i + dayOffset) % 7]);
			}, this);

			// Fill in spacer element with all the month names (invisible) so that the maximum width will affect layout
			var monthNames = dojo.date.locale.getNames('months', 'wide', 'standAlone', this.lang);
			dojo.forEach(monthNames, function(name){
				var monthSpacer = dojo.doc.createElement("div");
				this._setText(monthSpacer, name);
				this.monthLabelSpacer.appendChild(monthSpacer);
			}, this);

			this.value = null;
			this.attr('value', new Date());
		},

		_adjustDisplay: function(/*String*/part, /*int*/amount){
			this.displayMonth = dojo.date.add(this.displayMonth, part, amount);
			this._populateGrid();
		},

		_onDayClick: function(/*Event*/evt){
			dojo.stopEvent(evt);
			for(var node = evt.target; node && !node.dijitDateValue; node = node.parentNode);
			if(node && !dojo.hasClass(node, "dijitCalendarDisabledDate")){
				this.attr('value', node.dijitDateValue);
				this.onValueSelected(this.value);
			}
		},

		_onDayMouseOver: function(/*Event*/evt){
			var node = evt.target;
			if(node && (node.dijitDateValue || node == this.previousYearLabelNode || node == this.nextYearLabelNode) ){
				dojo.addClass(node, "dijitCalendarHoveredDate");
				this._currentNode = node;
			}
		},

		_onDayMouseOut: function(/*Event*/evt){
			if(!this._currentNode){ return; }
			for(var node = evt.relatedTarget; node;){
				if(node == this._currentNode){ return; }
				try{
					node = node.parentNode;
				}catch(x){
					node = null;
				}
			}
			dojo.removeClass(this._currentNode, "dijitCalendarHoveredDate");
			this._currentNode = null;
		},

		onValueSelected: function(/*Date*/date){
			// summary: a date cell was selected.  It may be the same as the previous value.
		},

		onChange: function(/*Date*/date){
			// summary: called only when the selected date has changed
		},

		isDisabledDate: function(/*Date*/dateObject, /*String?*/locale){
			// summary:
			//	May be overridden to disable certain dates in the calendar e.g. `isDisabledDate=dojo.date.locale.isWeekend`
/*=====
			return false; // Boolean
=====*/
		},

		getClassForDate: function(/*Date*/dateObject, /*String?*/locale){
			// summary:
			//  May be overridden to return CSS classes to associate with the date entry for the given dateObject,
			//  for example to indicate a holiday in specified locale.

/*=====
			return ""; // String
=====*/
		}
	}
);
<commit_msg>Better still, make the calendar non-selectable. Refs #7797 !strict<commit_after>dojo.provide("dijit._Calendar");

dojo.require("dojo.cldr.supplemental");
dojo.require("dojo.date");
dojo.require("dojo.date.locale");

dojo.require("dijit._Widget");
dojo.require("dijit._Templated");

dojo.declare(
	"dijit._Calendar",
	[dijit._Widget, dijit._Templated],
	{
	//
	//	summary:
	//		A simple GUI for choosing a date in the context of a monthly calendar.
	//
	//	description:
	//		A simple GUI for choosing a date in the context of a monthly calendar.
	//		This widget is used internally by other widgets and is not accessible
	//		as a standalone widget.
	//		This widget can't be used in a form because it doesn't serialize the date to an
	//		`<input>` field.  For a form element, use dijit.form.DateTextBox instead.
	//
	//		Note that the parser takes all dates attributes passed in the
	//		[RFC 3339 format](http://www.faqs.org/rfcs/rfc3339.html), e.g. `2005-06-30T08:05:00-07:00`
	//		so that they are serializable and locale-independent.
	//
	//	example:
	//	|	var calendar = new dijit._Calendar({}, dojo.byId("calendarNode"));
	//
	//	example:
	//	|

	//
		templatePath: dojo.moduleUrl("dijit", "templates/Calendar.html"),

		// value: Date
		// 	the currently selected Date
		value: new Date(),

		// dayWidth: String
		// 	How to represent the days of the week in the calendar header. See dojo.date.locale
		dayWidth: "narrow",

		setValue: function(/*Date*/ value){
			dojo.deprecated("dijit.Calendar:setValue() is deprecated.  Use attr('value', ...) instead.", "", "2.0");
			this.attr('value', value);
		},
		_setValueAttr: function(/*Date*/ value){
			// summary:
			//		Hook to make attr("value", ...) work.
			// description:
			// 		Set the current date and update the UI.  If the date is disabled, the selection will
			//		not change, but the display will change to the corresponding month.
			if(!this.value || dojo.date.compare(value, this.value)){
				value = new Date(value);
				this.displayMonth = new Date(value);
				if(!this.isDisabledDate(value, this.lang)){
					this.value = value;
					this.value.setHours(0,0,0,0);
					this.onChange(this.value);
				}
				this._populateGrid();
			}
		},

		_setText: function(node, text){
			while(node.firstChild){
				node.removeChild(node.firstChild);
			}
			node.appendChild(dojo.doc.createTextNode(text));
		},

		_populateGrid: function(){
			var month = this.displayMonth;
			month.setDate(1);
			var firstDay = month.getDay();
			var daysInMonth = dojo.date.getDaysInMonth(month);
			var daysInPreviousMonth = dojo.date.getDaysInMonth(dojo.date.add(month, "month", -1));
			var today = new Date();
			var selected = this.value;

			var dayOffset = dojo.cldr.supplemental.getFirstDayOfWeek(this.lang);
			if(dayOffset > firstDay){ dayOffset -= 7; }

			// Iterate through dates in the calendar and fill in date numbers and style info
			dojo.query(".dijitCalendarDateTemplate", this.domNode).forEach(function(template, i){
				i += dayOffset;
				var date = new Date(month);
				var number, clazz = "dijitCalendar", adj = 0;

				if(i < firstDay){
					number = daysInPreviousMonth - firstDay + i + 1;
					adj = -1;
					clazz += "Previous";
				}else if(i >= (firstDay + daysInMonth)){
					number = i - firstDay - daysInMonth + 1;
					adj = 1;
					clazz += "Next";
				}else{
					number = i - firstDay + 1;
					clazz += "Current";
				}

				if(adj){
					date = dojo.date.add(date, "month", adj);
				}
				date.setDate(number);

				if(!dojo.date.compare(date, today, "date")){
					clazz = "dijitCalendarCurrentDate " + clazz;
				}

				if(!dojo.date.compare(date, selected, "date")){
					clazz = "dijitCalendarSelectedDate " + clazz;
				}

				if(this.isDisabledDate(date, this.lang)){
					clazz = "dijitCalendarDisabledDate " + clazz;
				}

				var clazz2 = this.getClassForDate(date, this.lang);
				if(clazz2){
					clazz = clazz2 + " " + clazz;
				}

				template.className =  clazz + "Month dijitCalendarDateTemplate";
				template.dijitDateValue = date.valueOf();
				var label = dojo.query(".dijitCalendarDateLabel", template)[0];
				this._setText(label, date.getDate());
			}, this);

			// Fill in localized month name
			var monthNames = dojo.date.locale.getNames('months', 'wide', 'standAlone', this.lang);
			this._setText(this.monthLabelNode, monthNames[month.getMonth()]);

			// Fill in localized prev/current/next years
			var y = month.getFullYear() - 1;
			var d = new Date();
			dojo.forEach(["previous", "current", "next"], function(name){
				d.setFullYear(y++);
				this._setText(this[name+"YearLabelNode"],
					dojo.date.locale.format(d, {selector:'year', locale:this.lang}));
			}, this);

			// Set up repeating mouse behavior
			var _this = this;
			var typematic = function(nodeProp, dateProp, adj){
				_this._connects.push(
					dijit.typematic.addMouseListener(_this[nodeProp], _this, function(count){
						if(count >= 0){ _this._adjustDisplay(dateProp, adj); }
					}, 0.8, 500)
				);
			};
			typematic("incrementMonth", "month", 1);
			typematic("decrementMonth", "month", -1);
			typematic("nextYearLabelNode", "year", 1);
			typematic("previousYearLabelNode", "year", -1);
		},

		goToToday: function(){
			this.attr('value', new Date());
		},

		postCreate: function(){
			this.inherited(arguments);
			dojo.setSelectable(this.domNode, false);

			var cloneClass = dojo.hitch(this, function(clazz, n){
				var template = dojo.query(clazz, this.domNode)[0];
	 			for(var i=0; i<n; i++){
					template.parentNode.appendChild(template.cloneNode(true));
				}
			});

			// clone the day label and calendar day templates 6 times to make 7 columns
			cloneClass(".dijitCalendarDayLabelTemplate", 6);
			cloneClass(".dijitCalendarDateTemplate", 6);

			// now make 6 week rows
			cloneClass(".dijitCalendarWeekTemplate", 5);

			// insert localized day names in the header
			var dayNames = dojo.date.locale.getNames('days', this.dayWidth, 'standAlone', this.lang);
			var dayOffset = dojo.cldr.supplemental.getFirstDayOfWeek(this.lang);
			dojo.query(".dijitCalendarDayLabel", this.domNode).forEach(function(label, i){
				this._setText(label, dayNames[(i + dayOffset) % 7]);
			}, this);

			// Fill in spacer element with all the month names (invisible) so that the maximum width will affect layout
			var monthNames = dojo.date.locale.getNames('months', 'wide', 'standAlone', this.lang);
			dojo.forEach(monthNames, function(name){
				var monthSpacer = dojo.doc.createElement("div");
				this._setText(monthSpacer, name);
				this.monthLabelSpacer.appendChild(monthSpacer);
			}, this);

			this.value = null;
			this.attr('value', new Date());
		},

		_adjustDisplay: function(/*String*/part, /*int*/amount){
			this.displayMonth = dojo.date.add(this.displayMonth, part, amount);
			this._populateGrid();
		},

		_onDayClick: function(/*Event*/evt){
			dojo.stopEvent(evt);
			for(var node = evt.target; node && !node.dijitDateValue; node = node.parentNode);
			if(node && !dojo.hasClass(node, "dijitCalendarDisabledDate")){
				this.attr('value', node.dijitDateValue);
				this.onValueSelected(this.value);
			}
		},

		_onDayMouseOver: function(/*Event*/evt){
			var node = evt.target;
			if(node && (node.dijitDateValue || node == this.previousYearLabelNode || node == this.nextYearLabelNode) ){
				dojo.addClass(node, "dijitCalendarHoveredDate");
				this._currentNode = node;
			}
		},

		_onDayMouseOut: function(/*Event*/evt){
			if(!this._currentNode){ return; }
			for(var node = evt.relatedTarget; node;){
				if(node == this._currentNode){ return; }
				try{
					node = node.parentNode;
				}catch(x){
					node = null;
				}
			}
			dojo.removeClass(this._currentNode, "dijitCalendarHoveredDate");
			this._currentNode = null;
		},

		onValueSelected: function(/*Date*/date){
			// summary: a date cell was selected.  It may be the same as the previous value.
		},

		onChange: function(/*Date*/date){
			// summary: called only when the selected date has changed
		},

		isDisabledDate: function(/*Date*/dateObject, /*String?*/locale){
			// summary:
			//	May be overridden to disable certain dates in the calendar e.g. `isDisabledDate=dojo.date.locale.isWeekend`
/*=====
			return false; // Boolean
=====*/
		},

		getClassForDate: function(/*Date*/dateObject, /*String?*/locale){
			// summary:
			//  May be overridden to return CSS classes to associate with the date entry for the given dateObject,
			//  for example to indicate a holiday in specified locale.

/*=====
			return ""; // String
=====*/
		}
	}
);
<|endoftext|>


<commit_before>dojo.provide("dijit._base.wai");

dijit.wai = {
	onload: function(){
		// summary:
		//		Function that detects if we are in high-contrast mode or not,
		//		and sets up a timer to periodically confirm the value.
		//		figure out the background-image style property
		//		and apply that to the image.src property.
		// description:
		//		This must be a named function and not an anonymous
		//		function, so that the widget parsing code can make sure it
		//		registers its onload function after this function.
		//		DO NOT USE "this" within this function.

		// create div for testing if high contrast mode is on or images are turned off
		var div = document.createElement("div");
		div.id = "a11yTestNode";
		div.style.cssText = 'border: 1px solid;'
			+ 'border-color:red green;'
			+ 'position: absolute;'
			+ 'left: -999px;'
			+ 'top: -999px;'
			+ 'background-image: url("' + dojo.moduleUrl("dijit", "form/templates/blank.gif") + '");';
		dojo.body().appendChild(div);

		// test it
		function check(){
			var cs = dojo.getComputedStyle(div);
			if(cs){
				var bkImg = cs.backgroundImage;
				var needsA11y = (cs.borderTopColor==cs.borderRightColor) || (bkImg != null && (bkImg == "none" || bkImg == "url(invalid-url:)" ));
				dojo[needsA11y ? "addClass" : "removeClass"](dojo.body(), "dijit_a11y");
			}
		}
		check();
		if(dojo.isIE){
			setInterval(check, 4000);
		}
	}
};

// Test if computer is in high contrast mode.
// Make sure the a11y test runs first, before widgets are instantiated.
if(dojo.isIE || dojo.isMoz){	// NOTE: checking in Safari messes things up
	dojo._loaders.unshift(dijit.wai.onload);
}

dojo.mixin(dijit,
{
	hasWaiRole: function(/*Element*/ elem){
		// Summary: Return true if elem has a role attribute and false if not.
		if(elem.hasAttribute){
			return elem.hasAttribute("role");
		}else{
			return elem.getAttribute("role") ? true : false;
		}
	},

	getWaiRole: function(/*Element*/ elem){
		// Summary: Return the role of elem or an empty string if
		//		elem does not have a role.
		var value = elem.getAttribute("role");
		if(value){
			var prefixEnd = value.indexOf(":");
			return prefixEnd == -1 ? value : value.substring(prefixEnd+1);
		}else{
			return "";
		}
	},

	setWaiRole: function(/*Element*/ elem, /*String*/ role){
		// Summary: Set the role on elem. On Firefox 2 and below, "wairole:" is
		//		prepended to the provided role value.
		if(dojo.isFF && dojo.isFF < 3){
			elem.setAttribute("role", "wairole:"+role);
		}else{
			elem.setAttribute("role", role);
		}
	},

	removeWaiRole: function(/*Element*/ elem){
		// Summary: Removes the role attribute from elem.
		elem.removeAttribute("role");
	},

	hasWaiState: function(/*Element*/ elem, /*String*/ state){
		// Summary: Return true if elem has a value for the given state and
		//		false if it does not.
		//		On Firefox 2 and below, we check for an attribute in namespace
		//		"http://www.w3.org/2005/07/aaa" with a name of the given state.
		//		On all other browsers, we check for an attribute called
		//		"aria-"+state.
		if(dojo.isFF && dojo.isFF < 3){
			return elem.hasAttributeNS("http://www.w3.org/2005/07/aaa", state);
		}else{
			if(elem.hasAttribute){
				return elem.hasAttribute("aria-"+state);
			}else{
				return elem.getAttribute("aria-"+state) ? true : false;
			}
		}
	},

	getWaiState: function(/*Element*/ elem, /*String*/ state){
		// Summary: Return the value of the requested state on elem
		//		or an empty string if elem has no value for state.
		//		On Firefox 2 and below, we check for an attribute in namespace
		//		"http://www.w3.org/2005/07/aaa" with a name of the given state.
		//		On all other browsers, we check for an attribute called
		//		"aria-"+state.
		if(dojo.isFF && dojo.isFF < 3){
			return elem.getAttributeNS("http://www.w3.org/2005/07/aaa", state);
		}else{
			var value =  elem.getAttribute("aria-"+state);
			return value ? value : "";
		}
	},

	setWaiState: function(/*Element*/ elem, /*String*/ state, /*String*/ value){
		// Summary: Set state on elem to value.
		//		On Firefox 2 and below, we set an attribute in namespace
		//		"http://www.w3.org/2005/07/aaa" with a name of the given state.
		//		On all other browsers, we set an attribute called
		//		"aria-"+state.
		if(dojo.isFF && dojo.isFF < 3){
			elem.setAttributeNS("http://www.w3.org/2005/07/aaa",
				"aaa:"+state, value);
		}else{
			elem.setAttribute("aria-"+state, value);
		}
	},

	removeWaiState: function(/*Element*/ elem, /*String*/ state){
		// Summary: Removes the given state from elem.
		//		On Firefox 2 and below, we remove the attribute in namespace
		//		"http://www.w3.org/2005/07/aaa" with a name of the given state.
		//		On all other browsers, we remove the attribute called
		//		"aria-"+state.
		if(dojo.isFF && dojo.isFF < 3){
			elem.removeAttributeNS("http://www.w3.org/2005/07/aaa", state);
		}else{
			elem.removeAttribute("aria-"+state);
		}
	}
});
<commit_msg>fixes #4376.  I removed the left property altogether since top:-999px should be enough to move off screen and out of view.  added height:5px to make sure it has minimal size incase of stylesheet that sets height of all divs to 100% (thanks sfoster!)<commit_after>dojo.provide("dijit._base.wai");

dijit.wai = {
	onload: function(){
		// summary:
		//		Function that detects if we are in high-contrast mode or not,
		//		and sets up a timer to periodically confirm the value.
		//		figure out the background-image style property
		//		and apply that to the image.src property.
		// description:
		//		This must be a named function and not an anonymous
		//		function, so that the widget parsing code can make sure it
		//		registers its onload function after this function.
		//		DO NOT USE "this" within this function.

		// create div for testing if high contrast mode is on or images are turned off
		var div = document.createElement("div");
		div.id = "a11yTestNode";
		div.style.cssText = 'border: 1px solid;'
			+ 'border-color:red green;'
			+ 'position: absolute;'
			+ 'height: 5px;'
			+ 'top: -999px;'
			+ 'background-image: url("' + dojo.moduleUrl("dijit", "form/templates/blank.gif") + '");';
		dojo.body().appendChild(div);

		// test it
		function check(){
			var cs = dojo.getComputedStyle(div);
			if(cs){
				var bkImg = cs.backgroundImage;
				var needsA11y = (cs.borderTopColor==cs.borderRightColor) || (bkImg != null && (bkImg == "none" || bkImg == "url(invalid-url:)" ));
				dojo[needsA11y ? "addClass" : "removeClass"](dojo.body(), "dijit_a11y");
			}
		}
		check();
		if(dojo.isIE){
			setInterval(check, 4000);
		}
	}
};

// Test if computer is in high contrast mode.
// Make sure the a11y test runs first, before widgets are instantiated.
if(dojo.isIE || dojo.isMoz){	// NOTE: checking in Safari messes things up
	dojo._loaders.unshift(dijit.wai.onload);
}

dojo.mixin(dijit,
{
	hasWaiRole: function(/*Element*/ elem){
		// Summary: Return true if elem has a role attribute and false if not.
		if(elem.hasAttribute){
			return elem.hasAttribute("role");
		}else{
			return elem.getAttribute("role") ? true : false;
		}
	},

	getWaiRole: function(/*Element*/ elem){
		// Summary: Return the role of elem or an empty string if
		//		elem does not have a role.
		var value = elem.getAttribute("role");
		if(value){
			var prefixEnd = value.indexOf(":");
			return prefixEnd == -1 ? value : value.substring(prefixEnd+1);
		}else{
			return "";
		}
	},

	setWaiRole: function(/*Element*/ elem, /*String*/ role){
		// Summary: Set the role on elem. On Firefox 2 and below, "wairole:" is
		//		prepended to the provided role value.
		if(dojo.isFF && dojo.isFF < 3){
			elem.setAttribute("role", "wairole:"+role);
		}else{
			elem.setAttribute("role", role);
		}
	},

	removeWaiRole: function(/*Element*/ elem){
		// Summary: Removes the role attribute from elem.
		elem.removeAttribute("role");
	},

	hasWaiState: function(/*Element*/ elem, /*String*/ state){
		// Summary: Return true if elem has a value for the given state and
		//		false if it does not.
		//		On Firefox 2 and below, we check for an attribute in namespace
		//		"http://www.w3.org/2005/07/aaa" with a name of the given state.
		//		On all other browsers, we check for an attribute called
		//		"aria-"+state.
		if(dojo.isFF && dojo.isFF < 3){
			return elem.hasAttributeNS("http://www.w3.org/2005/07/aaa", state);
		}else{
			if(elem.hasAttribute){
				return elem.hasAttribute("aria-"+state);
			}else{
				return elem.getAttribute("aria-"+state) ? true : false;
			}
		}
	},

	getWaiState: function(/*Element*/ elem, /*String*/ state){
		// Summary: Return the value of the requested state on elem
		//		or an empty string if elem has no value for state.
		//		On Firefox 2 and below, we check for an attribute in namespace
		//		"http://www.w3.org/2005/07/aaa" with a name of the given state.
		//		On all other browsers, we check for an attribute called
		//		"aria-"+state.
		if(dojo.isFF && dojo.isFF < 3){
			return elem.getAttributeNS("http://www.w3.org/2005/07/aaa", state);
		}else{
			var value =  elem.getAttribute("aria-"+state);
			return value ? value : "";
		}
	},

	setWaiState: function(/*Element*/ elem, /*String*/ state, /*String*/ value){
		// Summary: Set state on elem to value.
		//		On Firefox 2 and below, we set an attribute in namespace
		//		"http://www.w3.org/2005/07/aaa" with a name of the given state.
		//		On all other browsers, we set an attribute called
		//		"aria-"+state.
		if(dojo.isFF && dojo.isFF < 3){
			elem.setAttributeNS("http://www.w3.org/2005/07/aaa",
				"aaa:"+state, value);
		}else{
			elem.setAttribute("aria-"+state, value);
		}
	},

	removeWaiState: function(/*Element*/ elem, /*String*/ state){
		// Summary: Removes the given state from elem.
		//		On Firefox 2 and below, we remove the attribute in namespace
		//		"http://www.w3.org/2005/07/aaa" with a name of the given state.
		//		On all other browsers, we remove the attribute called
		//		"aria-"+state.
		if(dojo.isFF && dojo.isFF < 3){
			elem.removeAttributeNS("http://www.w3.org/2005/07/aaa", state);
		}else{
			elem.removeAttribute("aria-"+state);
		}
	}
});
<|endoftext|>


<commit_before>// MapPreview
// ----------
// A web map client for displaying tile-based maps.
view = Backbone.View.extend({
    className: 'MapClient',
    id: 'map',
    initialize: function(options) {
        _.bindAll(this, 'ready', 'record', 'mm', 'mmNav');
    },
    ready: function() {
        var wax = this.generateWax();
        if (!wax.layers || wax.layers.length === 0) return;

        $.ajax({
            dataType: 'jsonp',
            url: this.waxURL(wax),
            context: this,
            callback: 'grid',
            callbackParameter: 'callback',
            success: this.record,
            error: function() {}
        });
    },
    waxURL: function(wax) {
        return this.model.options.uiHost + 'api/wax.json?' + $.param(wax);
    },
    generateWax: function(callback) {
        var wax = this.model.wax();
        wax.el = $(this.el).attr('id');
        wax.size && (delete wax.size);
        return wax;
    },
    record: function(data) {
        if (data && data.wax) {
            var api = this.generateWax().api;
            this.map = wax.Record(data.wax);
            _(this[api]).isFunction() && this[api]();
        }

        // Calculate the background luminosity from the first tile.
        setTimeout(function() {
            var tile = this.$('img:first')[0];
            if (!tile) return;
            if (tile.complete) setBackground();
            else $(tile).load(setBackground);

            function setBackground() {
                if (view.alphaImageLuminosity(tile) > 0.9) {
                    $(tile).closest('.MapClient').css({ backgroundColor: 'black' });
                }
            }
        }.bind(this), 0);
    },
    mm: function() {
        this.map.addCallback('zoomed', this.mmNav);
        this.mmNav();
    },
    mmNav: function() {
        if (!$('.zoom').size()) return;
        $('.zoom.active').removeClass('active');
        $('.zoom-' + this.map.getZoom()).addClass('active');
    }
});

// Calculates the luminosity (0-1) of all semi-transparent pixels.
view.alphaImageLuminosity = function(el) {
    if (!HTMLCanvasElement || !el.complete) return -1;

    var canvas = document.createElement('canvas');
    canvas.setAttribute('width', el.width);
    canvas.setAttribute('height', el.height);
    var c = canvas.getContext('2d');
    c.drawImage(el, 0, 0);

    var r = 0, g = 0, b = 0, total = 0;
    var pixels = c.getImageData(0, 0, el.width, el.height).data;

    // Look at every pixel's alpha value and only proceed if it is semi-transparent.
    for (var i = 3; i < pixels.length; i += 4) {
        if (pixels[i] < 255 && pixels[i] > 0) {
            total++;
            r += pixels[i - 3];
            g += pixels[i - 2];
            b += pixels[i - 1];
        }
    }

    if (!total) return 0;

    // Calculate average luminosity of all alpha pixels.
    // Using the median of all per-pixel luminosities would be better but is
    // computationally much more expensive and since this runs in the UI thread,
    // is not an option at this point.
    return Math.pow(r / total / 255, 2.2) * 0.2126 +
           Math.pow(g / total / 255, 2.2) * 0.7152 +
           Math.pow(b / total / 255, 2.2) * 0.0722;
};
<commit_msg>adjust threshold<commit_after>// MapPreview
// ----------
// A web map client for displaying tile-based maps.
view = Backbone.View.extend({
    className: 'MapClient',
    id: 'map',
    initialize: function(options) {
        _.bindAll(this, 'ready', 'record', 'mm', 'mmNav');
    },
    ready: function() {
        var wax = this.generateWax();
        if (!wax.layers || wax.layers.length === 0) return;

        $.ajax({
            dataType: 'jsonp',
            url: this.waxURL(wax),
            context: this,
            callback: 'grid',
            callbackParameter: 'callback',
            success: this.record,
            error: function() {}
        });
    },
    waxURL: function(wax) {
        return this.model.options.uiHost + 'api/wax.json?' + $.param(wax);
    },
    generateWax: function(callback) {
        var wax = this.model.wax();
        wax.el = $(this.el).attr('id');
        wax.size && (delete wax.size);
        return wax;
    },
    record: function(data) {
        if (data && data.wax) {
            var api = this.generateWax().api;
            this.map = wax.Record(data.wax);
            _(this[api]).isFunction() && this[api]();
        }

        // Calculate the background luminosity from the first tile.
        setTimeout(function() {
            var tile = this.$('img:first')[0];
            if (!tile) return;
            if (tile.complete) setBackground();
            else $(tile).load(setBackground);

            function setBackground() {
                if (view.alphaImageLuminosity(tile) > 0.8) {
                    $(tile).closest('.MapClient').css({ backgroundColor: 'black' });
                }
            }
        }.bind(this), 0);
    },
    mm: function() {
        this.map.addCallback('zoomed', this.mmNav);
        this.mmNav();
    },
    mmNav: function() {
        if (!$('.zoom').size()) return;
        $('.zoom.active').removeClass('active');
        $('.zoom-' + this.map.getZoom()).addClass('active');
    }
});

// Calculates the luminosity (0-1) of all semi-transparent pixels.
view.alphaImageLuminosity = function(el) {
    if (!HTMLCanvasElement || !el.complete) return -1;

    var canvas = document.createElement('canvas');
    canvas.setAttribute('width', el.width);
    canvas.setAttribute('height', el.height);
    var c = canvas.getContext('2d');
    c.drawImage(el, 0, 0);

    var r = 0, g = 0, b = 0, total = 0;
    var pixels = c.getImageData(0, 0, el.width, el.height).data;

    // Look at every pixel's alpha value and only proceed if it is semi-transparent.
    for (var i = 3; i < pixels.length; i += 4) {
        if (pixels[i] < 255 && pixels[i] > 0) {
            total++;
            r += pixels[i - 3];
            g += pixels[i - 2];
            b += pixels[i - 1];
        }
    }

    if (!total) return 0;

    // Calculate average luminosity of all alpha pixels.
    // Using the median of all per-pixel luminosities would be better but is
    // computationally much more expensive and since this runs in the UI thread,
    // is not an option at this point.
    return Math.pow(r / total / 255, 2.2) * 0.2126 +
           Math.pow(g / total / 255, 2.2) * 0.7152 +
           Math.pow(b / total / 255, 2.2) * 0.0722;
};
<|endoftext|>


<commit_before>/*
*   Copyright 2013 Comcast
*
*   Licensed under the Apache License, Version 2.0 (the "License");
*   you may not use this file except in compliance with the License.
*   You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
*   Unless required by applicable law or agreed to in writing, software
*   distributed under the License is distributed on an "AS IS" BASIS,
*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*   See the License for the specific language governing permissions and
*   limitations under the License.
*/

define('xooie/stylesheet', ['jquery', 'xooie/helpers'], function ($, helpers) {
  'use strict';

  function nameCheck(index, name) {
    var s = document.styleSheets[index];

    if (!helpers.isUndefined(s.ownerNode)) {
      return s.ownerNode.getAttribute('id') === name;
    }
    return s.id === name;
  }

  var Stylesheet = function (name) {
    //check to see if a stylesheet already exists with this name
    this.element = $('style[id=' + name + ']');

    if (this.element.length <= 0) {
      //if it does, use it, else create a new one
      this.element = $(['<style id="' + name + '">',
                          '/* This is a dynamically generated stylesheet: ' + name + ' */',
                      '</style>'].join(''));

      this.element.appendTo($('head'));
    }

    this._name = name;
  };

  Stylesheet.prototype.get = function () {
    return document.styleSheets[this.getIndex()];
  };

  Stylesheet.prototype.getRule = function (ruleName) {
    var i, rules;

    ruleName = ruleName.toLowerCase();

    //Check if this uses the IE format (styleSheet.rules) or the Mozilla/Webkit format
    rules = this.get().cssRules || this.get().rules;

    for (i = 0; i < rules.length; i += 1) {
      if (rules[i].selectorText.toLowerCase() === ruleName) {
        return rules[i];
      }
    }

    return false;
  };

  Stylesheet.prototype.addRule = function (ruleName, properties) {
    var rule = this.getRule(ruleName), index, prop, propString = '';

    if (!rule) {
      for (prop in properties) {
        if (properties.hasOwnProperty(prop)) {
          propString += prop + ': ' + properties[prop] + ';';
        }
      }

      if (this.get().insertRule) {
        //This is the W3C-preferred method
        index = this.get().cssRules.length;
        this.get().insertRule(ruleName + ' {' + propString + '}', index);
        rule = this.get().cssRules[index];
      } else {
        //support for IE < 9
        index = this.get().rules.length;
        this.get().addRule(ruleName, propString, index);
        rule = this.get().rules[index];
      }
    }

    return rule;
  };

  Stylesheet.prototype.deleteRule = function (ruleName) {
    var i, rules;

    ruleName = ruleName.toLowerCase();

    //Check if this uses the IE format (styleSheet.rules) or the Mozilla/Webkit format
    rules = this.get().cssRules || this.get().rules;

    for (i = 0; i < rules.length; i += 1) {
      if (rules[i].selectorText.toLowerCase() === ruleName) {
        if (this.get().deleteRule) {
          //this is the W3C-preferred method
          this.get().deleteRule(i);
        } else {
          //support for IE < 9
          this.get().removeRule(i);
        }

        return true;
      }
    }

    return false;
  };

  Stylesheet.prototype.getIndex = function () {
    var i;

    if (helpers.isUndefined(document.styleSheets)) {
      return;
    }

    if (!helpers.isUndefined(this._index) && nameCheck(this._index, this._name)) {
      return this._index;
    }

    for (i = 0; i < document.styleSheets.length; i += 1) {
      if (nameCheck(i, this._name)) {
        this._index = i;
        return i;
      }
    }
  };

  return Stylesheet;

});<commit_msg>fixes IE < 9 "Single contextual selectors" issue split ruleName on ',' loop over ruleNames applying the same propString<commit_after>/*
*   Copyright 2013 Comcast
*
*   Licensed under the Apache License, Version 2.0 (the "License");
*   you may not use this file except in compliance with the License.
*   You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
*   Unless required by applicable law or agreed to in writing, software
*   distributed under the License is distributed on an "AS IS" BASIS,
*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*   See the License for the specific language governing permissions and
*   limitations under the License.
*/

define('xooie/stylesheet', ['jquery', 'xooie/helpers'], function ($, helpers) {
  'use strict';

  function nameCheck(index, name) {
    var s = document.styleSheets[index];

    if (!helpers.isUndefined(s.ownerNode)) {
      return s.ownerNode.getAttribute('id') === name;
    }
    return s.id === name;
  }

  var Stylesheet = function (name) {
    //check to see if a stylesheet already exists with this name
    this.element = $('style[id=' + name + ']');

    if (this.element.length <= 0) {
      //if it does, use it, else create a new one
      this.element = $(['<style id="' + name + '">',
                          '/* This is a dynamically generated stylesheet: ' + name + ' */',
                      '</style>'].join(''));

      this.element.appendTo($('head'));
    }

    this._name = name;
  };

  Stylesheet.prototype.get = function () {
    return document.styleSheets[this.getIndex()];
  };

  Stylesheet.prototype.getRule = function (ruleName) {
    var i, rules;

    ruleName = ruleName.toLowerCase();

    //Check if this uses the IE format (styleSheet.rules) or the Mozilla/Webkit format
    rules = this.get().cssRules || this.get().rules;

    for (i = 0; i < rules.length; i += 1) {
      if (rules[i].selectorText.toLowerCase() === ruleName) {
        return rules[i];
      }
    }

    return false;
  };

  Stylesheet.prototype.addRule = function (ruleName, properties) {
    var rule = this.getRule(ruleName), index, prop, propString = '', ruleNameArray, i;

    if (!rule) {
      for (prop in properties) {
        if (properties.hasOwnProperty(prop)) {
          propString += prop + ': ' + properties[prop] + ';';
        }
      }

      if (this.get().insertRule) {
        //This is the W3C-preferred method
        index = this.get().cssRules.length;
        this.get().insertRule(ruleName + ' {' + propString + '}', index);
        rule = this.get().cssRules[index];
      } else {
        //support for IE < 9
        index = this.get().rules.length;
        ruleNameArray = ruleName.split(',');

        for(i = 0; i < ruleNameArray.length; i += 1) {
            this.get().addRule(ruleNameArray[i], propString, index+i);
        }

        rule = this.get().rules[index];
      }
    }

    return rule;
  };

  Stylesheet.prototype.deleteRule = function (ruleName) {
    var i, rules;

    ruleName = ruleName.toLowerCase();

    //Check if this uses the IE format (styleSheet.rules) or the Mozilla/Webkit format
    rules = this.get().cssRules || this.get().rules;

    for (i = 0; i < rules.length; i += 1) {
      if (rules[i].selectorText.toLowerCase() === ruleName) {
        if (this.get().deleteRule) {
          //this is the W3C-preferred method
          this.get().deleteRule(i);
        } else {
          //support for IE < 9
          this.get().removeRule(i);
        }

        return true;
      }
    }

    return false;
  };

  Stylesheet.prototype.getIndex = function () {
    var i;

    if (helpers.isUndefined(document.styleSheets)) {
      return;
    }

    if (!helpers.isUndefined(this._index) && nameCheck(this._index, this._name)) {
      return this._index;
    }

    for (i = 0; i < document.styleSheets.length; i += 1) {
      if (nameCheck(i, this._name)) {
        this._index = i;
        return i;
      }
    }
  };

  return Stylesheet;

});<|endoftext|>


<commit_before>"use strict";
var assert = require('assert');

var Suit = {
  Spades: 1,
  Diamonds: 2,
  Clubs: 3,
  Hearts: 4
};

var Stack = function() {

  Stack.prototype._cards = [];

  Stack.prototype.empty = function() {
    return true;
  };

  Stack.prototype.add = function(card) {
    this._cards.push(card);
  };

  Stack.prototype.top = function() {
    return this._cards[this._cards.length - 1];
  };

  return this;
};

var Card = function(suit,value) {
  this._suit = suit;
  this._value = value;

  Card.prototype.suit = function() {
    return this._suit;
  };

  Card.prototype.value = function() {
    return this._value;
  };

  return this;
};

describe('klondike', function() {
  describe('card', function() {
    it('has a suit and a value', function() {
      var card = new Card(Suit.Spades,1);
      assert.equal(Suit.Spades, card.suit());
      assert.equal(1, card.value());
    });
  });

  describe('stack', function() {
    it('is a concept', function() {
      assert(new Stack().empty());
    });

    it('can add card', function() {
      var stack = new Stack();
      stack.add(new Card(Suit.Spades, 1));

      assert.deepEqual(new Card(Suit.Spades, 1), stack.top());
    });

    var stackWithTwoCards = function() {
      var stack = new Stack();
      stack.add(new Card(Suit.Spades, 1));
      stack.add(new Card(Suit.Hearts, 2));

      return stack;
    };

    it('can add multiple cards', function() {
      var stack = stackWithTwoCards();
      assert.deepEqual(new Card(Suit.Hearts, 2), stack.top());
    });

    it('can pop cards', function() {
      var stack = stackWithTwoCards();
      stack.pop();
      assert.deepEqual(new Card(Suit.Spades, 1), stack.top());
    });
  });

});
<commit_msg>do the quickest possible pass<commit_after>"use strict";
var assert = require('assert');

var Suit = {
  Spades: 1,
  Diamonds: 2,
  Clubs: 3,
  Hearts: 4
};

var Stack = function() {

  Stack.prototype._cards = [];

  Stack.prototype.empty = function() {
    return true;
  };

  Stack.prototype.add = function(card) {
    this._cards.push(card);
  };

  Stack.prototype.top = function() {
    return this._cards[this._cards.length - 1];
  };

  Stack.prototype.pop = function() {
    return this._cards.pop();;
  };

  return this;
};

var Card = function(suit,value) {
  this._suit = suit;
  this._value = value;

  Card.prototype.suit = function() {
    return this._suit;
  };

  Card.prototype.value = function() {
    return this._value;
  };

  return this;
};

describe('klondike', function() {
  describe('card', function() {
    it('has a suit and a value', function() {
      var card = new Card(Suit.Spades,1);
      assert.equal(Suit.Spades, card.suit());
      assert.equal(1, card.value());
    });
  });

  describe('stack', function() {
    it('is a concept', function() {
      assert(new Stack().empty());
    });

    it('can add card', function() {
      var stack = new Stack();
      stack.add(new Card(Suit.Spades, 1));

      assert.deepEqual(new Card(Suit.Spades, 1), stack.top());
    });

    var stackWithTwoCards = function() {
      var stack = new Stack();
      stack.add(new Card(Suit.Spades, 1));
      stack.add(new Card(Suit.Hearts, 2));

      return stack;
    };

    it('can add multiple cards', function() {
      var stack = stackWithTwoCards();
      assert.deepEqual(new Card(Suit.Hearts, 2), stack.top());
    });

    it('can pop cards', function() {
      var stack = stackWithTwoCards();
      stack.pop();
      assert.deepEqual(new Card(Suit.Spades, 1), stack.top());
    });
  });

});
<|endoftext|>


<commit_before>jQuery(document).ready(function($) {

    $('html').on('click', function() {
        $('#overlay').fadeIn("slow");

    });

    $(window).on('scroll touchmove', function(){
        $('#overlay').fadeIn("slow");
    });

    $(window).off('scroll touchmove');

});<commit_msg>remove unbind<commit_after>jQuery(document).ready(function($) {

    $('html').on('click', function() {
        $('#overlay').fadeIn("slow");

    });

    $(window).on('scroll touchmove', function(){
        $('#overlay').fadeIn("slow");
    });

});<|endoftext|>


<commit_before>var path = require('path')
  , webpack = require('webpack')
  , ExtractTextPlugin = require("extract-text-webpack-plugin")
  , pkg = require('./package.json');

function makeConfig(options){
  var entry = options.entry
    , plugins = options.plugins || []

  var loaders = [
    { test: /\.css$/,  loader: options.extractStyles
        ? ExtractTextPlugin.extract("style-loader", "css-loader")
        : "style-loader!css-loader" },

    { test: /\.less$/, loader: options.extractStyles
        ? ExtractTextPlugin.extract("style-loader", "css-loader!less-loader")
        : "style-loader!css-loader!less-loader" },

    { test: /\.gif$/, loader: "url-loader?mimetype=image/png" },
    { test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000&minetype=application/font-woff" },
    { test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "file-loader?name=[name].[ext]" },

    { test: /\.jsx$|\.js$/, loader: 'babel-loader', exclude: /node_modules/ }
  ];

  if (options.hot){
    loaders.splice(loaders.length - 1,0,
      { test: /\.jsx$|\.js$/, loader: 'react-hot-loader', exclude: /node_modules/ })

    plugins.push(
      new webpack.HotModuleReplacementPlugin(),
      new webpack.NoErrorsPlugin())

    entry = [
      'webpack-dev-server/client?http://localhost:8080',
      'webpack/hot/only-dev-server',
      entry
    ]
  }

  if (options.loaders)
    loaders = loaders.concat(options.loaders)

  if (options.minimize)
    plugins.push(
      new webpack.optimize.UglifyJsPlugin({
        compress: { warnings: false, dead_code: true }
      }),
      new webpack.optimize.DedupePlugin(),
      new webpack.NoErrorsPlugin())
  else
    plugins.push(
      new webpack.DefinePlugin({
        '__VERSION__': JSON.stringify(pkg.version)
      }));

  if ( options.production || options.minimize )
    plugins.push(new webpack.DefinePlugin({
        '__VERSION__': JSON.stringify(pkg.version),
        "process.env": { NODE_ENV: JSON.stringify("production") }
      }))

  if (options.extractStyles)
    plugins.push(
      new ExtractTextPlugin(options.styleName || "styles.css", {
          allChunks: true
      }))

  if (options.banner) {
    plugins.push(
      new webpack.BannerPlugin(
        'v' + JSON.stringify(pkg.version) + ' | (c) ' + (new Date).getFullYear() + ' Jason Quense | '
        + 'https://github.com/jquense/react-widgets/blob/master/License.txt'
        , { entryOnly : true }))
  }

  return {
    cache: true,

    devtool: options.devtool,

    entry: entry,

    output: options.output,

    externals: options.externals,

    resolve: {
      extensions: ['', '.js', '.jsx']
    },

    module: {
      loaders: loaders
    },

    plugins: plugins,

    node: {
      Buffer: false
    }
  }
}

module.exports = {

  browser: makeConfig({

    banner: true,

    minimize: true,

    entry: './lib/index.js',

    output: {
      path: path.join(__dirname, './dist'),
      filename: 'react-widgets.js',
      library:  'ReactWidgets',
      libraryTarget: 'umd'
    },

    externals: {
      globalize: 'Globalize',
      react:  'React'
    }
  }),

  dev: makeConfig({

    hot: false,
    production: false,

    devtool: 'source-map',

    entry: './dev/dev.jsx',

    output: {
      filename: 'bundle.js',
      path: __dirname
    },

    // plugins: [
    //   new webpack.IgnorePlugin(/globalize$/)
    //]
  }),

  docBuild: makeConfig({

    minimize: true,

    extractStyles: true,

    styleName: 'docs.css',

    entry: './docs/components/docs.jsx',

    output: {
      path: path.join(__dirname, './docs/public'),
      filename: 'docs.js'
    },

    externals: {
      react:  'window.React',
      'babel/browser': 'window.babel'
    },

    loaders: [
      { test: /\.json$/, loader: 'json' },
      { test: /\.raw$/, loader: 'raw' },
      { test: /\.api\.md$/, loader: 'babel-loader!' + path.join(__dirname, './docs/vendor/apiLoader') },
      { test: /.md$/, loader: 'babel-loader!' + path.join(__dirname, './docs/vendor/mdLoader'), exclude: /\.api\.md$/ }
    ]

  }),

  docServer: makeConfig({

    devtool: 'source-map',

    hot: true,

    extractStyles: true,

    styleName: 'public/docs.css',

    entry:'./docs/components/docs.jsx',

    output: {
      path: path.join(__dirname, './docs/public'),
      filename: 'docs.js'
    },

    externals: {
      react: 'window.React',
      'babel/browser': 'window.babel'
    },

    loaders: [
      { test: /\.json$/, loader: 'json' },
      { test: /\.raw$/,  loader: 'raw'  },
      { test: /\.api\.md$/, loader: 'babel-loader!' + path.join(__dirname, './docs/vendor/apiLoader') },
      { test: /.md$/, loader: 'babel-loader!' + path.join(__dirname, './docs/vendor/mdLoader'), exclude: /\.api\.md$/ }
    ]
  }),

  test: makeConfig({

    devtool: 'inline-source-map',

    // entry:'./test.js',

    // output: {
    //   path: __dirname,
    //   filename: '_test.bundle.js'
    // },

    loaders: [
      { test: /sinon-chai/, loader: "imports?define=>false" }
    ]
  })
}
<commit_msg>Export the library as UMD format (support for AMD, CommonJS2 and global variable).<commit_after>var path = require('path')
  , webpack = require('webpack')
  , ExtractTextPlugin = require("extract-text-webpack-plugin")
  , pkg = require('./package.json');

function makeConfig(options){
  var entry = options.entry
    , plugins = options.plugins || []

  var loaders = [
    { test: /\.css$/,  loader: options.extractStyles
        ? ExtractTextPlugin.extract("style-loader", "css-loader")
        : "style-loader!css-loader" },

    { test: /\.less$/, loader: options.extractStyles
        ? ExtractTextPlugin.extract("style-loader", "css-loader!less-loader")
        : "style-loader!css-loader!less-loader" },

    { test: /\.gif$/, loader: "url-loader?mimetype=image/png" },
    { test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000&minetype=application/font-woff" },
    { test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "file-loader?name=[name].[ext]" },

    { test: /\.jsx$|\.js$/, loader: 'babel-loader', exclude: /node_modules/ }
  ];

  if (options.hot){
    loaders.splice(loaders.length - 1,0,
      { test: /\.jsx$|\.js$/, loader: 'react-hot-loader', exclude: /node_modules/ })

    plugins.push(
      new webpack.HotModuleReplacementPlugin(),
      new webpack.NoErrorsPlugin())

    entry = [
      'webpack-dev-server/client?http://localhost:8080',
      'webpack/hot/only-dev-server',
      entry
    ]
  }

  if (options.loaders)
    loaders = loaders.concat(options.loaders)

  if (options.minimize)
    plugins.push(
      new webpack.optimize.UglifyJsPlugin({
        compress: { warnings: false, dead_code: true }
      }),
      new webpack.optimize.DedupePlugin(),
      new webpack.NoErrorsPlugin())
  else
    plugins.push(
      new webpack.DefinePlugin({
        '__VERSION__': JSON.stringify(pkg.version)
      }));

  if ( options.production || options.minimize )
    plugins.push(new webpack.DefinePlugin({
        '__VERSION__': JSON.stringify(pkg.version),
        "process.env": { NODE_ENV: JSON.stringify("production") }
      }))

  if (options.extractStyles)
    plugins.push(
      new ExtractTextPlugin(options.styleName || "styles.css", {
          allChunks: true
      }))

  if (options.banner) {
    plugins.push(
      new webpack.BannerPlugin(
        'v' + JSON.stringify(pkg.version) + ' | (c) ' + (new Date).getFullYear() + ' Jason Quense | '
        + 'https://github.com/jquense/react-widgets/blob/master/License.txt'
        , { entryOnly : true }))
  }

  return {
    cache: true,

    devtool: options.devtool,

    entry: entry,

    output: options.output,

    externals: options.externals,

    resolve: {
      extensions: ['', '.js', '.jsx']
    },

    module: {
      loaders: loaders
    },

    plugins: plugins,

    node: {
      Buffer: false
    }
  }
}

module.exports = {

  browser: makeConfig({

    banner: true,

    minimize: true,

    entry: './lib/index.js',

    output: {
      path: path.join(__dirname, './dist'),
      filename: 'react-widgets.js',
      library:  'ReactWidgets',
      libraryTarget: 'umd'
    },

    externals: {
      globalize: 'Globalize',
      react: {
	    root: 'React',
	    commonjs: 'react',
	    commonjs2: 'react',
	    amd: 'react'
	  }
    }
  }),

  dev: makeConfig({

    hot: false,
    production: false,

    devtool: 'source-map',

    entry: './dev/dev.jsx',

    output: {
      filename: 'bundle.js',
      path: __dirname
    },

    // plugins: [
    //   new webpack.IgnorePlugin(/globalize$/)
    //]
  }),

  docBuild: makeConfig({

    minimize: true,

    extractStyles: true,

    styleName: 'docs.css',

    entry: './docs/components/docs.jsx',

    output: {
      path: path.join(__dirname, './docs/public'),
      filename: 'docs.js'
    },

    externals: {
      react:  'window.React',
      'babel/browser': 'window.babel'
    },

    loaders: [
      { test: /\.json$/, loader: 'json' },
      { test: /\.raw$/, loader: 'raw' },
      { test: /\.api\.md$/, loader: 'babel-loader!' + path.join(__dirname, './docs/vendor/apiLoader') },
      { test: /.md$/, loader: 'babel-loader!' + path.join(__dirname, './docs/vendor/mdLoader'), exclude: /\.api\.md$/ }
    ]

  }),

  docServer: makeConfig({

    devtool: 'source-map',

    hot: true,

    extractStyles: true,

    styleName: 'public/docs.css',

    entry:'./docs/components/docs.jsx',

    output: {
      path: path.join(__dirname, './docs/public'),
      filename: 'docs.js'
    },

    externals: {
      react: 'window.React',
      'babel/browser': 'window.babel'
    },

    loaders: [
      { test: /\.json$/, loader: 'json' },
      { test: /\.raw$/,  loader: 'raw'  },
      { test: /\.api\.md$/, loader: 'babel-loader!' + path.join(__dirname, './docs/vendor/apiLoader') },
      { test: /.md$/, loader: 'babel-loader!' + path.join(__dirname, './docs/vendor/mdLoader'), exclude: /\.api\.md$/ }
    ]
  }),

  test: makeConfig({

    devtool: 'inline-source-map',

    // entry:'./test.js',

    // output: {
    //   path: __dirname,
    //   filename: '_test.bundle.js'
    // },

    loaders: [
      { test: /sinon-chai/, loader: "imports?define=>false" }
    ]
  })
}
<|endoftext|>


<commit_before>"use strict";

// 3rd-party
var _     = require('lodash');
var async = require('async');

////////////////////////////////////////////////////////////////////////////////

module.exports.parserParameters = {
  addHelp:      true,
  help:         'Create user and assign with some groups',
  description:  'Create user'
};

module.exports.commandLineArguments = [
  {
    args:    [ 'action' ],
    options: {
      help:   'cli command add/update',
      choices: ['add', 'update']
    }
  },
  {
    args:    [ '--group' ],
    options: {
      dest:         'mark_to_add',
      help:         'add user to group',
      action:       'append',
      defaultValue: [],
      type: 'string'
    }
  },
  {
    args:    [ '--no-group' ],
    options: {
      dest:         'mark_to_remove',
      help:         'remove user from group',
      action:       'append',
      defaultValue: [],
      type: 'string'
    }
  },
  {
    args:    [ '-u', '--user' ],
    options: {
      help:         'target user',
      type: 'string',
      required: true
    }
  },
  {
    args:    [ '--pass' ],
    options: {
      help:         'user passsword. required only for add command',
      type: 'string'

    }
  },
  {
    args:    [ '--email' ],
    options: {
      help:         'user email. required only for add command',
      type: 'string'
    }
  }
];

module.exports.run = function (N, args, callback) {

  N.wire.emit([
      'init:models'
    ], N,

    function (err) {
      if (err) {
        callback(err);
        return;
      }

      var user      = null;
      var to_add    = {};
      var to_remove = [];

      // FIXME check to_remove and to_add intersection
      async.series([
        // fetch usergroups
        function (next) {
          var UserGroup = N.models.users.UserGroup;

          UserGroup.find().select('_id short_name').exec(function (err, docs) {
            if (err) {
              next(err);
              return;
            }

            docs.forEach(function (group) {
              if (args.mark_to_remove.indexOf(group.short_name) !== -1) {
                to_remove.push(group._id.toString());
              }
              if (args.mark_to_add.indexOf(group.short_name) !== -1) {
                to_add[group._id.toString()] = group;
              }
            });

            // FIXME check all groups were found from both lists?
            next();
          });
        },

        // find or create user
        function (next) {
          // FIXME test existing login and email
          var User = N.models.users.User;
          var auth = new N.models.users.AuthLink();

          if ('add' === args.action) {
            // FIXME user revalidator for pass and email test
            if (!args.pass || !args.email) {
              next('Invalid password or email');
              return;
            }

            user = new User({
              nick: args.user,
              joined_ts: new Date
            });

            user.save(function (err) {
              if (err) {
                next(err);
                return;
              }

              var provider = auth.providers.create({
                'type': 'plain',
                'email': args.email
              });

              provider.setPass(args.pass);

              auth.user_id = user._id;
              auth.providers.push(provider);

              auth.save(next);
            });
          } else {
            User.findOne({nick: args.user}).exec(function (err, doc) {
              if (err) {
                next(err);
                return;
              }
              if (!user) {
                next('User not found, check name or use `add`');
              }
              user = doc;
              next();
            });
          }
        },

        // update groups
        function (next) {
          if (!_.isEmpty(to_remove) && !_.isEmpty(user.usergroups)) {
            user.usergroups = user.usergroups.filter(function (group) {
              return to_remove.indexOf(group.toString()) === -1;
            });
          }
          if (!_.isEmpty(to_add)) {
            // remove from to_add list already assigned groups
            user.usergroups.forEach(function (group) {
              var group_id = group.toString();
              if (to_add[group_id]) {
                to_add = _.without(to_add, group_id);
              }
            });
            if (!_.isEmpty(to_add)) {
              _.values(to_add).forEach(function (group) {
                user.usergroups.push(group);
              });
            }
          }
          user.save(next);
        }
      ], function (err) {
        if (err) {
          callback("User creation error: " + String(err.message || err));
          return;
        }

        console.log('OK\n');
        process.exit(0);
      });
    }
  );
};
<commit_msg>Mode cli/user script to nodeca.users application.<commit_after><|endoftext|>