<commit_before>var Instance        = require("./Instance").Instance;
var Singleton       = require("./Singleton");
var OneAssociation  = require("./Associations/One");
var ManyAssociation = require("./Associations/Many");
var ChainFind       = require("./ChainFind");
var LazyLoad        = require("./LazyLoad");
var Utilities       = require("./Utilities");

exports.Model = Model;

function Model(opts) {
	opts = opts || {};

	if (!Array.isArray(opts.keys) || opts.keys.length < 2) {
		opts.keys = [ opts.id ];
	} else {
		opts.id = null;
	}

	var one_associations = [];
	var many_associations = [];
	var association_properties = [];
	var model_fields = [];

	for (var i = 0; i < opts.keys.length; i++) {
		model_fields.push(opts.keys[i]);
	}

	var createInstance = function (data, inst_opts, cb) {
		if (!inst_opts) {
			inst_opts = {};
		}
		var instance = new Instance({
			id                     : opts.id,
			keys                   : opts.keys,
			is_new                 : inst_opts.is_new || false,
			data                   : data,
			autoSave               : inst_opts.autoSave || false,
			extra                  : inst_opts.extra,
			extra_info             : inst_opts.extra_info,
			model                  : model,
			driver                 : opts.driver,
			table                  : opts.table,
			properties             : opts.properties,
			hooks                  : opts.hooks,
			methods                : opts.methods,
			validations            : opts.validations,
			association_properties : association_properties
		});
		if (model_fields !== null) {
			LazyLoad.extend(instance, model, opts.properties);
		}
		OneAssociation.extend(model, instance, opts.driver, one_associations, {
			autoFetch      : inst_opts.autoFetch || false,
			autoFetchLimit : inst_opts.autoFetchLimit,
			cascadeRemove  : inst_opts.cascadeRemove
		}, function () {
			ManyAssociation.extend(model, instance, opts.driver, many_associations, {
				autoFetch      : inst_opts.autoFetch || false,
				autoFetchLimit : inst_opts.autoFetchLimit,
				cascadeRemove  : inst_opts.cascadeRemove
			}, function () {
				if (typeof cb == "function") {
					return cb(instance);
				}
			});
		});
		return instance;
	};

	var model = function (data) {
		var instance;
		if (typeof data == "number") {
			var data2 = {};
			data2[opts.id] = data;

			return createInstance(data2);
		} else if (typeof data == "undefined") {
			data = {};
		}

		return createInstance(data, {
			is_new        : !data.hasOwnProperty(opts.id),
			autoSave      : opts.autoSave,
			cascadeRemove : opts.cascadeRemove
		});
	};

	for (var k in opts.properties) {
		if (opts.properties[k].lazyload !== true) {
			model_fields.push(k);
		}
	}

	OneAssociation.prepare(model, one_associations, association_properties, model_fields);
	ManyAssociation.prepare(model, many_associations);

	model.settings = opts.settings;

	model.drop = function (cb) {
		if (arguments.length === 0) {
			cb = function () {};
		}
		if (typeof opts.driver.drop == "function") {
			opts.driver.drop({
				table             : opts.table,
				properties        : opts.properties,
				one_associations  : one_associations,
				many_associations : many_associations
			}, cb);

			return this;
		}

		return cb(new Error("Driver does not support Model.drop()"));
	};

	model.sync = function (cb) {
		if (arguments.length === 0) {
			cb = function () {};
		}
		if (typeof opts.driver.sync == "function") {
			opts.driver.sync({
				keys              : opts.keys,
				table             : opts.table,
				properties        : opts.properties,
				indexes           : opts.indexes || [],
				one_associations  : one_associations,
				many_associations : many_associations
			}, cb);

			return this;
		}

		return cb(new Error("Driver does not support Model.sync()"));
	};

	model.get = function () {
		var conditions = {};
		var options    = {};
		var ids        = Array.prototype.slice.apply(arguments);
		var cb         = ids.pop();

		if (typeof cb != "function") {
			throw new Error("Missing Model.get() callback");
		}

		if (typeof ids[ids.length - 1] == "object") {
			options = ids.pop();
		}

		if (ids.length == 1 && Array.isArray(ids[0])) {
			ids = ids[0];
		}

		if (ids.length != opts.keys.length) {
			throw new Error("Model.get() IDs number missmatch (" + opts.keys.length + " needed, " + ids.length + " passed)");
		}

		for (var i = 0; i < opts.keys.length; i++) {
			conditions[opts.keys[i]] = ids[i];
		}

		opts.driver.find(model_fields, opts.table, conditions, { limit: 1 }, function (err, data) {
			if (err) {
				return cb(err);
			}
			if (data.length === 0) {
				return cb(new Error("Not found"));
			}
			Singleton.get(opts.driver.uid + "/" + opts.table + "/" + ids.join("."), {
				cache      : options.cache || opts.cache,
				save_check : opts.settings.get("instance.cacheSaveCheck")
			}, function (cb) {
				return createInstance(data[0], {
					autoSave       : opts.autoSave,
					autoFetch      : (options.autoFetchLimit === 0 ? false : opts.autoFetch),
					autoFetchLimit : options.autoFetchLimit || opts.autoFetchLimit,
					cascadeRemove  : options.cascadeRemove || opts.cascadeRemove
				}, cb);
			}, function (instance) {
				return cb(null, instance);
			});
		});

		return this;
	};

	model.find = function () {
		var options    = {};
		var conditions = null;
		var cb         = null;
		var order      = null;
		var merge      = null;

		for (var i = 0; i < arguments.length; i++) {
			switch (typeof arguments[i]) {
				case "number":
					options.limit = arguments[i];
					break;
				case "object":
					if (Array.isArray(arguments[i])) {
						if (arguments[i].length > 0) {
							order = arguments[i];
						}
					} else {
						if (conditions === null) {
							conditions = arguments[i];
						} else {
							if (options.hasOwnProperty("limit")) {
								arguments[i].limit = options.limit;
							}
							options = arguments[i];

							if (options.hasOwnProperty("__merge")) {
								merge = options.__merge;
								merge.select = Object.keys(options.extra);
								delete options.__merge;
							}
							if (options.hasOwnProperty("order")) {
								order = options.order;
								delete options.order;
							}
						}
					}
					break;
				case "function":
					cb = arguments[i];
					break;
				case "string":
					if (arguments[i][0] == "-") {
						order = [ arguments[i].substr(1), "Z" ];
					} else {
						order = [ arguments[i] ];
					}
					break;
			}
		}

		if (!options.hasOwnProperty("cache")) {
			options.cache = opts.cache;
		}

		if (order) {
			order = Utilities.standardizeOrder(order);
		}

		var chain = new ChainFind(model, {
			only         : options.only || model_fields,
			id           : opts.id,
			table        : opts.table,
			driver       : opts.driver,
			conditions   : conditions,
			associations : many_associations,
			limit        : options.limit,
			order        : order,
			merge        : merge,
			offset       : options.offset,
			newInstance  : function (data, cb) {
				Singleton.get(opts.driver.uid + "/" + opts.table + (merge ? "+" + merge.from.table : "") + "/" + data[opts.id], {
					cache      : options.cache,
					save_check : opts.settings.get("instance.cacheSaveCheck")
				}, function (cb) {
					return createInstance(data, {
						autoSave       : opts.autoSave,
						autoFetch      : (options.autoFetchLimit === 0 ? false : (options.autoFetch || opts.autoFetch)),
						autoFetchLimit : options.autoFetchLimit || opts.autoFetchLimit,
						cascadeRemove  : options.cascadeRemove || opts.cascadeRemove,
						extra          : options.extra,
						extra_info     : options.extra_info
					}, cb);
				}, function (instance) {
					return cb(null, instance);
				});
			}
		});
		if (cb === null) {
			return chain;
		}

		chain.run(cb);

		return this;
	};

	model.all = model.find;

	model.count = function () {
		var conditions = null;
		var cb         = null;

		for (var i = 0; i < arguments.length; i++) {
			switch (typeof arguments[i]) {
				case "object":
					conditions = arguments[i];
					break;
				case "function":
					cb = arguments[i];
					break;
			}
		}

		if (typeof cb != "function") {
			throw new Error("Missing Model.count() callback");
		}

		opts.driver.count(opts.table, conditions, {}, function (err, data) {
			if (err || data.length === 0) {
				return cb(err);
			}
			return cb(null, data[0].c);
		});
		return this;
	};

	model.aggregate = function () {
		var conditions = {};
		var properties = [];

		for (var i = 0; i < arguments.length; i++) {
			if (typeof arguments[i] == "object") {
				if (Array.isArray(arguments[i])) {
					properties = arguments[i];
				} else {
					conditions = arguments[i];
				}
			}
		}

		return new require("./AggregateFunctions")({
			table      : opts.table,
			driver     : opts.driver,
			conditions : conditions,
			properties : properties
		});
	};

	model.exists = function () {
		var ids = Array.prototype.slice.apply(arguments);
		var cb  = ids.pop();

		if (typeof cb != "function") {
			throw new Error("Missing Model.exists() callback");
		}

		var conditions = {};
		for (var i = 0; i < opts.keys.length; i++) {
			conditions[opts.keys[i]] = ids[i];
		}

		opts.driver.count(opts.table, conditions, {}, function (err, data) {
			if (err || data.length === 0) {
				return cb(err);
			}
			return cb(null, data[0].c > 0);
		});
		return this;
	};

	model.create = function () {
		var Instances = [];
		var options = {};
		var cb = null, idx = 0;
		var createNext = function () {
			if (idx >= Instances.length) {
				return cb(null, Instances);
			}

			Instances[idx] = createInstance(Instances[idx], {
				is_new    : true,
				autoSave  : opts.autoSave,
				autoFetch : false
			});
			Instances[idx].save(function (err) {
				if (err) {
					err.index = idx;
					err.instance = Instances[idx];

					return cb(err);
				}

				idx += 1;
				createNext();
			});
		};

		for (var i = 0; i < arguments.length; i++) {
			if (Array.isArray(arguments[i])) {
				Instances = Instances.concat(arguments[i]);
				continue;
			}

			switch (typeof arguments[i]) {
				case "object":
					options = arguments[i];
					break;
				case "function":
					cb = arguments[i];
					break;
			}
		}

		createNext();

		return this;
	};

	model.clear = function (cb) {
		opts.driver.clear(opts.table, function (err) {
			if (typeof cb == "function") cb(err);
		});

		return this;
	};

	Object.defineProperty(model, "table", {
		value: opts.table,
		enumerable: false
	});
	Object.defineProperty(model, "id", {
		value: opts.id,
		enumerable: false
	});
	Object.defineProperty(model, "keys", {
		value: opts.keys,
		enumerable: false
	});

	return model;
}
<commit_msg>Moves associations preparation to the end of model construction<commit_after>var Instance        = require("./Instance").Instance;
var Singleton       = require("./Singleton");
var OneAssociation  = require("./Associations/One");
var ManyAssociation = require("./Associations/Many");
var ChainFind       = require("./ChainFind");
var LazyLoad        = require("./LazyLoad");
var Utilities       = require("./Utilities");

exports.Model = Model;

function Model(opts) {
	opts = opts || {};

	if (!Array.isArray(opts.keys) || opts.keys.length < 2) {
		opts.keys = [ opts.id ];
	} else {
		opts.id = null;
	}

	var one_associations = [];
	var many_associations = [];
	var association_properties = [];
	var model_fields = [];

	for (var i = 0; i < opts.keys.length; i++) {
		model_fields.push(opts.keys[i]);
	}

	var createInstance = function (data, inst_opts, cb) {
		if (!inst_opts) {
			inst_opts = {};
		}
		var instance = new Instance({
			id                     : opts.id,
			keys                   : opts.keys,
			is_new                 : inst_opts.is_new || false,
			data                   : data,
			autoSave               : inst_opts.autoSave || false,
			extra                  : inst_opts.extra,
			extra_info             : inst_opts.extra_info,
			model                  : model,
			driver                 : opts.driver,
			table                  : opts.table,
			properties             : opts.properties,
			hooks                  : opts.hooks,
			methods                : opts.methods,
			validations            : opts.validations,
			association_properties : association_properties
		});
		if (model_fields !== null) {
			LazyLoad.extend(instance, model, opts.properties);
		}
		OneAssociation.extend(model, instance, opts.driver, one_associations, {
			autoFetch      : inst_opts.autoFetch || false,
			autoFetchLimit : inst_opts.autoFetchLimit,
			cascadeRemove  : inst_opts.cascadeRemove
		}, function () {
			ManyAssociation.extend(model, instance, opts.driver, many_associations, {
				autoFetch      : inst_opts.autoFetch || false,
				autoFetchLimit : inst_opts.autoFetchLimit,
				cascadeRemove  : inst_opts.cascadeRemove
			}, function () {
				if (typeof cb == "function") {
					return cb(instance);
				}
			});
		});
		return instance;
	};

	var model = function (data) {
		var instance;
		if (typeof data == "number") {
			var data2 = {};
			data2[opts.id] = data;

			return createInstance(data2);
		} else if (typeof data == "undefined") {
			data = {};
		}

		return createInstance(data, {
			is_new        : !data.hasOwnProperty(opts.id),
			autoSave      : opts.autoSave,
			cascadeRemove : opts.cascadeRemove
		});
	};

	for (var k in opts.properties) {
		if (opts.properties[k].lazyload !== true) {
			model_fields.push(k);
		}
	}

	model.settings = opts.settings;

	model.drop = function (cb) {
		if (arguments.length === 0) {
			cb = function () {};
		}
		if (typeof opts.driver.drop == "function") {
			opts.driver.drop({
				table             : opts.table,
				properties        : opts.properties,
				one_associations  : one_associations,
				many_associations : many_associations
			}, cb);

			return this;
		}

		return cb(new Error("Driver does not support Model.drop()"));
	};

	model.sync = function (cb) {
		if (arguments.length === 0) {
			cb = function () {};
		}
		if (typeof opts.driver.sync == "function") {
			opts.driver.sync({
				keys              : opts.keys,
				table             : opts.table,
				properties        : opts.properties,
				indexes           : opts.indexes || [],
				one_associations  : one_associations,
				many_associations : many_associations
			}, cb);

			return this;
		}

		return cb(new Error("Driver does not support Model.sync()"));
	};

	model.get = function () {
		var conditions = {};
		var options    = {};
		var ids        = Array.prototype.slice.apply(arguments);
		var cb         = ids.pop();

		if (typeof cb != "function") {
			throw new Error("Missing Model.get() callback");
		}

		if (typeof ids[ids.length - 1] == "object") {
			options = ids.pop();
		}

		if (ids.length == 1 && Array.isArray(ids[0])) {
			ids = ids[0];
		}

		if (ids.length != opts.keys.length) {
			throw new Error("Model.get() IDs number missmatch (" + opts.keys.length + " needed, " + ids.length + " passed)");
		}

		for (var i = 0; i < opts.keys.length; i++) {
			conditions[opts.keys[i]] = ids[i];
		}

		opts.driver.find(model_fields, opts.table, conditions, { limit: 1 }, function (err, data) {
			if (err) {
				return cb(err);
			}
			if (data.length === 0) {
				return cb(new Error("Not found"));
			}
			Singleton.get(opts.driver.uid + "/" + opts.table + "/" + ids.join("."), {
				cache      : options.cache || opts.cache,
				save_check : opts.settings.get("instance.cacheSaveCheck")
			}, function (cb) {
				return createInstance(data[0], {
					autoSave       : opts.autoSave,
					autoFetch      : (options.autoFetchLimit === 0 ? false : opts.autoFetch),
					autoFetchLimit : options.autoFetchLimit || opts.autoFetchLimit,
					cascadeRemove  : options.cascadeRemove || opts.cascadeRemove
				}, cb);
			}, function (instance) {
				return cb(null, instance);
			});
		});

		return this;
	};

	model.find = function () {
		var options    = {};
		var conditions = null;
		var cb         = null;
		var order      = null;
		var merge      = null;

		for (var i = 0; i < arguments.length; i++) {
			switch (typeof arguments[i]) {
				case "number":
					options.limit = arguments[i];
					break;
				case "object":
					if (Array.isArray(arguments[i])) {
						if (arguments[i].length > 0) {
							order = arguments[i];
						}
					} else {
						if (conditions === null) {
							conditions = arguments[i];
						} else {
							if (options.hasOwnProperty("limit")) {
								arguments[i].limit = options.limit;
							}
							options = arguments[i];

							if (options.hasOwnProperty("__merge")) {
								merge = options.__merge;
								merge.select = Object.keys(options.extra);
								delete options.__merge;
							}
							if (options.hasOwnProperty("order")) {
								order = options.order;
								delete options.order;
							}
						}
					}
					break;
				case "function":
					cb = arguments[i];
					break;
				case "string":
					if (arguments[i][0] == "-") {
						order = [ arguments[i].substr(1), "Z" ];
					} else {
						order = [ arguments[i] ];
					}
					break;
			}
		}

		if (!options.hasOwnProperty("cache")) {
			options.cache = opts.cache;
		}

		if (order) {
			order = Utilities.standardizeOrder(order);
		}

		var chain = new ChainFind(model, {
			only         : options.only || model_fields,
			id           : opts.id,
			table        : opts.table,
			driver       : opts.driver,
			conditions   : conditions,
			associations : many_associations,
			limit        : options.limit,
			order        : order,
			merge        : merge,
			offset       : options.offset,
			newInstance  : function (data, cb) {
				Singleton.get(opts.driver.uid + "/" + opts.table + (merge ? "+" + merge.from.table : "") + "/" + data[opts.id], {
					cache      : options.cache,
					save_check : opts.settings.get("instance.cacheSaveCheck")
				}, function (cb) {
					return createInstance(data, {
						autoSave       : opts.autoSave,
						autoFetch      : (options.autoFetchLimit === 0 ? false : (options.autoFetch || opts.autoFetch)),
						autoFetchLimit : options.autoFetchLimit || opts.autoFetchLimit,
						cascadeRemove  : options.cascadeRemove || opts.cascadeRemove,
						extra          : options.extra,
						extra_info     : options.extra_info
					}, cb);
				}, function (instance) {
					return cb(null, instance);
				});
			}
		});
		if (cb === null) {
			return chain;
		}

		chain.run(cb);

		return this;
	};

	model.all = model.find;

	model.count = function () {
		var conditions = null;
		var cb         = null;

		for (var i = 0; i < arguments.length; i++) {
			switch (typeof arguments[i]) {
				case "object":
					conditions = arguments[i];
					break;
				case "function":
					cb = arguments[i];
					break;
			}
		}

		if (typeof cb != "function") {
			throw new Error("Missing Model.count() callback");
		}

		opts.driver.count(opts.table, conditions, {}, function (err, data) {
			if (err || data.length === 0) {
				return cb(err);
			}
			return cb(null, data[0].c);
		});
		return this;
	};

	model.aggregate = function () {
		var conditions = {};
		var properties = [];

		for (var i = 0; i < arguments.length; i++) {
			if (typeof arguments[i] == "object") {
				if (Array.isArray(arguments[i])) {
					properties = arguments[i];
				} else {
					conditions = arguments[i];
				}
			}
		}

		return new require("./AggregateFunctions")({
			table      : opts.table,
			driver     : opts.driver,
			conditions : conditions,
			properties : properties
		});
	};

	model.exists = function () {
		var ids = Array.prototype.slice.apply(arguments);
		var cb  = ids.pop();

		if (typeof cb != "function") {
			throw new Error("Missing Model.exists() callback");
		}

		var conditions = {};
		for (var i = 0; i < opts.keys.length; i++) {
			conditions[opts.keys[i]] = ids[i];
		}

		opts.driver.count(opts.table, conditions, {}, function (err, data) {
			if (err || data.length === 0) {
				return cb(err);
			}
			return cb(null, data[0].c > 0);
		});
		return this;
	};

	model.create = function () {
		var Instances = [];
		var options = {};
		var cb = null, idx = 0;
		var createNext = function () {
			if (idx >= Instances.length) {
				return cb(null, Instances);
			}

			Instances[idx] = createInstance(Instances[idx], {
				is_new    : true,
				autoSave  : opts.autoSave,
				autoFetch : false
			});
			Instances[idx].save(function (err) {
				if (err) {
					err.index = idx;
					err.instance = Instances[idx];

					return cb(err);
				}

				idx += 1;
				createNext();
			});
		};

		for (var i = 0; i < arguments.length; i++) {
			if (Array.isArray(arguments[i])) {
				Instances = Instances.concat(arguments[i]);
				continue;
			}

			switch (typeof arguments[i]) {
				case "object":
					options = arguments[i];
					break;
				case "function":
					cb = arguments[i];
					break;
			}
		}

		createNext();

		return this;
	};

	model.clear = function (cb) {
		opts.driver.clear(opts.table, function (err) {
			if (typeof cb == "function") cb(err);
		});

		return this;
	};

	Object.defineProperty(model, "table", {
		value: opts.table,
		enumerable: false
	});
	Object.defineProperty(model, "id", {
		value: opts.id,
		enumerable: false
	});
	Object.defineProperty(model, "keys", {
		value: opts.keys,
		enumerable: false
	});

	OneAssociation.prepare(model, one_associations, association_properties, model_fields);
	ManyAssociation.prepare(model, many_associations);

	return model;
}
<|endoftext|>


<commit_before>import React, {Component} from 'react';

import RaisedButton from 'src/RaisedButton';
import Tip from 'src/Tip';
import TipProvider from 'src/TipProvider';
import Widget from 'src/Widget';
import WidgetHeader from 'src/WidgetHeader';

import PropTypeDescTable from 'components/PropTypeDescTable';
import doc from 'examples/assets/propTypes/TipBody.json';

import 'sass/containers/app/modules/popup/TipExamples.scss';

export default class TipExamples extends Component {

    constructor(props) {

        super(props);

        this.state = {
            tipVisible1: false,
            tipVisible2: false,
            tipVisible4: false,
            tipVisible5: false,
            tipVisible6: false,
            tipVisible7: false,
            tipVisible8: false,
            tipVisible9: false,
            tipVisible10: false,
            tipVisible11: false,
            tipVisible12: false,
            tipVisible13: false,
            tipVisible14: false,
            tipVisible15: false,
            triggerEl1: null,
            triggerEl2: null,
            triggerEl4: null,
            triggerEl5: null,
            triggerEl6: null,
            triggerEl7: null,
            triggerEl8: null,
            triggerEl9: null,
            triggerEl10: null,
            triggerEl11: null,
            triggerEl12: null,
            triggerEl13: null,
            triggerEl14: null,
            triggerEl15: null
        };

        this.showTip = ::this.showTip;
        this.hideTip = ::this.hideTip;

    }

    showTip(e, id) {
        this.setState({
            [`tipVisible${id}`]: true,
            [`triggerEl${id}`]: e.currentTarget
        });
    }

    hideTip(id) {
        this.setState({
            [`tipVisible${id}`]: false
        });
    }

    render() {

        const {
            tipVisible1, tipVisible2, tipVisible4, tipVisible5, tipVisible6,
            tipVisible7, tipVisible8, tipVisible9, tipVisible10, tipVisible11,
            tipVisible12, tipVisible13, tipVisible14, tipVisible15,
            triggerEl1, triggerEl2, triggerEl4, triggerEl5, triggerEl6,
            triggerEl7, triggerEl8, triggerEl9, triggerEl10, triggerEl11,
            triggerEl12, triggerEl13, triggerEl14, triggerEl15
        } = this.state;

        return (

Tip

                    A Tip can be used as an alternative to a Drop Down Tip that can contain elements
                    inside.

Examples

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="With value"/>

                                    Set the value property to show different position of Tip.

                                        <RaisedButton className="trigger-position-button"
                                                      value="Top Left"
                                                      onMouseEnter={(e) => {
                                                          this.showTip(e, 7);
                                                      }}/>
                                        <RaisedButton className="trigger-position-button"
                                                      value="Top"
                                                      onMouseEnter={(e) => {
                                                          this.showTip(e, 8);
                                                      }}/>
                                        <RaisedButton className="trigger-position-button"
                                                      value="Top right"
                                                      onMouseEnter={(e) => {
                                                          this.showTip(e, 9);
                                                      }}/>

                                        <RaisedButton className="trigger-position-button"
                                                      value="Right Top"
                                                      onMouseEnter={(e) => {
                                                          this.showTip(e, 13);
                                                      }}/>
                                        <RaisedButton className="trigger-position-button"
                                                      value="Right"
                                                      onMouseEnter={(e) => {
                                                          this.showTip(e, 14);
                                                      }}/>
                                        <RaisedButton className="trigger-position-button"
                                                      value="Right Bottom"
                                                      onMouseEnter={(e) => {
                                                          this.showTip(e, 15);
                                                      }}/>

                                        <RaisedButton className="trigger-position-button"
                                                      value="Bottom Left"
                                                      onMouseEnter={(e) => {
                                                          this.showTip(e, 4);
                                                      }}/>
                                        <RaisedButton className="trigger-position-button"
                                                      value="Bottom"
                                                      onMouseEnter={(e) => {
                                                          this.showTip(e, 5);
                                                      }}/>
                                        <RaisedButton className="trigger-position-button"
                                                      value="Bottom Right"
                                                      onMouseEnter={(e) => {
                                                          this.showTip(e, 6);
                                                      }}/>

                                        <RaisedButton className="trigger-position-button"
                                                      value="Left Top"
                                                      onMouseEnter={(e) => {
                                                          this.showTip(e, 10);
                                                      }}/>
                                        <RaisedButton className="trigger-position-button"
                                                      value="Left"
                                                      onMouseEnter={(e) => {
                                                          this.showTip(e, 11);
                                                      }}/>
                                        <RaisedButton className="trigger-position-button"
                                                      value="Left Bottom"
                                                      onMouseEnter={(e) => {
                                                          this.showTip(e, 12);
                                                      }}/>

                                <Tip visible={tipVisible4}
                                     triggerEl={triggerEl4}
                                     position={Tip.Position.BOTTOM_LEFT}
                                     onRequestClose={() => {
                                         this.hideTip(4);
                                     }}>
                                    Tip Content
                                </Tip>
                                <Tip visible={tipVisible5}
                                     triggerEl={triggerEl5}
                                     position={Tip.Position.BOTTOM}
                                     onRequestClose={() => {
                                         this.hideTip(5);
                                     }}>
                                    Tip Content
                                </Tip>
                                <Tip visible={tipVisible6}
                                     triggerEl={triggerEl6}
                                     position={Tip.Position.BOTTOM_RIGHT}
                                     onRequestClose={() => {
                                         this.hideTip(6);
                                     }}>
                                    Tip Content
                                </Tip>

                                <Tip visible={tipVisible7}
                                     triggerEl={triggerEl7}
                                     position={Tip.Position.TOP_LEFT}
                                     onRequestClose={() => {
                                         this.hideTip(7);
                                     }}>
                                    Tip Content
                                </Tip>
                                <Tip visible={tipVisible8}
                                     triggerEl={triggerEl8}
                                     position={Tip.Position.TOP}
                                     onRequestClose={() => {
                                         this.hideTip(8);
                                     }}>
                                    Tip Content
                                </Tip>
                                <Tip visible={tipVisible9}
                                     triggerEl={triggerEl9}
                                     position={Tip.Position.TOP_RIGHT}
                                     onRequestClose={() => {
                                         this.hideTip(9);
                                     }}>
                                    Tip Content
                                </Tip>

                                <Tip visible={tipVisible10}
                                     triggerEl={triggerEl10}
                                     position={Tip.Position.LEFT_TOP}
                                     onRequestClose={() => {
                                         this.hideTip(10);
                                     }}>
                                    Tip Content
                                </Tip>
                                <Tip visible={tipVisible11}
                                     triggerEl={triggerEl11}
                                     position={Tip.Position.LEFT}
                                     onRequestClose={() => {
                                         this.hideTip(11);
                                     }}>
                                    Tip Content
                                </Tip>
                                <Tip visible={tipVisible12}
                                     triggerEl={triggerEl12}
                                     position={Tip.Position.LEFT_BOTTOM}
                                     onRequestClose={() => {
                                         this.hideTip(12);
                                     }}>
                                    Tip Content
                                </Tip>

                                <Tip visible={tipVisible13}
                                     triggerEl={triggerEl13}
                                     position={Tip.Position.RIGHT_TOP}
                                     onRequestClose={() => {
                                         this.hideTip(13);
                                     }}>
                                    Tip Content
                                </Tip>
                                <Tip visible={tipVisible14}
                                     triggerEl={triggerEl14}
                                     position={Tip.Position.RIGHT}
                                     onRequestClose={() => {
                                         this.hideTip(14);
                                     }}>
                                    Tip Content
                                </Tip>
                                <Tip visible={tipVisible15}
                                     triggerEl={triggerEl15}
                                     position={Tip.Position.RIGHT_BOTTOM}
                                     onRequestClose={() => {
                                         this.hideTip(15);
                                     }}>
                                    Tip Content
                                </Tip>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="Customized Tip Triangle"/>

                                <RaisedButton className="trigger-button"
                                              value="Show Tip"
                                              onMouseEnter={(e) => {
                                                  this.showTip(e, 1);
                                              }}/>

                                <Tip className="customized-tip"
                                     visible={tipVisible1}
                                     triggerEl={triggerEl1}
                                     triangle={
                                         <svg xmlns="http://www.w3.org/2000/svg"
                                              version="1.1"
                                              className="customized-tip-triangle"
                                              width="17"
                                              height="7">
                                             <polyline points="0,7 9,0 17,7"
                                                       style={{stroke: '#e7e7e7', fill: '#fff'}}/>
                                         </svg>
                                     }
                                     onRequestClose={() => {
                                         this.hideTip(1);
                                     }}>
                                    Tip Content
                                </Tip>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="Customized Tip Triangle"/>

                                <TipProvider text="Tip Content">
                                    <RaisedButton className="trigger-button"
                                                  value="Show Tip"/>
                                </TipProvider>

                </Widget>

Properties

                <PropTypeDescTable data={doc}/>

        );
    }
};<commit_msg>update Tip examples<commit_after>import React, {Component} from 'react';

import RaisedButton from 'src/RaisedButton';
import Tip from 'src/Tip';
import TipProvider from 'src/TipProvider';
import Widget from 'src/Widget';
import WidgetHeader from 'src/WidgetHeader';

import PropTypeDescTable from 'components/PropTypeDescTable';
import doc from 'examples/assets/propTypes/TipBody.json';

import 'sass/containers/app/modules/popup/TipExamples.scss';

export default class TipExamples extends Component {

    constructor(props) {

        super(props);

        this.state = {
            tipVisible: {},
            triggerEl: {}
        };

        this.showTip = ::this.showTip;
        this.hideTip = ::this.hideTip;

    }

    showTip(e, id) {

        const {tipVisible, triggerEl} = this.state;

        tipVisible[id] = true;

        if (!triggerEl[id]) {
            triggerEl[id] = e.target;
        }

        this.setState({
            tipVisible,
            triggerEl
        });

    }

    hideTip(id) {

        const {tipVisible} = this.state;

        tipVisible[id] = false;

        this.setState({
            tipVisible
        });

    }

    render() {

        const {tipVisible, triggerEl} = this.state;

        return (

Tip

                    A Tip can be used as an alternative to a Drop Down Tip that can contain elements
                    inside.

Examples

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="With value"/>

                                    Set the value property to show different position of Tip.

                                        <RaisedButton className="trigger-position-button"
                                                      value="Top Left"
                                                      onMouseEnter={(e) => {
                                                          this.showTip(e, 3);
                                                      }}/>
                                        <RaisedButton className="trigger-position-button"
                                                      value="Top"
                                                      onMouseEnter={(e) => {
                                                          this.showTip(e, 4);
                                                      }}/>
                                        <RaisedButton className="trigger-position-button"
                                                      value="Top right"
                                                      onMouseEnter={(e) => {
                                                          this.showTip(e, 5);
                                                      }}/>

                                        <RaisedButton className="trigger-position-button"
                                                      value="Right Top"
                                                      onMouseEnter={(e) => {
                                                          this.showTip(e, 9);
                                                      }}/>
                                        <RaisedButton className="trigger-position-button"
                                                      value="Right"
                                                      onMouseEnter={(e) => {
                                                          this.showTip(e, 10);
                                                      }}/>
                                        <RaisedButton className="trigger-position-button"
                                                      value="Right Bottom"
                                                      onMouseEnter={(e) => {
                                                          this.showTip(e, 11);
                                                      }}/>

                                        <RaisedButton className="trigger-position-button"
                                                      value="Bottom Left"
                                                      onMouseEnter={(e) => {
                                                          this.showTip(e, 0);
                                                      }}/>
                                        <RaisedButton className="trigger-position-button"
                                                      value="Bottom"
                                                      onMouseEnter={(e) => {
                                                          this.showTip(e, 1);
                                                      }}/>
                                        <RaisedButton className="trigger-position-button"
                                                      value="Bottom Right"
                                                      onMouseEnter={(e) => {
                                                          this.showTip(e, 2);
                                                      }}/>

                                        <RaisedButton className="trigger-position-button"
                                                      value="Left Top"
                                                      onMouseEnter={(e) => {
                                                          this.showTip(e, 6);
                                                      }}/>
                                        <RaisedButton className="trigger-position-button"
                                                      value="Left"
                                                      onMouseEnter={(e) => {
                                                          this.showTip(e, 7);
                                                      }}/>
                                        <RaisedButton className="trigger-position-button"
                                                      value="Left Bottom"
                                                      onMouseEnter={(e) => {
                                                          this.showTip(e, 8);
                                                      }}/>

                                <Tip visible={tipVisible[0]}
                                     triggerEl={triggerEl[0]}
                                     position={Tip.Position.BOTTOM_LEFT}
                                     onRequestClose={() => {
                                         this.hideTip(0);
                                     }}>
                                    Tip Content
                                </Tip>
                                <Tip visible={tipVisible[1]}
                                     triggerEl={triggerEl[1]}
                                     position={Tip.Position.BOTTOM}
                                     onRequestClose={() => {
                                         this.hideTip(1);
                                     }}>
                                    Tip Content
                                </Tip>
                                <Tip visible={tipVisible[2]}
                                     triggerEl={triggerEl[2]}
                                     position={Tip.Position.BOTTOM_RIGHT}
                                     onRequestClose={() => {
                                         this.hideTip(2);
                                     }}>
                                    Tip Content
                                </Tip>

                                <Tip visible={tipVisible[3]}
                                     triggerEl={triggerEl[3]}
                                     position={Tip.Position.TOP_LEFT}
                                     onRequestClose={() => {
                                         this.hideTip(3);
                                     }}>
                                    Tip Content
                                </Tip>
                                <Tip visible={tipVisible[4]}
                                     triggerEl={triggerEl[4]}
                                     position={Tip.Position.TOP}
                                     onRequestClose={() => {
                                         this.hideTip(4);
                                     }}>
                                    Tip Content
                                </Tip>
                                <Tip visible={tipVisible[5]}
                                     triggerEl={triggerEl[5]}
                                     position={Tip.Position.TOP_RIGHT}
                                     onRequestClose={() => {
                                         this.hideTip(5);
                                     }}>
                                    Tip Content
                                </Tip>

                                <Tip visible={tipVisible[6]}
                                     triggerEl={triggerEl[6]}
                                     position={Tip.Position.LEFT_TOP}
                                     onRequestClose={() => {
                                         this.hideTip(6);
                                     }}>
                                    Tip Content
                                </Tip>
                                <Tip visible={tipVisible[7]}
                                     triggerEl={triggerEl[7]}
                                     position={Tip.Position.LEFT}
                                     onRequestClose={() => {
                                         this.hideTip(7);
                                     }}>
                                    Tip Content
                                </Tip>
                                <Tip visible={tipVisible[8]}
                                     triggerEl={triggerEl[8]}
                                     position={Tip.Position.LEFT_BOTTOM}
                                     onRequestClose={() => {
                                         this.hideTip(8);
                                     }}>
                                    Tip Content
                                </Tip>

                                <Tip visible={tipVisible[9]}
                                     triggerEl={triggerEl[9]}
                                     position={Tip.Position.RIGHT_TOP}
                                     onRequestClose={() => {
                                         this.hideTip(9);
                                     }}>
                                    Tip Content
                                </Tip>
                                <Tip visible={tipVisible[10]}
                                     triggerEl={triggerEl[10]}
                                     position={Tip.Position.RIGHT}
                                     onRequestClose={() => {
                                         this.hideTip(10);
                                     }}>
                                    Tip Content
                                </Tip>
                                <Tip visible={tipVisible[11]}
                                     triggerEl={triggerEl[11]}
                                     position={Tip.Position.RIGHT_BOTTOM}
                                     onRequestClose={() => {
                                         this.hideTip(11);
                                     }}>
                                    Tip Content
                                </Tip>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="Customized Tip Triangle"/>

                                <RaisedButton className="trigger-button"
                                              value="Show Tip"
                                              onMouseEnter={(e) => {
                                                  this.showTip(e, 12);
                                              }}/>

                                <Tip className="customized-tip"
                                     visible={tipVisible[12]}
                                     triggerEl={triggerEl[12]}
                                     triangle={
                                         <svg xmlns="http://www.w3.org/2000/svg"
                                              version="1.1"
                                              className="customized-tip-triangle"
                                              width="17"
                                              height="7">
                                             <polyline points="0,7 9,0 17,7"
                                                       style={{stroke: '#e7e7e7', fill: '#fff'}}/>
                                         </svg>
                                     }
                                     onRequestClose={() => {
                                         this.hideTip(12);
                                     }}>
                                    Tip Content
                                </Tip>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="Customized Tip Triangle"/>

                                <TipProvider text="Tip Content">
                                    <RaisedButton className="trigger-button"
                                                  value="Show Tip"/>
                                </TipProvider>

                </Widget>

Properties

                <PropTypeDescTable data={doc}/>

        );
    }
};<|endoftext|>


<commit_before>var Instance        = require("./Instance").Instance;
var Singleton       = require("./Singleton");
var OneAssociation  = require("./Associations/One");
var ManyAssociation = require("./Associations/Many");
var ChainFind       = require("./ChainFind");
var LazyLoad        = require("./LazyLoad");
var Utilities       = require("./Utilities");

exports.Model = Model;

function Model(opts) {
	opts = opts || {};

	if (!Array.isArray(opts.keys) || opts.keys.length < 2) {
		opts.keys = [ opts.id ];
	} else {
		opts.id = null;
	}

	var one_associations = [];
	var many_associations = [];
	var association_properties = [];
	var model_fields = [];

	for (var i = 0; i < opts.keys.length; i++) {
		model_fields.push(opts.keys[i]);
	}

	var createInstance = function (data, inst_opts, cb) {
		if (!inst_opts) {
			inst_opts = {};
		}
		var instance = new Instance({
			id                     : opts.id,
			keys                   : opts.keys,
			is_new                 : inst_opts.is_new || false,
			data                   : data,
			autoSave               : inst_opts.autoSave || false,
			extra                  : inst_opts.extra,
			extra_info             : inst_opts.extra_info,
			model                  : model,
			driver                 : opts.driver,
			table                  : opts.table,
			properties             : opts.properties,
			hooks                  : opts.hooks,
			methods                : opts.methods,
			validations            : opts.validations,
			association_properties : association_properties
		});
		if (model_fields !== null) {
			LazyLoad.extend(instance, model, opts.properties);
		}
		OneAssociation.extend(model, instance, opts.driver, one_associations, {
			autoFetch      : inst_opts.autoFetch || false,
			autoFetchLimit : inst_opts.autoFetchLimit,
			cascadeRemove  : inst_opts.cascadeRemove
		}, function () {
			ManyAssociation.extend(model, instance, opts.driver, many_associations, {
				autoFetch      : inst_opts.autoFetch || false,
				autoFetchLimit : inst_opts.autoFetchLimit,
				cascadeRemove  : inst_opts.cascadeRemove
			}, function () {
				if (typeof cb == "function") {
					return cb(instance);
				}
			});
		});
		return instance;
	};

	var model = function (data) {
		var instance;
		if (typeof data == "number") {
			var data2 = {};
			data2[opts.id] = data;

			return createInstance(data2);
		} else if (typeof data == "undefined") {
			data = {};
		}

		return createInstance(data, {
			is_new        : !data.hasOwnProperty(opts.id),
			autoSave      : opts.autoSave,
			cascadeRemove : opts.cascadeRemove
		});
	};

	for (var k in opts.properties) {
		if (opts.properties[k].lazyload !== true) {
			model_fields.push(k);
		}
	}

	model.settings = opts.settings;

	model.drop = function (cb) {
		if (arguments.length === 0) {
			cb = function () {};
		}
		if (typeof opts.driver.drop == "function") {
			opts.driver.drop({
				table             : opts.table,
				properties        : opts.properties,
				one_associations  : one_associations,
				many_associations : many_associations
			}, cb);

			return this;
		}

		return cb(new Error("Driver does not support Model.drop()"));
	};

	model.sync = function (cb) {
		if (arguments.length === 0) {
			cb = function () {};
		}
		if (typeof opts.driver.sync == "function") {
			opts.driver.sync({
				keys              : opts.keys,
				table             : opts.table,
				properties        : opts.properties,
				indexes           : opts.indexes || [],
				one_associations  : one_associations,
				many_associations : many_associations
			}, cb);

			return this;
		}

		return cb(new Error("Driver does not support Model.sync()"));
	};

	model.get = function () {
		var conditions = {};
		var options    = {};
		var ids        = Array.prototype.slice.apply(arguments);
		var cb         = ids.pop();

		if (typeof cb != "function") {
			throw new Error("Missing Model.get() callback");
		}

		if (typeof ids[ids.length - 1] == "object") {
			options = ids.pop();
		}

		if (ids.length == 1 && Array.isArray(ids[0])) {
			ids = ids[0];
		}

		if (ids.length != opts.keys.length) {
			throw new Error("Model.get() IDs number missmatch (" + opts.keys.length + " needed, " + ids.length + " passed)");
		}

		for (var i = 0; i < opts.keys.length; i++) {
			conditions[opts.keys[i]] = ids[i];
		}

		if (!options.hasOwnProperty("autoFetchLimit")) {
			options.autoFetchLimit = opts.autoFetchLimit;
		}
		if (!options.hasOwnProperty("cascadeRemove")) {
			options.cascadeRemove = opts.cascadeRemove;
		}

		opts.driver.find(model_fields, opts.table, conditions, { limit: 1 }, function (err, data) {
			if (err) {
				return cb(err);
			}
			if (data.length === 0) {
				return cb(new Error("Not found"));
			}
			Singleton.get(opts.driver.uid + "/" + opts.table + "/" + ids.join("."), {
				cache      : options.cache || opts.cache,
				save_check : opts.settings.get("instance.cacheSaveCheck")
			}, function (cb) {
				return createInstance(data[0], {
					autoSave       : opts.autoSave,
					autoFetch      : (options.autoFetchLimit === 0 ? false : opts.autoFetch),
					autoFetchLimit : options.autoFetchLimit,
					cascadeRemove  : options.cascadeRemove
				}, cb);
			}, function (instance) {
				return cb(null, instance);
			});
		});

		return this;
	};

	model.find = function () {
		var options    = {};
		var conditions = null;
		var cb         = null;
		var order      = null;
		var merge      = null;

		for (var i = 0; i < arguments.length; i++) {
			switch (typeof arguments[i]) {
				case "number":
					options.limit = arguments[i];
					break;
				case "object":
					if (Array.isArray(arguments[i])) {
						if (arguments[i].length > 0) {
							order = arguments[i];
						}
					} else {
						if (conditions === null) {
							conditions = arguments[i];
						} else {
							if (options.hasOwnProperty("limit")) {
								arguments[i].limit = options.limit;
							}
							options = arguments[i];

							if (options.hasOwnProperty("__merge")) {
								merge = options.__merge;
								merge.select = Object.keys(options.extra);
								delete options.__merge;
							}
							if (options.hasOwnProperty("order")) {
								order = options.order;
								delete options.order;
							}
						}
					}
					break;
				case "function":
					cb = arguments[i];
					break;
				case "string":
					if (arguments[i][0] == "-") {
						order = [ arguments[i].substr(1), "Z" ];
					} else {
						order = [ arguments[i] ];
					}
					break;
			}
		}

		if (!options.hasOwnProperty("cache")) {
			options.cache = opts.cache;
		}
		if (!options.hasOwnProperty("autoFetchLimit")) {
			options.autoFetchLimit = opts.autoFetchLimit;
		}
		if (!options.hasOwnProperty("cascadeRemove")) {
			options.cascadeRemove = opts.cascadeRemove;
		}

		if (order) {
			order = Utilities.standardizeOrder(order);
		}

		var chain = new ChainFind(model, {
			only         : options.only || model_fields,
			id           : opts.id,
			table        : opts.table,
			driver       : opts.driver,
			conditions   : conditions,
			associations : many_associations,
			limit        : options.limit,
			order        : order,
			merge        : merge,
			offset       : options.offset,
			newInstance  : function (data, cb) {
				var uid = opts.driver.uid + "/" + opts.table + (merge ? "+" + merge.from.table : "");
				for (var i = 0; i < opts.keys.length; i++) {
					uid += "/" + data[opts.keys[i]];
				}

				Singleton.get(uid, {
					cache      : options.cache,
					save_check : opts.settings.get("instance.cacheSaveCheck")
				}, function (cb) {
					return createInstance(data, {
						autoSave       : opts.autoSave,
						autoFetch      : (options.autoFetchLimit === 0 ? false : (options.autoFetch || opts.autoFetch)),
						autoFetchLimit : options.autoFetchLimit,
						cascadeRemove  : options.cascadeRemove,
						extra          : options.extra,
						extra_info     : options.extra_info
					}, cb);
				}, function (instance) {
					return cb(null, instance);
				});
			}
		});
		if (cb === null) {
			return chain;
		}

		chain.run(cb);

		return this;
	};

	model.all = model.find;

	model.one = function () {
		var args = Array.prototype.slice.apply(arguments);
		var cb   = null;

		// extract callback
		for (var i = 0; i < args.length; i++) {
			if (typeof args[i] == "function") {
				cb = args.splice(i, 1)[0];
				break;
			}
		}

		if (cb === null) {
			throw new Error("Model.one() called without callback");
		}

		// add limit 1
		args.push(1);
		args.push(function (err, results) {
			if (err) {
				return cb(err);
			}
			return cb(null, results.length ? results[0] : null);
		});

		return this.find.apply(this, args);
	};

	model.count = function () {
		var conditions = null;
		var cb         = null;

		for (var i = 0; i < arguments.length; i++) {
			switch (typeof arguments[i]) {
				case "object":
					conditions = arguments[i];
					break;
				case "function":
					cb = arguments[i];
					break;
			}
		}

		if (typeof cb != "function") {
			throw new Error("Missing Model.count() callback");
		}

		opts.driver.count(opts.table, conditions, {}, function (err, data) {
			if (err || data.length === 0) {
				return cb(err);
			}
			return cb(null, data[0].c);
		});
		return this;
	};

	model.aggregate = function () {
		var conditions = {};
		var properties = [];

		for (var i = 0; i < arguments.length; i++) {
			if (typeof arguments[i] == "object") {
				if (Array.isArray(arguments[i])) {
					properties = arguments[i];
				} else {
					conditions = arguments[i];
				}
			}
		}

		return new require("./AggregateFunctions")({
			table       : opts.table,
			driver_name : opts.driver_name,
			driver      : opts.driver,
			conditions  : conditions,
			properties  : properties
		});
	};

	model.exists = function () {
		var ids = Array.prototype.slice.apply(arguments);
		var cb  = ids.pop();

		if (typeof cb != "function") {
			throw new Error("Missing Model.exists() callback");
		}

		var conditions = {};
		for (var i = 0; i < opts.keys.length; i++) {
			conditions[opts.keys[i]] = ids[i];
		}

		opts.driver.count(opts.table, conditions, {}, function (err, data) {
			if (err || data.length === 0) {
				return cb(err);
			}
			return cb(null, data[0].c > 0);
		});
		return this;
	};

	model.create = function () {
		var Instances = [];
		var options = {};
		var cb = null, idx = 0, single = false;
		var createNext = function () {
			if (idx >= Instances.length) {
				return cb(null, single ? Instances[0] : Instances);
			}

			Instances[idx] = createInstance(Instances[idx], {
				is_new    : true,
				autoSave  : opts.autoSave,
				autoFetch : false
			});
			Instances[idx].save(function (err) {
				if (err) {
					err.index = idx;
					err.instance = Instances[idx];

					return cb(err);
				}

				idx += 1;
				createNext();
			});
		};

		for (var i = 0; i < arguments.length; i++) {
			switch (typeof arguments[i]) {
				case "object":
					if ( !single && Array.isArray(arguments[i]) ) {
						Instances = Instances.concat(arguments[i]);
					} else if (i == 0) {
						single = true;
						Instances.push(arguments[i]);
					} else {
						options = arguments[i];
					}
					break;
				case "function":
					cb = arguments[i];
					break;
			}
		}

		createNext();

		return this;
	};

	model.clear = function (cb) {
		opts.driver.clear(opts.table, function (err) {
			if (typeof cb == "function") cb(err);
		});

		return this;
	};

	Object.defineProperty(model, "table", {
		value: opts.table,
		enumerable: false
	});
	Object.defineProperty(model, "id", {
		value: opts.id,
		enumerable: false
	});
	Object.defineProperty(model, "keys", {
		value: opts.keys,
		enumerable: false
	});
	Object.defineProperty(model, "properties", {
		value: opts.properties,
		enumerable: false
	});

	OneAssociation.prepare(model, one_associations, association_properties, model_fields);
	ManyAssociation.prepare(model, many_associations);

	return model;
}
<commit_msg>Changes Model.get use of Singleton.get to create the UID similar to Model.find (#150)<commit_after>var Instance        = require("./Instance").Instance;
var Singleton       = require("./Singleton");
var OneAssociation  = require("./Associations/One");
var ManyAssociation = require("./Associations/Many");
var ChainFind       = require("./ChainFind");
var LazyLoad        = require("./LazyLoad");
var Utilities       = require("./Utilities");

exports.Model = Model;

function Model(opts) {
	opts = opts || {};

	if (!Array.isArray(opts.keys) || opts.keys.length < 2) {
		opts.keys = [ opts.id ];
	} else {
		opts.id = null;
	}

	var one_associations = [];
	var many_associations = [];
	var association_properties = [];
	var model_fields = [];

	for (var i = 0; i < opts.keys.length; i++) {
		model_fields.push(opts.keys[i]);
	}

	var createInstance = function (data, inst_opts, cb) {
		if (!inst_opts) {
			inst_opts = {};
		}
		var instance = new Instance({
			id                     : opts.id,
			keys                   : opts.keys,
			is_new                 : inst_opts.is_new || false,
			data                   : data,
			autoSave               : inst_opts.autoSave || false,
			extra                  : inst_opts.extra,
			extra_info             : inst_opts.extra_info,
			model                  : model,
			driver                 : opts.driver,
			table                  : opts.table,
			properties             : opts.properties,
			hooks                  : opts.hooks,
			methods                : opts.methods,
			validations            : opts.validations,
			association_properties : association_properties
		});
		if (model_fields !== null) {
			LazyLoad.extend(instance, model, opts.properties);
		}
		OneAssociation.extend(model, instance, opts.driver, one_associations, {
			autoFetch      : inst_opts.autoFetch || false,
			autoFetchLimit : inst_opts.autoFetchLimit,
			cascadeRemove  : inst_opts.cascadeRemove
		}, function () {
			ManyAssociation.extend(model, instance, opts.driver, many_associations, {
				autoFetch      : inst_opts.autoFetch || false,
				autoFetchLimit : inst_opts.autoFetchLimit,
				cascadeRemove  : inst_opts.cascadeRemove
			}, function () {
				if (typeof cb == "function") {
					return cb(instance);
				}
			});
		});
		return instance;
	};

	var model = function (data) {
		var instance;
		if (typeof data == "number") {
			var data2 = {};
			data2[opts.id] = data;

			return createInstance(data2);
		} else if (typeof data == "undefined") {
			data = {};
		}

		return createInstance(data, {
			is_new        : !data.hasOwnProperty(opts.id),
			autoSave      : opts.autoSave,
			cascadeRemove : opts.cascadeRemove
		});
	};

	for (var k in opts.properties) {
		if (opts.properties[k].lazyload !== true) {
			model_fields.push(k);
		}
	}

	model.settings = opts.settings;

	model.drop = function (cb) {
		if (arguments.length === 0) {
			cb = function () {};
		}
		if (typeof opts.driver.drop == "function") {
			opts.driver.drop({
				table             : opts.table,
				properties        : opts.properties,
				one_associations  : one_associations,
				many_associations : many_associations
			}, cb);

			return this;
		}

		return cb(new Error("Driver does not support Model.drop()"));
	};

	model.sync = function (cb) {
		if (arguments.length === 0) {
			cb = function () {};
		}
		if (typeof opts.driver.sync == "function") {
			opts.driver.sync({
				keys              : opts.keys,
				table             : opts.table,
				properties        : opts.properties,
				indexes           : opts.indexes || [],
				one_associations  : one_associations,
				many_associations : many_associations
			}, cb);

			return this;
		}

		return cb(new Error("Driver does not support Model.sync()"));
	};

	model.get = function () {
		var conditions = {};
		var options    = {};
		var ids        = Array.prototype.slice.apply(arguments);
		var cb         = ids.pop();

		if (typeof cb != "function") {
			throw new Error("Missing Model.get() callback");
		}

		if (typeof ids[ids.length - 1] == "object") {
			options = ids.pop();
		}

		if (ids.length == 1 && Array.isArray(ids[0])) {
			ids = ids[0];
		}

		if (ids.length != opts.keys.length) {
			throw new Error("Model.get() IDs number missmatch (" + opts.keys.length + " needed, " + ids.length + " passed)");
		}

		for (var i = 0; i < opts.keys.length; i++) {
			conditions[opts.keys[i]] = ids[i];
		}

		if (!options.hasOwnProperty("autoFetchLimit")) {
			options.autoFetchLimit = opts.autoFetchLimit;
		}
		if (!options.hasOwnProperty("cascadeRemove")) {
			options.cascadeRemove = opts.cascadeRemove;
		}

		opts.driver.find(model_fields, opts.table, conditions, { limit: 1 }, function (err, data) {
			if (err) {
				return cb(err);
			}
			if (data.length === 0) {
				return cb(new Error("Not found"));
			}
			Singleton.get(opts.driver.uid + "/" + opts.table + "/" + ids.join("/"), {
				cache      : options.cache || opts.cache,
				save_check : opts.settings.get("instance.cacheSaveCheck")
			}, function (cb) {
				return createInstance(data[0], {
					autoSave       : opts.autoSave,
					autoFetch      : (options.autoFetchLimit === 0 ? false : opts.autoFetch),
					autoFetchLimit : options.autoFetchLimit,
					cascadeRemove  : options.cascadeRemove
				}, cb);
			}, function (instance) {
				return cb(null, instance);
			});
		});

		return this;
	};

	model.find = function () {
		var options    = {};
		var conditions = null;
		var cb         = null;
		var order      = null;
		var merge      = null;

		for (var i = 0; i < arguments.length; i++) {
			switch (typeof arguments[i]) {
				case "number":
					options.limit = arguments[i];
					break;
				case "object":
					if (Array.isArray(arguments[i])) {
						if (arguments[i].length > 0) {
							order = arguments[i];
						}
					} else {
						if (conditions === null) {
							conditions = arguments[i];
						} else {
							if (options.hasOwnProperty("limit")) {
								arguments[i].limit = options.limit;
							}
							options = arguments[i];

							if (options.hasOwnProperty("__merge")) {
								merge = options.__merge;
								merge.select = Object.keys(options.extra);
								delete options.__merge;
							}
							if (options.hasOwnProperty("order")) {
								order = options.order;
								delete options.order;
							}
						}
					}
					break;
				case "function":
					cb = arguments[i];
					break;
				case "string":
					if (arguments[i][0] == "-") {
						order = [ arguments[i].substr(1), "Z" ];
					} else {
						order = [ arguments[i] ];
					}
					break;
			}
		}

		if (!options.hasOwnProperty("cache")) {
			options.cache = opts.cache;
		}
		if (!options.hasOwnProperty("autoFetchLimit")) {
			options.autoFetchLimit = opts.autoFetchLimit;
		}
		if (!options.hasOwnProperty("cascadeRemove")) {
			options.cascadeRemove = opts.cascadeRemove;
		}

		if (order) {
			order = Utilities.standardizeOrder(order);
		}

		var chain = new ChainFind(model, {
			only         : options.only || model_fields,
			id           : opts.id,
			table        : opts.table,
			driver       : opts.driver,
			conditions   : conditions,
			associations : many_associations,
			limit        : options.limit,
			order        : order,
			merge        : merge,
			offset       : options.offset,
			newInstance  : function (data, cb) {
				var uid = opts.driver.uid + "/" + opts.table + (merge ? "+" + merge.from.table : "");
				for (var i = 0; i < opts.keys.length; i++) {
					uid += "/" + data[opts.keys[i]];
				}

				Singleton.get(uid, {
					cache      : options.cache,
					save_check : opts.settings.get("instance.cacheSaveCheck")
				}, function (cb) {
					return createInstance(data, {
						autoSave       : opts.autoSave,
						autoFetch      : (options.autoFetchLimit === 0 ? false : (options.autoFetch || opts.autoFetch)),
						autoFetchLimit : options.autoFetchLimit,
						cascadeRemove  : options.cascadeRemove,
						extra          : options.extra,
						extra_info     : options.extra_info
					}, cb);
				}, function (instance) {
					return cb(null, instance);
				});
			}
		});
		if (cb === null) {
			return chain;
		}

		chain.run(cb);

		return this;
	};

	model.all = model.find;

	model.one = function () {
		var args = Array.prototype.slice.apply(arguments);
		var cb   = null;

		// extract callback
		for (var i = 0; i < args.length; i++) {
			if (typeof args[i] == "function") {
				cb = args.splice(i, 1)[0];
				break;
			}
		}

		if (cb === null) {
			throw new Error("Model.one() called without callback");
		}

		// add limit 1
		args.push(1);
		args.push(function (err, results) {
			if (err) {
				return cb(err);
			}
			return cb(null, results.length ? results[0] : null);
		});

		return this.find.apply(this, args);
	};

	model.count = function () {
		var conditions = null;
		var cb         = null;

		for (var i = 0; i < arguments.length; i++) {
			switch (typeof arguments[i]) {
				case "object":
					conditions = arguments[i];
					break;
				case "function":
					cb = arguments[i];
					break;
			}
		}

		if (typeof cb != "function") {
			throw new Error("Missing Model.count() callback");
		}

		opts.driver.count(opts.table, conditions, {}, function (err, data) {
			if (err || data.length === 0) {
				return cb(err);
			}
			return cb(null, data[0].c);
		});
		return this;
	};

	model.aggregate = function () {
		var conditions = {};
		var properties = [];

		for (var i = 0; i < arguments.length; i++) {
			if (typeof arguments[i] == "object") {
				if (Array.isArray(arguments[i])) {
					properties = arguments[i];
				} else {
					conditions = arguments[i];
				}
			}
		}

		return new require("./AggregateFunctions")({
			table       : opts.table,
			driver_name : opts.driver_name,
			driver      : opts.driver,
			conditions  : conditions,
			properties  : properties
		});
	};

	model.exists = function () {
		var ids = Array.prototype.slice.apply(arguments);
		var cb  = ids.pop();

		if (typeof cb != "function") {
			throw new Error("Missing Model.exists() callback");
		}

		var conditions = {};
		for (var i = 0; i < opts.keys.length; i++) {
			conditions[opts.keys[i]] = ids[i];
		}

		opts.driver.count(opts.table, conditions, {}, function (err, data) {
			if (err || data.length === 0) {
				return cb(err);
			}
			return cb(null, data[0].c > 0);
		});
		return this;
	};

	model.create = function () {
		var Instances = [];
		var options = {};
		var cb = null, idx = 0, single = false;
		var createNext = function () {
			if (idx >= Instances.length) {
				return cb(null, single ? Instances[0] : Instances);
			}

			Instances[idx] = createInstance(Instances[idx], {
				is_new    : true,
				autoSave  : opts.autoSave,
				autoFetch : false
			});
			Instances[idx].save(function (err) {
				if (err) {
					err.index = idx;
					err.instance = Instances[idx];

					return cb(err);
				}

				idx += 1;
				createNext();
			});
		};

		for (var i = 0; i < arguments.length; i++) {
			switch (typeof arguments[i]) {
				case "object":
					if ( !single && Array.isArray(arguments[i]) ) {
						Instances = Instances.concat(arguments[i]);
					} else if (i == 0) {
						single = true;
						Instances.push(arguments[i]);
					} else {
						options = arguments[i];
					}
					break;
				case "function":
					cb = arguments[i];
					break;
			}
		}

		createNext();

		return this;
	};

	model.clear = function (cb) {
		opts.driver.clear(opts.table, function (err) {
			if (typeof cb == "function") cb(err);
		});

		return this;
	};

	Object.defineProperty(model, "table", {
		value: opts.table,
		enumerable: false
	});
	Object.defineProperty(model, "id", {
		value: opts.id,
		enumerable: false
	});
	Object.defineProperty(model, "keys", {
		value: opts.keys,
		enumerable: false
	});
	Object.defineProperty(model, "properties", {
		value: opts.properties,
		enumerable: false
	});

	OneAssociation.prepare(model, one_associations, association_properties, model_fields);
	ManyAssociation.prepare(model, many_associations);

	return model;
}
<|endoftext|>


<commit_before>const request = require('./request')

module.exports = requestPromise

function requestPromise(opts) {
  return new Promise(function(resolve, reject) {
    request(opts, function(err, response, body) {
      if (err) {
        reject(err)
      } else if (response.statusCode >= 400) {
        err = new Error('Status code ' + response.statusCode)
        err.response = response
        err.body = body
        reject(err)
      } else {
        resolve(body)
      }
    })
  })
}
<commit_msg>Allow the same behavior with promise as without<commit_after>const request = require('./request')

module.exports = requestPromise

function requestPromise(opts) {
  return new Promise(function (resolve, reject) {
    request(opts, function (err, response, body) {
      if (err) {
        reject(err)
      } else if (response.statusCode >= 400) {
        err = new Error('Status code ' + response.statusCode)
        err.response = response
        err.body = body
        reject(err)
      } else {
        var result = {
          body: body,
          response: response
        };
        resolve(result);
      }
    })
  })
}
<|endoftext|>