<commit_before>var require = {
    baseUrl: "./",
    paths: {
        "text": "lib/requirejs-text/text",
        "Fayde": "lib/fayde/Fayde",
        "Utils": "lib/fayde.utils/Fayde.Utils",
        "Tone": "lib/Tone.js/Tone",
        "Tween": "lib/tween.ts/build/tween.min"
    },
    deps: [
        "text",
        "Fayde",
        "Utils",
        "Tone/core/Tone",
        "Tone/core/Master",
        "Tone/source/Oscillator",
        "Tone/component/LFO",
        "Tone/effect/PingPongDelay",
        "Tween"
    ],
    callback: function (
        text,
        Fayde,
        Utils,
        Tone,
        Master,
        Oscillator,
        LFO,
        PingPonDelay,
        Tween
        ) {
        window.Tone = Tone;

        Fayde.LoadConfigJson(function (config, err) {
            if (err)
                console.warn('Could not load fayde configuration file.', err);
            Fayde.Run();
        });
    },
    shim: {
        "Fayde": {
            exports: "Fayde",
            deps: ["text"]
        },
        "Utils": {
            deps: ["Fayde"]
        }
    }
};<commit_msg>spelling error<commit_after>var require = {
    baseUrl: "./",
    paths: {
        "text": "lib/requirejs-text/text",
        "Fayde": "lib/fayde/Fayde",
        "Utils": "lib/fayde.utils/Fayde.Utils",
        "Tone": "lib/Tone.js/Tone",
        "Tween": "lib/tween.ts/build/tween.min"
    },
    deps: [
        "text",
        "Fayde",
        "Utils",
        "Tone/core/Tone",
        "Tone/core/Master",
        "Tone/source/Oscillator",
        "Tone/component/LFO",
        "Tone/effect/PingPongDelay",
        "Tween"
    ],
    callback: function (
        text,
        Fayde,
        Utils,
        Tone,
        Master,
        Oscillator,
        LFO,
        PingPongDelay,
        Tween
        ) {
        window.Tone = Tone;

        Fayde.LoadConfigJson(function (config, err) {
            if (err)
                console.warn('Could not load fayde configuration file.', err);
            Fayde.Run();
        });
    },
    shim: {
        "Fayde": {
            exports: "Fayde",
            deps: ["text"]
        },
        "Utils": {
            deps: ["Fayde"]
        }
    }
};<|endoftext|>


<commit_before>function Cube (element_id) {
	var _DOM = document.getElementById(element_id);
	this.DOM = _DOM;

	var sides = ['front','top','bottom','back','left','right'];

	for (i in sides) {this[sides[i]]=['z','-y','y','-z','-x','x'][i]}

	return this;
}

var cube = new Cube('cube3d') // main cube object	<commit_msg>add fill method. which fill DOM cube sides with appropriate values<commit_after>function Cube (element_id) {
	var DOM = document.getElementById(element_id);
	this.DOM = DOM;

	var sides = ['front','top','bottom','back','left','right'];

	for (i in sides) {this[sides[i]]=['z','-y','y','-z','-x','x'][i]}

	function fill () { // fill DOM cube sides with appropriate values
		for (i in sides) {
			var element = document.getElementById(sides[i]);
			var value = this[sides[i]];
			element.innerHTML=value;
		}
	}
	this.fill = fill;

	return this;
}

var cube = new Cube('cube3d') // main cube object
cube.fill();<|endoftext|>


<commit_before>define([
    'require',
    'domReady!',
    './lib/jquery',
//    './jqueryPlugin!./lib/dist/history.js/scripts/bundled/html4+html5/jquery.history',
    './lib/modernizr',
    './core/init',
    './core/parser',
    './core/store',
    './patterns',
    './patterns/change',
    './patterns/fancybox',
    './patterns/floatingpanel',
    './patterns/fullcalendar',
    './patterns/old_modal',
    './patterns/selfhealing',
    './patterns/setclass',
    './patterns/toggle',
    './patterns/tooltip'
], function(require) {
    var mapal = require('./core/init');
    mapal.registerWidthClass("narrow", 0, 780);
    mapal.registerWidthClass("medium", 0, 1109);
    mapal.registerWidthClass("wide", 1110, null);

    mapal.store = require('./core/store');

    // register our patterns
    // rethink naming once all patterns are migrated to this style
    mapal.passivePatterns.change = require('./patterns/change');
    mapal.passivePatterns.fullcalendar = require('./patterns/fullcalendar');
    mapal.passivePatterns.toggle = require('./patterns/toggle');
    mapal.passivePatterns.tooltip = require('./patterns/tooltip');

    // Register as active pattern to prevent errors on clicks.
    // XXX: hack, what does this do?
    mapal.patterns.tooltip = { execute: function() {} };
    mapal.patterns.fancybox = require('./patterns/fancybox');
    mapal.patterns.floatingPanelContextual = require('./patterns/floatingpanel');
    mapal.patterns.modal = require('./patterns/old_modal');
    mapal.patterns.selfHealing = require('./patterns/selfhealing');
    mapal.patterns.setclass = require('./patterns/setclass');

    // new-style patterns
    mapal.newstyle = require('./patterns');

    $(document).on('inject.patterns.scan', function(ev, opts) {
        mapal.initContent(ev.target, opts);
    });

    // wait for the DOM to be ready and initialize
    var doc = require('domReady!');
    mapal.init();
    mapal.initContent(doc.body);
    $(doc).trigger("setupFinished", doc);
});
<commit_msg>non-blocking init on dom Ready!<commit_after>define([
    'require',
    'domReady!',
    './lib/jquery',
//    './jqueryPlugin!./lib/dist/history.js/scripts/bundled/html4+html5/jquery.history',
    './lib/modernizr',
    './core/init',
    './core/parser',
    './core/store',
    './patterns',
    './patterns/change',
    './patterns/fancybox',
    './patterns/floatingpanel',
    './patterns/fullcalendar',
    './patterns/old_modal',
    './patterns/selfhealing',
    './patterns/setclass',
    './patterns/toggle',
    './patterns/tooltip'
], function(require) {
    var mapal = require('./core/init');
    mapal.registerWidthClass("narrow", 0, 780);
    mapal.registerWidthClass("medium", 0, 1109);
    mapal.registerWidthClass("wide", 1110, null);

    mapal.store = require('./core/store');

    // register our patterns
    // rethink naming once all patterns are migrated to this style
    mapal.passivePatterns.change = require('./patterns/change');
    mapal.passivePatterns.fullcalendar = require('./patterns/fullcalendar');
    mapal.passivePatterns.toggle = require('./patterns/toggle');
    mapal.passivePatterns.tooltip = require('./patterns/tooltip');

    // Register as active pattern to prevent errors on clicks.
    // XXX: hack, what does this do?
    mapal.patterns.tooltip = { execute: function() {} };
    mapal.patterns.fancybox = require('./patterns/fancybox');
    mapal.patterns.floatingPanelContextual = require('./patterns/floatingpanel');
    mapal.patterns.modal = require('./patterns/old_modal');
    mapal.patterns.selfHealing = require('./patterns/selfhealing');
    mapal.patterns.setclass = require('./patterns/setclass');

    // new-style patterns
    mapal.newstyle = require('./patterns');

    $(document).on('inject.patterns.scan', function(ev, opts) {
        mapal.initContent(ev.target, opts);
    });

    // wait for the DOM to be ready and initialize
    $(document).ready(function(){
        mapal.init();
        mapal.initContent(document.body);
    });
    $(document).trigger("setupFinished", document);
});
<|endoftext|>


<commit_before>/**
	_enyo.Async_ is the base kind for handling asynchronous operations.

	_enyo.Async_ is an **Object**, not a **Component**; thus, you may not declare
	an _Async_ in a _components_ block. If you want to use _Async_ as a
	component, you should probably be using
	enyo.WebService instead.

	An Async object represents a task that has not yet completed. You may attach
	callback functions to an Async, to be called when the task completes or
	encounters an error.

	More information on _Async_ and its usage is available in the
	Async documentation
	in the Enyo Developer Guide.

*/
enyo.kind({
	name: "enyo.Async",
	kind: enyo.Object,
	//* @protected
	failed: false,
	context: null,
	constructor: function() {
		this.responders = [];
		this.errorHandlers = [];
	},
	accumulate: function(inArray, inMethodArgs) {
		var fn = (inMethodArgs.length < 2) ? inMethodArgs[0] : enyo.bind(inMethodArgs[0], inMethodArgs[1]);
		inArray.push(fn);
	},
	//* @public
	/**
		Registers a response function.
		First parameter is an optional this context for the response method.
		Second (or only) parameter is the function object.
	*/
	response: function(/* [inContext], inResponder */) {
		this.accumulate(this.responders, arguments);
		return this;
	},
	/**
		Registers an error handler.
		First parameter is an optional this context for the response method.
		Second (or only) parameter is the function object.
	*/
	error: function(/* [inContext], inResponder */) {
		this.accumulate(this.errorHandlers, arguments);
		return this;
	},
	//* @protected
	route: function(inAsync, inValue) {
		var r = enyo.bind(this, "respond");
		inAsync.response(function(inSender, inValue) {
			r(inValue);
		});
		var f = enyo.bind(this, "fail");
		inAsync.error(function(inSender, inValue) {
			f(inValue);
		});
		inAsync.go(inValue);
	},
	handle: function(inValue, inHandlers) {
		var r = inHandlers.shift();
		if (r) {
			if (r instanceof enyo.Async) {
				this.route(r, inValue);
			} else {
				// handler can return a new 'value'
				var v = enyo.call(this.context || this, r, [this, inValue]);
				// ... but only if it returns something other than undefined
				v = (v !== undefined) ? v : inValue;
				// next handler
				(this.failed ? this.fail : this.respond).call(this, v);
			}
		}
	},
	startTimer: function() {
		this.startTime = enyo.now();
		if (this.timeout) {
			this.timeoutJob = setTimeout(enyo.bind(this, "timeoutComplete"), this.timeout);
		}
	},
	endTimer: function() {
		if (this.timeoutJob) {
			this.endTime = enyo.now();
			clearTimeout(this.timeoutJob);
			this.timeoutJob = null;
			this.latency = this.endTime - this.startTime;
		}
	},
	timeoutComplete: function() {
		this.timedout = true;
		this.fail("timeout");
	},
	//* @protected
	//* Called as part of the async implementation, triggers the handler chain.
	respond: function(inValue) {
		this.failed = false;
		this.endTimer();
		this.handle(inValue, this.responders);
	},
	//* @public
	//* Can be called from any handler to trigger the error chain.
	fail: function(inError) {
		this.failed = true;
		this.endTimer();
		this.handle(inError, this.errorHandlers);
	},
	//* Called from an error handler, this method clears the error
	// condition and resumes calling handler methods.
	recover: function() {
		this.failed = false;
	},
	//* Starts the async activity. Overridden in subkinds.
	go: function(inValue) {
		enyo.asyncMethod(this, function() {
			this.respond(inValue);
		});
		return this;
	}
});
<commit_msg>ENYO-811: document timeout property of enyo.Async.js<commit_after>/**
	_enyo.Async_ is the base kind for handling asynchronous operations.

	_enyo.Async_ is an **Object**, not a **Component**; thus, you may not declare
	an _Async_ in a _components_ block. If you want to use _Async_ as a
	component, you should probably be using
	enyo.WebService instead.

	An Async object represents a task that has not yet completed. You may attach
	callback functions to an Async, to be called when the task completes or
	encounters an error.

	More information on _Async_ and its usage is available in the
	Async documentation
	in the Enyo Developer Guide.
*/
enyo.kind({
	name: "enyo.Async",
	kind: enyo.Object,
	published: {
		/**
			if set to a non-0 value, this is the number of milliseconds to
			wait after the _go_ call before failing with the "timeout" error.
		*/
		timeout: 0
	},
	//* @protected
	failed: false,
	context: null,
	constructor: function() {
		this.responders = [];
		this.errorHandlers = [];
	},
	accumulate: function(inArray, inMethodArgs) {
		var fn = (inMethodArgs.length < 2) ? inMethodArgs[0] : enyo.bind(inMethodArgs[0], inMethodArgs[1]);
		inArray.push(fn);
	},
	//* @public
	/**
		Registers a response function.
		First parameter is an optional this context for the response method.
		Second (or only) parameter is the function object.
	*/
	response: function(/* [inContext], inResponder */) {
		this.accumulate(this.responders, arguments);
		return this;
	},
	/**
		Registers an error handler.
		First parameter is an optional this context for the response method.
		Second (or only) parameter is the function object.
	*/
	error: function(/* [inContext], inResponder */) {
		this.accumulate(this.errorHandlers, arguments);
		return this;
	},
	//* @protected
	route: function(inAsync, inValue) {
		var r = enyo.bind(this, "respond");
		inAsync.response(function(inSender, inValue) {
			r(inValue);
		});
		var f = enyo.bind(this, "fail");
		inAsync.error(function(inSender, inValue) {
			f(inValue);
		});
		inAsync.go(inValue);
	},
	handle: function(inValue, inHandlers) {
		var r = inHandlers.shift();
		if (r) {
			if (r instanceof enyo.Async) {
				this.route(r, inValue);
			} else {
				// handler can return a new 'value'
				var v = enyo.call(this.context || this, r, [this, inValue]);
				// ... but only if it returns something other than undefined
				v = (v !== undefined) ? v : inValue;
				// next handler
				(this.failed ? this.fail : this.respond).call(this, v);
			}
		}
	},
	startTimer: function() {
		this.startTime = enyo.now();
		if (this.timeout) {
			this.timeoutJob = setTimeout(enyo.bind(this, "timeoutComplete"), this.timeout);
		}
	},
	endTimer: function() {
		if (this.timeoutJob) {
			this.endTime = enyo.now();
			clearTimeout(this.timeoutJob);
			this.timeoutJob = null;
			this.latency = this.endTime - this.startTime;
		}
	},
	timeoutComplete: function() {
		this.timedout = true;
		this.fail("timeout");
	},
	//* @protected
	//* Called as part of the async implementation, triggers the handler chain.
	respond: function(inValue) {
		this.failed = false;
		this.endTimer();
		this.handle(inValue, this.responders);
	},
	//* @public
	//* Can be called from any handler to trigger the error chain.
	fail: function(inError) {
		this.failed = true;
		this.endTimer();
		this.handle(inError, this.errorHandlers);
	},
	//* Called from an error handler, this method clears the error
	// condition and resumes calling handler methods.
	recover: function() {
		this.failed = false;
	},
	//* Starts the async activity. Overridden in subkinds.
	go: function(inValue) {
		enyo.asyncMethod(this, function() {
			this.respond(inValue);
		});
		return this;
	}
});
<|endoftext|>


<commit_before>openerp.pos_multi_session = function(instance){
    var module = instance.point_of_sale;
    var _t = instance.web._t;

    module.OrderWidget.include({
        rerender_orderline: function(order_line){
            if (order_line.node)
                return this._super(order_line);
        }
    })
    module.ReceiptScreenWidget = module.ReceiptScreenWidget.extend({
        finishOrder: function() {
            this.pos.get('selectedOrder').destroy({'reason': 'finishOrder'});
        }
    })

    var PosModelSuper = module.PosModel;
    module.PosModel = module.PosModel.extend({
        initialize: function(){
            var self = this;
            PosModelSuper.prototype.initialize.apply(this, arguments)
            this.multi_session = false;
            this.ready = this.ready.then(function(){
                             if (self.config.multi_session_id){
                                 self.multi_session = new module.MultiSession(self);
                                 self.multi_session.start();
                                 self.multi_session.request_sync_all();
                             }
                         });
            this.ms_syncing_in_progress = false;
            this.get('orders').bind('remove', function(order,_unused_,options){
                order.ms_remove_order();
            });
            this.get('orders').bind('add', function(order,_unused_,options){
                if (!self.ms_syncing_in_progress && self.multi_session){
                    self.multi_session.sync_sequence_number();
                }
            });

        },
        ms_my_info: function(){
            return {
                'user': {
                    'id': this.pos_session.user_id[0],
                    'name': this.pos_session.user_id[1],
                },
                'pos': {
                    'id': this.config.id,
                    'name': this.config.name,
                }
            }
        },
        on_removed_order: function(removed_order,index,reason){
            if (this.multi_session){
                if (reason === 'finishOrder'){
                    if (this.get('orders').size() > 0){
                        return this.set({'selectedOrder' : this.get('orders').at(index) || this.get('orders').first()});
                    }
                    this.add_new_order();
                    this.get('selectedOrder').ms_replace_empty_order = true;
                    return;
                } else if (this.ms_syncing_in_progress){
                    if (this.get('orders').size() == 0){
                        this.add_new_order();
                    }
                    return;
                }
            }
            var self = this;
            return PosModelSuper.prototype.on_removed_order.apply(this, arguments)
        },

        ms_on_update: function(message){
            this.ms_syncing_in_progress = true; // don't broadcast updates made from this message
            var error = false;
            try{
                console.log('on_update', message)
                var action = message.action;
                var data = message.data || {}
                var order = false;
                if (data.uid){
                    order = this.get('orders').find(function(order){
                                return order.uid == data.uid;
                            })
                }
                if (order && action == 'remove_order'){
                    order.destroy({'reason': 'abandon'})
                } else if (action == 'update') {
                    this.ms_do_update(order, data);
                }
            }catch(err){
                error = err;
                console.error(err);
            }
            this.ms_syncing_in_progress = false;
            if (error){
                throw(error)
            }

            if (action == 'sync_sequence_number'){
                this.ms_do_sync_sequence_number(data);
            } else if (action == 'request_sync_all'){
                //don't executing sync_sequence_number, because new POS sync sequence_number on start, because new order is created automatically
                //this.multi_session.sync_sequence_number();
                this.get('orders').each(function(r){
                    if (!r.is_empty()){
                        r.ms_update();
                    }
                })
            }
        },
        ms_on_add_order: function(current_order){
            if (current_order && current_order.ms_replace_empty_order && current_order.is_empty()){
                //replace order
                current_order.destroy({'reason': 'abandon'})
            }else{
                // keep current_order active
                this.set('selectedOrder', current_order);
            }
        },
        ms_create_order: function(options){
            options = _.extend({pos: this}, options || {});
            return new module.Order(options);
        },
        ms_do_sync_sequence_number: function(data){
            if (data.sequence_number < this.pos_session.sequence_number){
                // another pos has obsolete sequence_number
                this.multi_session.sync_sequence_number(this.pos_session.sequence_number);
            } else {
                // update sequence_number (value for next number)
                this.pos_session.sequence_number = data.sequence_number;
            }
            /*
            this.get('orders').each(function(r){
                var sn = data[r.uid];
                if (sn != r.sequence_number){
                    r.sequence_number = sn;
                }
            })
             */
        },
        ms_do_update: function(order, data){
            var pos = this;
            var sequence_number = data.sequence_number;
            if (!order){
                var create_new_order = pos.config.multi_session_accept_incoming_orders || !(data.ms_info && data.ms_info.created.user.id != pos.ms_my_info().user.id)
                if (sequence_number == this.pos_session.sequence_number){
                    //ok
                } else if (sequence_number > this.pos_session.sequence_number){
                    // this pos has obsolete sequence_number
                    this.pos_session.sequence_number = sequence_number;
                } else if (sequence_number < this.pos_session.sequence_number){
                    // another pos has obsolete sequence_number
                    pos.multi_session.sync_sequence_number();
                    if (create_new_order)
                        this.pos_session.sequence_number--; // decrease temporarily, because it is increased right after creating new order
                }
                if (!create_new_order){
                    return;
                }
                order = this.ms_create_order({ms_info:data.ms_info})
                order.uid = data.uid;
                order.sequence_number = data.sequence_number
                var current_order = this.get_order();
                this.get('orders').add(order);
                this.ms_on_add_order(current_order);
            } else {
                order.ms_info = data.ms_info;
            }
            var not_found = order.get('orderLines').map(function(r){
                                return r.uid;
                            })
            _.each(data.lines, function(dline){
                dline = dline[2];
                var line = order.get('orderLines').find(function(r){
                    return dline.uid == r.uid
                })
                not_found = _.without(not_found, dline.uid);
                var product = pos.db.get_product_by_id(dline.product_id);
                if (!line){
                    line = new module.Orderline({}, {pos: pos, order: order, product: product});
                    line.uid = dline.uid
                }
                line.ms_info = dline.ms_info || {}
                if(dline.qty !== undefined){
                    line.set_quantity(dline.qty);
                }
                if(dline.price_unit !== undefined){
                    line.set_unit_price(dline.price_unit);
                }
                if(dline.discount !== undefined){
                    line.set_discount(dline.discount);
                }
                order.get('orderLines').add(line)
            })

            _.each(not_found, function(uid){
                var line = order.get('orderLines').find(function(r){
                               return uid == r.uid;
                           })
                order.get('orderLines').remove(line);
            })

        }
    })

    var is_first_order = true;
    var OrderSuper = module.Order;
    module.Order = module.Order.extend({
        initialize: function(options){
            var self = this;
            options = options || {}
            OrderSuper.prototype.initialize.apply(this, arguments);
            this.ms_info = {}
            if (!_.isEmpty(options.ms_info)){
                this.ms_info = options.ms_info;
            } else if (this.pos.multi_session){
                this.ms_info['created'] = this.pos.ms_my_info();
            }
            this.ms_replace_empty_order = is_first_order;
            is_first_order = false;
            this.bind('change:sync', function(){
                self.ms_update();
            })
        },
        removeOrderline: function(line){
            OrderSuper.prototype.removeOrderline.apply(this, arguments);
            line.order.trigger('change:sync');
        },
        addProduct: function(){
            OrderSuper.prototype.addProduct.apply(this, arguments);
            this.trigger('change:sync')
        },
        ms_check: function(){
            if (! this.pos.multi_session )
                return;
            if (this.pos.ms_syncing_in_progress)
                return;
            return true;
        },
        ms_update: function(){
            var self = this;
            if (!this.ms_check())
                return;
            if (this.ms_update_timeout)
                // restart timeout
                clearTimeout(this.ms_update_timeout)
            this.ms_update_timeout = setTimeout(
                function(){
                    self.ms_update_timeout = false;
                    self.do_ms_update();
                }, 300)
        },
        ms_remove_order: function(){
            if (!this.ms_check())
                return;
            this.do_ms_remove_order();
        },
        do_ms_remove_order: function(){
            this.pos.multi_session.remove_order({'uid': this.uid});
        },
        export_as_JSON: function(){
            var data = OrderSuper.prototype.export_as_JSON.apply(this, arguments);
            data.ms_info = this.ms_info;
            return data;
        },
        do_ms_update: function(){
            var data = this.export_as_JSON();
            this.pos.multi_session.update(data);
        }
    })
    var OrderlineSuper = module.Orderline;
    module.Orderline = module.Orderline.extend({
        initialize: function(){
            var self = this;
            OrderlineSuper.prototype.initialize.apply(this, arguments);
            this.ms_info = {}
            if (this.order.ms_check()){
                this.ms_info['created'] = this.order.pos.ms_my_info();
            }
            this.bind('change', function(line){
                if (self.order.ms_check() && !line.ms_changing_selected){
                    line.ms_info['changed'] = line.order.pos.ms_my_info();
                    line.order.ms_info['changed'] = line.order.pos.ms_my_info();
                    var order_lines = line.order.get('orderLines');
                    order_lines.trigger('change', order_lines); // to rerender line
                    line.order.trigger('change:sync')
                }
            })
            this.uid = this.order.generateUniqueId() + '-' + this.id;
        },
        set_selected: function(){
            this.ms_changing_selected = true;
            OrderlineSuper.prototype.set_selected.apply(this, arguments);
            this.ms_changing_selected = false;
        },
        export_as_JSON: function(){
            var data = OrderlineSuper.prototype.export_as_JSON.apply(this, arguments);
            data.uid = this.uid;
            data.ms_info = this.ms_info;
            return data;
        }
    })

    module.MultiSession = Backbone.Model.extend({
        initialize: function(pos){
            this.pos = pos;
        },
        start: function(){
            var self = this;
            //var  done = new $.Deferred();

            this.bus = instance.bus.bus;
            this.bus.last = this.pos.db.load('bus_last', 0);
            this.bus.on("notification", this, this.on_notification);
            this.bus.start_polling();

            //return done;
        },
        request_sync_all: function(){
            this.send({'action': 'request_sync_all'})
        },
        sync_sequence_number: function(){
            var orders = {};
            this.pos.get('orders').each(function(r){
                orders[r.uid] = r.sequence_number;
            })
            var data = {
                'sequence_number': this.pos.pos_session.sequence_number,
                //'orders': orders,
            }
            this.send({action: 'sync_sequence_number', data: data})
        },
        remove_order: function(data){
            this.send({action: 'remove_order', data: data})
        },
        update: function(data){
            this.send({action: 'update', data: data})
        },
        send: function(message){
            console.log('send', message)
           var self = this;
            var send_it = function() {
                return openerp.session.rpc("/pos_multi_session/update", {multi_session_id: self.pos.config.multi_session_id[0], message: message});
            };
            var tries = 0;
            send_it().fail(function(error, e) {
                e.preventDefault();
                tries += 1;
                if (tries < 3)
                    return send_it();
            });
        },
        on_notification: function(notification) {
            var self = this;
            if (typeof notification[0][0] === 'string') {
                notification = [notification]
            }
            for (var i = 0; i < notification.length; i++) {
                var channel = notification[i][0];
                var message = notification[i][1];
                this.on_notification_do(channel, message);
            }
        },
        on_notification_do: function (channel, message) {
            if(Array.isArray(channel) && channel[1] === 'pos.multi_session'){
                try{
                    this.pos.ms_on_update(message)
                }catch(err){
                    this.pos.pos_widget.screen_selector.show_popup('error',{
                        message: _t('Error'),
                        comment: err,
                    })
                }
            }
            this.pos.db.save('bus_last', this.bus.last)
        }
    })
}<commit_msg>Fix ms_info and al order now saved when refresh page<commit_after>openerp.pos_multi_session = function(instance){
    var module = instance.point_of_sale;
    var _t = instance.web._t;

    module.OrderWidget.include({
        rerender_orderline: function(order_line){
            if (order_line.node)
                return this._super(order_line);
        }
    })
    module.ReceiptScreenWidget = module.ReceiptScreenWidget.extend({
        finishOrder: function() {
            this.pos.get('selectedOrder').destroy({'reason': 'finishOrder'});
        }
    })

    var PosModelSuper = module.PosModel;
    module.PosModel = module.PosModel.extend({
        initialize: function(){
            var self = this;
            PosModelSuper.prototype.initialize.apply(this, arguments)
            this.multi_session = false;
            this.ready = this.ready.then(function(){
                             if (self.config.multi_session_id){
                                 self.multi_session = new module.MultiSession(self);
                                 self.multi_session.start();
                                 self.multi_session.request_sync_all();
                             }
                         });
            this.ms_syncing_in_progress = false;
            this.get('orders').bind('remove', function(order,_unused_,options){
                order.ms_remove_order();
            });
            this.get('orders').bind('add', function(order,_unused_,options){
                if (!self.ms_syncing_in_progress && self.multi_session){
                    self.multi_session.sync_sequence_number();
                }
            });

        },
        ms_my_info: function(){
            return {
                'user': {
                    'id': this.pos_session.user_id[0],
                    'name': this.pos_session.user_id[1],
                },
                'pos': {
                    'id': this.config.id,
                    'name': this.config.name,
                }
            }
        },
        on_removed_order: function(removed_order,index,reason){
            if (this.multi_session){
                if (reason === 'finishOrder'){
                    if (this.get('orders').size() > 0){
                        return this.set({'selectedOrder' : this.get('orders').at(index) || this.get('orders').first()});
                    }
                    this.add_new_order();
                    this.get('selectedOrder').ms_replace_empty_order = true;
                    return;
                } else if (this.ms_syncing_in_progress){
                    if (this.get('orders').size() == 0){
                        this.add_new_order();
                    }
                    return;
                }
            }
            var self = this;
            return PosModelSuper.prototype.on_removed_order.apply(this, arguments)
        },

        ms_on_update: function(message){
            this.ms_syncing_in_progress = true; // don't broadcast updates made from this message
            var error = false;
            try{
                console.log('on_update', message)
                var action = message.action;
                var data = message.data || {}
                var order = false;
                if (data.uid){
                    order = this.get('orders').find(function(order){
                                return order.uid == data.uid;
                            })
                }
                if (order && action == 'remove_order'){
                    order.destroy({'reason': 'abandon'})
                } else if (action == 'update') {
                    this.ms_do_update(order, data);
                }
            }catch(err){
                error = err;
                console.error(err);
            }
            this.ms_syncing_in_progress = false;
            if (error){
                throw(error)
            }

            if (action == 'sync_sequence_number'){
                this.ms_do_sync_sequence_number(data);
            } else if (action == 'request_sync_all'){
                //don't executing sync_sequence_number, because new POS sync sequence_number on start, because new order is created automatically
                //this.multi_session.sync_sequence_number();
                this.get('orders').each(function(r){
                    if (!r.is_empty()){
                        r.ms_update();
                    }
                })
            }
        },
        ms_on_add_order: function(current_order){
            if (current_order && current_order.ms_replace_empty_order && current_order.is_empty()){
                //replace order
                current_order.destroy({'reason': 'abandon'})
            }else{
                // keep current_order active
                this.set('selectedOrder', current_order);
            }
        },
        ms_create_order: function(options){
            options = _.extend({pos: this}, options || {});
            return new module.Order(options);
        },
        ms_do_sync_sequence_number: function(data){
            if (data.sequence_number < this.pos_session.sequence_number){
                // another pos has obsolete sequence_number
                this.multi_session.sync_sequence_number(this.pos_session.sequence_number);
            } else {
                // update sequence_number (value for next number)
                this.pos_session.sequence_number = data.sequence_number;
            }
            /*
            this.get('orders').each(function(r){
                var sn = data[r.uid];
                if (sn != r.sequence_number){
                    r.sequence_number = sn;
                }
            })
             */
        },
        ms_do_update: function(order, data){
            var pos = this;
            var sequence_number = data.sequence_number;
            if (!order){
                var create_new_order = pos.config.multi_session_accept_incoming_orders || !(data.ms_info && data.ms_info.created.user.id != pos.ms_my_info().user.id)
                if (sequence_number == this.pos_session.sequence_number){
                    //ok
                } else if (sequence_number > this.pos_session.sequence_number){
                    // this pos has obsolete sequence_number
                    this.pos_session.sequence_number = sequence_number;
                } else if (sequence_number < this.pos_session.sequence_number){
                    // another pos has obsolete sequence_number
                    pos.multi_session.sync_sequence_number();
                    if (create_new_order)
                        this.pos_session.sequence_number--; // decrease temporarily, because it is increased right after creating new order
                }
                if (!create_new_order){
                    return;
                }
                order = this.ms_create_order({ms_info:data.ms_info})
                order.uid = data.uid;
                order.sequence_number = data.sequence_number
                var current_order = this.get_order();
                this.get('orders').add(order);
                this.ms_on_add_order(current_order);
            } else {
                order.ms_info = data.ms_info;
            }
            var not_found = order.get('orderLines').map(function(r){
                                return r.uid;
                            })
            _.each(data.lines, function(dline){
                dline = dline[2];
                var line = order.get('orderLines').find(function(r){
                    return dline.uid == r.uid
                })
                not_found = _.without(not_found, dline.uid);
                var product = pos.db.get_product_by_id(dline.product_id);
                if (!line){
                    line = new module.Orderline({}, {pos: pos, order: order, product: product});
                    line.uid = dline.uid
                }
                line.ms_info = dline.ms_info || {}
                if(dline.qty !== undefined){
                    line.set_quantity(dline.qty);
                }
                if(dline.price_unit !== undefined){
                    line.set_unit_price(dline.price_unit);
                }
                if(dline.discount !== undefined){
                    line.set_discount(dline.discount);
                }
                order.get('orderLines').add(line)
            })

            _.each(not_found, function(uid){
                var line = order.get('orderLines').find(function(r){
                               return uid == r.uid;
                           })
                order.get('orderLines').remove(line);
            })

        },
        load_server_data: function(){
            res = PosModelSuper.prototype.load_server_data.apply(this, arguments);
            var self = this;
            return res.then(function(){
                             if (self.config.multi_session_id){
                                 self.multi_session = new exports.MultiSession(self);
                                 self.multi_session.start();
                                 self.multi_session.request_sync_all();
                             }
                         })
        },
    })

    var is_first_order = true;
    var OrderSuper = module.Order;
    module.Order = module.Order.extend({
        initialize: function(options){
            var self = this;
            options = options || {}
            OrderSuper.prototype.initialize.apply(this, arguments);
            this.ms_info = {}
            if (!_.isEmpty(options.ms_info)){
                this.ms_info = options.ms_info;
            } else if (this.pos.multi_session){
                this.ms_info['created'] = this.pos.ms_my_info();
            }
            this.ms_replace_empty_order = is_first_order;
            is_first_order = false;
            this.bind('change:sync', function(){
                self.ms_update();
            })
        },
        removeOrderline: function(line){
            OrderSuper.prototype.removeOrderline.apply(this, arguments);
            line.order.trigger('change:sync');
        },
        addProduct: function(){
            OrderSuper.prototype.addProduct.apply(this, arguments);
            this.trigger('change:sync')
        },
        ms_check: function(){
            if (! this.pos.multi_session )
                return;
            if (this.pos.ms_syncing_in_progress)
                return;
            return true;
        },
        ms_update: function(){
            var self = this;
            if (!this.ms_check())
                return;
            if (this.ms_update_timeout)
                // restart timeout
                clearTimeout(this.ms_update_timeout)
            this.ms_update_timeout = setTimeout(
                function(){
                    self.ms_update_timeout = false;
                    self.do_ms_update();
                }, 300)
        },
        ms_remove_order: function(){
            if (!this.ms_check())
                return;
            this.do_ms_remove_order();
        },
        do_ms_remove_order: function(){
            this.pos.multi_session.remove_order({'uid': this.uid});
        },
        export_as_JSON: function(){
            var data = OrderSuper.prototype.export_as_JSON.apply(this, arguments);
            data.ms_info = this.ms_info;
            return data;
        },
        do_ms_update: function(){
            var data = this.export_as_JSON();
            this.pos.multi_session.update(data);
        }
    })
    var OrderlineSuper = module.Orderline;
    module.Orderline = module.Orderline.extend({
        initialize: function(){
            var self = this;
            OrderlineSuper.prototype.initialize.apply(this, arguments);
            this.ms_info = {}
            if (this.order.ms_check()){
                this.ms_info['created'] = this.order.pos.ms_my_info();
            }
            this.bind('change', function(line){
                if (self.order.ms_check() && !line.ms_changing_selected){
                    line.ms_info['changed'] = line.order.pos.ms_my_info();
                    line.order.ms_info['changed'] = line.order.pos.ms_my_info();
                    var order_lines = line.order.get('orderLines');
                    order_lines.trigger('change', order_lines); // to rerender line
                    line.order.trigger('change:sync')
                }
            })
            this.uid = this.order.generateUniqueId() + '-' + this.id;
        },
        set_selected: function(){
            this.ms_changing_selected = true;
            OrderlineSuper.prototype.set_selected.apply(this, arguments);
            this.ms_changing_selected = false;
        },
        export_as_JSON: function(){
            var data = OrderlineSuper.prototype.export_as_JSON.apply(this, arguments);
            data.uid = this.uid;
            data.ms_info = this.ms_info;
            return data;
        }
    })

    module.MultiSession = Backbone.Model.extend({
        initialize: function(pos){
            this.pos = pos;
        },
        start: function(){
            var self = this;
            //var  done = new $.Deferred();

            this.bus = instance.bus.bus;
            this.bus.last = this.pos.db.load('bus_last', 0);
            this.bus.on("notification", this, this.on_notification);
            this.bus.start_polling();

            //return done;
        },
        request_sync_all: function(){
            this.send({'action': 'request_sync_all'})
        },
        sync_sequence_number: function(){
            var orders = {};
            this.pos.get('orders').each(function(r){
                orders[r.uid] = r.sequence_number;
            })
            var data = {
                'sequence_number': this.pos.pos_session.sequence_number,
                //'orders': orders,
            }
            this.send({action: 'sync_sequence_number', data: data})
        },
        remove_order: function(data){
            this.send({action: 'remove_order', data: data})
        },
        update: function(data){
            this.send({action: 'update', data: data})
        },
        send: function(message){
            console.log('send', message)
           var self = this;
            var send_it = function() {
                return openerp.session.rpc("/pos_multi_session/update", {multi_session_id: self.pos.config.multi_session_id[0], message: message});
            };
            var tries = 0;
            send_it().fail(function(error, e) {
                e.preventDefault();
                tries += 1;
                if (tries < 3)
                    return send_it();
            });
        },
        on_notification: function(notification) {
            var self = this;
            if (typeof notification[0][0] === 'string') {
                notification = [notification]
            }
            for (var i = 0; i < notification.length; i++) {
                var channel = notification[i][0];
                var message = notification[i][1];
                this.on_notification_do(channel, message);
            }
        },
        on_notification_do: function (channel, message) {
            if(Array.isArray(channel) && channel[1] === 'pos.multi_session'){
                try{
                    this.pos.ms_on_update(message)
                }catch(err){
                    this.pos.pos_widget.screen_selector.show_popup('error',{
                        message: _t('Error'),
                        comment: err,
                    })
                }
            }
            this.pos.db.save('bus_last', this.bus.last)
        }
    })
}
<|endoftext|>


<commit_before>(function () {

    angular.module('foodGenerator')
        .service('recipeStorageService', recipeStorageService);

    function recipeStorageService($window, recipeService) {

        this.addMarkedRecipe = addMarkedRecipe;
        this.removeMarkedRecipe = removeMarkedRecipe;
        this.getMarkedRecipes = getMarkedRecipes;
        this.clearMarkedRecipes = clearMarkedRecipes;

        this.addRecentlyViewedRecipe = addRecentlyViewedRecipe;
        this.getRecentlyViewedRecipes = getRecentlyViewedRecipes;
        this.clearRecentlyViewedRecipes = clearRecentlyViewedRecipes;

        this.addToShoppingList = addToShoppingList;
        this.removeFromShoppingList = removeFromShoppingList;
        this.getShoppingListRecipes = getShoppingListRecipes;
        this.clearShoppingList = clearShoppingList;

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

        // Marked Recipes

        function addMarkedRecipe(recipe) {
            console.log("Adding recipe '" + recipe.title + "' to marked recipes.");
            addRecipeToStorage(recipe, 'foodgenerator.recipes.marked');
        }

        function removeMarkedRecipe(recipe) {
            if (removeRecipeFromStorage(recipe, 'foodgenerator.recipes.marked')) {
                console.log("Removed recipe '" + recipe.title + "' from marked recipes.");
            } else {
                console.error("Could not remove recipe '" + recipe.title + "': not contained in marked recipe list.");
            }
        }

        function getMarkedRecipes() {
            return getRecipesFromIdList(getRecipeStorage('foodgenerator.recipes.marked'));
        }

        function clearMarkedRecipes() {
            clearRecipeStorage('foodgenerator.recipes.marked');
        }

        // Recently Viewed Recipes

        function addRecentlyViewedRecipe(recipe) {
            console.log("Registering new view for recipe '" + recipe.title + "'.");
            addRecipeToStorage(recipe, 'foodgenerator.recipes.recent');
        }

        function getRecentlyViewedRecipes() {
            return getRecipesFromIdList(getRecipeStorage('foodgenerator.recipes.recent'));
        }

        function clearRecentlyViewedRecipes() {
            clearRecipeStorage('foodgenerator.recipes.marked');
        }

        // Shopping List

        function addToShoppingList(recipe) {
            console.log("Adding recipe '" + recipe.title + "' to shopping list.");
            addRecipeToStorage(recipe, 'foodgenerator.recipes.shopping');
        }

        function removeFromShoppingList(recipe) {
            if (removeRecipeFromStorage(recipe, 'foodgenerator.recipes.shopping')) {
                console.log("Removed recipe '" + recipe.title + "' from shopping list.");
            } else {
                console.error("Could not remove recipe '" + recipe.title + "': not contained in shopping list.");
            }
        }

        function getShoppingListRecipes() {
            return getRecipesFromIdList(getRecipeStorage('foodgenerator.recipes.shopping'));
        }

        function clearShoppingList() {
            clearRecipeStorage('foodgenerator.recipes.shopping');
        }

        // Generic Functions

        function addRecipeToStorage(recipe, storageName) {
            // in case it is contained, remove element from current position
            removeRecipeFromStorage(recipe, storageName);

            // create a new list with the new recipe as only item
            var reorderedStorage = [recipe._id];

            // append other recipes if defined
            var recipeStorage = getRecipeStorage(storageName);
            if (recipeStorage) {
                reorderedStorage.push.apply(reorderedStorage, recipeStorage);
            }

            // save back to local storage
            setRecipeStorage(storageName, reorderedStorage);
        }

        function removeRecipeFromStorage(recipe, storageName) {
            var recipeStorage = getRecipeStorage(storageName);
            if (recipeStorage && recipeStorage.length) {
                var recipeIndex = recipeStorage.indexOf(recipe._id);

                if (recipeIndex > 0) {
                    // remove if list not empty and not a single element
                    recipeStorage.splice(recipeIndex, 1);
                    setRecipeStorage(storageName, recipeStorage);
                    return true;
                } else if (recipeIndex == 0) {
                    // clear if it the only element
                    clearRecipeStorage(storageName);
                }
            }
            return false;
        }

        function getRecipeStorage(storageName) {
            var recipeStorage = $window.localStorage[storageName];
            if (recipeStorage == undefined) {
                return [];
            }
            console.log("Returning recipe storage '" + storageName + "': " + recipeStorage);
            return recipeStorage.split(",");
        }

        function setRecipeStorage(storageName, recipeStorage) {
            var storageString = "";
            for (var index in recipeStorage) {
                //noinspection JSUnfilteredForInLoop
                storageString += recipeStorage[index] + ",";
            }
            storageString = storageString.slice(0, -1);
            $window.localStorage[storageName] = storageString;
        }

        function clearRecipeStorage(storageName) {
            $window.localStorage.removeItem(storageName);
        }

        function getRecipesFromIdList(recipeIds) {
            var recipes = [];
            for (var index in recipeIds) {
                //noinspection JSUnfilteredForInLoop
                recipeService.get(recipeIds[index]).then(function (response) {
                    recipes.push(response.data);
                })
            }
            return recipes;
        }

    }

})();
<commit_msg>fixed index bug when removing recipes from storage<commit_after>(function () {

    angular.module('foodGenerator')
        .service('recipeStorageService', recipeStorageService);

    function recipeStorageService($window, recipeService) {

        this.addMarkedRecipe = addMarkedRecipe;
        this.removeMarkedRecipe = removeMarkedRecipe;
        this.getMarkedRecipes = getMarkedRecipes;
        this.clearMarkedRecipes = clearMarkedRecipes;

        this.addRecentlyViewedRecipe = addRecentlyViewedRecipe;
        this.getRecentlyViewedRecipes = getRecentlyViewedRecipes;
        this.clearRecentlyViewedRecipes = clearRecentlyViewedRecipes;

        this.addToShoppingList = addToShoppingList;
        this.removeFromShoppingList = removeFromShoppingList;
        this.getShoppingListRecipes = getShoppingListRecipes;
        this.clearShoppingList = clearShoppingList;

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

        // Marked Recipes

        function addMarkedRecipe(recipe) {
            console.log("Adding recipe '" + recipe.title + "' to marked recipes.");
            addRecipeToStorage(recipe, 'foodgenerator.recipes.marked');
        }

        function removeMarkedRecipe(recipe) {
            if (removeRecipeFromStorage(recipe, 'foodgenerator.recipes.marked')) {
                console.log("Removed recipe '" + recipe.title + "' from marked recipes.");
            } else {
                console.error("Could not remove recipe '" + recipe.title + "': not contained in marked recipe list.");
            }
        }

        function getMarkedRecipes() {
            return getRecipesFromIdList(getRecipeStorage('foodgenerator.recipes.marked'));
        }

        function clearMarkedRecipes() {
            clearRecipeStorage('foodgenerator.recipes.marked');
        }

        // Recently Viewed Recipes

        function addRecentlyViewedRecipe(recipe) {
            console.log("Registering new view for recipe '" + recipe.title + "'.");
            addRecipeToStorage(recipe, 'foodgenerator.recipes.recent');
        }

        function getRecentlyViewedRecipes() {
            return getRecipesFromIdList(getRecipeStorage('foodgenerator.recipes.recent'));
        }

        function clearRecentlyViewedRecipes() {
            clearRecipeStorage('foodgenerator.recipes.recent');
        }

        // Shopping List

        function addToShoppingList(recipe) {
            console.log("Adding recipe '" + recipe.title + "' to shopping list.");
            addRecipeToStorage(recipe, 'foodgenerator.recipes.shopping');
        }

        function removeFromShoppingList(recipe) {
            if (removeRecipeFromStorage(recipe, 'foodgenerator.recipes.shopping')) {
                console.log("Removed recipe '" + recipe.title + "' from shopping list.");
            } else {
                console.error("Could not remove recipe '" + recipe.title + "': not contained in shopping list.");
            }
        }

        function getShoppingListRecipes() {
            return getRecipesFromIdList(getRecipeStorage('foodgenerator.recipes.shopping'));
        }

        function clearShoppingList() {
            clearRecipeStorage('foodgenerator.recipes.shopping');
        }

        // Generic Functions

        function addRecipeToStorage(recipe, storageName) {
            // in case it is contained, remove element from current position
            removeRecipeFromStorage(recipe, storageName);

            // create a new list with the new recipe as only item
            var reorderedStorage = [recipe._id];

            // append other recipes if defined
            var recipeStorage = getRecipeStorage(storageName);
            if (recipeStorage) {
                reorderedStorage.push.apply(reorderedStorage, recipeStorage);
            }

            // save back to local storage
            setRecipeStorage(storageName, reorderedStorage);
        }

        function removeRecipeFromStorage(recipe, storageName) {
            var recipeStorage = getRecipeStorage(storageName);
            if (recipeStorage && recipeStorage.length) {
                var recipeIndex = recipeStorage.indexOf(recipe._id);

                if (recipeIndex > -1 && recipeStorage.length == 1) {
                    // clear if it is the only element
                    clearRecipeStorage(storageName);
                    return true;
                } else if (recipeIndex > -1) {
                    // remove if list not empty and not a single element
                    recipeStorage.splice(recipeIndex, 1);
                    setRecipeStorage(storageName, recipeStorage);
                    return true;
                }
            }
            return false;
        }

        function getRecipeStorage(storageName) {
            var recipeStorage = $window.localStorage[storageName];
            if (recipeStorage == undefined) {
                return [];
            }
            console.log("Returning recipe storage '" + storageName + "': " + recipeStorage);
            return recipeStorage.split(",");
        }

        function setRecipeStorage(storageName, recipeStorage) {
            var storageString = "";
            for (var index in recipeStorage) {
                //noinspection JSUnfilteredForInLoop
                storageString += recipeStorage[index] + ",";
            }
            storageString = storageString.slice(0, -1);
            $window.localStorage[storageName] = storageString;
        }

        function clearRecipeStorage(storageName) {
            $window.localStorage.removeItem(storageName);
        }

        function getRecipesFromIdList(recipeIds) {
            var recipes = [];
            for (var index in recipeIds) {
                //noinspection JSUnfilteredForInLoop
                recipeService.get(recipeIds[index]).then(function (response) {
                    recipes.push(response.data);
                })
            }
            return recipes;
        }

    }

})();
<|endoftext|>


<commit_before>/*global namespace*/
(function () {
    var expect = namespace.expect;

    var shim = namespace.shim;
    var forEach = shim.forEach;
    var getKeys = shim.getKeys;
    var every = shim.every;
    var indexOf = shim.indexOf;

    var utils = namespace.utils;
    var isRegExp = utils.isRegExp;
    var isArray = utils.isArray;

    expect.addAssertion('[not] to be', function (expect, subject, value) {
        this.assert(subject === value);
    });

    expect.addAssertion('[not] to be true', function (expect, subject) {
        expect(subject, '[not] to be', true);
    });

    expect.addAssertion('[not] to be (ok|truthy)', function (expect, subject) {
        this.assert(subject);
    });

    expect.addAssertion('[not] to be false', function (expect, subject) {
        expect(subject, '[not] to be', false);
    });

    expect.addAssertion('[not] to be falsy', function (expect, subject) {
        expect(subject, '[!not] to be truthy');
    });

    expect.addAssertion('[not] to be null', function (expect, subject) {
        expect(subject, '[not] to be', null);
    });

    expect.addAssertion('[not] to be undefined', function (expect, subject) {
        expect(typeof subject, '[not] to be', 'undefined');
    });

    expect.addAssertion('[not] to be NaN', function (expect, subject) {
        expect(isNaN(subject), '[not] to be true');
    });

    expect.addAssertion('[not] to be (a|an)', function (expect, subject, type) {
        if ('string' === typeof type) {
            // typeof with support for 'array'
            expect('array' === type ? isArray(subject) :
                    'object' === type ? 'object' === typeof subject && null !== subject :
                        /^reg(?:exp?|ular expression)$/.test(type) ? isRegExp(subject) :
                            type === typeof subject,
                   '[not] to be true');
        } else {
            expect(subject instanceof type, '[not] to be true');
        }

        return this;
    });

    // Alias for common '[not] to be (a|an)' assertions
    expect.addAssertion('[not] to be (a|an) (boolean|number|string|function|object|array|regexp|regex|regular expression)', function (expect, subject) {
        var matches = /(.* be (?:a|an)) ([\w\s]+)/.exec(this.testDescription);
        expect(subject, matches[1], matches[2]);
    });

    forEach(['string', 'array', 'object'], function (type) {
        expect.addAssertion('to be (the|an) empty ' + type, function (expect, subject) {
            expect(subject, 'to be a', type);
            expect(subject, 'to be empty');
        });

        expect.addAssertion('to be a non-empty ' + type, function (expect, subject) {
            expect(subject, 'to be a', type);
            expect(subject, 'not to be empty');
        });
    });

    expect.addAssertion('[not] to match', function (expect, subject, regexp) {
        expect(regexp.exec(subject), '[not] to be truthy');
    });

    expect.addAssertion('[not] to have [own] property', function (expect, subject, key, value) {
        if (arguments.length === 4) {
            expect(subject, 'to have [own] property', key);
            expect(subject[key], '[not] to equal', value);
        } else {
            expect(this.flags.own ?
                   subject && subject.hasOwnProperty(key) :
                   subject && subject[key] !== undefined,
                   '[not] to be truthy');
        }
    });

    expect.addAssertion('[not] to have [own] properties', function (expect, subject, properties) {
        if (properties && isArray(properties)) {
            forEach(properties, function (property) {
                expect(subject, '[not] to have [own] property', property);
            });
        } else if (properties && typeof properties === 'object') {
            // TODO the not flag does not make a lot of sense in this case
            forEach(getKeys(properties), function (property) {
                if (this.flags.not) {
                    expect(subject, 'not to have [own] property', property);
                } else {
                    expect(subject, 'to have [own] property', property, properties[property]);
                }
            }, this);
        } else {
            throw new Error("Assertion '" + this.testDescription + "' only supports " +
                            "input in the form of an Array or an Object.");
        }
    });

    expect.addAssertion('[not] to have length', function (expect, subject, length) {
        if (!subject || typeof subject.length !== 'number') {
            throw new Error("Assertion '" + this.testDescription +
                            "' only supports array like objects");
        }
        expect(subject.length, '[not] to be', length);
    });

    expect.addAssertion('[not] to be empty', function (expect, subject) {
        var length;
        if (subject && 'number' === typeof subject.length) {
            length = subject.length;
        } else if (isArray(subject) || typeof subject === 'string') {
            length = subject.length;
        } else if (subject && typeof subject === 'object') {
            length = getKeys(subject).length;
        } else {
            throw new Error("Assertion '" + this.testDescription +
                            "' only supports strings, arrays and objects");
        }
        expect(length, '[not] to be', 0);
    });

    expect.addAssertion('to be non-empty', function (expect, subject) {
        expect(subject, 'not to be empty');
    });

    expect.addAssertion('to [not] [only] have (key|keys)', '[not] to have (key|keys)', function (expect, subject, keys) {
        keys = isArray(keys) ?
            keys :
            Array.prototype.slice.call(arguments, 2);

        var hasKeys = subject && every(keys, function (key) {
            return subject.hasOwnProperty(key);
        });
        if (this.flags.only) {
            expect(hasKeys && getKeys(subject).length === keys.length, '[not] to be truthy');
        } else {
            expect(hasKeys, '[not] to be truthy');
        }
    });

    expect.addAssertion('[not] to contain', function (expect, subject, arg) {
        var args = Array.prototype.slice.call(arguments, 2);
        var that = this;

        if ('string' === typeof subject) {
            forEach(args, function (arg) {
                expect(subject.indexOf(arg) !== -1, '[not] to be truthy');
            });
        } else if (isArray(subject)) {
            forEach(args, function (arg) {
                expect(subject && indexOf(subject, arg) !== -1, '[not] to be truthy');
            });
        } else if (subject === null) {
            expect(that.flags.not, '[not] to be falsy');
        } else {
            throw new Error("Assertion '" + this.testDescription +
                            "' only supports strings and arrays");
        }
    });

    expect.addAssertion('[not] to be finite', function (expect, subject) {
        expect(typeof subject === 'number' && isFinite(subject), '[not] to be truthy');
    });

    expect.addAssertion('[not] to be infinite', function (expect, subject) {
        expect(typeof subject === 'number' && !isNaN(subject) && !isFinite(subject), '[not] to be truthy');
    });

    expect.addAssertion('[not] to be within', function (expect, subject, start, finish) {
        this.args = [start + '..' + finish];
        expect(subject, 'to be a number');
        expect(subject >= start && subject <= finish, '[not] to be true');
    });

    expect.addAssertion('<', 'to be (<|less than|below)', function (expect, subject, value) {
        expect(subject < value, 'to be true');
    });

    expect.addAssertion('<=', 'to be (<=|less than or equal to)', function (expect, subject, value) {
        expect(subject <= value, 'to be true');
    });

    expect.addAssertion('>', 'to be (>|greater than|above)', function (expect, subject, value) {
        expect(subject > value, 'to be true');
    });

    expect.addAssertion('>=', 'to be (>=|greater than or equal to)', function (expect, subject, value) {
        expect(subject >= value, 'to be true');
    });

    expect.addAssertion('to be positive', function (expect, subject) {
        expect(subject, '>', 0);
    });

    expect.addAssertion('to be negative', function (expect, subject) {
        expect(subject, '<', 0);
    });

    expect.addAssertion('[not] to equal', function (expect, subject, value) {
        try {
            expect(this.equal(value, subject), '[not] to be true');
        } catch (e) {
            if (!this.flags.not) {
                e.expected = value;
                e.actual = subject;
                // Explicitly tell mocha to stringify and diff arrays
                // and objects, but only when the types are identical
                // and non-primitive:
                if (e.actual && e.expected &&
                    typeof e.actual === 'object' &&
                    typeof e.expected === 'object' &&
                    isArray(e.actual) === isArray(e.expected)) {
                    e.showDiff = true;
                }
            }
            throw e;
        }
    });

    expect.addAssertion('[not] to (throw|throw error|throw exception)', function (expect, subject, arg) {
        this.errorMode = 'bubble';
        if (typeof subject !== 'function') {
            throw new Error("Assertion '" + this.testDescription +
                            "' only supports functions");
        }

        var thrown = false;
        var argType = typeof arg;

        try {
            subject();
        } catch (e) {
            var subject = 'string' === typeof e ? e : e.message;
            if ('function' === argType) {
                arg(e);
            } else if ('string' === argType) {
                expect(subject, '[not] to be', arg);
            } else if (isRegExp(arg)) {
                expect(subject, '[not] to match', arg);
            }
            thrown = true;
        }

        this.errorMode = 'default';
        if ('string' === argType || isRegExp(arg)) {
            // in the presence of a matcher, ensure the `not` only applies to
            // the matching.
            expect(thrown, 'to be true');
        } else {
            expect(thrown, '[not] to be true');
        }
    });

    expect.addAssertion('to be (a|an) [non-empty] (map|hash|object) whose values satisfy', function (expect, subject, callbackOrString) {
        var callback;
        if ('function' === typeof callbackOrString) {
            callback = callbackOrString;
        } else if ('string' === typeof callbackOrString) {
            var args = Array.prototype.slice.call(arguments, 2);
            callback = function (value) {
                expect.apply(expect, [value].concat(args));
            };
        } else {
            throw new Error('Assertions "' + this.testDescription + '" expects a functions as argument');
        }
        this.errorMode = 'nested';
        expect(subject, 'to be an object');
        if (this.flags['non-empty']) {
            expect(subject, 'to be non-empty');
        }
        this.errorMode = 'default';

        var errors = [];
        forEach(getKeys(subject), function (key, index) {
            try {
                callback(subject[key], index);
            } catch (e) {
                errors.push('    ' + key + ': ' + e.message.replace(/\n/g, '\n    '));
            }
        });

        if (errors.length > 0) {
            var objectString = this.inspect(subject);
            var prefix = /\n/.test(objectString) ? '\n' : ' ';
            var message = 'failed expectation in' + prefix + objectString + ':\n' +
                errors.join('\n');
            throw new Error(message);
        }
    });

    expect.addAssertion('to be (a|an) [non-empty] array whose items satisfy', function (expect, subject, callbackOrString) {
        var callback;
        if ('function' === typeof callbackOrString) {
            callback = callbackOrString;
        } else if ('string' === typeof callbackOrString) {
            var args = Array.prototype.slice.call(arguments, 2);
            callback = function (item) {
                expect.apply(expect, [item].concat(args));
            };
        } else {
            throw new Error('Assertions "' + this.testDescription + '" expects a functions as argument');
        }
        this.errorMode = 'nested';
        expect(subject, 'to be an array');
        if (this.flags['non-empty']) {
            expect(subject, 'to be non-empty');
        }
        this.errorMode = 'bubble';
        expect(subject, 'to be a map whose values satisfy', callback);
    });

    forEach(['string', 'number', 'boolean', 'array', 'object', 'function', 'regexp', 'regex', 'regular expression'], function (type) {
        expect.addAssertion('to be (a|an) [non-empty] array of ' + type + 's', function (expect, subject) {
            expect(subject, 'to be an array whose items satisfy', function (item) {
                expect(item, 'to be a', type);
            });
            if (this.flags['non-empty']) {
                expect(subject, 'to be non-empty');
            }
        });
    });

    expect.addAssertion('to be (a|an) [non-empty] (map|hash|object) whose keys satisfy', function (expect, subject, callbackOrString) {
        var callback;
        if ('function' === typeof callbackOrString) {
            this.errorMode = 'nested';
            callback = callbackOrString;
        } else if ('string' === typeof callbackOrString) {
            var args = Array.prototype.slice.call(arguments, 2);
            callback = function (key) {
                expect.apply(expect, [key].concat(args));
            };
        } else {
            throw new Error('Assertions "' + this.testDescription + '" expects a functions as argument');
        }
        this.errorMode = 'nested';
        expect(subject, 'to be an object');
        if (this.flags['non-empty']) {
            expect(subject, 'to be non-empty');
        }
        this.errorMode = 'default';

        var errors = [];
        var keys = getKeys(subject);
        forEach(keys, function (key) {
            try {
                callback(key);
            } catch (e) {
                errors.push('    ' + key + ': ' + e.message.replace(/\n/g, '\n    '));
            }
        });

        if (errors.length > 0) {
            var message = 'failed expectation on keys ' + keys.join(', ') + ':\n' +
                errors.join('\n');
            throw new Error(message);
        }
    });
}());
<commit_msg>Use expect to implement 'to be'<commit_after>/*global namespace*/
(function () {
    var expect = namespace.expect;

    var shim = namespace.shim;
    var forEach = shim.forEach;
    var getKeys = shim.getKeys;
    var every = shim.every;
    var indexOf = shim.indexOf;

    var utils = namespace.utils;
    var isRegExp = utils.isRegExp;
    var isArray = utils.isArray;

    expect.addAssertion('[not] to be (ok|truthy)', function (expect, subject) {
        this.assert(subject);
    });

    expect.addAssertion('[not] to be', function (expect, subject, value) {
        expect(subject === value, '[not] to be truthy');
    });

    expect.addAssertion('[not] to be true', function (expect, subject) {
        expect(subject, '[not] to be', true);
    });

    expect.addAssertion('[not] to be false', function (expect, subject) {
        expect(subject, '[not] to be', false);
    });

    expect.addAssertion('[not] to be falsy', function (expect, subject) {
        expect(subject, '[!not] to be truthy');
    });

    expect.addAssertion('[not] to be null', function (expect, subject) {
        expect(subject, '[not] to be', null);
    });

    expect.addAssertion('[not] to be undefined', function (expect, subject) {
        expect(typeof subject, '[not] to be', 'undefined');
    });

    expect.addAssertion('[not] to be NaN', function (expect, subject) {
        expect(isNaN(subject), '[not] to be true');
    });

    expect.addAssertion('[not] to be (a|an)', function (expect, subject, type) {
        if ('string' === typeof type) {
            // typeof with support for 'array'
            expect('array' === type ? isArray(subject) :
                    'object' === type ? 'object' === typeof subject && null !== subject :
                        /^reg(?:exp?|ular expression)$/.test(type) ? isRegExp(subject) :
                            type === typeof subject,
                   '[not] to be true');
        } else {
            expect(subject instanceof type, '[not] to be true');
        }

        return this;
    });

    // Alias for common '[not] to be (a|an)' assertions
    expect.addAssertion('[not] to be (a|an) (boolean|number|string|function|object|array|regexp|regex|regular expression)', function (expect, subject) {
        var matches = /(.* be (?:a|an)) ([\w\s]+)/.exec(this.testDescription);
        expect(subject, matches[1], matches[2]);
    });

    forEach(['string', 'array', 'object'], function (type) {
        expect.addAssertion('to be (the|an) empty ' + type, function (expect, subject) {
            expect(subject, 'to be a', type);
            expect(subject, 'to be empty');
        });

        expect.addAssertion('to be a non-empty ' + type, function (expect, subject) {
            expect(subject, 'to be a', type);
            expect(subject, 'not to be empty');
        });
    });

    expect.addAssertion('[not] to match', function (expect, subject, regexp) {
        expect(regexp.exec(subject), '[not] to be truthy');
    });

    expect.addAssertion('[not] to have [own] property', function (expect, subject, key, value) {
        if (arguments.length === 4) {
            expect(subject, 'to have [own] property', key);
            expect(subject[key], '[not] to equal', value);
        } else {
            expect(this.flags.own ?
                   subject && subject.hasOwnProperty(key) :
                   subject && subject[key] !== undefined,
                   '[not] to be truthy');
        }
    });

    expect.addAssertion('[not] to have [own] properties', function (expect, subject, properties) {
        if (properties && isArray(properties)) {
            forEach(properties, function (property) {
                expect(subject, '[not] to have [own] property', property);
            });
        } else if (properties && typeof properties === 'object') {
            // TODO the not flag does not make a lot of sense in this case
            forEach(getKeys(properties), function (property) {
                if (this.flags.not) {
                    expect(subject, 'not to have [own] property', property);
                } else {
                    expect(subject, 'to have [own] property', property, properties[property]);
                }
            }, this);
        } else {
            throw new Error("Assertion '" + this.testDescription + "' only supports " +
                            "input in the form of an Array or an Object.");
        }
    });

    expect.addAssertion('[not] to have length', function (expect, subject, length) {
        if (!subject || typeof subject.length !== 'number') {
            throw new Error("Assertion '" + this.testDescription +
                            "' only supports array like objects");
        }
        expect(subject.length, '[not] to be', length);
    });

    expect.addAssertion('[not] to be empty', function (expect, subject) {
        var length;
        if (subject && 'number' === typeof subject.length) {
            length = subject.length;
        } else if (isArray(subject) || typeof subject === 'string') {
            length = subject.length;
        } else if (subject && typeof subject === 'object') {
            length = getKeys(subject).length;
        } else {
            throw new Error("Assertion '" + this.testDescription +
                            "' only supports strings, arrays and objects");
        }
        expect(length, '[not] to be', 0);
    });

    expect.addAssertion('to be non-empty', function (expect, subject) {
        expect(subject, 'not to be empty');
    });

    expect.addAssertion('to [not] [only] have (key|keys)', '[not] to have (key|keys)', function (expect, subject, keys) {
        keys = isArray(keys) ?
            keys :
            Array.prototype.slice.call(arguments, 2);

        var hasKeys = subject && every(keys, function (key) {
            return subject.hasOwnProperty(key);
        });
        if (this.flags.only) {
            expect(hasKeys && getKeys(subject).length === keys.length, '[not] to be truthy');
        } else {
            expect(hasKeys, '[not] to be truthy');
        }
    });

    expect.addAssertion('[not] to contain', function (expect, subject, arg) {
        var args = Array.prototype.slice.call(arguments, 2);
        var that = this;

        if ('string' === typeof subject) {
            forEach(args, function (arg) {
                expect(subject.indexOf(arg) !== -1, '[not] to be truthy');
            });
        } else if (isArray(subject)) {
            forEach(args, function (arg) {
                expect(subject && indexOf(subject, arg) !== -1, '[not] to be truthy');
            });
        } else if (subject === null) {
            expect(that.flags.not, '[not] to be falsy');
        } else {
            throw new Error("Assertion '" + this.testDescription +
                            "' only supports strings and arrays");
        }
    });

    expect.addAssertion('[not] to be finite', function (expect, subject) {
        expect(typeof subject === 'number' && isFinite(subject), '[not] to be truthy');
    });

    expect.addAssertion('[not] to be infinite', function (expect, subject) {
        expect(typeof subject === 'number' && !isNaN(subject) && !isFinite(subject), '[not] to be truthy');
    });

    expect.addAssertion('[not] to be within', function (expect, subject, start, finish) {
        this.args = [start + '..' + finish];
        expect(subject, 'to be a number');
        expect(subject >= start && subject <= finish, '[not] to be true');
    });

    expect.addAssertion('<', 'to be (<|less than|below)', function (expect, subject, value) {
        expect(subject < value, 'to be true');
    });

    expect.addAssertion('<=', 'to be (<=|less than or equal to)', function (expect, subject, value) {
        expect(subject <= value, 'to be true');
    });

    expect.addAssertion('>', 'to be (>|greater than|above)', function (expect, subject, value) {
        expect(subject > value, 'to be true');
    });

    expect.addAssertion('>=', 'to be (>=|greater than or equal to)', function (expect, subject, value) {
        expect(subject >= value, 'to be true');
    });

    expect.addAssertion('to be positive', function (expect, subject) {
        expect(subject, '>', 0);
    });

    expect.addAssertion('to be negative', function (expect, subject) {
        expect(subject, '<', 0);
    });

    expect.addAssertion('[not] to equal', function (expect, subject, value) {
        try {
            expect(this.equal(value, subject), '[not] to be true');
        } catch (e) {
            if (!this.flags.not) {
                e.expected = value;
                e.actual = subject;
                // Explicitly tell mocha to stringify and diff arrays
                // and objects, but only when the types are identical
                // and non-primitive:
                if (e.actual && e.expected &&
                    typeof e.actual === 'object' &&
                    typeof e.expected === 'object' &&
                    isArray(e.actual) === isArray(e.expected)) {
                    e.showDiff = true;
                }
            }
            throw e;
        }
    });

    expect.addAssertion('[not] to (throw|throw error|throw exception)', function (expect, subject, arg) {
        this.errorMode = 'bubble';
        if (typeof subject !== 'function') {
            throw new Error("Assertion '" + this.testDescription +
                            "' only supports functions");
        }

        var thrown = false;
        var argType = typeof arg;

        try {
            subject();
        } catch (e) {
            var subject = 'string' === typeof e ? e : e.message;
            if ('function' === argType) {
                arg(e);
            } else if ('string' === argType) {
                expect(subject, '[not] to be', arg);
            } else if (isRegExp(arg)) {
                expect(subject, '[not] to match', arg);
            }
            thrown = true;
        }

        this.errorMode = 'default';
        if ('string' === argType || isRegExp(arg)) {
            // in the presence of a matcher, ensure the `not` only applies to
            // the matching.
            expect(thrown, 'to be true');
        } else {
            expect(thrown, '[not] to be true');
        }
    });

    expect.addAssertion('to be (a|an) [non-empty] (map|hash|object) whose values satisfy', function (expect, subject, callbackOrString) {
        var callback;
        if ('function' === typeof callbackOrString) {
            callback = callbackOrString;
        } else if ('string' === typeof callbackOrString) {
            var args = Array.prototype.slice.call(arguments, 2);
            callback = function (value) {
                expect.apply(expect, [value].concat(args));
            };
        } else {
            throw new Error('Assertions "' + this.testDescription + '" expects a functions as argument');
        }
        this.errorMode = 'nested';
        expect(subject, 'to be an object');
        if (this.flags['non-empty']) {
            expect(subject, 'to be non-empty');
        }
        this.errorMode = 'default';

        var errors = [];
        forEach(getKeys(subject), function (key, index) {
            try {
                callback(subject[key], index);
            } catch (e) {
                errors.push('    ' + key + ': ' + e.message.replace(/\n/g, '\n    '));
            }
        });

        if (errors.length > 0) {
            var objectString = this.inspect(subject);
            var prefix = /\n/.test(objectString) ? '\n' : ' ';
            var message = 'failed expectation in' + prefix + objectString + ':\n' +
                errors.join('\n');
            throw new Error(message);
        }
    });

    expect.addAssertion('to be (a|an) [non-empty] array whose items satisfy', function (expect, subject, callbackOrString) {
        var callback;
        if ('function' === typeof callbackOrString) {
            callback = callbackOrString;
        } else if ('string' === typeof callbackOrString) {
            var args = Array.prototype.slice.call(arguments, 2);
            callback = function (item) {
                expect.apply(expect, [item].concat(args));
            };
        } else {
            throw new Error('Assertions "' + this.testDescription + '" expects a functions as argument');
        }
        this.errorMode = 'nested';
        expect(subject, 'to be an array');
        if (this.flags['non-empty']) {
            expect(subject, 'to be non-empty');
        }
        this.errorMode = 'bubble';
        expect(subject, 'to be a map whose values satisfy', callback);
    });

    forEach(['string', 'number', 'boolean', 'array', 'object', 'function', 'regexp', 'regex', 'regular expression'], function (type) {
        expect.addAssertion('to be (a|an) [non-empty] array of ' + type + 's', function (expect, subject) {
            expect(subject, 'to be an array whose items satisfy', function (item) {
                expect(item, 'to be a', type);
            });
            if (this.flags['non-empty']) {
                expect(subject, 'to be non-empty');
            }
        });
    });

    expect.addAssertion('to be (a|an) [non-empty] (map|hash|object) whose keys satisfy', function (expect, subject, callbackOrString) {
        var callback;
        if ('function' === typeof callbackOrString) {
            this.errorMode = 'nested';
            callback = callbackOrString;
        } else if ('string' === typeof callbackOrString) {
            var args = Array.prototype.slice.call(arguments, 2);
            callback = function (key) {
                expect.apply(expect, [key].concat(args));
            };
        } else {
            throw new Error('Assertions "' + this.testDescription + '" expects a functions as argument');
        }
        this.errorMode = 'nested';
        expect(subject, 'to be an object');
        if (this.flags['non-empty']) {
            expect(subject, 'to be non-empty');
        }
        this.errorMode = 'default';

        var errors = [];
        var keys = getKeys(subject);
        forEach(keys, function (key) {
            try {
                callback(key);
            } catch (e) {
                errors.push('    ' + key + ': ' + e.message.replace(/\n/g, '\n    '));
            }
        });

        if (errors.length > 0) {
            var message = 'failed expectation on keys ' + keys.join(', ') + ':\n' +
                errors.join('\n');
            throw new Error(message);
        }
    });
}());
<|endoftext|>


<commit_before>$(function () {
    // Movimentar Linhas
    (function () {
        // Tabela
        var table = $('.table');
        // Movimentar Linhas
        table.on('click', '.table-move', function () {
            console.log(this);
        });
    })();
});
<commit_msg>Issue #51 Início da construção de movimentador de elementos em listagem.<commit_after>$(function () {
    // Movimentar Linhas
    (function () {
        // Tabela
        var table = $('.table');
        // Draggable
        table.find('tbody').sortable({
            axis: 'y',
            scroll: true,
            items: '> tr',
            handle: '.table-move'
        }).disableSelection();
    })();
});
<|endoftext|>