<commit_before>"use strict";

const StringView = require("../lib/StringView.js");

class ID {
	constructor(input){
		if (input instanceof ArrayBuffer){
			this.buffer = input;
			this.dataView = new Uint8Array(input);
			this.stringView = new StringView(this.buffer);
		} else if (ArrayBuffer.isView(input)){
			this.buffer = input.buffer;
			if(input instanceof Uint8Array)
				this.dataView = input;
			else
				this.dataView = new Uint8Array(this.buffer);
			this.stringView = new StringView(this.buffer);
		} else if (typeof input === "string"){
			this.stringView = StringView.makeFromBase64(input);
			this.buffer = this.stringView.buffer;
			this.dataView = new Uint8Array(this.buffer);
		} else {
			throw new TypeError("Illegal type for ID constructor: "+ typeof input);
		}
	}

	get idLength(){
		return this.buffer.byteLength * 8;
	}

	get idArray(){
		return this.dataView;
	}

	get idString(){
		if(this.base64 === undefined)
			this.base64 = this.stringView.toBase64(true);
		return this.base64;
	}

	leftShiftIn(bit){
		return ID.leftShiftIn(this, bit);
	}

	compareTo(id){
		return ID.compare(this, id);
	}

	add(arrayLike){
		return ID.add(this, arrayLike);
	}

	subtract(arrayLike){
		return ID.subtract(this, arrayLike);
	}

	inOpenBound(aL1, aL2){
		return ID.inOpenBound(this, aL1, aL2);
	}

	inLeftOpenBound(aL1, aL2){
		return ID.inRightOpenBound(this, aL1, aL2);
	}

	inRightOpenBound(aL1, aL2){
		return ID.inLeftOpenBound(this, aL1, aL2);
	}

	inClosedBound(aL1, aL2){
		return ID.inClosedBound(this, aL1, aL2);
	}

	static leftShiftIn(id, bit){
		let out = ID.uint8FromArrayLike(id).slice(0);

		for (let i = out.length - 1; i >= 0; i--) {
			let old = out[i];
			out[i] = (old << 1) + bit;
			bit = (old & 0x80) >> 7;
		};

		return new ID(out);
	}

	static compare(id1, id2){
		let arr1 = ID.uint8FromArrayLike(id1),
			arr2 = ID.uint8FromArrayLike(id2),
			loopLen = (arr1.length > arr2.length) ? arr1.length : arr2.length,
			retVal = 0;

		for(let i = 0; i<loopLen && retVal===0; i++){
			let pt1 = (arr1.length-loopLen+i < 0) ? 0x00 : arr1[arr1.length-loopLen+i],
				pt2 = (arr2.length-loopLen+i < 0) ? 0x00 : arr2[arr2.length-loopLen+i];

			retVal = pt1 - pt2;
		};

		return retVal;
	}

	static add(aL1, aL2){
		let arr1 = ID.uint8FromArrayLike(aL1),
			arr2 = ID.uint8FromArrayLike(aL2),
			out,
			addition;

		if(arr1.length > arr2.length){
			out = arr1.slice(0);
			addition = arr2;
		} else {
			out = arr2.slice(0);
			addition = arr1;
		}

		let carry = 0;
		for (let i = out.length - 1; i >= 0; i--) {
			let addIter = i + addition.length - out.length,
				pt = (addIter < 0) ? 0x00 : addition[addIter],
				old = out[i];

			out[i] += pt + carry;
			carry = old > out[i];

		};

		return new ID(out);
	}

	static subtract(aL1, aL2){
		let arr1 = ID.uint8FromArrayLike(aL1),
			arr2 = ID.uint8FromArrayLike(aL2),
			out,
			subtraction;

		if(arr1.length > arr2.length){
			out = arr1.slice(0);
			subtraction = new Uint8Array(arr1.length);
			subtraction.set(arr2, arr1.length-arr2.length);
		} else {
			out = new Uint8Array(arr2.length);
			out.set(arr1, arr2.length-arr1.length);
			subtraction = arr2;
		}

		return ID.add(out, ID.twosComplement(subtraction));
	}

	static inOpenBound(al_value, al_LB, al_UB){
		let bVal = ID.boundsChecks(al_value, al_LB, al_UB);
		return bVal[0] && !(bVal[1] || bVal[2]);
	}

	static inLeftOpenBound(al_value, al_LB, al_UB){
		let bVal = ID.boundsChecks(al_value, al_LB, al_UB);
		return bVal[0] || bVal[2] && !bVal[1];
	}

	static inRightOpenBound(al_value, al_LB, al_UB){
		let bVal = ID.boundsChecks(al_value, al_LB, al_UB);
		return bVal[0] || bVal[1] && !bVal[2];
	}

	static inClosedBound(al_value, al_LB, al_UB){
		let bVal = ID.boundsChecks(al_value, al_LB, al_UB);
		return bVal[0] || bVal[1] || bVal[2];
	}

	static boundsChecks(al_value, al_LB, al_UB){
		let cmpLB = ID.compare(al_value, al_LB),
			cmpUB = ID.compare(al_value, al_UB),
			order = ID.compare(al_LB, al_UB);

		return [
			(order < 0)? (cmpLB>0 && cmpUB<0) : (cmpLB<0 || cmpUB>0), //Strictly in bounds.
			cmpLB === 0, //On left bound.
			cmpUB === 0 //On right bound.
		];
	}

	static powerOfTwoBuffer(power){
		let bytes = power/8;
		bytes = (bytes | 0) === bytes ? bytes : (bytes | 0) + 1;

		let out = new Uint8Array(bytes);
		out[0] = 0x01 << power%8;

		return out;
	}

	static onesComplement(arrayLike){
		let arr = ID.uint8FromArrayLike(arrayLike).slice(0);

		for (var i = arr.length - 1; i >= 0; i--) {
			arr[i] = ~arr[i]
		};

		return arr;
	}

	static twosComplement(arrayLike){
		return ID.add([0x01], ID.onesComplement(arrayLike));
	}

	static uint8FromArrayLike(arrayLike){
		if (arrayLike instanceof ArrayBuffer || arrayLike instanceof Array){
			return new Uint8Array(arrayLike);
		} else if (ArrayBuffer.isView(arrayLike)){
			return new Uint8Array(arrayLike.buffer);
		} else if (arrayLike instanceof ID){
			return arrayLike.dataView;
		} else {
			throw new TypeError(arrayLike + "is not an array-like type: "+ typeof arrayLike);
		}
	}
}

module.exports = ID;<commit_msg>Update for ID code to handle generation of Arraylike from str.<commit_after>"use strict";

const StringView = require("../lib/StringView.js");

class ID {
	constructor(input){
		if (input instanceof ArrayBuffer){
			this.buffer = input;
			this.dataView = new Uint8Array(input);
			this.stringView = new StringView(this.buffer);
		} else if (ArrayBuffer.isView(input)){
			this.buffer = input.buffer;
			if(input instanceof Uint8Array)
				this.dataView = input;
			else
				this.dataView = new Uint8Array(this.buffer);
			this.stringView = new StringView(this.buffer);
		} else if (typeof input === "string"){
			this.stringView = StringView.makeFromBase64(input);
			this.buffer = this.stringView.buffer;
			this.dataView = new Uint8Array(this.buffer);
		} else {
			throw new TypeError("Illegal type for ID constructor: "+ typeof input);
		}
	}

	get idLength(){
		return this.buffer.byteLength * 8;
	}

	get idArray(){
		return this.dataView;
	}

	get idString(){
		if(this.base64 === undefined)
			this.base64 = this.stringView.toBase64(true);
		return this.base64;
	}

	leftShiftIn(bit){
		return ID.leftShiftIn(this, bit);
	}

	compareTo(id){
		return ID.compare(this, id);
	}

	add(arrayLike){
		return ID.add(this, arrayLike);
	}

	subtract(arrayLike){
		return ID.subtract(this, arrayLike);
	}

	inOpenBound(aL1, aL2){
		return ID.inOpenBound(this, aL1, aL2);
	}

	inLeftOpenBound(aL1, aL2){
		return ID.inRightOpenBound(this, aL1, aL2);
	}

	inRightOpenBound(aL1, aL2){
		return ID.inLeftOpenBound(this, aL1, aL2);
	}

	inClosedBound(aL1, aL2){
		return ID.inClosedBound(this, aL1, aL2);
	}

	static leftShiftIn(id, bit){
		let out = ID.uint8FromArrayLike(id).slice(0);

		for (let i = out.length - 1; i >= 0; i--) {
			let old = out[i];
			out[i] = (old << 1) + bit;
			bit = (old & 0x80) >> 7;
		};

		return new ID(out);
	}

	static compare(id1, id2){
		let arr1 = ID.uint8FromArrayLike(id1),
			arr2 = ID.uint8FromArrayLike(id2),
			loopLen = (arr1.length > arr2.length) ? arr1.length : arr2.length,
			retVal = 0;

		for(let i = 0; i<loopLen && retVal===0; i++){
			let pt1 = (arr1.length-loopLen+i < 0) ? 0x00 : arr1[arr1.length-loopLen+i],
				pt2 = (arr2.length-loopLen+i < 0) ? 0x00 : arr2[arr2.length-loopLen+i];

			retVal = pt1 - pt2;
		};

		return retVal;
	}

	static add(aL1, aL2){
		let arr1 = ID.uint8FromArrayLike(aL1),
			arr2 = ID.uint8FromArrayLike(aL2),
			out,
			addition;

		if(arr1.length > arr2.length){
			out = arr1.slice(0);
			addition = arr2;
		} else {
			out = arr2.slice(0);
			addition = arr1;
		}

		let carry = 0;
		for (let i = out.length - 1; i >= 0; i--) {
			let addIter = i + addition.length - out.length,
				pt = (addIter < 0) ? 0x00 : addition[addIter],
				old = out[i];

			out[i] += pt + carry;
			carry = old > out[i];

		};

		return new ID(out);
	}

	static subtract(aL1, aL2){
		let arr1 = ID.uint8FromArrayLike(aL1),
			arr2 = ID.uint8FromArrayLike(aL2),
			out,
			subtraction;

		if(arr1.length > arr2.length){
			out = arr1.slice(0);
			subtraction = new Uint8Array(arr1.length);
			subtraction.set(arr2, arr1.length-arr2.length);
		} else {
			out = new Uint8Array(arr2.length);
			out.set(arr1, arr2.length-arr1.length);
			subtraction = arr2;
		}

		return ID.add(out, ID.twosComplement(subtraction));
	}

	static inOpenBound(al_value, al_LB, al_UB){
		let bVal = ID.boundsChecks(al_value, al_LB, al_UB);
		return bVal[0] && !(bVal[1] || bVal[2]);
	}

	static inLeftOpenBound(al_value, al_LB, al_UB){
		let bVal = ID.boundsChecks(al_value, al_LB, al_UB);
		return bVal[0] || bVal[2] && !bVal[1];
	}

	static inRightOpenBound(al_value, al_LB, al_UB){
		let bVal = ID.boundsChecks(al_value, al_LB, al_UB);
		return bVal[0] || bVal[1] && !bVal[2];
	}

	static inClosedBound(al_value, al_LB, al_UB){
		let bVal = ID.boundsChecks(al_value, al_LB, al_UB);
		return bVal[0] || bVal[1] || bVal[2];
	}

	static boundsChecks(al_value, al_LB, al_UB){
		let cmpLB = ID.compare(al_value, al_LB),
			cmpUB = ID.compare(al_value, al_UB),
			order = ID.compare(al_LB, al_UB);

		return [
			(order < 0)? (cmpLB>0 && cmpUB<0) : (cmpLB<0 || cmpUB>0), //Strictly in bounds.
			cmpLB === 0, //On left bound.
			cmpUB === 0 //On right bound.
		];
	}

	static powerOfTwoBuffer(power){
		let bytes = power/8;
		bytes = (bytes | 0) === bytes ? bytes : (bytes | 0) + 1;

		let out = new Uint8Array(bytes);
		out[0] = 0x01 << power%8;

		return out;
	}

	static onesComplement(arrayLike){
		let arr = ID.uint8FromArrayLike(arrayLike).slice(0);

		for (var i = arr.length - 1; i >= 0; i--) {
			arr[i] = ~arr[i]
		};

		return arr;
	}

	static twosComplement(arrayLike){
		return ID.add([0x01], ID.onesComplement(arrayLike));
	}

	static uint8FromArrayLike(arrayLike){
		if (arrayLike instanceof ArrayBuffer || arrayLike instanceof Array){
			return new Uint8Array(arrayLike);
		} else if (ArrayBuffer.isView(arrayLike)){
			return new Uint8Array(arrayLike.buffer);
		} else if (arrayLike instanceof ID){
			return arrayLike.dataView;
		} else if (typeof arrayLike === "string"){
			return new Uint8Array(StringView.makeFromBase64(input).buffer);
		} else {
			throw new TypeError(arrayLike + "is not an array-like type: "+ typeof arrayLike);
		}
	}
}

module.exports = ID;<|endoftext|>


<commit_before>/*#ifndef(UMD)*/
"use strict";
/*global _gpfIgnore*/ // Helper to remove unused parameter warning
/*global _GPF_FS_TYPE_NOT_FOUND*/ // _GPF_FS_TYPE_NOT_FOUND
/*global _GPF_FS_TYPE_FILE*/ // _GPF_FS_TYPE_FILE
/*global _GPF_FS_TYPE_DIRECTORY*/ // _GPF_FS_TYPE_DIRECTORY
/*global _GPF_FS_TYPE_UNKNOWN*/ // _GPF_FS_TYPE_UNKNOWN
/*global _gpfSetReadOnlyProperty*/ // gpf.setReadOnlyProperty
/*global _gpfEventsFire*/ // gpf.events.fire (internal, parameters must match)
/*global _GPF_EVENT_ERROR*/ // gpf.events.EVENT_ERROR
/*global _GPF_EVENT_DATA*/ // gpf.events.EVENT_DATA
/*global _GPF_EVENT_END_OF_DATA*/ // gpf.events.EVENT_END_OF_DATA
/*global _gpfI*/ // gpf.interfaces
/*#endif*/

gpf.fs = {

    /**
     * Get host file storage handler
     *
     * @returns {gpf.interfaces.IFileStorage}
     */
    host: function () {
        return null;
    },

    /**
     * Find and identify files matching the pattern, trigger a file event
     * when a file is found
     *
     * @param {gpf.interfaces.IFileStorage|undefined} fs file storage interface.
     * If undefined the host one is used.
     * @param {String} basePath
     * @param {String[]} filters Patterns (see gpf.path.match) of files to
     * detect
     * @param {gpf.events.Handler} eventsHandler
     *
     * @event gpf.events.EVENT_DATA
     * a matching file has been identified
     * @eventParam {String} path
     *
     * @event gpf.events.EVENT_END_OF_DATA
     */
    find: function (fs, basePath, filters, eventsHandler) {
        var
            pendingCount = 0,
            match = gpf.path.match,
            _done = function () {
                if (0 === --pendingCount) {
                    _gpfEventsFire.apply(null, [
                        _GPF_EVENT_END_OF_DATA,
                        {},
                        eventsHandler
                    ]);
                }
            },
            _error = function (event) {
                _gpfEventsFire.apply(null, [
                    event,
                    {},
                    eventsHandler
                ]);
            },
            _explore = function (fileInfo) {
                if (_GPF_FS_TYPE_DIRECTORY === fileInfo.type) {

                } else if (_GPF_FS_TYPE_FILE === fileInfo.type) {
                    if (match(filters, fileInfo.)) {
                        _gpfEventsFire.apply(null, [
                            _GPF_EVENT_DATA,
                            {
                                path: currentPath
                            },
                            eventsHandler
                        ]);
                    }

                }
            };
        if (undefined === fs) {
            fs = gpf.fs.host();
        }
        filters = gpf.path.compileMatchPattern(filters);
        fs.getInfo(basePath, function (event) {
            if (_GPF_EVENT_ERROR === event.type) {
                _error(event);
            } else {
                _explore(event.get("info"));
            }
        });

        function _explore(currentPath) {
            ++pendingCount;
            fs.getInfo(currentPath, function (event) {
                if (_GPF_EVENT_ERROR === event.type) {
                    _gpfEventsFire.apply(null, [
                        event,
                        {},
                        eventsHandler
                    ]);

                } else if (_GPF_FS_TYPE_DIRECTORY === event.type) {
                    ++pendingCount;
                    var enumerator;
                    fs.explore(currentPath, function (event) {
                        if (_GPF_EVENT_ERROR === event.type) {
                            _gpfEventsFire.apply(null, [
                                event,
                                {},
                                eventsHandler
                            ]);
                        } else {
                            _gpfI.IEnumerator.each(event.get("enumerator"), function (info) {

                            }, _done());
                        }
                    })
/**
 * TODO create an IEnumerator on folder to get all sub elements
                    IEnumerator

                    _fs.readdir(currentPath, function (err, list) {
                        var
                            len,
                            idx;
                        if (err) {
                            console.error(err);
                        } else {
                            len = list.length;
                            for (idx = 0; idx < len; ++idx) {
                                _explore(_path.join(currentPath, list[idx]));
                            }
                        }
                        _done();
                    });
*/

                } else {
                    if (match(filters, currentPath)) {
                        _gpfEventsFire.apply(null, [
                            _GPF_EVENT_DATA,
                            {
                                path: currentPath
                            },
                            eventsHandler
                        ]);
                    }
                }
                _done();

            });
        }
        _explore(basePath);
    }

};

// Create file system constants
(function () {
    var gpfFs = gpf.fs,
        mappings = {
            TYPE_NOT_FOUND: _GPF_FS_TYPE_NOT_FOUND,
            TYPE_FILE: _GPF_FS_TYPE_FILE,
            TYPE_DIRECTORY: _GPF_FS_TYPE_DIRECTORY,
            TYPE_UNKNOWN: _GPF_FS_TYPE_UNKNOWN
        },
        key;
    for (key in mappings) {
        if (mappings.hasOwnProperty(key)) {
            _gpfSetReadOnlyProperty(gpfFs, key, mappings[key]);
        }
    }

}());<commit_msg>WIP (not working)<commit_after>/*#ifndef(UMD)*/
"use strict";
/*global _gpfIgnore*/ // Helper to remove unused parameter warning
/*global _GPF_FS_TYPE_NOT_FOUND*/ // _GPF_FS_TYPE_NOT_FOUND
/*global _GPF_FS_TYPE_FILE*/ // _GPF_FS_TYPE_FILE
/*global _GPF_FS_TYPE_DIRECTORY*/ // _GPF_FS_TYPE_DIRECTORY
/*global _GPF_FS_TYPE_UNKNOWN*/ // _GPF_FS_TYPE_UNKNOWN
/*global _gpfSetReadOnlyProperty*/ // gpf.setReadOnlyProperty
/*global _gpfEventsFire*/ // gpf.events.fire (internal, parameters must match)
/*global _GPF_EVENT_ERROR*/ // gpf.events.EVENT_ERROR
/*global _GPF_EVENT_DATA*/ // gpf.events.EVENT_DATA
/*global _GPF_EVENT_END_OF_DATA*/ // gpf.events.EVENT_END_OF_DATA
/*global _gpfI*/ // gpf.interfaces
/*#endif*/

gpf.fs = {

    /**
     * Get host file storage handler
     *
     * @returns {gpf.interfaces.IFileStorage}
     */
    host: function () {
        return null;
    },

    /**
     * Find and identify files matching the pattern, trigger a file event
     * when a file is found
     *
     * @param {gpf.interfaces.IFileStorage|undefined} fs file storage interface.
     * If undefined the host one is used.
     * @param {String} basePath
     * @param {String[]} filters Patterns (see gpf.path.match) of files to
     * detect
     * @param {gpf.events.Handler} eventsHandler
     *
     * @event gpf.events.EVENT_DATA
     * a matching file has been identified
     * @eventParam {String} path
     *
     * @event gpf.events.EVENT_END_OF_DATA
     */
    find: function (fs, basePath, filters, eventsHandler) {
        var
            pendingCount = 0,
            match = gpf.path.match,
            _fire = function (event, params) {
                if (!params) {
                    params = {};
                }
                _gpfEventsFire.apply(null, [event, params, eventsHandler]);
            },
            _done = function () {
                if (0 === --pendingCount) {
                    _fire(_GPF_EVENT_END_OF_DATA);
                }
            },
            _error = function (event) {
                _fire(event);
            },
            _explore = function (fileInfo) {
                if (_GPF_FS_TYPE_DIRECTORY === fileInfo.type) {

                } else if (_GPF_FS_TYPE_FILE === fileInfo.type) {
                    if (match(filters, fileInfo.filePath)) {
                        _gpfEventsFire.apply(null, [
                            _GPF_EVENT_DATA,
                            {
                                path: currentPath
                            },
                            eventsHandler
                        ]);
                    }

                }
            };
        if (!fs) {
            fs = gpf.fs.host();
        }
        filters = gpf.path.compileMatchPattern(filters);
        fs.getInfo(basePath, function (event) {
            if (_GPF_EVENT_ERROR === event.type) {
                _error(event);
            } else {
                _explore(event.get("info"));
            }
        });

        function _explore(currentPath) {
            ++pendingCount;
            fs.getInfo(currentPath, function (event) {
                if (_GPF_EVENT_ERROR === event.type) {
                    _gpfEventsFire.apply(null, [
                        event,
                        {},
                        eventsHandler
                    ]);

                } else if (_GPF_FS_TYPE_DIRECTORY === event.type) {
                    ++pendingCount;
                    var enumerator;
                    fs.explore(currentPath, function (event) {
                        if (_GPF_EVENT_ERROR === event.type) {
                            _gpfEventsFire.apply(null, [
                                event,
                                {},
                                eventsHandler
                            ]);
                        } else {
                            _gpfI.IEnumerator.each(event.get("enumerator"), function (info) {

                            }, _done());
                        }
                    })
/**
 * TODO create an IEnumerator on folder to get all sub elements
                    IEnumerator

                    _fs.readdir(currentPath, function (err, list) {
                        var
                            len,
                            idx;
                        if (err) {
                            console.error(err);
                        } else {
                            len = list.length;
                            for (idx = 0; idx < len; ++idx) {
                                _explore(_path.join(currentPath, list[idx]));
                            }
                        }
                        _done();
                    });
*/

                } else {
                    if (match(filters, currentPath)) {
                        _gpfEventsFire.apply(null, [
                            _GPF_EVENT_DATA,
                            {
                                path: currentPath
                            },
                            eventsHandler
                        ]);
                    }
                }
                _done();

            });
        }
        _explore(basePath);
    }

};

// Create file system constants
(function () {
    var gpfFs = gpf.fs,
        mappings = {
            TYPE_NOT_FOUND: _GPF_FS_TYPE_NOT_FOUND,
            TYPE_FILE: _GPF_FS_TYPE_FILE,
            TYPE_DIRECTORY: _GPF_FS_TYPE_DIRECTORY,
            TYPE_UNKNOWN: _GPF_FS_TYPE_UNKNOWN
        },
        key;
    for (key in mappings) {
        if (mappings.hasOwnProperty(key)) {
            _gpfSetReadOnlyProperty(gpfFs, key, mappings[key]);
        }
    }

}());<|endoftext|>


<commit_before>// jNottery (c) 2014, Tomasz Zduńczyk <tomasz@zdunczyk.org>
// Released under the MIT license.

(function($) {
    var OBJ_NOTE = 0,
        OBJ_SELECTION = 1,
        OBJ_ELEMENT = 2;

    var last_range = null;

    window.tt = function(obj, context) {
        var $obj,
            target,
            obj_type;

        if(obj instanceof tt.core.Note) {
            if(obj instanceof tt.core.SelectionNote)
                $obj = tt.range.getElements(obj.range);
            else
                $obj = obj.element;

            target = obj;
            obj_type = OBJ_NOTE;
        } else if(obj.tt_selection && obj.tt_selection instanceof tt.core.Selection) {
            $obj = obj;
            target = obj.tt_selection;
            obj_type = OBJ_SELECTION;
        } else {
            $obj = new $.fn.init(obj, context);
            obj_type = OBJ_ELEMENT;
        }

        return $.extend({}, $obj, {
            arrowPosition: function(options) {
                return tt.tooltip.arrowPosition($.extend({}, { root: $(this) }, options));
            },
            tooltip: function(options) {
                var first_note,
                    tooltip,
                    add_note_to = $(this),
                    note_factory = function(content) {
                        return new tt.core.ElementNote(add_note_to, content);
                    };

                last_range && tt.range.clear(last_range);

                // stick to one note per element
                switch(obj_type) {
                    case OBJ_NOTE: {
                        add_note_to = target.element;
                        first_note = target;
                        break;
                    }
                    case OBJ_SELECTION: {
                        add_note_to = target.element;
                        last_range = target.range;

                        note_factory = function(content) {
                            last_range = null;
                            return new tt.core.SelectionNote(add_note_to, target.range, content);
                        };

                        break;
                    }
                    default: {
                        $.each(tt.core.getNotes($(this)), function(id, note) {
                            if(note instanceof tt.core.ElementNote) {
                                first_note = note;
                                return false;
                            }
                        });
                    }
                }

                tooltip = tt.tooltip.open($.extend({}, {
                    root: $(this),
                    edit: (first_note ? first_note.id : false),
                    content: (first_note ? first_note.getContent() : ''),
                    init: function(tooltip) {

                        tooltip.on({
                            'btn.edit.click.tt': function() {
                                tt.tooltip.switchEditMode(false);
                            },
                            'btn.submit.click.tt': function() {
                                tt.tooltip.switchEditMode(true);
                            },
                            'btn.facebook.click.tt': function() {
                                tt.vendor.facebook(document.URL);
                            },
                            'btn.twitter.click.tt': function() {
                                tt.vendor.bitly(document.URL, function(short_url) {
                                    tt.vendor.twitter(short_url);
                                });
                            },
                            'btn.link.click.tt': function() {
                                tt.vendor.bitly(document.URL, function(short_url) {
                                    window.prompt('Here is link to this page containing your notes (Ctrl + C to save in clipboard)', short_url);
                                });
                            },
                            'btn.save.click.tt': function() {
                                var agent = navigator.userAgent.toLowerCase(),
                                    letter = 'D';

                                if(window.opera && window.opera.version() < 9)
                                    letter = 'T';
                                else if(agent.indexOf('konqueror') !== -1)
                                    letter = 'B';

                                alert('Your notes are currently encoded in URL. Press ' + (agent.indexOf('mac') !== -1 ? 'Cmd' : 'Ctrl') + ' + ' + letter + ' to bookmark this page and all of your notes at once.');
                            }
                        });
                    }
                }, options));

                tooltip.off('submit.tt').on('submit.tt', function(e, tooltip) {
                    var note_id = tooltip.edit();

                    if(!note_id)
                        tooltip.edit(tt.core.addNote(note_factory(tooltip.content())));
                    else
                        tt.core.getNote(add_note_to, note_id).setContent(tooltip.content());

                    tt.core.updateHash();
                });

                tooltip.off('delete.tt').on('delete.tt', function(e, tooltip) {
                    var note_id = tooltip.edit();

                    if(note_id) {
                        tt.core.getNote(add_note_to, note_id).remove();
                        $(this).trigger('btn.close.click.tt');

                        tt.core.updateHash();
                    }
                });

                tooltip.off('close.tt');

                if(obj_type === OBJ_SELECTION) {
                    tooltip.on('close.tt', function(e, tooltip) {
                        if(!tooltip.edit()) {
                            tt.range.clear(target.range);
                            last_range = null;
                        }
                    });
                }

                return tooltip;
            },
            init: function(options) {
                if(!rangy.initialized)
                    rangy.init();

                tt.core.init($.extend({}, { root: $(this) }, options));

                if(options && options.vendor)
                    tt.vendor.init(options.vendor);

                return this;
            },
            selection: function() {
                var range = tt.range.getFrom($(this)),
                    result;

                tt.range.apply(range);
                result = tt.range.getElements(range);

                result.tt_selection = new tt.core.Selection($(this), range);
                return result;
            }
        });
    };

})(window.jQuery);<commit_msg>[feat] check if the content field has been left empty<commit_after>// jNottery (c) 2014, Tomasz Zduńczyk <tomasz@zdunczyk.org>
// Released under the MIT license.

(function($) {
    var OBJ_NOTE = 0,
        OBJ_SELECTION = 1,
        OBJ_ELEMENT = 2;

    var last_range = null;

    window.tt = function(obj, context) {
        var $obj,
            target,
            obj_type;

        if(obj instanceof tt.core.Note) {
            if(obj instanceof tt.core.SelectionNote)
                $obj = tt.range.getElements(obj.range);
            else
                $obj = obj.element;

            target = obj;
            obj_type = OBJ_NOTE;
        } else if(obj.tt_selection && obj.tt_selection instanceof tt.core.Selection) {
            $obj = obj;
            target = obj.tt_selection;
            obj_type = OBJ_SELECTION;
        } else {
            $obj = new $.fn.init(obj, context);
            obj_type = OBJ_ELEMENT;
        }

        return $.extend({}, $obj, {
            arrowPosition: function(options) {
                return tt.tooltip.arrowPosition($.extend({}, { root: $(this) }, options));
            },
            tooltip: function(options) {
                var first_note,
                    tooltip,
                    add_note_to = $(this),
                    note_factory = function(content) {
                        return new tt.core.ElementNote(add_note_to, content);
                    };

                last_range && tt.range.clear(last_range);

                // stick to one note per element
                switch(obj_type) {
                    case OBJ_NOTE: {
                        add_note_to = target.element;
                        first_note = target;
                        break;
                    }
                    case OBJ_SELECTION: {
                        add_note_to = target.element;
                        last_range = target.range;

                        note_factory = function(content) {
                            last_range = null;
                            return new tt.core.SelectionNote(add_note_to, target.range, content);
                        };

                        break;
                    }
                    default: {
                        $.each(tt.core.getNotes($(this)), function(id, note) {
                            if(note instanceof tt.core.ElementNote) {
                                first_note = note;
                                return false;
                            }
                        });
                    }
                }

                tooltip = tt.tooltip.open($.extend({}, {
                    root: $(this),
                    edit: (first_note ? first_note.id : false),
                    content: (first_note ? first_note.getContent() : ''),
                    init: function(tooltip) {

                        tooltip.on({
                            'btn.edit.click.tt': function() {
                                tt.tooltip.switchEditMode(false);
                            },
                            'btn.facebook.click.tt': function() {
                                tt.vendor.facebook(document.URL);
                            },
                            'btn.twitter.click.tt': function() {
                                tt.vendor.bitly(document.URL, function(short_url) {
                                    tt.vendor.twitter(short_url);
                                });
                            },
                            'btn.link.click.tt': function() {
                                tt.vendor.bitly(document.URL, function(short_url) {
                                    window.prompt('Here is link to this page containing your notes (Ctrl + C to save in clipboard)', short_url);
                                });
                            },
                            'btn.save.click.tt': function() {
                                var agent = navigator.userAgent.toLowerCase(),
                                    letter = 'D';

                                if(window.opera && window.opera.version() < 9)
                                    letter = 'T';
                                else if(agent.indexOf('konqueror') !== -1)
                                    letter = 'B';

                                alert('Your notes are currently encoded in URL. Press ' + (agent.indexOf('mac') !== -1 ? 'Cmd' : 'Ctrl') + ' + ' + letter + ' to bookmark this page and all of your notes at once.');
                            }
                        });
                    }
                }, options));

                tooltip.off('submit.tt').on('submit.tt', function(e, tooltip) {
                    var note_id = tooltip.edit(),
                        content = tooltip.content();

                    if(!content)
                        return false;

                    if(!note_id)
                        tooltip.edit(tt.core.addNote(note_factory(content)));
                    else
                        tt.core.getNote(add_note_to, note_id).setContent(content);

                    tt.tooltip.switchEditMode(true);
                    tt.core.updateHash();
                });

                tooltip.off('delete.tt').on('delete.tt', function(e, tooltip) {
                    var note_id = tooltip.edit();

                    if(note_id) {
                        tt.core.getNote(add_note_to, note_id).remove();
                        $(this).trigger('btn.close.click.tt');

                        tt.core.updateHash();
                    }
                });

                tooltip.off('close.tt');

                if(obj_type === OBJ_SELECTION) {
                    tooltip.on('close.tt', function(e, tooltip) {
                        if(!tooltip.edit()) {
                            tt.range.clear(target.range);
                            last_range = null;
                        }
                    });
                }

                return tooltip;
            },
            init: function(options) {
                if(!rangy.initialized)
                    rangy.init();

                tt.core.init($.extend({}, { root: $(this) }, options));

                if(options && options.vendor)
                    tt.vendor.init(options.vendor);

                return this;
            },
            selection: function() {
                var range = tt.range.getFrom($(this)),
                    result;

                tt.range.apply(range);
                result = tt.range.getElements(range);

                result.tt_selection = new tt.core.Selection($(this), range);
                return result;
            }
        });
    };

})(window.jQuery);<|endoftext|>


<commit_before>// --------------------------------------------------------------------------------------------------------------------
// tyn.io - (c) 2015 Tynio.
// --------------------------------------------------------------------------------------------------------------------

// core
var util = require('util')
var dgram = require('dgram')
var events = require('events')
var os = require('os')

// --------------------------------------------------------------------------------------------------------------------

var TYPES = {
  c : true,
  g : true,
  t : true,
  s : true,
}

function getPeriod(interval) {
  var period = Math.floor(Date.now() / interval) * interval
  return new Date(period)
}

function createStatsServer(opts, callback) {
  // check which options we have been given
  if ( !opts ) {
    opts = {}
  }
  if ( typeof opts === 'function') {
    callback = opts
    opts = {}
  }
  callback = callback || function() {}

  var port     = opts.port     || 9526
  var interval = opts.interval || 15 * 1000 // default: 15s
  var info = {
    pid : process.pid,
    host : os.hostname(),
  }

  // to emit 'stats' messages
  var ee = new events.EventEmitter()

  // remember which period we're currently in
  var currentPeriod

  // this is the data we'll use for this server
  var counters = {
    'statto.packets.total' : 0,
    'statto.msgs.total'    : 0,
    'statto.msgs.good'     : 0,
    'statto.msgs.bad'      : 0,
  }
  var timers   = {}
  var gauges   = {}
  var sets     = {}

  var server = dgram.createSocket('udp4')

  server.on("error", function (err) {
    // console.log("server error:\n" + err.stack)
    server.close()
    callback(err)
  })

  server.on('message', function (msg, rinfo) {
    ee.emit('debug', util.format('Received %d bytes from %s:%d', msg.length, rinfo.address, rinfo.port))

    // some meta stats
    counters['statto.packets.total']++

    // ToDo: convert op into multiple ops if string contains "\n"
    var op = msg.toString()
    op = op.replace(/\n$/, '')
    ee.emit('debug', 'Op = ' + op)

    // see what type of message this is:
    var parts = op.split(/:/)

    var type = parts[0]
    var key  = parts[1]
    var val  = type === 's' ? parts[2] : parts[2]|0

    counters['statto.msgs.total']++
    if ( type in TYPES ) {
      counters['statto.msgs.good']++
    }
    else {
      counters['statto.msgs.bad']++
      return
    }

    if ( type === 'c' ) {
      // this is a counter
      if ( !counters[key] ) {
        counters[key] = 0
      }
      counters[key] += val
    }
    else if ( type === 'g' ) {
      // gauge
      gauges[key] = val
    }
    else if ( type === 't' ) {
      // timer
      if ( !timers[key] ) {
        timers[key] = []
      }
      timers[key].push(val)
    }
    else if ( type === 's' ) {
      // set
      if ( !sets[key] ) {
        sets[key] = {}
      }
      if ( !sets[key][val] ) {
        sets[key][val] = 0
      }
      sets[key][val] += 1
    }
    else {
      throw new Error('Program error, unknown type ' + type)
    }
  })

  server.bind(port, function() {
    callback(null, port)
  })

  function flush() {
    // remember the last period and the stats
    var ts = currentPeriod.toISOString()
    var lastStats = {
      counters : counters,
      gauges   : gauges,
      timers   : timers,
      sets     : sets,
      info     : info,
      ts       : ts,
    }

    // now emit these on the nextTick
    process.nextTick(function() {
      ee.emit('stats', lastStats)
    })

    // reset the current stats
    counters = {
      'statto.packets.total' : 0,
      'statto.msgs.total'    : 0,
      'statto.msgs.good'     : 0,
      'statto.msgs.bad'      : 0,
    }
    timers   = {}
    gauges   = {}
    sets     = {}

    // set the new currentPeriod
    currentPeriod = getPeriod(interval)

    // figure out the next interval
    var nextPeriod = currentPeriod.getTime() + interval
    setTimeout(flush, nextPeriod - Date.now())
  }

  // set the new currentPeriod
  currentPeriod = getPeriod(interval)

  // figure out the next interval
  var nextPeriod = currentPeriod.getTime() + interval
  setTimeout(flush, nextPeriod - Date.now())

  return ee
}

// --------------------------------------------------------------------------------------------------------------------

module.exports = createStatsServer

// --------------------------------------------------------------------------------------------------------------------
<commit_msg>Add stats related to each set of timers<commit_after>// --------------------------------------------------------------------------------------------------------------------
// tyn.io - (c) 2015 Tynio.
// --------------------------------------------------------------------------------------------------------------------

// core
var util = require('util')
var dgram = require('dgram')
var events = require('events')
var os = require('os')

// --------------------------------------------------------------------------------------------------------------------

var TYPES = {
  c : true,
  g : true,
  t : true,
  s : true,
}

function getPeriod(interval) {
  var period = Math.floor(Date.now() / interval) * interval
  return new Date(period)
}

function createStatsServer(opts, callback) {
  // check which options we have been given
  if ( !opts ) {
    opts = {}
  }
  if ( typeof opts === 'function') {
    callback = opts
    opts = {}
  }
  callback = callback || function() {}

  var port     = opts.port     || 9526
  var interval = opts.interval || 15 * 1000 // default: 15s
  var info = {
    pid : process.pid,
    host : os.hostname(),
  }

  // to emit 'stats' messages
  var ee = new events.EventEmitter()

  // remember which period we're currently in
  var currentPeriod

  // this is the data we'll use for this server
  var counters = {
    'statto.packets.total' : 0,
    'statto.msgs.total'    : 0,
    'statto.msgs.good'     : 0,
    'statto.msgs.bad'      : 0,
  }
  var timers   = {}
  var gauges   = {}
  var sets     = {}

  var server = dgram.createSocket('udp4')

  server.on("error", function (err) {
    // console.log("server error:\n" + err.stack)
    server.close()
    callback(err)
  })

  server.on('message', function (msg, rinfo) {
    ee.emit('debug', util.format('Received %d bytes from %s:%d', msg.length, rinfo.address, rinfo.port))

    // some meta stats
    counters['statto.packets.total']++

    // ToDo: convert op into multiple ops if string contains "\n"
    var op = msg.toString()
    op = op.replace(/\n$/, '')
    ee.emit('debug', 'Op = ' + op)

    // see what type of message this is:
    var parts = op.split(/:/)

    var type = parts[0]
    var key  = parts[1]
    var val  = type === 's' ? parts[2] : parts[2]|0

    counters['statto.msgs.total']++
    if ( type in TYPES ) {
      counters['statto.msgs.good']++
    }
    else {
      counters['statto.msgs.bad']++
      return
    }

    if ( type === 'c' ) {
      // this is a counter
      if ( !counters[key] ) {
        counters[key] = 0
      }
      counters[key] += val
    }
    else if ( type === 'g' ) {
      // gauge
      gauges[key] = val
    }
    else if ( type === 't' ) {
      // timer
      if ( !timers[key] ) {
        timers[key] = []
      }
      timers[key].push(val)
    }
    else if ( type === 's' ) {
      // set
      if ( !sets[key] ) {
        sets[key] = {}
      }
      if ( !sets[key][val] ) {
        sets[key][val] = 0
      }
      sets[key][val] += 1
    }
    else {
      throw new Error('Program error, unknown type ' + type)
    }
  })

  server.bind(port, function() {
    callback(null, port)
  })

  function flush() {
    // remember the last period and the stats
    var ts = currentPeriod.toISOString()
    var lastStats = {
      counters : counters,
      gauges   : gauges,
      timers   : timers,
      sets     : sets,
      info     : info,
      ts       : ts,
    }

    // process some lastStats so the backends don't have to
    var timerKeys = Object.keys(lastStats.timers)
    timerKeys.forEach(function(timer) {
      // see if we have any data
      if ( lastStats.timers[timer].length === 0 ) {
        lastStats.timers[timer] = {}
      }

      // yes, got some timings, sort them first
      var times = lastStats.timers[timer].sort(function(a, b) { return a - b })

      // calculate some stats per timer
      var data = {
        sum   : times.reduce(function(a, b) { return a + b }),
        count : times.length,
        min   : times[0],
        max   : times[times.length-1],
        times : times,
      }
      data.mean = data.sum / data.count

      // find the median
      var middle = Math.floor(data.count/2)
      // take the middle value, or the average of the middle two
      var median = (data.count % 2) ? times[middle] : (times[middle-1] + times[middle])/2
      data.median = median

      // find the standard deviation
      var sumOfDiffs = 0
      for (var i = 0; i < data.count; i++) {
        sumOfDiffs += (times[i] - data.mean) * (times[i] - data.mean)
      }
      data.std = Math.sqrt(sumOfDiffs / data.count)

      lastStats.timers[timer] = data
    })

    // now emit these on the nextTick
    process.nextTick(function() {
      ee.emit('stats', lastStats)
    })

    // reset the current stats
    counters = {
      'statto.packets.total' : 0,
      'statto.msgs.total'    : 0,
      'statto.msgs.good'     : 0,
      'statto.msgs.bad'      : 0,
    }
    timers   = {}
    gauges   = {}
    sets     = {}

    // set the new currentPeriod
    currentPeriod = getPeriod(interval)

    // figure out the next interval
    var nextPeriod = currentPeriod.getTime() + interval
    setTimeout(flush, nextPeriod - Date.now())
  }

  // set the new currentPeriod
  currentPeriod = getPeriod(interval)

  // figure out the next interval
  var nextPeriod = currentPeriod.getTime() + interval
  setTimeout(flush, nextPeriod - Date.now())

  return ee
}

// --------------------------------------------------------------------------------------------------------------------

module.exports = createStatsServer

// --------------------------------------------------------------------------------------------------------------------
<|endoftext|>


<commit_before>var Cache = require('magazine'),
    cadence = require('cadence'),
    Cursor = require('./cursor'),
    fs = require('fs'),
    Queue = require('./queue'),
    Script = require('./script'),
    Sheaf = require('./sheaf'),
    Balancer = require('./balancer'),
    Descent = require('./descent'),
    Locker = require('./locker'),
    Player = require('./player'),
    Logger = require('./logger'),
    ok = require('assert').ok,
    path = require('path')

// TODO temporary
var scram = require('./scram')

function extend(to, from) {
    for (var key in from) to[key] = from[key]
    return to
}

function Strata (options) {
    if (!options.serializers) {
        var json = require('./json')
        options.serializers = {
            key: json.serializer,
            record: json.serializer
        }
        options.deserializers = {
            key: json.deserialize,
            record: json.deserialize
        }
    }
    if (!options.framer) {
        var UTF8 = require('./frame/utf8')
        options.framer = new UTF8(options.checksum || 'sha1')
    }
    options.player = new Player(options)
    this.sheaf = options.sheaf = new Sheaf(options)
    this.logger = new Logger(options)
}

Strata.prototype.create = cadence(function (async) {
    this.sheaf.createMagazine()
    var locker = this.sheaf.createLocker(), count = 0, root, leaf, journal
    async([function () {
        locker.dispose()
    }], function () {
        fs.stat(this.sheaf.directory, async())
    }, function (stat) {
        ok(stat.isDirectory(), 'database ' + this.sheaf.directory + ' is not a directory.')
    }, function () {
        fs.readdir(this.sheaf.directory, async())
    }, function (files) {
        ok(!files.filter(function (f) { return ! /^\./.test(f) }).length,
              'database ' + this.sheaf.directory + ' is not empty.')
        this.logger.mkdir(async())
    }, function () {
        root = locker.encache(this.sheaf.createPage(0))
        leaf = locker.encache(this.sheaf.createPage(1))
    }, [function () {
        locker.unlock(root)
        locker.unlock(leaf)
    }], function () {
        var script = this.logger.createScript()
        root.splice(0, 0, { address: leaf.address, heft: 0 })
        script.writeBranch(root)
        script.rewriteLeaf(leaf)
        script.commit(async())
    })
})

Strata.prototype.open = cadence(function (async) {
    this.sheaf.createMagazine()

    // TODO instead of rescue, you might try/catch the parts that you know
    // are likely to cause errors and raise an error of a Strata type.

    // TODO or you might need some way to catch a callback error. Maybe an
    // outer most catch block?

    // TODO or if you're using Cadence, doesn't the callback get wrapped
    // anyway?
    async(function () {
        fs.stat(this.sheaf.directory, async())
    }, function stat (error, stat) {
        fs.readdir(path.join(this.sheaf.directory, 'pages'), async())
    }, function (files) {
        files.forEach(function (file) {
            if (/^\d+\.\d+$/.test(file)) {
                this.sheaf.nextAddress = Math.max(+(file.split('.').shift()) + 1, this.sheaf.nextAddress)
            }
        }, this)
    })
})

Strata.prototype.close = cadence(function (async) {
    // TODO that's a lot of indirection.
    var cartridge = this.sheaf.metaRoot.cartridge, lock = cartridge.value.page.lock

    lock.unlock()
    // TODO
    lock.dispose()

    cartridge.release()

    var purge = this.sheaf.magazine.purge()
    while (purge.cartridge) {
        purge.cartridge.remove()
        purge.next()
    }
    purge.release()

    ok(!this.sheaf.magazine.count, 'pages still held by cache')
})

Strata.prototype.left = function (descents, exclusive, callback) {
    this.toLeaf(descents[0].left, descents, null, exclusive, callback)
}

Strata.prototype.right = function (descents, exclusive, callback) {
    this.toLeaf(descents[0].right, descents, null, exclusive, callback)
}

Strata.prototype.key = function (key) {
    return function (descents, exclusive, callback) {
        this.toLeaf(descents[0].key(key), descents, null, exclusive, callback)
    }
}

Strata.prototype.leftOf = function (key) {
    return cadence(function (async, descents, exclusive) {
        var conditions = [ descents[0].leaf, descents[0].found([key]) ]
        async(function () {
            descents[0].descend(descents[0].key(key), function () {
                return conditions.some(function (condition) {
                    return condition.call(descents[0])
                })
            }, async())
        }, function (page, index) {
            if (descents[0].page.address % 2) {
                return [ new Cursor(this.sheaf, this.logger, descents, false, key) ]
            } else {
                descents[0].setIndex(descents[0].index - 1)
                this.toLeaf(descents[0].right, descents, null, exclusive, async())
            }
        })
    })
}

Strata.prototype.toLeaf = cadence(function (async, sought, descents, key, exclusive) {
    async(function () {
        descents[0].descend(sought, descents[0].penultimate, async())
    }, function () {
        if (exclusive) descents[0].exclude()
        descents[0].descend(sought, descents[0].leaf, async())
    }, function () {
        return [ new Cursor(this.sheaf, this.logger, descents, exclusive, key) ]
    })
})

Strata.prototype.cursor = cadence(function (async, key, exclusive) {
    var descents = [ new Descent(this.sheaf, this.sheaf.createLocker()) ]
    async([function () {
        if (descents.length) {
            descents[0].locker.unlock(descents[0].page)
            descents[0].locker.dispose()
        }
    }], function () {
        if  (typeof key == 'function') {
            key.call(this, descents, exclusive, async())
        } else {
            this.toLeaf(descents[0].key(key), descents, key, exclusive, async())
        }
    }, function (cursor) {
        return [ cursor ]
    })
})

Strata.prototype.iterator = function (key, callback) {
    this.cursor(key, false, callback)
}

Strata.prototype.mutator = function (key, callback) {
    this.cursor(key, true, callback)
}

Strata.prototype.balance = function (callback) {
    new Balancer(this.sheaf, this.logger).balance(callback)
}

Strata.prototype.vivify = cadence(function (async) {
    var locker = this.sheaf.createLocker(), root

    function record (item) {
        return { address: item.address }
    }

    async(function () {
        locker.lock(0, false, async())
    }, function (page) {
        async([function () {
            locker.unlock(page)
            locker.dispose()
        }], function () {
            expand.call(this, page, root = page.items.map(record), 0, async())
        })
    })

    var expand = cadence(function (async, parent, pages, index) {
        var block = async(function () {
            if (index < pages.length) {
                var address = pages[index].address
                async(function () {
                    locker.lock(address, false, async())
                }, [function (page) {
                    console.log('foo', page)
                    locker.unlock(page)
                }], function (page) {
                    return page
                })
            } else {
                return [ block.break, pages ]
            }
        }, function (page) {
            if (page.address % 2 == 0) {
                async(function () {
                    pages[index].children = page.items.map(record)
                    if (index) {
                        pages[index].key = parent.items[index].key
                    }
                    expand.call(this, page, pages[index].children, 0, async())
                }, function () {
                    expand.call(this, parent, pages, index + 1, async())
                })
            } else {
                async(function () {
                    pages[index].children = []
                    pages[index].ghosts = page.ghosts

                    for (var i = 0, I = page.items.length; i < I; i++) {
                        pages[index].children.push(page.items[i].record)
                    }
                }, function () {
                    expand.call(this, parent, pages, index + 1, async())
                })
            }
        }, function () {
            return [ block.break, pages ]
        })()
    })
})

Strata.prototype.purge = function (downTo) {
    var purge = this.sheaf.magazine.purge()
    while (purge.cartridge && this.sheaf.magazine.heft > downTo) {
        purge.cartridge.remove()
        purge.next()
    }
    purge.release()
}

Strata.prototype.__defineGetter__('balanced', function () {
    ok(false)
    return ! Object.keys(this.sheaf.lengths).length
})

module.exports = Strata
<commit_msg>Finalizers are now working correctly.<commit_after>var Cache = require('magazine'),
    cadence = require('cadence'),
    Cursor = require('./cursor'),
    fs = require('fs'),
    Queue = require('./queue'),
    Script = require('./script'),
    Sheaf = require('./sheaf'),
    Balancer = require('./balancer'),
    Descent = require('./descent'),
    Locker = require('./locker'),
    Player = require('./player'),
    Logger = require('./logger'),
    ok = require('assert').ok,
    path = require('path')

// TODO temporary
var scram = require('./scram')

function extend(to, from) {
    for (var key in from) to[key] = from[key]
    return to
}

function Strata (options) {
    if (!options.serializers) {
        var json = require('./json')
        options.serializers = {
            key: json.serializer,
            record: json.serializer
        }
        options.deserializers = {
            key: json.deserialize,
            record: json.deserialize
        }
    }
    if (!options.framer) {
        var UTF8 = require('./frame/utf8')
        options.framer = new UTF8(options.checksum || 'sha1')
    }
    options.player = new Player(options)
    this.sheaf = options.sheaf = new Sheaf(options)
    this.logger = new Logger(options)
}

Strata.prototype.create = cadence(function (async) {
    this.sheaf.createMagazine()
    var locker = this.sheaf.createLocker(), count = 0, root, leaf, journal
    async([function () {
        locker.dispose()
    }], function () {
        fs.stat(this.sheaf.directory, async())
    }, function (stat) {
        ok(stat.isDirectory(), 'database ' + this.sheaf.directory + ' is not a directory.')
    }, function () {
        fs.readdir(this.sheaf.directory, async())
    }, function (files) {
        ok(!files.filter(function (f) { return ! /^\./.test(f) }).length,
              'database ' + this.sheaf.directory + ' is not empty.')
        this.logger.mkdir(async())
    }, function () {
        root = locker.encache(this.sheaf.createPage(0))
        leaf = locker.encache(this.sheaf.createPage(1))
    }, [function () {
        locker.unlock(root)
        locker.unlock(leaf)
    }], function () {
        var script = this.logger.createScript()
        root.splice(0, 0, { address: leaf.address, heft: 0 })
        script.writeBranch(root)
        script.rewriteLeaf(leaf)
        script.commit(async())
    })
})

Strata.prototype.open = cadence(function (async) {
    this.sheaf.createMagazine()

    // TODO instead of rescue, you might try/catch the parts that you know
    // are likely to cause errors and raise an error of a Strata type.

    // TODO or you might need some way to catch a callback error. Maybe an
    // outer most catch block?

    // TODO or if you're using Cadence, doesn't the callback get wrapped
    // anyway?
    async(function () {
        fs.stat(this.sheaf.directory, async())
    }, function stat (error, stat) {
        fs.readdir(path.join(this.sheaf.directory, 'pages'), async())
    }, function (files) {
        files.forEach(function (file) {
            if (/^\d+\.\d+$/.test(file)) {
                this.sheaf.nextAddress = Math.max(+(file.split('.').shift()) + 1, this.sheaf.nextAddress)
            }
        }, this)
    })
})

Strata.prototype.close = cadence(function (async) {
    // TODO that's a lot of indirection.
    var cartridge = this.sheaf.metaRoot.cartridge, lock = cartridge.value.page.lock

    lock.unlock()
    // TODO
    lock.dispose()

    cartridge.release()

    var purge = this.sheaf.magazine.purge()
    while (purge.cartridge) {
        purge.cartridge.remove()
        purge.next()
    }
    purge.release()

    ok(!this.sheaf.magazine.count, 'pages still held by cache')
})

Strata.prototype.left = function (descents, exclusive, callback) {
    this.toLeaf(descents[0].left, descents, null, exclusive, callback)
}

Strata.prototype.right = function (descents, exclusive, callback) {
    this.toLeaf(descents[0].right, descents, null, exclusive, callback)
}

Strata.prototype.key = function (key) {
    return function (descents, exclusive, callback) {
        this.toLeaf(descents[0].key(key), descents, null, exclusive, callback)
    }
}

Strata.prototype.leftOf = function (key) {
    return cadence(function (async, descents, exclusive) {
        var conditions = [ descents[0].leaf, descents[0].found([key]) ]
        async(function () {
            descents[0].descend(descents[0].key(key), function () {
                return conditions.some(function (condition) {
                    return condition.call(descents[0])
                })
            }, async())
        }, function (page, index) {
            if (descents[0].page.address % 2) {
                return [ new Cursor(this.sheaf, this.logger, descents, false, key) ]
            } else {
                descents[0].setIndex(descents[0].index - 1)
                this.toLeaf(descents[0].right, descents, null, exclusive, async())
            }
        })
    })
}

Strata.prototype.toLeaf = cadence(function (async, sought, descents, key, exclusive) {
    async(function () {
        descents[0].descend(sought, descents[0].penultimate, async())
    }, function () {
        if (exclusive) descents[0].exclude()
        descents[0].descend(sought, descents[0].leaf, async())
    }, function () {
        return [ new Cursor(this.sheaf, this.logger, descents, exclusive, key) ]
    })
})

Strata.prototype.cursor = cadence(function (async, key, exclusive) {
    var descents = [ new Descent(this.sheaf, this.sheaf.createLocker()) ]
    async([function () {
        if (descents.length) {
            descents[0].locker.unlock(descents[0].page)
            descents[0].locker.dispose()
        }
    }], function () {
        if  (typeof key == 'function') {
            key.call(this, descents, exclusive, async())
        } else {
            this.toLeaf(descents[0].key(key), descents, key, exclusive, async())
        }
    }, function (cursor) {
        return [ cursor ]
    })
})

Strata.prototype.iterator = function (key, callback) {
    this.cursor(key, false, callback)
}

Strata.prototype.mutator = function (key, callback) {
    this.cursor(key, true, callback)
}

Strata.prototype.balance = function (callback) {
    new Balancer(this.sheaf, this.logger).balance(callback)
}

Strata.prototype.vivify = cadence(function (async) {
    var locker = this.sheaf.createLocker(), root

    function record (item) {
        return { address: item.address }
    }

    async(function () {
        locker.lock(0, false, async())
    }, function (page) {
        async([function () {
            locker.unlock(page)
            locker.dispose()
        }], function () {
            expand.call(this, page, root = page.items.map(record), 0, async())
        })
    })

    var expand = cadence(function (async, parent, pages, index) {
        var block = async(function () {
            if (index < pages.length) {
                var address = pages[index].address
                async(function () {
                    locker.lock(address, false, async())
                }, [function (page) {
                    console.log('foo', page)
                    locker.unlock(page)
                }])
            } else {
                return [ block.break, pages ]
            }
        }, function (page) {
            if (page.address % 2 == 0) {
                async(function () {
                    pages[index].children = page.items.map(record)
                    if (index) {
                        pages[index].key = parent.items[index].key
                    }
                    expand.call(this, page, pages[index].children, 0, async())
                }, function () {
                    expand.call(this, parent, pages, index + 1, async())
                })
            } else {
                async(function () {
                    pages[index].children = []
                    pages[index].ghosts = page.ghosts

                    for (var i = 0, I = page.items.length; i < I; i++) {
                        pages[index].children.push(page.items[i].record)
                    }
                }, function () {
                    expand.call(this, parent, pages, index + 1, async())
                })
            }
        }, function () {
            return [ block.break, pages ]
        })()
    })
})

Strata.prototype.purge = function (downTo) {
    var purge = this.sheaf.magazine.purge()
    while (purge.cartridge && this.sheaf.magazine.heft > downTo) {
        purge.cartridge.remove()
        purge.next()
    }
    purge.release()
}

Strata.prototype.__defineGetter__('balanced', function () {
    ok(false)
    return ! Object.keys(this.sheaf.lengths).length
})

module.exports = Strata
<|endoftext|>


<commit_before>// services/pulse-wire.js
// Copyright (C) 2014 Rob Colbert <rob.isConnected@gmail.com>

'use strict';
/* global io:false */

function PulseWire($rootScope, Configuration, UserSession) {
  this.$rootScope = $rootScope;
  this.Configuration = Configuration;
  this.UserSession = UserSession;
  this.open = false;
  this.connect();
}

PulseWire.prototype.connect = function ( ) {
  var connectUrl = this.Configuration.buildApiUrl('/');
  connectUrl = 'http://localhost:10010/';
  console.log('socket.io connecting to', connectUrl);
  this.socket = io.connect(connectUrl);
  this.attach();
};

PulseWire.prototype.emit = function (eventName, eventData) {
  this.socket.emit(eventName, eventData);
};

PulseWire.prototype.attach = function ( ) {
  var self = this;

  this.socket.on('hello', function (data) {
    console.log('pulsewire.hello', data);
    self.server = data;
    self.open = true;
    self.$rootScope.$broadcast('pulsewire.hello', data);
  });

  this.socket.on('post', function (data) {
    console.log('pulsewire.post', data);
    self.$rootScope.$broadcast('pulsewire.post', data);
  });

  this.socket.on('thought', function (data) {
    console.log('pulsewire.thought', data);
    self.$rootScope.$broadcast('pulsewire.thought', data);
  });

  this.socket.on('comment', function (data) {
    console.log('pulsewire.comment', data);
    self.$rootScope.$broadcast('pulsewire.comment', data);
  });

  this.socket.on('mail', function (data) {
    console.log('pulsewire.mail', data);
    self.$rootScope.$broadcast('pulsewire.mail', data);
  });

  this.socket.on('message', function (data) {
    console.log('pulsewire.message', data);
    self.$rootScope.$broadcast('pulsewire.message', data);
  });
};

PulseWire.$inject = [
  '$rootScope',
  'Configuration',
  'UserSession'
];

angular.module('robcolbertApp')
.service('PulseWire', PulseWire);
<commit_msg>PulseWire connect fix for prod<commit_after>// services/pulse-wire.js
// Copyright (C) 2014 Rob Colbert <rob.isConnected@gmail.com>

'use strict';
/* global io:false */

function PulseWire($rootScope, Configuration, UserSession) {
  this.$rootScope = $rootScope;
  this.Configuration = Configuration;
  this.UserSession = UserSession;
  this.open = false;
  this.connect();
}

PulseWire.prototype.connect = function ( ) {
  var connectUrl = this.Configuration.buildApiUrl('/');
  //connectUrl = 'http://localhost:10010/';
  console.log('socket.io connecting to', connectUrl);
  this.socket = io.connect(connectUrl);
  this.attach();
};

PulseWire.prototype.emit = function (eventName, eventData) {
  this.socket.emit(eventName, eventData);
};

PulseWire.prototype.attach = function ( ) {
  var self = this;

  this.socket.on('hello', function (data) {
    console.log('pulsewire.hello', data);
    self.server = data;
    self.open = true;
    self.$rootScope.$broadcast('pulsewire.hello', data);
  });

  this.socket.on('post', function (data) {
    console.log('pulsewire.post', data);
    self.$rootScope.$broadcast('pulsewire.post', data);
  });

  this.socket.on('thought', function (data) {
    console.log('pulsewire.thought', data);
    self.$rootScope.$broadcast('pulsewire.thought', data);
  });

  this.socket.on('comment', function (data) {
    console.log('pulsewire.comment', data);
    self.$rootScope.$broadcast('pulsewire.comment', data);
  });

  this.socket.on('mail', function (data) {
    console.log('pulsewire.mail', data);
    self.$rootScope.$broadcast('pulsewire.mail', data);
  });

  this.socket.on('message', function (data) {
    console.log('pulsewire.message', data);
    self.$rootScope.$broadcast('pulsewire.message', data);
  });
};

PulseWire.$inject = [
  '$rootScope',
  'Configuration',
  'UserSession'
];

angular.module('robcolbertApp')
.service('PulseWire', PulseWire);
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import PropTypes from 'prop-types'
import {
  Text, View, StyleSheet, Dimensions,
  Modal, TouchableHighlight, Animated, ScrollView
} from 'react-native'
import styles, { btnStyle, sheetStyle, hairlineWidth } from './styles'

const TITLE_H = 40
const MESSAGE_H = 40
const CANCEL_MARGIN = 6
const BUTTON_H = 50 + hairlineWidth
const WARN_COLOR = '#ff3b30'
const MAX_HEIGHT = Dimensions.get('window').height * 0.7

class ActionSheet extends Component {
  constructor (props) {
    super(props)
    this.scrollEnabled = false
    this.translateY = this._calculateHeight(props)
    this.state = {
      visible: false,
      sheetAnim: new Animated.Value(this.translateY)
    }
    this._cancel = this._cancel.bind(this)
  }

  componentWillReceiveProps (nextProps) {
    this.translateY = this._calculateHeight(nextProps)
  }

  show () {
    this.setState({visible: true})
    this._showSheet()
  }

  hide (index) {
    this._hideSheet(() => {
      this.setState({visible: false})
      this.props.onPress(index)
    })
  }

  _cancel () {
    const { cancelButtonIndex } = this.props
    // 保持和 ActionSheetIOS 一致，
    // 未设置 cancelButtonIndex 时，点击背景不隐藏 ActionSheet
    if (cancelButtonIndex > -1) {
      this.hide(cancelButtonIndex)
    }
  }

  _showSheet () {
    Animated.timing(this.state.sheetAnim, {
      toValue: 0,
      duration: 250
    }).start()
  }

  _hideSheet (callback) {
    Animated.timing(this.state.sheetAnim, {
      toValue: this.translateY,
      duration: 150
    }).start(callback || function () {})
  }

  get cancelMargin() {
    return this.props.cancelMargin || CANCEL_MARGIN;
  }

  _calculateHeight (props) {
    let count = props.options.length
    let height = BUTTON_H * count + this.cancelMargin
    if (props.title) height += TITLE_H
    if (props.message) height += MESSAGE_H
    if (height > MAX_HEIGHT) {
      this.scrollEnabled = true
      return MAX_HEIGHT
    } else {
      this.scrollEnabled = false
      return height
    }
  }

  _renderTitle () {
    const title = this.props.title

    if (!title) {
      return null
    }

    if (React.isValidElement(title)) {
      return (
        <View style={sheetStyle.title}>{title}</View>
      )
    }

    return (
      <View style={[sheetStyle.title, this.props.titleWrapperStyle]}>
        <Text style={[sheetStyle.titleText, this.props.titleTextStyle]}>{title}</Text>
      </View>
    )
  }

  _renderMessage () {
    const message = this.props.message

    if (!message) {
      return null
    }

    if (React.isValidElement(message)) {
      return (
        <View style={sheetStyle.message}>{message}</View>
      )
    }

    return (
      <View style={sheetStyle.message}>
        <Text style={sheetStyle.titleText}>{message}</Text>
      </View>
    )
  }

  _renderCancelButton () {
    let {options, cancelButtonIndex, tintColor} = this.props
    if (cancelButtonIndex > -1 && options[cancelButtonIndex]) {
      return (
        <TouchableHighlight
          activeOpacity={1}
          underlayColor="#f4f4f4"
          style={[btnStyle.wrapper, {marginTop: 6}, this.props.buttonWrapperStyle, this.props.cancelButtonWrapperStyle]}
          onPress={this._cancel}
        >
          <Text style={[btnStyle.title, {fontWeight: '700', color: tintColor}, this.props.cancelButtonTitleStyle]}>{options[cancelButtonIndex]}</Text>
        </TouchableHighlight>
      )
    } else {
      return null
    }
  }

  _createButton (title, fontColor, index, style) {
    let titleNode = null
    if (React.isValidElement(title)) {
      titleNode = title
    } else {
      titleNode = <Text style={[btnStyle.title, {color: fontColor}, this.props.buttonTitleStyle]}>{title}</Text>
    }
    return (
      <TouchableHighlight
        key={index}
        activeOpacity={1}
        underlayColor="#f4f4f4"
        style={[btnStyle.wrapper, style || {}, this.props.buttonWrapperStyle]}
        onPress={this.hide.bind(this, index)}
      >
        {titleNode}
      </TouchableHighlight>
    )
  }

  _renderOptions () {
    let {options, tintColor, cancelButtonIndex, destructiveButtonIndex} = this.props
    return options.map((title, index) => {
      let fontColor = destructiveButtonIndex === index ? WARN_COLOR : tintColor
      return index === cancelButtonIndex ? null : this._createButton(title, fontColor, index)
    })
  }

  render () {
    const { cancelButtonIndex } = this.props
    const { visible, sheetAnim } = this.state

    return (
      <Modal
        visible={visible}
        transparent={true}
        animationType="none"
        onRequestClose={this._cancel}
      >
        <View style={[sheetStyle.wrapper, this.props.wrapperStyle]}>
          <Text style={[styles.overlay, this.props.overlayStyle]} onPress={this._cancel}></Text>
          <Animated.View
            style={[sheetStyle.bd, {height: this.translateY, transform: [{translateY: sheetAnim}]}, this.props.bodyStyle]}
          >
            {this._renderTitle()}
            {this._renderMessage()}
            <ScrollView
              scrollEnabled={this.scrollEnabled}
              contentContainerStyle={sheetStyle.options}>
              {this._renderOptions()}
            </ScrollView>
            {this._renderCancelButton()}
          </Animated.View>
        </View>
      </Modal>
    )
  }
}

ActionSheet.propTypes = {
  title: PropTypes.oneOfType([ PropTypes.string, PropTypes.element]),
  message: PropTypes.oneOfType([ PropTypes.string, PropTypes.element]),
  options: PropTypes.arrayOf((propVal, key, componentName, location, propFullName) => {
    if (typeof propVal[key] !== 'string' && !React.isValidElement(propVal[key])) {
      return new Error(
        'Invalid prop `' + propFullName + '` supplied to' +
        ' `' + componentName + '`. Validation failed.'
      )
    }
  }),
  tintColor: PropTypes.string,
  cancelButtonIndex: PropTypes.number,
  destructiveButtonIndex: PropTypes.number,
  onPress: PropTypes.func
}

ActionSheet.defaultProps = {
  tintColor: '#007aff',
  onPress: () => {}
}

export default ActionSheet
<commit_msg>Underlay color prop<commit_after>import React, { Component } from 'react'
import PropTypes from 'prop-types'
import {
  Text, View, StyleSheet, Dimensions,
  Modal, TouchableHighlight, Animated, ScrollView
} from 'react-native'
import styles, { btnStyle, sheetStyle, hairlineWidth } from './styles'

const TITLE_H = 40
const MESSAGE_H = 40
const CANCEL_MARGIN = 6
const BUTTON_H = 50 + hairlineWidth
const WARN_COLOR = '#ff3b30'
const MAX_HEIGHT = Dimensions.get('window').height * 0.7

class ActionSheet extends Component {
  constructor (props) {
    super(props)
    this.scrollEnabled = false
    this.translateY = this._calculateHeight(props)
    this.state = {
      visible: false,
      sheetAnim: new Animated.Value(this.translateY)
    }
    this._cancel = this._cancel.bind(this)
  }

  componentWillReceiveProps (nextProps) {
    this.translateY = this._calculateHeight(nextProps)
  }

  show () {
    this.setState({visible: true})
    this._showSheet()
  }

  hide (index) {
    this._hideSheet(() => {
      this.setState({visible: false})
      this.props.onPress(index)
    })
  }

  _cancel () {
    const { cancelButtonIndex } = this.props
    // 保持和 ActionSheetIOS 一致，
    // 未设置 cancelButtonIndex 时，点击背景不隐藏 ActionSheet
    if (cancelButtonIndex > -1) {
      this.hide(cancelButtonIndex)
    }
  }

  _showSheet () {
    Animated.timing(this.state.sheetAnim, {
      toValue: 0,
      duration: 250
    }).start()
  }

  _hideSheet (callback) {
    Animated.timing(this.state.sheetAnim, {
      toValue: this.translateY,
      duration: 150
    }).start(callback || function () {})
  }

  get cancelMargin() {
    return this.props.cancelMargin || CANCEL_MARGIN;
  }

  _calculateHeight (props) {
    let count = props.options.length
    let height = BUTTON_H * count + this.cancelMargin
    if (props.title) height += TITLE_H
    if (props.message) height += MESSAGE_H
    if (height > MAX_HEIGHT) {
      this.scrollEnabled = true
      return MAX_HEIGHT
    } else {
      this.scrollEnabled = false
      return height
    }
  }

  _renderTitle () {
    const title = this.props.title

    if (!title) {
      return null
    }

    if (React.isValidElement(title)) {
      return (
        <View style={sheetStyle.title}>{title}</View>
      )
    }

    return (
      <View style={[sheetStyle.title, this.props.titleWrapperStyle]}>
        <Text style={[sheetStyle.titleText, this.props.titleTextStyle]}>{title}</Text>
      </View>
    )
  }

  _renderMessage () {
    const message = this.props.message

    if (!message) {
      return null
    }

    if (React.isValidElement(message)) {
      return (
        <View style={sheetStyle.message}>{message}</View>
      )
    }

    return (
      <View style={sheetStyle.message}>
        <Text style={sheetStyle.titleText}>{message}</Text>
      </View>
    )
  }

  _renderCancelButton () {
    let {options, cancelButtonIndex, tintColor} = this.props
    if (cancelButtonIndex > -1 && options[cancelButtonIndex]) {
      return (
        <TouchableHighlight
          activeOpacity={1}
          underlayColor={this.props.buttonUnderlayColor || "#f4f4f4"}
          style={[btnStyle.wrapper, {marginTop: 6}, this.props.buttonWrapperStyle, this.props.cancelButtonWrapperStyle]}
          onPress={this._cancel}
        >
          <Text style={[btnStyle.title, {fontWeight: '700', color: tintColor}, this.props.cancelButtonTitleStyle]}>{options[cancelButtonIndex]}</Text>
        </TouchableHighlight>
      )
    } else {
      return null
    }
  }

  _createButton (title, fontColor, index, style) {
    let titleNode = null
    if (React.isValidElement(title)) {
      titleNode = title
    } else {
      titleNode = <Text style={[btnStyle.title, {color: fontColor}, this.props.buttonTitleStyle]}>{title}</Text>
    }
    return (
      <TouchableHighlight
        key={index}
        activeOpacity={1}
        underlayColor={this.props.buttonUnderlayColor || "#f4f4f4"}
        style={[btnStyle.wrapper, style || {}, this.props.buttonWrapperStyle]}
        onPress={this.hide.bind(this, index)}
      >
        {titleNode}
      </TouchableHighlight>
    )
  }

  _renderOptions () {
    let {options, tintColor, cancelButtonIndex, destructiveButtonIndex} = this.props
    return options.map((title, index) => {
      let fontColor = destructiveButtonIndex === index ? WARN_COLOR : tintColor
      return index === cancelButtonIndex ? null : this._createButton(title, fontColor, index)
    })
  }

  render () {
    const { cancelButtonIndex } = this.props
    const { visible, sheetAnim } = this.state

    return (
      <Modal
        visible={visible}
        transparent={true}
        animationType="none"
        onRequestClose={this._cancel}
      >
        <View style={[sheetStyle.wrapper, this.props.wrapperStyle]}>
          <Text style={[styles.overlay, this.props.overlayStyle]} onPress={this._cancel}></Text>
          <Animated.View
            style={[sheetStyle.bd, {height: this.translateY, transform: [{translateY: sheetAnim}]}, this.props.bodyStyle]}
          >
            {this._renderTitle()}
            {this._renderMessage()}
            <ScrollView
              scrollEnabled={this.scrollEnabled}
              contentContainerStyle={sheetStyle.options}>
              {this._renderOptions()}
            </ScrollView>
            {this._renderCancelButton()}
          </Animated.View>
        </View>
      </Modal>
    )
  }
}

ActionSheet.propTypes = {
  title: PropTypes.oneOfType([ PropTypes.string, PropTypes.element]),
  message: PropTypes.oneOfType([ PropTypes.string, PropTypes.element]),
  options: PropTypes.arrayOf((propVal, key, componentName, location, propFullName) => {
    if (typeof propVal[key] !== 'string' && !React.isValidElement(propVal[key])) {
      return new Error(
        'Invalid prop `' + propFullName + '` supplied to' +
        ' `' + componentName + '`. Validation failed.'
      )
    }
  }),
  tintColor: PropTypes.string,
  cancelButtonIndex: PropTypes.number,
  destructiveButtonIndex: PropTypes.number,
  onPress: PropTypes.func
}

ActionSheet.defaultProps = {
  tintColor: '#007aff',
  onPress: () => {}
}

export default ActionSheet
<|endoftext|>


<commit_before>'strict use'

var tableHeader = ['Customer Name', 'Address', 'Credit Card Type', 'Credit Card Number', '# of Choc Chip', '# of Oat Raisin', '# of Cutters', '# of shirts', 'Total Cost (includes sales tax)', 'Process Order'];
var OrdersTable = document.getElementById('orders');
var el2;
var elContent = '';
var el;
var storedString = localStorage.order;
var orders = storedString.split(',');
var butt = document.getElementById('button');

function appendEl(elContent) { //creates and appends an element, relies on global variables
  el = document.createElement('td');
  el.textContent = elContent;
  el2.appendChild(el);
  OrdersTable.appendChild(el2);
}

function makeHeader() {
  el2 = document.createElement('tr');
  for (var i = 0; i < tableHeader.length; i++) {
    appendEl(tableHeader[i]);
  }
}

function makeTable() {
  makeHeader();
  el2 = document.createElement('tr');
  for (var j = 0; j < orders.length + 1; j++) {
    if (j % (tableHeader.length - 1) === 0 && j != 0) {
      var filledButton = document.createElement('button');
      filledButton.type = 'button';
      var buttonText = document.createTextNode('Fill Order ' + j/(tableHeader.length - 1));
      filledButton.appendChild(buttonText);
      el2.appendChild(filledButton);
      OrdersTable.appendChild(el2);
      el2 = document.createElement('tr');
    }
    elContent = orders[j];
    appendEl(elContent);
  }
}

function filledHandler(event) {
  alert('in the handler, yay!')
}

if(localStorage.order) {
  makeTable();
}

butt.addEventListener('onclick', filledHandler(event));
<commit_msg>added fill order buttons, removed order from js array<commit_after>'strict use'

var tableHeader = ['Customer Name', 'Address', 'Credit Card Type', 'Credit Card Number', '# of Choc Chip', '# of Oat Raisin', '# of Cutters', '# of shirts', 'Total Cost (includes sales tax)', 'Process Order'];
var OrdersTable = document.getElementById('orders');
var el2;
var elContent = '';
var el;
var storedString = localStorage.order;
var orders = storedString.split(',');
var removedOrder = [];

function appendEl(elContent) { //creates and appends an element, relies on global variables
  el = document.createElement('td');
  el.textContent = elContent;
  el2.appendChild(el);
  OrdersTable.appendChild(el2);
}

function makeHeader() {
  el2 = document.createElement('tr');
  for (var i = 0; i < tableHeader.length; i++) {
    appendEl(tableHeader[i]);
  }
}

function makeTable() {
  makeHeader();
  el2 = document.createElement('tr');
  for (var j = 0; j < orders.length + 1; j++) {
    if (j % (tableHeader.length - 1) === 0 && j != 0) {
      var filledButton = document.createElement('button');
      filledButton.name = j/(tableHeader.length - 1);
      var buttonText = document.createTextNode('Fill Order');
      filledButton.appendChild(buttonText);
      el2.appendChild(filledButton);
      OrdersTable.appendChild(el2);
      el2 = document.createElement('tr');
    }
    elContent = orders[j];
    appendEl(elContent);
  }
}

function removeFromOrders(OrderNum) {
  var start = OrderNum*(tableHeader.length - 1) - (tableHeader.length - 1); //where to start removing from the orders array
  var end = OrderNum*(tableHeader.length - 1);
  for (var i = start; i < end; i++) {
    removedOrder.push(orders[i]);
  }
}

function filledHandler(event) {
  event.preventDefault();
  var orderNum = event.target.name; //figure out which order needs to be moved;
  removeFromOrders(orderNum);
  console.log(removedOrder);
  // switchLocalStorage();
  // makeTable();
}

if(localStorage.order) {
  makeTable();
}

document.addEventListener('click', filledHandler);
<|endoftext|>