<commit_before>; (function () {
    var initializing = !1, fnTest = /xyz/.test(function () { xyz }) ? /\b_super\b/ : /.*/, __class = function () { }; __class.export = []; __class.extend = function (n) { __class.export.push(n); function i() { !initializing && this.ctor && this.ctor.apply(this, arguments) } var f = this.prototype, u, r, t; initializing = !0, u = new this, initializing = !1; for (t in n) t != "statics" && (u[t] = typeof n[t] == "function" && typeof f[t] == "function" && fnTest.test(n[t]) ? function (n, t) { return function () { var r = this._super, i; return this._super = f[n], i = t.apply(this, arguments), this._super = r, i } }(t, n[t]) : n[t]); for (r in this) this.hasOwnProperty(r) && r != "extend" && (i[r] = this[r]); if (i.prototype = u, n.statics) for (t in n.statics) n.statics.hasOwnProperty(t) && (i[t] = n.statics[t], t == "ctor" && i[t]()); return i.prototype.constructor = i, i.extend = arguments.callee, i.implement = function (n) { for (var t in n) u[t] = n[t] }, i };

    var observable = __class.extend({
        "statics": {
            "ctor": function () {
                this.methods = ["concat", "every", "filter", "forEach", "indexOf", "join", "lastIndexOf", "map", "pop", "push", "reduce", "reduceRight", "reverse", "shift", "slice", "some", "sort", "splice", "unshift", "valueOf"],
                this.triggerStr = ["concat", "pop", "push", "reverse", "shift", "sort", "splice", "unshift"].join(",");
            },
            "type": function (obj) {
                var typeStr = Object.prototype.toString.call(obj).split(" ")[1];
                return typeStr.substr(0, typeStr.length - 1).toLowerCase();
            },
            "isArray": function (obj) {
                return this.type(obj) == "array";
            },
            "isInArray": function (arr, item) {
                for (var i = arr.length; --i > -1;) {
                    if (item === arr[i]) return true;
                }
                return false;
            },
            "isFunction": function (obj) {
                return this.type(obj) == "function";
            },
            "watch": function (target, arr) {
                return new this(target, arr);
            }
        },
        "ctor": function (target, arr) {
            for (var prop in target) {
                if (target.hasOwnProperty(prop)) {
                    if ((arr && observable.isInArray(arr, prop)) || !arr) {
                        this.watch(target, prop);
                    }
                }
            }
            if (target.change) throw "naming conflicts！observable will extend 'change' method to your object ."
            var self = this;
            target.change = function (fn) {
                self.propertyChangedHandler = fn;
            }
        },
        "onPropertyChanged": function (prop, value) {
            this.propertyChangedHandler && this.propertyChangedHandler(prop, value);
        },
        "mock": function (target) {
            var self = this;
            observable.methods.forEach(function (item) {
                target[item] = function () {
                    var result = Array.prototype[item].apply(this, Array.prototype.slice.call(arguments));
                    for (var cprop in this) {
                        if (this.hasOwnProperty(cprop) && cprop != "_super" && !observable.isFunction(this[cprop])) {
                            self.watch(this, cprop);
                        }
                    }
                    if (new RegExp("\\b" + item + "\\b").test(observable.triggerStr)) {
                        self.onPropertyChanged("array", item);
                    }
                    return result;
                };
            });
        },
        "watch": function (target, prop) {
            if (prop.substr(0, 2) == "__") return;
            var self = this;
            if (observable.isFunction(target[prop])) return;

            var currentValue = target["__" + prop] = target[prop];
            Object.defineProperty(target, prop, {
                get: function () {
                    return this["__" + prop];
                },
                set: function (value) {
                    this["__" + prop] = value;
                    self.onPropertyChanged(prop, value);
                }
            });

            if (observable.isArray(target)) {
                this.mock(target);
            }
            if (typeof currentValue == "object") {
                if (observable.isArray(currentValue)) {
                    this.mock(currentValue);
                }
                for (var cprop in currentValue) {
                    if (currentValue.hasOwnProperty(cprop) && cprop != "_super") {
                        this.watch(currentValue, cprop);
                    }
                }
            }
        }
    });

    var matrix3D = __class.extend({

        statics: {
            DEG_TO_RAD: Math.PI / 180
        },
        ctor: function (n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44) {

            this.elements = Float32Array ? new Float32Array(16) : [];

            // TODO: if n11 is undefined, then just set to identity, otherwise copy all other values into matrix
            //   we should not support semi specification of Matrix4, it is just weird.

            var te = this.elements;

            te[0] = (n11 !== undefined) ? n11 : 1; te[4] = n12 || 0; te[8] = n13 || 0; te[12] = n14 || 0;
            te[1] = n21 || 0; te[5] = (n22 !== undefined) ? n22 : 1; te[9] = n23 || 0; te[13] = n24 || 0;
            te[2] = n31 || 0; te[6] = n32 || 0; te[10] = (n33 !== undefined) ? n33 : 1; te[14] = n34 || 0;
            te[3] = n41 || 0; te[7] = n42 || 0; te[11] = n43 || 0; te[15] = (n44 !== undefined) ? n44 : 1;
        },
        set: function (n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44) {

            var te = this.elements;

            te[0] = n11; te[4] = n12; te[8] = n13; te[12] = n14;
            te[1] = n21; te[5] = n22; te[9] = n23; te[13] = n24;
            te[2] = n31; te[6] = n32; te[10] = n33; te[14] = n34;
            te[3] = n41; te[7] = n42; te[11] = n43; te[15] = n44;

            return this;

        },
        identity: function () {
            this.set(

               1, 0, 0, 0,
               0, 1, 0, 0,
               0, 0, 1, 0,
               0, 0, 0, 1

           );

            return this;
        },
        append: function (m) {
            return this.multiplyMatrices(this, m);

        },
        multiplyMatrices: function (a, b) {

            var ae = a.elements;
            var be = b.elements;
            var te = this.elements;

            var a11 = ae[0], a12 = ae[4], a13 = ae[8], a14 = ae[12];
            var a21 = ae[1], a22 = ae[5], a23 = ae[9], a24 = ae[13];
            var a31 = ae[2], a32 = ae[6], a33 = ae[10], a34 = ae[14];
            var a41 = ae[3], a42 = ae[7], a43 = ae[11], a44 = ae[15];

            var b11 = be[0], b12 = be[4], b13 = be[8], b14 = be[12];
            var b21 = be[1], b22 = be[5], b23 = be[9], b24 = be[13];
            var b31 = be[2], b32 = be[6], b33 = be[10], b34 = be[14];
            var b41 = be[3], b42 = be[7], b43 = be[11], b44 = be[15];

            te[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
            te[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
            te[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
            te[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;

            te[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
            te[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
            te[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
            te[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;

            te[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
            te[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
            te[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
            te[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;

            te[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
            te[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
            te[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
            te[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;

            return this;

        },
        appendTransform: function (perspective, x, y, z, scaleX, scaleY, scaleZ, rotateX, rotateY, rotateZ, regX, regY, regZ) {

            var rx = rotateX * matrix3D.DEG_TO_RAD;
            var cosx = Math.cos(rx);
            var sinx = Math.sin(rx);

            var ry = rotateY * matrix3D.DEG_TO_RAD;
            var cosy = Math.cos(ry);
            var siny = Math.sin(ry);
            var rz = rotateZ * matrix3D.DEG_TO_RAD;
            var cosz = Math.cos(rz*-1);
            var sinz = Math.sin(rz*-1);

            this.append(new matrix3D(
                cosy, 0, siny, x,
                0, 1, 0, y,
                -siny, 0, cosy, z,
                siny / perspective, 0, -cosy / perspective, (perspective - z) / perspective
            ));

            this.append(new matrix3D(
                1, 0, 0, 0,
                0, cosx, sinx, 0,
                0, -sinx, cosx, 0,
                0, sinx / perspective, -cosx / perspective, 1
            ));

                this.append(new matrix3D(
                    cosz * scaleX, sinz * scaleY, 0, 0,
                   -sinz * scaleX, cosz * scaleY, 0, 0,
                    0, 0, 1 * scaleZ, 0,
                   0, 0, -1 / perspective, 1
                ));

            if (regX || regY || regZ) {

                this.elements[12] -= regX * this.elements[0] + regY * this.elements[4] + regZ * this.elements[8];
                this.elements[13] -= regX * this.elements[1] + regY * this.elements[5] + regZ * this.elements[9];
                this.elements[14] -= regX * this.elements[2] + regY * this.elements[6] + regZ * this.elements[10];
            }
            return this;
        }

    });

    window.Transform = function (element) {
            element.perspective = 400;
            element.scaleX = element.scaleY = element.scaleZ = 1;
            element.x = element.y = element.z = element.rotateX = element.rotateY = element.rotateZ = element.regX = element.regY = element.skewX = element.skewY = element.regX = element.regY = element.regZ = 0;
            element.matrix3D = new matrix3D();
            var observer = observable.watch(element, ["x", "y", "z", "scaleX", "scaleY", "scaleZ", "perspective", "rotateX", "rotateY", "rotateZ", "regX", "regY", "regZ"]);

            this.element = element;
            var self = this;
            observer.propertyChangedHandler = function () {
                var mtx = self.element.matrix3D.identity().appendTransform(self.element.perspective, self.element.x, self.element.y, self.element.z, self.element.scaleX, self.element.scaleY, self.element.scaleZ, self.element.rotateX, self.element.rotateY, self.element.rotateZ, self.element.regX, self.element.regY, self.element.regZ);

                self.element.style.transform = self.element.style.msTransform = self.element.style.OTransform = self.element.style.MozTransform = self.element.style.webkitTransform = "matrix3d(" + Array.prototype.slice.call(mtx.elements).join(",") + ")";
            }
        }

})();<commit_msg>all in one cmt<commit_after>; (function () {
    var initializing = !1, fnTest = /xyz/.test(function () { xyz }) ? /\b_super\b/ : /.*/, __class = function () { }; __class.export = []; __class.extend = function (n) { __class.export.push(n); function i() { !initializing && this.ctor && this.ctor.apply(this, arguments) } var f = this.prototype, u, r, t; initializing = !0, u = new this, initializing = !1; for (t in n) t != "statics" && (u[t] = typeof n[t] == "function" && typeof f[t] == "function" && fnTest.test(n[t]) ? function (n, t) { return function () { var r = this._super, i; return this._super = f[n], i = t.apply(this, arguments), this._super = r, i } }(t, n[t]) : n[t]); for (r in this) this.hasOwnProperty(r) && r != "extend" && (i[r] = this[r]); if (i.prototype = u, n.statics) for (t in n.statics) n.statics.hasOwnProperty(t) && (i[t] = n.statics[t], t == "ctor" && i[t]()); return i.prototype.constructor = i, i.extend = arguments.callee, i.implement = function (n) { for (var t in n) u[t] = n[t] }, i };

    var observable = __class.extend({
        "statics": {
            "ctor": function () {
                this.methods = ["concat", "every", "filter", "forEach", "indexOf", "join", "lastIndexOf", "map", "pop", "push", "reduce", "reduceRight", "reverse", "shift", "slice", "some", "sort", "splice", "unshift", "valueOf"],
                this.triggerStr = ["concat", "pop", "push", "reverse", "shift", "sort", "splice", "unshift"].join(",");
            },
            "type": function (obj) {
                var typeStr = Object.prototype.toString.call(obj).split(" ")[1];
                return typeStr.substr(0, typeStr.length - 1).toLowerCase();
            },
            "isArray": function (obj) {
                return this.type(obj) == "array";
            },
            "isInArray": function (arr, item) {
                for (var i = arr.length; --i > -1;) {
                    if (item === arr[i]) return true;
                }
                return false;
            },
            "isFunction": function (obj) {
                return this.type(obj) == "function";
            },
            "watch": function (target, arr) {
                return new this(target, arr);
            }
        },
        "ctor": function (target, arr) {
            for (var prop in target) {
                if (target.hasOwnProperty(prop)) {
                    if ((arr && observable.isInArray(arr, prop)) || !arr) {
                        this.watch(target, prop);
                    }
                }
            }
            if (target.change) throw "naming conflicts！observable will extend 'change' method to your object ."
            var self = this;
            target.change = function (fn) {
                self.propertyChangedHandler = fn;
            }
        },
        "onPropertyChanged": function (prop, value) {
            this.propertyChangedHandler && this.propertyChangedHandler(prop, value);
        },
        "mock": function (target) {
            var self = this;
            observable.methods.forEach(function (item) {
                target[item] = function () {
                    var result = Array.prototype[item].apply(this, Array.prototype.slice.call(arguments));
                    for (var cprop in this) {
                        if (this.hasOwnProperty(cprop) && cprop != "_super" && !observable.isFunction(this[cprop])) {
                            self.watch(this, cprop);
                        }
                    }
                    if (new RegExp("\\b" + item + "\\b").test(observable.triggerStr)) {
                        self.onPropertyChanged("array", item);
                    }
                    return result;
                };
            });
        },
        "watch": function (target, prop) {
            if (prop.substr(0, 2) == "__") return;
            var self = this;
            if (observable.isFunction(target[prop])) return;

            var currentValue = target["__" + prop] = target[prop];
            Object.defineProperty(target, prop, {
                get: function () {
                    return this["__" + prop];
                },
                set: function (value) {
                    this["__" + prop] = value;
                    self.onPropertyChanged(prop, value);
                }
            });

            if (observable.isArray(target)) {
                this.mock(target);
            }
            if (typeof currentValue == "object") {
                if (observable.isArray(currentValue)) {
                    this.mock(currentValue);
                }
                for (var cprop in currentValue) {
                    if (currentValue.hasOwnProperty(cprop) && cprop != "_super") {
                        this.watch(currentValue, cprop);
                    }
                }
            }
        }
    });

    var matrix3D = __class.extend({

        statics: {
            DEG_TO_RAD: Math.PI / 180
        },
        ctor: function (n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44) {

            this.elements = Float32Array ? new Float32Array(16) : [];

            // TODO: if n11 is undefined, then just set to identity, otherwise copy all other values into matrix
            //   we should not support semi specification of Matrix4, it is just weird.

            var te = this.elements;

            te[0] = (n11 !== undefined) ? n11 : 1; te[4] = n12 || 0; te[8] = n13 || 0; te[12] = n14 || 0;
            te[1] = n21 || 0; te[5] = (n22 !== undefined) ? n22 : 1; te[9] = n23 || 0; te[13] = n24 || 0;
            te[2] = n31 || 0; te[6] = n32 || 0; te[10] = (n33 !== undefined) ? n33 : 1; te[14] = n34 || 0;
            te[3] = n41 || 0; te[7] = n42 || 0; te[11] = n43 || 0; te[15] = (n44 !== undefined) ? n44 : 1;
        },
        set: function (n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44) {

            var te = this.elements;

            te[0] = n11; te[4] = n12; te[8] = n13; te[12] = n14;
            te[1] = n21; te[5] = n22; te[9] = n23; te[13] = n24;
            te[2] = n31; te[6] = n32; te[10] = n33; te[14] = n34;
            te[3] = n41; te[7] = n42; te[11] = n43; te[15] = n44;

            return this;

        },
        identity: function () {
            this.set(

               1, 0, 0, 0,
               0, 1, 0, 0,
               0, 0, 1, 0,
               0, 0, 0, 1

           );

            return this;
        },
        append: function (m) {
            return this.multiplyMatrices(this, m);

        },
        multiplyMatrices: function (a, b) {

            var ae = a.elements;
            var be = b.elements;
            var te = this.elements;

            var a11 = ae[0], a12 = ae[4], a13 = ae[8], a14 = ae[12];
            var a21 = ae[1], a22 = ae[5], a23 = ae[9], a24 = ae[13];
            var a31 = ae[2], a32 = ae[6], a33 = ae[10], a34 = ae[14];
            var a41 = ae[3], a42 = ae[7], a43 = ae[11], a44 = ae[15];

            var b11 = be[0], b12 = be[4], b13 = be[8], b14 = be[12];
            var b21 = be[1], b22 = be[5], b23 = be[9], b24 = be[13];
            var b31 = be[2], b32 = be[6], b33 = be[10], b34 = be[14];
            var b41 = be[3], b42 = be[7], b43 = be[11], b44 = be[15];

            te[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
            te[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
            te[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
            te[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;

            te[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
            te[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
            te[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
            te[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;

            te[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
            te[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
            te[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
            te[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;

            te[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
            te[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
            te[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
            te[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;

            return this;

        },
        appendTransform: function (perspective, x, y, z, scaleX, scaleY, scaleZ, rotateX, rotateY, rotateZ, regX, regY, regZ) {

            var rx = rotateX * matrix3D.DEG_TO_RAD;
            var cosx = Math.cos(rx);
            var sinx = Math.sin(rx);

            var ry = rotateY * matrix3D.DEG_TO_RAD;
            var cosy = Math.cos(ry);
            var siny = Math.sin(ry);
            var rz = rotateZ * matrix3D.DEG_TO_RAD;
            var cosz = Math.cos(rz*-1);
            var sinz = Math.sin(rz*-1);

            this.append(new matrix3D(
                cosy, 0, siny, x,
                0, 1, 0, y,
                -siny, 0, cosy, z,
                siny / perspective, 0, -cosy / perspective, (perspective - z) / perspective
            ));

            this.append(new matrix3D(
                1, 0, 0, 0,
                0, cosx, sinx, 0,
                0, -sinx, cosx, 0,
                0, sinx / perspective, -cosx / perspective, 1
            ));

                this.append(new matrix3D(
                    cosz * scaleX, sinz * scaleY, 0, 0,
                   -sinz * scaleX, cosz * scaleY, 0, 0,
                    0, 0, 1 * scaleZ, 0,
                   0, 0, -1 / perspective, 1
                ));

            if (regX || regY || regZ) {

                this.elements[12] -= regX * this.elements[0] + regY * this.elements[4] + regZ * this.elements[8];
                this.elements[13] -= regX * this.elements[1] + regY * this.elements[5] + regZ * this.elements[9];
                this.elements[14] -= regX * this.elements[2] + regY * this.elements[6] + regZ * this.elements[10];
            }
            return this;
        }

    });

    window.Transform = function (element) {
        return new _Transform(element);
    }

    function _Transform(element) {
        element.perspective = 400;
        element.scaleX = element.scaleY = element.scaleZ = 1;
        element.x = element.y = element.z = element.rotateX = element.rotateY = element.rotateZ = element.regX = element.regY = element.skewX = element.skewY = element.regX = element.regY = element.regZ = 0;
        element.matrix3D = new matrix3D();
        var observer = observable.watch(element, ["x", "y", "z", "scaleX", "scaleY", "scaleZ", "perspective", "rotateX", "rotateY", "rotateZ", "regX", "regY", "regZ"]);

        this.element = element;
        var self = this;
        observer.propertyChangedHandler = function () {
            var mtx = self.element.matrix3D.identity().appendTransform(self.element.perspective, self.element.x, self.element.y, self.element.z, self.element.scaleX, self.element.scaleY, self.element.scaleZ, self.element.rotateX, self.element.rotateY, self.element.rotateZ, self.element.regX, self.element.regY, self.element.regZ);

            self.element.style.transform = self.element.style.msTransform = self.element.style.OTransform = self.element.style.MozTransform = self.element.style.webkitTransform = "matrix3d(" + Array.prototype.slice.call(mtx.elements).join(",") + ")";
        }
    }

})();<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import YTSearch from 'youtube-api-search';

import SearchBar from './components/searchBar';

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

YTSearch({key: API_KEY, term: 'daft punk'}, function(data){
  console.log(data)
})
//create new component that will produce HTML

const App = () => {
  return (

      <SearchBar />

//JSX
  )
}

//take componenets generated HTML and place it into DOM

ReactDOM.render(<App/>, document.querySelector('.container'));//second argument is target DOM node where App will be inserted<commit_msg>main app converted to class component<commit_after>import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import YTSearch from 'youtube-api-search';

import SearchBar from './components/searchBar';

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

YTSearch({key: API_KEY, term: 'daft punk'}, function(data){
  console.log(data)
})
//create new component that will produce HTML

class App extends Component {
  render(){
      return (

        <SearchBar />

//JSX
    )
  }
}

//take componenets generated HTML and place it into DOM

ReactDOM.render(<App/>, document.querySelector('.container'));//second argument is target DOM node where App will be inserted<|endoftext|>


<commit_before>'use strict';

/* Services */

angular.module('paliTipitaka.services', ['pali.services', 'pali.filters', 'pali.directives', 'pali.jqlext']).
  factory('resizableViews', ['$document', function($document) {
    var leftView, viewwrapper, arrow, separator, rightView;
    var startLeftViewWidth, startRightViewWidth, initialMouseX;

    function initViews(allContainerId, leftViewId, viewwrapperId, arrowId, separatorId, rightViewId) {
      leftView    = angular.element(document.getElementById(leftViewId));
      viewwrapper = angular.element(document.getElementById(viewwrapperId));
      arrow       = angular.element(document.getElementById(arrowId));
      separator   = angular.element(document.getElementById(separatorId));
      rightView   = angular.element(document.getElementById(rightViewId));

      var width = document.getElementById(allContainerId).offsetWidth;
      var leftViewWidth = 250; //px
      var viewwrapperWidth = 7; //px
      var rightViewWidth = width - leftViewWidth - viewwrapperWidth;

      // set default width
      leftView.css(   'width', leftViewWidth    + 'px');
      rightView.css(  'width', rightViewWidth   + 'px');
      viewwrapper.css('width', viewwrapperWidth + 'px');

      arrow.bind('click', function() {
        var lwidth = parseInt(leftView.css('width').replace('px', ''));
        var rwidth = parseInt(rightView.css('width').replace('px', ''));
        leftView.css('width', '0');
        rightView.css('width', lwidth + rwidth + 'px');
      });

      separator.bind('mousedown', function($event) {
        $event.preventDefault();
        startLeftViewWidth = parseInt(leftView.css('width').replace('px', ''));
        startRightViewWidth = parseInt(rightView.css('width').replace('px', ''));
        initialMouseX = $event.clientX;
        $document.bind('mousemove', mousemove);
        $document.bind('mouseup', mouseup);
        return false;
      });
    }

    function mousemove($event) {
      // calculate the delta of mouse cursor movement
      var dx = $event.clientX - initialMouseX;

      var newlw = startLeftViewWidth + dx;
      if (newlw < 0) {
        leftView.css('width', '0');
        rightView.css('width', startLeftViewWidth + startRightViewWidth + 'px');
        return false;
      }

      var newrw = startRightViewWidth - dx;
      if (newrw < 0) {
        leftView.css('width', startLeftViewWidth + startRightViewWidth + 'px');
        rightView.css('width', '0');
        return false;
      }

      leftView.css('width', newlw + 'px');
      rightView.css('width', newrw + 'px');
      return false;
    }

    function mouseup() {
      $document.unbind('mousemove', mousemove);
      $document.unbind('mouseup', mouseup);
    }

    var serviceInstance = { initViews: initViews };
    return serviceInstance;
  }]).

  factory('htmlDoc2View', ['paliString', function(paliString) {
    /**
     * wrap all words in the element
     * @param {DOM element} FIXME: is this HTML or XML dom element?
     */
    function wrapWordsInElement(xmlElement) {
      // 1: element node
      if (xmlElement.nodeType == 1) {
        for (var i=0; i<xmlElement.childNodes.length; i++)
          // recursively call self to process
          wrapWordsInElement(xmlElement.childNodes[i]);
        return;
      }

      // 3: text node
      if (xmlElement.nodeType == 3) {
        var string = xmlElement.nodeValue;
        if (string.replace(/\s*/, '') !== '')
          // string is not whitespace
          xmlElement.parentNode.replaceChild(paliString.toDom(string), xmlElement);
        return;
      }

      console.log('In end of wrapWordsInElement: ');
      console.log(xmlElement);
    }

    function getView(htmlDoc) {
      /* cloneNode() is important. otherwise the second time nothing will show up */
      var body = htmlDoc.getElementsByTagName('body')[0].cloneNode(true);
      for (var i=0; i<body.childNodes.length; i++) {
        wrapWordsInElement(body.childNodes[i]);
      }

      return angular.element(body);
    }

    var serviceInstance = { getView: getView };
    return serviceInstance;
  }]).

  factory('paliString', ['$rootScope', 'htmlString2Dom', 'jqlext', 'tooltipHandler', 'paliIndexes',
                function($rootScope, htmlString2Dom, jqlext, tooltipHandler, paliIndexes) {
    // when user's mouse hovers over words, delay a period of time before look up.
    var DELAY_INTERVAL = 1000; // ms

    function onWordMouseOver(e) {
      this.style.color = 'red';
      if (!$rootScope.setting.showTooltip) return;

      setTimeout(angular.bind(this, function() {
        // 'this' keyword here refers to raw dom element
        if (this.style.color === 'red') {
          // mouse is still on word
          var tooltipPosition = {
            'left': (jqlext.offset(this).left + 'px'),
            'top': (jqlext.offset(this).top + this.offsetHeight + 'px')
          };

          var word = this.innerHTML.toLowerCase();
          tooltipHandler.showContent(word, tooltipPosition);
        }
      }), DELAY_INTERVAL);
    }

    function onWordMouseOut(e) {
      this.style.color = '';
      if (!$rootScope.setting.showTooltip) return;

      setTimeout(angular.bind(this, function() {
        tooltipHandler.hideContent();
      }), DELAY_INTERVAL);
    }

    function onWordDbclick(e) {
      var word = this.innerHTML.toLowerCase();
      if (!paliIndexes.isValidPaliWord(word)) return;
      var url = 'http://palidictionary.appspot.com/browse/' + word[0] + '/' + word;
      if ($rootScope.isDevServer) url += '?track=no';
      window.open(url);
    }

    function toDom(string) {
      // wrap all pali words in span
      var spanContainer = htmlString2Dom.string2dom(markInSpan(string));
      for (var i=0; i<spanContainer.childNodes.length; i++) {
        var node = spanContainer.childNodes[i];
        var tagName = node.tagName;
        if (tagName && tagName.toLowerCase() === 'span') {
          node.onmouseover = onWordMouseOver;
          node.onmouseout = onWordMouseOut;
          node.ondblclick = onWordDbclick;
        }
      }
      return spanContainer;
    }

    function markInSpan(string) {
      return string.replace(/[AaBbCcDdEeGgHhIiJjKkLlMmNnOoPpRrSsTtUuVvYyĀāĪīŪūṀṁṂṃŊŋṆṇṄṅÑñṬṭḌḍḶḷ]+/g, '$&');
    }

    var serviceInstance = { toDom: toDom };
    return serviceInstance;
  }]).

  factory('htmlString2Dom', [function() {
    /**
     * @see http://stackoverflow.com/questions/3103962/converting-html-string-into-dom-elements
     * @see http://stackoverflow.com/questions/888875/how-to-parse-html-from-javascript-in-firefox
     */
    function string2dom(string) {
      var spanContainer = document.createElement('span');
      spanContainer.innerHTML = string;
      return spanContainer;
    }

    var serviceInstance = { string2dom: string2dom };
    return serviceInstance;
  }]);
<commit_msg>simplify service<commit_after>'use strict';

/* Services */

angular.module('paliTipitaka.services', ['pali.services', 'pali.filters', 'pali.directives', 'pali.jqlext']).
  factory('resizableViews', ['$document', function($document) {
    var leftView, viewwrapper, arrow, separator, rightView;
    var startLeftViewWidth, startRightViewWidth, initialMouseX;

    function initViews(allContainerId, leftViewId, viewwrapperId, arrowId, separatorId, rightViewId) {
      leftView    = angular.element(document.getElementById(leftViewId));
      viewwrapper = angular.element(document.getElementById(viewwrapperId));
      arrow       = angular.element(document.getElementById(arrowId));
      separator   = angular.element(document.getElementById(separatorId));
      rightView   = angular.element(document.getElementById(rightViewId));

      var width = document.getElementById(allContainerId).offsetWidth;
      var leftViewWidth = 250; //px
      var viewwrapperWidth = 7; //px
      var rightViewWidth = width - leftViewWidth - viewwrapperWidth;

      // set default width
      leftView.css(   'width', leftViewWidth    + 'px');
      rightView.css(  'width', rightViewWidth   + 'px');
      viewwrapper.css('width', viewwrapperWidth + 'px');

      arrow.bind('click', function() {
        var lwidth = parseInt(leftView.css('width').replace('px', ''));
        var rwidth = parseInt(rightView.css('width').replace('px', ''));
        leftView.css('width', '0');
        rightView.css('width', lwidth + rwidth + 'px');
      });

      separator.bind('mousedown', function($event) {
        $event.preventDefault();
        startLeftViewWidth = parseInt(leftView.css('width').replace('px', ''));
        startRightViewWidth = parseInt(rightView.css('width').replace('px', ''));
        initialMouseX = $event.clientX;
        $document.bind('mousemove', mousemove);
        $document.bind('mouseup', mouseup);
        return false;
      });
    }

    function mousemove($event) {
      // calculate the delta of mouse cursor movement
      var dx = $event.clientX - initialMouseX;

      var newlw = startLeftViewWidth + dx;
      if (newlw < 0) {
        leftView.css('width', '0');
        rightView.css('width', startLeftViewWidth + startRightViewWidth + 'px');
        return false;
      }

      var newrw = startRightViewWidth - dx;
      if (newrw < 0) {
        leftView.css('width', startLeftViewWidth + startRightViewWidth + 'px');
        rightView.css('width', '0');
        return false;
      }

      leftView.css('width', newlw + 'px');
      rightView.css('width', newrw + 'px');
      return false;
    }

    function mouseup() {
      $document.unbind('mousemove', mousemove);
      $document.unbind('mouseup', mouseup);
    }

    var serviceInstance = { initViews: initViews };
    return serviceInstance;
  }]).

  factory('htmlDoc2View', ['paliString', function(paliString) {
    /**
     * wrap all words in the element
     * @param {DOM element} FIXME: is this HTML or XML dom element?
     */
    function wrapWordsInElement(xmlElement) {
      // 1: element node
      if (xmlElement.nodeType == 1) {
        for (var i=0; i<xmlElement.childNodes.length; i++)
          // recursively call self to process
          wrapWordsInElement(xmlElement.childNodes[i]);
        return;
      }

      // 3: text node
      if (xmlElement.nodeType == 3) {
        var string = xmlElement.nodeValue;
        if (string.replace(/\s*/, '') !== '')
          // string is not whitespace
          xmlElement.parentNode.replaceChild(paliString.toDom(string), xmlElement);
        return;
      }

      console.log('In end of wrapWordsInElement: ');
      console.log(xmlElement);
    }

    function getView(htmlDoc) {
      /* cloneNode() is important. otherwise the second time nothing will show up */
      var body = htmlDoc.getElementsByTagName('body')[0].cloneNode(true);
      for (var i=0; i<body.childNodes.length; i++) {
        wrapWordsInElement(body.childNodes[i]);
      }

      return angular.element(body);
    }

    var serviceInstance = { getView: getView };
    return serviceInstance;
  }]).

  factory('paliString', ['$rootScope', 'jqlext', 'tooltipHandler', 'paliIndexes',
                function($rootScope, jqlext, tooltipHandler, paliIndexes) {
    // when user's mouse hovers over words, delay a period of time before look up.
    var DELAY_INTERVAL = 1000; // ms

    function onWordMouseOver(e) {
      this.style.color = 'red';
      if (!$rootScope.setting.showTooltip) return;

      setTimeout(angular.bind(this, function() {
        // 'this' keyword here refers to raw dom element
        if (this.style.color === 'red') {
          // mouse is still on word
          var tooltipPosition = {
            'left': (jqlext.offset(this).left + 'px'),
            'top': (jqlext.offset(this).top + this.offsetHeight + 'px')
          };

          var word = this.innerHTML.toLowerCase();
          tooltipHandler.showContent(word, tooltipPosition);
        }
      }), DELAY_INTERVAL);
    }

    function onWordMouseOut(e) {
      this.style.color = '';
      if (!$rootScope.setting.showTooltip) return;

      setTimeout(angular.bind(this, function() {
        tooltipHandler.hideContent();
      }), DELAY_INTERVAL);
    }

    function onWordDbclick(e) {
      var word = this.innerHTML.toLowerCase();
      if (!paliIndexes.isValidPaliWord(word)) return;
      var url = 'http://palidictionary.appspot.com/browse/' + word[0] + '/' + word;
      if ($rootScope.isDevServer) url += '?track=no';
      window.open(url);
    }

    function toDom(string) {
      // wrap all pali words in span
      var spanContainer = htmlStr2Dom(markInSpan(string));
      for (var i=0; i<spanContainer.childNodes.length; i++) {
        var node = spanContainer.childNodes[i];
        var tagName = node.tagName;
        if (tagName && tagName.toLowerCase() === 'span') {
          node.onmouseover = onWordMouseOver;
          node.onmouseout = onWordMouseOut;
          node.ondblclick = onWordDbclick;
        }
      }
      return spanContainer;
    }

    function htmlStr2Dom(string) {
      // @see http://stackoverflow.com/questions/3103962/converting-html-string-into-dom-elements
      // @see http://stackoverflow.com/questions/888875/how-to-parse-html-from-javascript-in-firefox
      var spanContainer = document.createElement('span');
      spanContainer.innerHTML = string;
      return spanContainer;
    }

    function markInSpan(string) {
      return string.replace(/[AaBbCcDdEeGgHhIiJjKkLlMmNnOoPpRrSsTtUuVvYyĀāĪīŪūṀṁṂṃŊŋṆṇṄṅÑñṬṭḌḍḶḷ]+/g, '$&');
    }

    var serviceInstance = { toDom: toDom };
    return serviceInstance;
  }]);
<|endoftext|>


<commit_before>;
/* main initialization routine */
$.fn.towelFoundation = function() {
    /* onReady */
    $(function() {
        var onReady = window.onReady || [];
        for (var i=0, l=onReady.length; i<l; i++) onReady[i].apply(null, [$]);
    });

    return this;
};

/* various plugins */
$.fn.flash = function() {
    return this.each(function() {
        var $this = $(this),
            opacity = $this.css('opacity');

        $this.css('opacity', 0.3).animate({opacity: opacity});
    });
};

$.fn.autogrow = function() {
    return this.not('.hasAutogrow').addClass('hasAutogrow').elastic();
};

/* gettext dummy
* if you need internationalizations, read here how to activate:
* https://docs.djangoproject.com/en/dev/topics/i18n/translation/#internationalization-in-javascript-code
* */
if (window.gettext === undefined) {
    window.gettext = function(msgid) {
        return msgid
    }
}

/* init forms */
(function($) {
    if (!window.onForm) window.onForm = [];

    var onForm = window.onForm,
        initForms = function(elem) {
            var elem = $(elem || document);
            for (var i=0, len=onForm.length; i<len; ++i)
                onForm[i].apply(null, [elem, $]);
        };

    onForm.push(function(elem, $) {
        if ($.fn.chosen)
            elem.find('select').not('.plain').chosen();
        if ($.fn.datePicker) {
            elem.find('.type-date').each(function() {
                var self = $(this),
                    input = self.find('input.dateinput');

                Date.format = self.data('date-format');
                input.datePicker({
                    horizontalPosition: $.dpConst.POS_RIGHT,
                    displayClose: true,
                    startDate: new Date(Date.parse('1990-01-01'))
                });

                var lnk = input.parent().find('.dp-choose-date');
                lnk.html('');
            });
        }

        elem.find('textarea.autogrow, .autogrow textarea').autogrow();
    });

    onReady.push(function() { initForms(); });

    /* inject function into the global namespace */
    if (!window.initForms) window.initForms = initForms;

    $(document.body).on('updateLive', function(event, elem) {
        event.stopPropagation();
        elem.flash();
        initForms(elem);
    });
})(jQuery);

/* ajax modals */
(function($) {
    var initModal = function() {
            var modal = this,
                $elem = $(this);

            $elem.find('form').each(function() {
                var $form = $(this),
                    handleResponse = function(data) {
                        window.modalLoad.locked = false;

                        if (typeof(data) == 'string') {
                            $elem.html(data);
                            initModal.call($elem.get(0));
                        } else {
                            updateLive(data);
                            if (!('!keep' in data))
                                $elem.foundation('reveal', 'close');
                        }
                    }

                // set modal to locked: navigating away will be prevented
                // and also closing the modal will prompt the user
                $form.filter('[method="post"]').on('change', function(event) {
                    window.modalLoad.locked = true;
                });

                $form.on('submit', function() {
                    if (this.method.toLowerCase() == 'post') {
                        if ($.fn.ajaxSubmit) {
                            // jquery.form.js is available, XHR file uploads will
                            // work too
                            var $bar = $elem.find('.progress-bar');

                            $(this).ajaxSubmit({
                                uploadProgress: function(evt, pos, total, percComplete) {
                                    $bar.width(percComplete + '%');
                                },
                                beforeSubmit: function() {
                                    $bar.width('0%');
                                },
                                success: handleResponse
                            });
                        } else {
                            $.post(this.action, $form.serialize(), handleResponse);
                        }
                    } else {
                        $.get(this.action, $form.serialize(), handleResponse);
                    }
                    return false;
                });

                // focus the first form element
                (function(form) {
                    setTimeout(function() {
                        initForms(form);
                        $('input:visible, textarea', form).first().focus();
                    }, 150);
                })(this);
            });
        },
        modalLoad = function(url, cls) {
            var modal = $('div.reveal-modal');
            if (!modal.length) {
                /* create div for holding AJAX-loaded modals, once */
                modal = $('
').addClass('reveal-modal').appendTo('body');
                modal.on('close', function(event) {
                    if (event.target != this) {
                        // another element triggered the hide event. Ignore it.
                        return true;
                    }

                    // if the modal is locked (i.e. uploading/submission in progress)
                    if (window.modalLoad.locked) {
                        if (!confirm(gettext('You have unsaved changes. Do you really want to throw them away?'))) {
                            return false;
                        }
                    }

                    // unlock the modal
                    window.modalLoad.locked = false;
                    $('#logo').focus().blur();
                });
            }

            modal.removeClass().addClass('reveal-modal');
            if (cls)
                modal.addClass(cls);

            modal.empty().load(url, function() {
                var $m = $(this),
                    cls = $m.find('[data-reveal-class]').data('reveal-class');
                if (cls)
                    $m.addClass(cls);
                initModal.call(this);
                $m.foundation('reveal', 'open');
            });
        };

    $(document.body).on('click', 'a[data-toggle="ajaxmodal"]', function(e) {
        e.preventDefault();
        modalLoad(this.href, $(this).data('reveal-class'));
    });

    // prevent navigating away without saving:
    $(window).on('beforeunload', function() {
        if (window.modalLoad.locked) {
          return gettext('You have unsaved changes. Do you really want to throw them away?')
        };
    });

    /* inject function into the global namespace */
    if (!window.modalLoad) window.modalLoad = modalLoad;
})(jQuery);

/* jQuery / Django CSRF handling
Thanks, https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax */
jQuery(document).ajaxSend(function(event, xhr, settings) {
    function getCookie(name) {
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
    function sameOrigin(url) {
        // url could be relative or scheme relative or absolute
        var host = document.location.host; // host + port
        var protocol = document.location.protocol;
        var sr_origin = '//' + host;
        var origin = protocol + sr_origin;
        // Allow absolute or scheme relative URLs to same origin
        return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
            (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
            // or any other URL that isn't scheme relative or absolute i.e relative.
            !(/^(\/\/|http:|https:).*/.test(url));
    }
    function safeMethod(method) {
        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    }

    if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
        xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
    }
});
<commit_msg>Datepicker: Full last century<commit_after>;
/* main initialization routine */
$.fn.towelFoundation = function() {
    /* onReady */
    $(function() {
        var onReady = window.onReady || [];
        for (var i=0, l=onReady.length; i<l; i++) onReady[i].apply(null, [$]);
    });

    return this;
};

/* various plugins */
$.fn.flash = function() {
    return this.each(function() {
        var $this = $(this),
            opacity = $this.css('opacity');

        $this.css('opacity', 0.3).animate({opacity: opacity});
    });
};

$.fn.autogrow = function() {
    return this.not('.hasAutogrow').addClass('hasAutogrow').elastic();
};

/* gettext dummy
* if you need internationalizations, read here how to activate:
* https://docs.djangoproject.com/en/dev/topics/i18n/translation/#internationalization-in-javascript-code
* */
if (window.gettext === undefined) {
    window.gettext = function(msgid) {
        return msgid
    }
}

/* init forms */
(function($) {
    if (!window.onForm) window.onForm = [];

    var onForm = window.onForm,
        initForms = function(elem) {
            var elem = $(elem || document);
            for (var i=0, len=onForm.length; i<len; ++i)
                onForm[i].apply(null, [elem, $]);
        };

    onForm.push(function(elem, $) {
        if ($.fn.chosen)
            elem.find('select').not('.plain').chosen();
        if ($.fn.datePicker) {
            elem.find('.type-date').each(function() {
                var self = $(this),
                    input = self.find('input.dateinput');

                Date.format = self.data('date-format');
                input.datePicker({
                    horizontalPosition: $.dpConst.POS_RIGHT,
                    displayClose: true,
                    startDate: new Date(1900, 1, 1)
                });

                var lnk = input.parent().find('.dp-choose-date');
                lnk.html('');
            });
        }

        elem.find('textarea.autogrow, .autogrow textarea').autogrow();
    });

    onReady.push(function() { initForms(); });

    /* inject function into the global namespace */
    if (!window.initForms) window.initForms = initForms;

    $(document.body).on('updateLive', function(event, elem) {
        event.stopPropagation();
        elem.flash();
        initForms(elem);
    });
})(jQuery);

/* ajax modals */
(function($) {
    var initModal = function() {
            var modal = this,
                $elem = $(this);

            $elem.find('form').each(function() {
                var $form = $(this),
                    handleResponse = function(data) {
                        window.modalLoad.locked = false;

                        if (typeof(data) == 'string') {
                            $elem.html(data);
                            initModal.call($elem.get(0));
                        } else {
                            updateLive(data);
                            if (!('!keep' in data))
                                $elem.foundation('reveal', 'close');
                        }
                    }

                // set modal to locked: navigating away will be prevented
                // and also closing the modal will prompt the user
                $form.filter('[method="post"]').on('change', function(event) {
                    window.modalLoad.locked = true;
                });

                $form.on('submit', function() {
                    if (this.method.toLowerCase() == 'post') {
                        if ($.fn.ajaxSubmit) {
                            // jquery.form.js is available, XHR file uploads will
                            // work too
                            var $bar = $elem.find('.progress-bar');

                            $(this).ajaxSubmit({
                                uploadProgress: function(evt, pos, total, percComplete) {
                                    $bar.width(percComplete + '%');
                                },
                                beforeSubmit: function() {
                                    $bar.width('0%');
                                },
                                success: handleResponse
                            });
                        } else {
                            $.post(this.action, $form.serialize(), handleResponse);
                        }
                    } else {
                        $.get(this.action, $form.serialize(), handleResponse);
                    }
                    return false;
                });

                // focus the first form element
                (function(form) {
                    setTimeout(function() {
                        initForms(form);
                        $('input:visible, textarea', form).first().focus();
                    }, 150);
                })(this);
            });
        },
        modalLoad = function(url, cls) {
            var modal = $('div.reveal-modal');
            if (!modal.length) {
                /* create div for holding AJAX-loaded modals, once */
                modal = $('
').addClass('reveal-modal').appendTo('body');
                modal.on('close', function(event) {
                    if (event.target != this) {
                        // another element triggered the hide event. Ignore it.
                        return true;
                    }

                    // if the modal is locked (i.e. uploading/submission in progress)
                    if (window.modalLoad.locked) {
                        if (!confirm(gettext('You have unsaved changes. Do you really want to throw them away?'))) {
                            return false;
                        }
                    }

                    // unlock the modal
                    window.modalLoad.locked = false;
                    $('#logo').focus().blur();
                });
            }

            modal.removeClass().addClass('reveal-modal');
            if (cls)
                modal.addClass(cls);

            modal.empty().load(url, function() {
                var $m = $(this),
                    cls = $m.find('[data-reveal-class]').data('reveal-class');
                if (cls)
                    $m.addClass(cls);
                initModal.call(this);
                $m.foundation('reveal', 'open');
            });
        };

    $(document.body).on('click', 'a[data-toggle="ajaxmodal"]', function(e) {
        e.preventDefault();
        modalLoad(this.href, $(this).data('reveal-class'));
    });

    // prevent navigating away without saving:
    $(window).on('beforeunload', function() {
        if (window.modalLoad.locked) {
          return gettext('You have unsaved changes. Do you really want to throw them away?')
        };
    });

    /* inject function into the global namespace */
    if (!window.modalLoad) window.modalLoad = modalLoad;
})(jQuery);

/* jQuery / Django CSRF handling
Thanks, https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax */
jQuery(document).ajaxSend(function(event, xhr, settings) {
    function getCookie(name) {
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
    function sameOrigin(url) {
        // url could be relative or scheme relative or absolute
        var host = document.location.host; // host + port
        var protocol = document.location.protocol;
        var sr_origin = '//' + host;
        var origin = protocol + sr_origin;
        // Allow absolute or scheme relative URLs to same origin
        return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
            (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
            // or any other URL that isn't scheme relative or absolute i.e relative.
            !(/^(\/\/|http:|https:).*/.test(url));
    }
    function safeMethod(method) {
        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    }

    if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
        xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
    }
});
<|endoftext|>


<commit_before>'use strict';

module.exports = function (grunt) {

    // Load external grunt task config.
    grunt.loadTasks('./grunt');

    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-jscs');

    grunt.initConfig({
        config: {
            files: {
                lint: [
                    'src/**/*.js'
                ]
            }
        },
        jshint: {
            options: {
                jshintrc: '.jshintrc'
            },
            all: [
                '<%= config.files.lint %>'
            ]
        },
        jscs: {
            options: {
                config: '.jscsrc'
            },
            src: '<%= config.files.lint %>'
        }
    });

    grunt.registerTask('lint', 'Run the JS linters.', [
        'jshint',
        'jscs'
    ]);

    grunt.registerTask('test', 'Run the tests.', function (env) {
        'lint'
    });

};
<commit_msg>Adding karma test task to the gruntfile.<commit_after>'use strict';

module.exports = function (grunt) {

    if (grunt.option('help')) {
        require('load-grunt-tasks')(grunt);
    } else {
        require('jit-grunt')(grunt, {
            force: 'grunt-force-task'
        });
    }

    require('time-grunt')(grunt);

    grunt.initConfig({
        config: {
            lib: 'bower_components',
            modules: 'src',
            files: {
                lint: [
                    'src/**/*.js'
                ],
                karmaTests: 'tests/unit/**/*.js'
            }
        },
        jshint: {
            options: {
                jshintrc: '.jshintrc'
            },
            all: [
                '<%= config.files.lint %>'
            ]
        },
        jscs: {
            options: {
                config: '.jscsrc'
            },
            src: '<%= config.files.lint %>'
        },
    });

    // Load external grunt task config.
    grunt.loadTasks('./grunt');

    grunt.registerTask('default', [
        'test'
    ]);

    grunt.registerTask('lint', 'Run the JS linters.', [
        'jshint',
        'jscs'
    ]);

    grunt.registerTask('test', 'Run the tests.', function (env) {
        var karmaTarget = 'dev';
        if (grunt.option('debug')) {
            karmaTarget = 'debug';
        }
        if (grunt.option('verbose')) {
            karmaTask = 'verbose';
        }
        if (env === 'ci' || env === 'travis') {
            karmaTarget = 'ci';
        }
        grunt.task.run([
            'force:lint',
            'force:karma:' + karmaTarget,
            'errorcodes'
        ]);
    });

    grunt.registerTask('travis', 'Run the tests in Travis', [
        'test:travis'
    ]);

    // This is used in combination with grunt-force-task to make the most of a
    // Travis build, so all tasks can run but the build will fail if any of the
    // tasks failed/errored.
    grunt.registerTask('errorcodes', 'Fatally error if any errors or warnings have occurred but Grunt has been forced to continue', function () {
        grunt.log.writeln('errorcount: ' + grunt.fail.errorcount);
        grunt.log.writeln('warncount: ' + grunt.fail.warncount);
        if (grunt.fail.warncount > 0 || grunt.fail.errorcount > 0) {
            grunt.fatal('Errors have occurred.');
        }
    });

};
<|endoftext|>


<commit_before>import React          from 'react'
import ChannelToolbar from './channel-toolbar'

import Paper
  from 'material-ui/lib/paper'
import Avatar
  from 'material-ui/lib/avatar'
import Slider
  from 'material-ui/lib/slider'
import FlatButton
  from 'material-ui/lib/flat-button'
import Divider
  from 'material-ui/lib/divider'
import Toggle
  from 'material-ui/lib/toggle'

import Card from 'material-ui/lib/card/card';
import CardActions from 'material-ui/lib/card/card-actions';
import CardHeader from 'material-ui/lib/card/card-header';
import CardMedia from 'material-ui/lib/card/card-media';
import CardTitle from 'material-ui/lib/card/card-title';
import CardText from 'material-ui/lib/card/card-text';

import { green400 }
  from 'material-ui/lib/styles/colors'

class Channel extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      expanded: false,
    }
  }
  updateVolume(e, value) {
    const { id, sendMessage } = this.props
    sendMessage('channelVolume', {
      [id]: value
    })
  }
  toggleMuted(e) {
    const { id, muted, sendMessage } = this.props
    sendMessage('channelMuted', {
      [id]: !muted
    })
  }
  setMode(newMode) {
    const { id, mode, sendMessage } = this.props
    if ('free' != mode) {
      sendMessage('channelMode', {
        [id]: newMode
      })
    }
  }
  renderControls() {
    const {
      id,
      level,
      mode,
      muted,
      sendMessage,
    } = this.props
    switch (mode) {
      case 'defunct':
        return (

        )
      case 'free':
      default:
        return (

            {/*

              <Avatar icon={remove} />

            */}

              <Toggle
                onToggle       = {::this.toggleMuted}
                defaultToggled = {!muted} />

              <Slider
                onChange       = {::this.updateVolume}
                disabled       = {muted}
                min            = {1}
                max            = {100}
                value          = {level}
                defaultValue   = {level} />

        )
    }
  }
  renderActions() {
    const { mode } = this.props
    switch (mode) {
      case 'free':
      case 'defunct':
        return (

        )
      default:
        return (

            <Divider />

              <FlatButton
                style      = {styles.button}
                primary    = {true}
                label      = 'Master'
                icon       = {speaker}
                onClick    = {() => this.setMode('master')}
              />
              <FlatButton
                style      = {styles.button}
                primary    = {true}
                label      = 'On hold'
                icon       = {pause}
                onClick    = {() => this.setMode('on_hold')}
              />
              <FlatButton
                style      = {styles.button}
                secondary  = {true}
                label      = 'Reject'
                icon       = {cancel}
                onClick    = {() => this.setMode('free')}
              />

        )
    }
  }
  render() {
    const { mode } = this.props
    const colors = {
      defunct : '#dedede',
    }

    return

    return (

<Card expanded={this.state.expanded} onExpandChange={this.handleExpandChange}>
        <CardHeader
          title="URL Avatar"
          subtitle="Subtitle"
          avatar="http://lorempixel.com/100/100/nature/"
          actAsExpander={true}
          showExpandableButton={true}
        />
        <CardText>
          This toggle controls the expanded state of the component.
          <Toggle toggled={this.state.expanded} onToggle={this.handleToggle} />
        </CardText>
        <CardMedia
          expandable={true}
          overlay={<CardTitle title="Overlay title" subtitle="Overlay subtitle" />}
        >

        </CardMedia>
        <CardTitle title="Card title" subtitle="Card subtitle" expandable={true} />
        <CardText expandable={true}>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit.
          Donec mattis pretium massa. Aliquam erat volutpat. Nulla facilisi.
          Donec vulputate interdum sollicitudin. Nunc lacinia auctor quam sed pellentesque.
          Aliquam dui mauris, mattis quis lacus id, pellentesque lobortis odio.
        </CardText>
        <CardActions>
          <FlatButton label="Expand" onTouchTap={this.handleExpand} />
          <FlatButton label="Reduce" onTouchTap={this.handleReduce} />
        </CardActions>
      </Card>

        <Paper style={{
            ...styles.paper,
            borderLeft : `12px solid ${colors[mode] || green400}`,
          }}>
          <ChannelToolbar {...this.props} />
          {this.renderControls()}
          {this.renderActions()}
        </Paper>

    )
  }
}

const styles = {
  component: {
    padding         : '1em 1em 0 1em',
  },
  paper: {
    width           : '100%',
  },
  controls: {
    display         : 'flex',
    flexDirection   : 'row',
    alignItems      : 'center',
    height          : '60px',
    marginBottom    : '10px',
    padding         : '10px 0',
  },
  avatar: {
    padding         : '0 0 0 20px',
  },
  toggle: {
    padding         : '0 10px',
  },
  slider: {
    margin          : '22px 20px 0 0',
    width           : '100%',
  },
}

export default Channel
<commit_msg>implement channel modes<commit_after>import React          from 'react'
import ReactDOM       from 'react-dom'
import ChannelToolbar from './channel-toolbar'
import moment         from 'moment'

import { updateChannelContact, updateChannelVolume }
  from '../js/actions'

import Paper
  from 'material-ui/lib/paper'
import Divider
  from 'material-ui/lib/divider'
import FlatButton
  from 'material-ui/lib/flat-button'
import RaisedButton
  from 'material-ui/lib/raised-button'
import Slider
  from 'material-ui/lib/slider'
import Toggle
  from 'material-ui/lib/toggle'
import TextField
  from 'material-ui/lib/text-field'

import IconCommunicationCall
  from 'material-ui/lib/svg-icons/communication/call'
import IconAvPause
  from 'material-ui/lib/svg-icons/av/pause'
import IconAvStop
  from 'material-ui/lib/svg-icons/av/stop'
import IconSocialPerson
  from 'material-ui/lib/svg-icons/social/person'

import { green400, green500, yellow500, red500, grey500, orange500 }
  from 'material-ui/lib/styles/colors'

class Channel extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      timer : null,
      now   : Date.now(),
      edit  : false,
    }
  }
  setMode(newMode) {
    const { id, mode, sendMessage } = this.props
    if ('free' != mode) {
      sendMessage('channelMode', {
        [id]: newMode
      })
    }
  }
  updateVolume(e, value) {
    const { id, sendMessage } = this.props
    sendMessage('channelVolume', {
      [id]: value
    })
    dispatch(updateChannelVolume(id, value))
  }
  toggleMuted(e) {
    const { id, muted, sendMessage } = this.props
    sendMessage('channelMuted', {
      [id]: !muted
    })
  }
  toggleEdit(e) {
    const { edit } = this.state
    if (!edit && this.refs.contact) {
      this.refs.contact.focus()
    }
    this.setState({
      edit : !edit,
    })
  }
  timer() {
    //const { timestamp, client : { diff } } = this.props
    const { timestamp } = this.props
    const diff = 0 // temp
    if (timestamp) {
      this.setState({
        now : Date.now() - diff
      })
    }
  }
  updateContact() {
    const { id, dispatch, sendMessage } = this.props
    if (this.refs.contact) {
      const caller = {
        'name' : this.refs.contact.getValue(),
      }
      dispatch(updateChannelContact(id, caller))
      sendMessage('channelContactInfo', {
        [id] : caller
      })
    }
    this.setState({
      edit : false,
    })
  }
  componentDidMount() {
    this.setState({
      timer : window.setInterval(::this.timer, 1000)
    })
  }
  renderChannel() {
    const { mode, muted, level, contact } = this.props
    switch (mode) {
      case 'free':
        return (

              phone

        )
      case 'defunct':
        return (

        )
      case 'ring':
        return (

                ring_volume

              {contact.name && (

                  Incoming call from {contact.name}

              )}

{contact.number}

            <Divider />

              <FlatButton
                style      = {{color: green500, ...styles.button}}
                label      = 'Answer'
                icon       = {<IconCommunicationCall />}
                onClick    = {() => this.setMode('master')}
              />
              <FlatButton
                style      = {{color: grey500, ...styles.button}}
                label      = 'On hold'
                icon       = {<IconAvPause />}
                onClick    = {() => this.setMode('on_hold')}
              />
              <FlatButton
                style      = {{color: red500, ...styles.button}}
                label      = 'Reject'
                icon       = {<IconAvStop />}
                onClick    = {() => this.setMode('free')}
              />

        )
      case 'master':
      case 'on_hold':
        return (

                {!!this.state.edit ? (

                    <TextField
                      ref               = 'contact'
                      defaultValue      = {contact.name}
                      floatingLabelText = 'Contact name'
                    />
                    <FlatButton
                      style             = {{marginLeft: '10px'}}
                      label             = 'Save'
                      onTouchTap        = {::this.updateContact}
                    />
                    <FlatButton
                      style             = {{marginLeft: '10px'}}
                      label             = 'Cancel'
                      onTouchTap        = {::this.toggleEdit}
                    />

                ) : (

                    {contact.name && (

                        {contact.name}

                    )}
                    <RaisedButton
                      style      = {{marginTop: '10px'}}
                      primary    = {true}
                      label      = 'Edit contact'
                      icon       = {<IconSocialPerson />}
                      onTouchTap = {::this.toggleEdit}
                    />

                )}

{contact.number}

                  <Toggle
                    onToggle       = {::this.toggleMuted}
                    defaultToggled = {!muted} />

                  <Slider
                    onChange       = {::this.updateVolume}
                    disabled       = {muted}
                    min            = {1}
                    max            = {100}
                    value          = {level}
                    defaultValue   = {level} />

              <Divider />

                <FlatButton
                  style      = {{color: green500, ...styles.button}}
                  label      = 'Master'
                  icon       = {<IconCommunicationCall />}
                  onClick    = {() => this.setMode('master')}
                />
                <FlatButton
                  style      = {{color: grey500, ...styles.button}}
                  label      = 'On hold'
                  icon       = {<IconAvPause />}
                  onClick    = {() => this.setMode('on_hold')}
                />
                <FlatButton
                  style      = {{color: red500, ...styles.button}}
                  label      = 'Hang up'
                  icon       = {<IconAvStop />}
                  onClick    = {() => this.setMode('free')}
                />

        )
      default:
        return
    }
  }
  render() {
    const { mode, timestamp } = this.props
    const hours = moment(this.state.now).diff(timestamp, 'hours')
    const colors = {
      'defunct' : '#dedede',
      'ring'    : red500,
      'master'  : yellow500,
      'on_hold' : orange500,
    }
    return (

        <Paper
          style={{
            borderLeft : `12px solid ${colors[mode] || '#00bcd4'}`,
          }}>
          <ChannelToolbar {...this.props}
            timer = {(('master' === mode || 'on_hold' === mode) && timestamp) ? (

                {hours > 0 && {hours}:}
                {moment(moment(this.state.now).diff(timestamp)).format('mm:ss')}

            ) : null}
          />
          {this.renderChannel()}
        </Paper>

    )
  }
}

const styles = {
  button: {
  },
  component: {
    padding         : '1em 0 0 0',
  },
  paper: {
    width           : '100%',
  },
  controls: {
    display         : 'flex',
    flexDirection   : 'row',
    alignItems      : 'center',
    height          : '60px',
    marginBottom    : '10px',
    padding         : '10px 0',
  },
  avatar: {
    padding         : '0 0 0 20px',
  },
  toggle: {
    padding         : '0 10px',
  },
  slider: {
    margin          : '22px 20px 0 0',
    width           : '100%',
  },
}

export default Channel

//import React          from 'react'
//import ChannelToolbar from './channel-toolbar'
//
//import Paper
//  from 'material-ui/lib/paper'
//import Avatar
//  from 'material-ui/lib/avatar'
//import Slider
//  from 'material-ui/lib/slider'
//import FlatButton
//  from 'material-ui/lib/flat-button'
//import Divider
//  from 'material-ui/lib/divider'
//import Toggle
//  from 'material-ui/lib/toggle'
//
//import Card from 'material-ui/lib/card/card';
//import CardActions from 'material-ui/lib/card/card-actions';
//import CardHeader from 'material-ui/lib/card/card-header';
//import CardMedia from 'material-ui/lib/card/card-media';
//import CardTitle from 'material-ui/lib/card/card-title';
//import CardText from 'material-ui/lib/card/card-text';
//
//import { green400 }
//  from 'material-ui/lib/styles/colors'
//
//class Channel extends React.Component {
//  constructor(props) {
//    super(props)
//    this.state = {
//      expanded: false,
//    }
//  }
//  updateVolume(e, value) {
//    const { id, sendMessage } = this.props
//    sendMessage('channelVolume', {
//      [id]: value
//    })
//  }
//  toggleMuted(e) {
//    const { id, muted, sendMessage } = this.props
//    sendMessage('channelMuted', {
//      [id]: !muted
//    })
//  }
//  setMode(newMode) {
//    const { id, mode, sendMessage } = this.props
//    if ('free' != mode) {
//      sendMessage('channelMode', {
//        [id]: newMode
//      })
//    }
//  }
//  renderControls() {
//    const {
//      id,
//      level,
//      mode,
//      muted,
//      sendMessage,
//    } = this.props
//    switch (mode) {
//      case 'defunct':
//        return (
//
//        )
//      case 'free':
//      default:
//        return (
//

//            {/*
//

//              <Avatar icon={remove} />
//

//            */}
//

//              <Toggle
//                onToggle       = {::this.toggleMuted}
//                defaultToggled = {!muted} />
//

//

//              <Slider
//                onChange       = {::this.updateVolume}
//                disabled       = {muted}
//                min            = {1}
//                max            = {100}
//                value          = {level}
//                defaultValue   = {level} />
//

//

//        )
//    }
//  }
//  renderActions() {
//    const { mode } = this.props
//    switch (mode) {
//      case 'free':
//      case 'defunct':
//        return (
//
//        )
//      default:
//        return (
//

//            <Divider />
//

//              <FlatButton
//                style      = {styles.button}
//                primary    = {true}
//                label      = 'Master'
//                icon       = {speaker}
//                onClick    = {() => this.setMode('master')}
//              />
//              <FlatButton
//                style      = {styles.button}
//                primary    = {true}
//                label      = 'On hold'
//                icon       = {pause}
//                onClick    = {() => this.setMode('on_hold')}
//              />
//              <FlatButton
//                style      = {styles.button}
//                secondary  = {true}
//                label      = 'Reject'
//                icon       = {cancel}
//                onClick    = {() => this.setMode('free')}
//              />
//

//

//        )
//    }
//  }
//  render() {
//    const { mode } = this.props
//    const colors = {
//      defunct : '#dedede',
//    }
//
//
//
//
//    return
//
//
//
//
//
//    return (
//

//
//<Card expanded={this.state.expanded} onExpandChange={this.handleExpandChange}>
//        <CardHeader
//          title="URL Avatar"
//          subtitle="Subtitle"
//          avatar="http://lorempixel.com/100/100/nature/"
//          actAsExpander={true}
//          showExpandableButton={true}
//        />
//        <CardText>
//          This toggle controls the expanded state of the component.
//          <Toggle toggled={this.state.expanded} onToggle={this.handleToggle} />
//        </CardText>
//        <CardMedia
//          expandable={true}
//          overlay={<CardTitle title="Overlay title" subtitle="Overlay subtitle" />}
//        >
//
//        </CardMedia>
//        <CardTitle title="Card title" subtitle="Card subtitle" expandable={true} />
//        <CardText expandable={true}>
//          Lorem ipsum dolor sit amet, consectetur adipiscing elit.
//          Donec mattis pretium massa. Aliquam erat volutpat. Nulla facilisi.
//          Donec vulputate interdum sollicitudin. Nunc lacinia auctor quam sed pellentesque.
//          Aliquam dui mauris, mattis quis lacus id, pellentesque lobortis odio.
//        </CardText>
//        <CardActions>
//          <FlatButton label="Expand" onTouchTap={this.handleExpand} />
//          <FlatButton label="Reduce" onTouchTap={this.handleReduce} />
//        </CardActions>
//      </Card>
//
//
//
//
//        <Paper style={{
//            ...styles.paper,
//            borderLeft : `12px solid ${colors[mode] || green400}`,
//          }}>
//          <ChannelToolbar {...this.props} />
//          {this.renderControls()}
//          {this.renderActions()}
//        </Paper>
//

//    )
//  }
//}
//
//const styles = {
//  component: {
//    padding         : '1em 1em 0 1em',
//  },
//  paper: {
//    width           : '100%',
//  },
//  controls: {
//    display         : 'flex',
//    flexDirection   : 'row',
//    alignItems      : 'center',
//    height          : '60px',
//    marginBottom    : '10px',
//    padding         : '10px 0',
//  },
//  avatar: {
//    padding         : '0 0 0 20px',
//  },
//  toggle: {
//    padding         : '0 10px',
//  },
//  slider: {
//    margin          : '22px 20px 0 0',
//    width           : '100%',
//  },
//}
//
//export default Channel
<|endoftext|>


<commit_before>'use strict';
var lrSnippet = require('grunt-contrib-livereload/lib/utils').livereloadSnippet;
var mountFolder = function (connect, dir) {
    return connect.static(require('path').resolve(dir));
};

module.exports = function (grunt) {
    // load all grunt tasks
    require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);

    // configurable paths
    var config = {
        name: 'gpub',
        src: 'src',
        dist: 'dist',
        libs: 'libs',
        example:'examples'
    };

    try {
        config.src = require('./component.json').appPath || config.src;
    } catch (e) {}

    grunt.initConfig({
        config: config,
        livereload:{
            port: 35723
        },
        watch: {
            livereload: {
                files: [
                    '<%= config.example %>/*.html',
                    '<%= config.example %>/*.js',
                    '{.tmp,<%= config.src %>}/*.js'
                ],
                tasks: ['livereload']
            }
        },
        connect: {
            options: {
                port: 9100,
                // Change this to '0.0.0.0' to access the server from outside.
                hostname: 'localhost'
            },
            livereload: {
                options: {
                    middleware: function (connect) {
                        return [
                            lrSnippet,
                            mountFolder(connect, '.tmp'),
                            mountFolder(connect, config.src),
                            mountFolder(connect, config.libs),
                            mountFolder(connect, config.example)
                        ];
                    }
                }
            },
            test: {
                options: {
                    middleware: function (connect) {
                        return [
                            mountFolder(connect, '.tmp'),
                            mountFolder(connect, 'test')
                        ];
                    }
                }
            },
            dev:{
                options: {}
            }
        },
        open: {
            server: {
                url: 'http://localhost:<%= connect.options.port %>'
            }
        },
        clean: {
            dist: {
                files: [{
                    dot: true,
                    src: [
                        '.tmp',
                        '<%= config.dist %>/*',
                        '!<%= config.dist %>/.git*'
                    ]
                }]
            },
            server: '.tmp'
        },
        jshint: {
            options: {
                jshintrc: '.jshintrc'
            },
            all: [
                'Gruntfile.js',
                '<%= config.src %>/{,*/}*.js'
            ]
        },
        karma: {
            options: {
                configFile: 'karma.conf.js',
                runnerPort: 9999,
                browsers: ['Chrome', 'Firefox']
            },
            unit: {
                reporters: 'dots'
            },
            continuous: {
                singleRun: true,
                browsers: ['PhantomJS']
            },
            ci: {
                singleRun: true,
                browsers: ['PhantomJS']
            }
        },
        concat: {
            dist: {
                files: {
                    '<%= config.dist %>/<%= config.name %>.js': [
                        '.tmp/{,*/}*.js',
                        '<%= config.src %>/{,*/}*.js'
                    ]
                }
            }
        },
        uglify: {
            dist: {
                files: {
                    '<%= config.dist %>/<%= config.name %>.min.js': [
                        '<%= config.dist %>/<%= config.name %>.js'
                    ]
                }
            }
        },
        copy: {
            dist: {
                files: [{
                    expand: true,
                    dot: true,
                    cwd: '<%= config.src %>',
                    dest: '<%= config.dist %>',
                    src: []
                }]
            }
        }
    });

    grunt.renameTask('regarde', 'watch');

    grunt.registerTask('server', [
        'clean:server',
        'livereload-start',
        'connect:livereload',
        'open',
        'watch'
    ]);

    grunt.registerTask('test', [
        'clean:server',
        'connect:test',
        'karma:ci'
    ]);

    grunt.registerTask('build', [
        'clean:dist',
        'jshint',
        'test',
        'concat',
        'copy',
        'uglify',
    ]);

    grunt.registerTask('default', ['build']);
};
<commit_msg>Gruntfile: Updated test runner port so we can test and run the server at the same time.<commit_after>'use strict';
var lrSnippet = require('grunt-contrib-livereload/lib/utils').livereloadSnippet;
var mountFolder = function (connect, dir) {
    return connect.static(require('path').resolve(dir));
};

module.exports = function (grunt) {
    // load all grunt tasks
    require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);

    // configurable paths
    var config = {
        name: 'gpub',
        src: 'src',
        dist: 'dist',
        libs: 'libs',
        example:'examples'
    };

    try {
        config.src = require('./component.json').appPath || config.src;
    } catch (e) {}

    grunt.initConfig({
        config: config,
        livereload:{
            port: 35723
        },
        watch: {
            livereload: {
                files: [
                    '<%= config.example %>/*.html',
                    '<%= config.example %>/*.js',
                    '{.tmp,<%= config.src %>}/*.js'
                ],
                tasks: ['livereload']
            }
        },
        connect: {
            options: {
                port: 9100,
                // Change this to '0.0.0.0' to access the server from outside.
                hostname: 'localhost'
            },
            livereload: {
                options: {
                    middleware: function (connect) {
                        return [
                            lrSnippet,
                            mountFolder(connect, '.tmp'),
                            mountFolder(connect, config.src),
                            mountFolder(connect, config.libs),
                            mountFolder(connect, config.example)
                        ];
                    }
                }
            },
            test: {
                options: {
                    port:4545,
                    middleware: function (connect) {
                        return [
                            mountFolder(connect, '.tmp'),
                            mountFolder(connect, 'test')
                        ];
                    }
                }
            },
            dev:{
                options: {}
            }
        },
        open: {
            server: {
                url: 'http://localhost:<%= connect.options.port %>'
            }
        },
        clean: {
            dist: {
                files: [{
                    dot: true,
                    src: [
                        '.tmp',
                        '<%= config.dist %>/*',
                        '!<%= config.dist %>/.git*'
                    ]
                }]
            },
            server: '.tmp'
        },
        jshint: {
            options: {
                jshintrc: '.jshintrc'
            },
            all: [
                'Gruntfile.js',
                '<%= config.src %>/{,*/}*.js'
            ]
        },
        karma: {
            options: {
                configFile: 'karma.conf.js',
                runnerPort: 9999,
                browsers: ['Chrome', 'Firefox']
            },
            unit: {
                reporters: 'dots'
            },
            continuous: {
                singleRun: true,
                browsers: ['PhantomJS']
            },
            ci: {
                singleRun: true,
                browsers: ['PhantomJS']
            }
        },
        concat: {
            dist: {
                files: {
                    '<%= config.dist %>/<%= config.name %>.js': [
                        '.tmp/{,*/}*.js',
                        '<%= config.src %>/{,*/}*.js'
                    ]
                }
            }
        },
        uglify: {
            dist: {
                files: {
                    '<%= config.dist %>/<%= config.name %>.min.js': [
                        '<%= config.dist %>/<%= config.name %>.js'
                    ]
                }
            }
        },
        copy: {
            dist: {
                files: [{
                    expand: true,
                    dot: true,
                    cwd: '<%= config.src %>',
                    dest: '<%= config.dist %>',
                    src: []
                }]
            }
        }
    });

    grunt.renameTask('regarde', 'watch');

    grunt.registerTask('server', [
        'clean:server',
        'livereload-start',
        'connect:livereload',
        'open',
        'watch'
    ]);

    grunt.registerTask('test', [
        'clean:server',
        'connect:test',
        'karma:ci'
    ]);

    grunt.registerTask('build', [
        'clean:dist',
        'jshint',
        'test',
        'concat',
        'copy',
        'uglify',
    ]);

    grunt.registerTask('default', ['build']);
};
<|endoftext|>