<commit_before>/*var person = new Object();
person.name = "Gaohaoyang";
person.job = "FE";
person.sayName = function() {
    console.log(this.name);
}

var person = {
    name: "Gaohaoyang",
    job: "FE",
    sayName: function() {
        console.log(this.name);
    }
};

function foo(x, y) {
    if (typeof x === 'number' &&
        typeof y === 'number') {
        return x + y;
    } else {
        return 0;
    }
}
foo(1, 2); // 3

function add(a, b) {
    return a + b;
}

//function variable
var add = function(a, b) {
    // body...
};

// IEF(Immediately Executed Function)
(function() {
    // body...
})();

/*return function() {
    // body...
};*/

//NFE(Named Function Expression)
/*var add = function foo(a, b) {
    // body...
};*/

/*var num = add(1, 2);
console.log(num);

var add = function(a, b) {
    return a + b;
};*/

/*var func = function nfe() {};
console.log(func === nfe);*/
// 在 IE6~8，得到 false
// 在 IE9+ 及现代浏览器中 Uncaught ReferenceError: nfe is not defined
//

/*var func = new Function('a','b','console.log(a+b);');
func(1,2);//3

var func2 = Function('a','b','console.log(a+b);');
func2(1,2);//3*/

/*console.log(this.document === document); //true
console.log(this === window); //true

this.a = 91;
console.log(window.a); //91*/

/*function f1 () {
    return this;
}
console.log(f1() === window);//true, global object

function f2 () {
    "use strict";//使用严格模式
    return this;
}
console.log(f1() === undefined);//true*/

/*var o = {
    prop: 37,
    f: function() {
        return this.prop;
    }
};
console.log(o.f()); // logs 37
var o = {
    prop: 37
};

function independent() {
    return this.prop;
}
o.f = independent;
console.log(o.f()); // logs 37*/

/*var o = {
    f: function() {
        return this.a + this.b;
    }
};
var p = Object.create(o);
p.a = 1;
p.b = 2;
console.log(p.f()); //3*/
/*function modulus() {
    return Math.sqrt(this.re * this.re + this.im * this.im);
}
var o = {
    re: 1,
    im: -1,
    get phase() {
        return Math.atan2(this.im, this.re);
    }
};
Object.defineProperty(o, 'modulus', {
    get: modulus,
    enumerable: true,
    configurable: true
});
console.log(o.phase, o.modulus); // -0.78 1.4142*/

/*function MyClass() {
    this.a = 25;
}
var o = new MyClass();
console.log(o.a); //25

//new MyClass() 的时候，MyClass()中的this会指向一个空对象，这个对象的原型会指向 MyClass.prototype。MyClass()没有返回值或者返回为基本类型时，默认将this返回。
//
function C2() {
    this.a = 26;
    return {
        a: 24
    };
}

o = new C2();
console.log(o.a); //24

//因为返回了对象，将这个对象作为返回值*/

/*function add(c, d) {
    return this.a + this.b + c + d;
}
var o = {
    a: 1,
    b: 3
};
add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16
add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34
function bar() {
    console.log(Object.prototype.toString.call(this));
}
bar.call(7); // "[object Number]"*/

/*function f() {
    return this.a;
}
var g = f.bind({
    a: "test"
});
console.log(g()); // test
var o = {
    a: 37,
    f: f,
    g: g
};
console.log(o.f(), o.g()); // 37, test*/

// 绑定之后再调用时，仍然会按绑定时的内容走，所以 o.g() 结果是 test
//

/*function foo(x, y, z) {
    arguments.length; // 2
    arguments[0]; // 1
    arguments[0] = 10;
    x; // change to 10

    arguments[2] = 100;
    z; // still undefined!!!
    arguments.callee === foo; // true
}

foo(1, 2);
foo.length; // 3
foo.name; //"foo"*/

/*function foo(x, y) {
    console.log(x, y, this);
}

foo.call(100, 1, 2); //1 2 Number {[[PrimitiveValue]]: 100}
foo.apply(true, [3, 4]); //3 4 Boolean {[[PrimitiveValue]]: true}
foo.apply(null); //undefined undefined Window
foo.apply(undefined); //undefined undefined Window*/

/*this.x = 9;
var module = {
    x: 81,
    getX: function() {
        return console.log(this.x);
    }
};

module.getX(); //81

var getX = module.getX;
getX(); //9

var boundGetX = getX.bind(module);
boundGetX(); //81*/

/*function add(a, b, c) {
    return a + b + c;
}

var func = add.bind(undefined, 100);
func(1, 2); //103

var fun2 = fun.bind(undefined, 200);
func2(10); //310*/

/*function foo() {
    this.b = 100;
    return this.a;
}

console.log(foo()); //undefined

var func = foo.bind({
    a: 1
});

console.log(func()); //1
console.log(new func()); //foo {b: 100}*/

/*function outer() {
    var localVal = 30;
    return localVal;
}

console.log(outer()); //30

function outer2() {
    var localVal = 30;
    return function() {
        return localVal;
    };
}

var func = outer2();
console.log(func()); //30

! function() {
    var localData = "localData here";
    document.addEventListener('click',
        function() {
            console.log(localData);
        });
}();

! function() {
    var localData = "localData here";
    var url = "http://www.baidu.com/";
    $.ajax({
        url: url,
        success: function() {
            // do sth...
            console.log(localData);
        }
    });
}()
*/

/*document.body.innerHTML = "
aaa
" + "
bbb

ccc
";
for (var i = 1; i < 4; i++) {
    document.getElementById('div' + i).
    addEventListener('click', function() {
        alert(i); // all are 4!
    });
}*/

/*document.body.innerHTML = "
aaa
" + "
bbb

ccc
";
for (var i = 1; i < 4; i++) {
    ! function(i) {
        document.getElementById('div' + i).
        addEventListener('click', function() {
            alert(i); // 1, 2, 3
        });
    }(i);
}*/

/*(function() {
    var _userId = 9527;
    var _typeId = "item";
    var exp = {};

    function converter(userId) {
        return +userId;
    }

    exp.getUserId = function() {
        return converter(_userId);
    };

    exp.getTypeId = function() {
        return _typeId;
    };

    window.a = exp;
})();

console.log(a.getUserId()); //9527
console.log(a.getTypeId()); //item

console.log(a._userId); //undefined
console.log(a._typeId); //undefined
console.log(converter); //Uncaught ReferenceError: converter is not defined*/

/////////////////////////////////////////////////////////////////
//************************OOP********************************* //
/////////////////////////////////////////////////////////////////

/*function Foo() {
    this.y = 2;
}
console.log(typeof Foo.prototype); //object

Foo.prototype.x = 1;
var obj3 = new Foo();

console.log(obj3.y); //2
console.log(obj3.x); //1*/

//例

/*function Person(name, age) {
    this.name = name;
    this.age = age;
}

Person.prototype.LEGS_NUM = 2;
Person.prototype.ARMS_NUM = 2;

Person.prototype.hi = function() {
    console.log('Hi, my name is ' + this.name + ". I'm " + this.age + ' years old now');
};

Person.prototype.walking = function() {
    console.log(this.name + ' is walking...');
};

function Student(name, age, className) {
    Person.call(this, name, age); //使 Person 中的 this 指向 Student
    this.className = className;
}

Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;

Student.prototype.hi = function() {
    console.log('Hi, my name is ' + this.name + ". I'm " + this.age + ' years old now, and from ' + this.className + ".");
};

Student.prototype.learn = function(subject) {
    console.log(this.name + ' is learning ' + subject + ' at ' + this.className + '.');
}

//test
var gao = new Student('Gao', '24', 'Class 3123');
console.log(gao);
gao.hi(); //Hi, my name is Gao. I'm 24 years old now, and from Class 3123.
gao.LEGS_NUM; //2
gao.walking(); //Gao is walking...
gao.learn('JavaScript'); //Gao is learning JavaScript at Class 3123.

Student.prototype.x = 101;
console.log(gao.x); //101

Student.prototype = {
    y: 2
};
console.log(gao.x); //101
console.log(gao.y); //undefined

var ying = new Student('Ying', 24, 'UI');
console.log(ying.x); //undefined
console.log(ying.y); //2*/

/*Object.prototype.x = 1;
var obj = {};
console.log(obj.x); //1
console.log(obj);

for (var k in obj) {
    console.log('result--->' + k);
}
// result--->x

for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
        console.log("result--->" + key);
    }
}

Object.defineProperty(Object.prototype, 'x', {
    writable: true,
    value: 1
});
var obj = {};
console.log(obj.x);//1
console.log(obj);
for (var k in obj) {
    console.log('result--->' + k);
}
// nothing output here*/

/*console.log([1, 2] instanceof Array); //true
console.log([1, 2] instanceof Object); //true
console.log(new Object() instanceof Array); //false*/

/*function Person() {}

function Student() {}

Student.prototype = Person.prototype; //1

Student.prototype = new Person(); //2

Student.prototype = Object.create(Person.prototype); //3

Student.prototype.constructor = Student;

if (!Object.create) {
    Object.create = function(proto) {
        function F() {}
        F.prototype = proto;
        return new F;
    };
}*/

//---------------模拟重载------------------

/*function Person() {
    var args = arguments;
    if (typeof args[0] === 'object' && args[0]) {
        if (args[0].name) {
            this.name = args[0].name;
        }
        if(args[0].age){
            this.age = args[0].age;
        }
    } else {
        if (args[0]) {
            this.name = args[0];
        }
        if (args[1]) {
            this.age = args[1];
        }
    }
}

//重写 toString 方法
Person.prototype.toString = function() {
    console.log('name='+this.name+', age='+this.age);
};

var gao = new Person({name:'Gao',age:24});
gao.toString();

var ying = new Person('Ying',25);
ying.toString();*/

//-------------------调用子类方法-----------------------

/*function Person(name) {
    this.name = name;
}

function Student(name, className) {
    this.className = className;
    Person.call(this, name); // 调用基类的构造器
}

var gao = new Student('Gao', '3123');
console.log(gao); // Student {className: "3123", name: "Gao"}

Person.prototype.init = function() {};

Student.prototype.init = function() {
    // do sth...
    Person.prototype.init.apply(this, arguments); // 同时也想调用父类被覆盖的方法
};*/

//---------------------链式调用---------------------------

/*function ClassManager() {}
ClassManager.prototype.addClass = function(str) {
    console.log('Class: ' + str + ' added');
    return this;
};

var manager = new ClassManager();
manager.addClass('classA').addClass('classB').addClass('classC');
// Class: classA added
// Class: classB added
// Class: classC added*/

//---------------------抽象类--------------------------

function DetectorBase() {
    throw new Error('Abstract class can not be invoked directly!');
}

DetectorBase.detect = function() {
    console.log('Detection starting...');
}
DetectorBase.stop = function() {
    console.log('Detection stopped.');
};
DetectorBase.init = function() {
    throw new Error('Error');
}

// var d = new DetectorBase();

function LinkDetector() {}
LinkDetector.prototype = Object.create(DetectorBase.prototype);
LinkDetector.prototype.constructor = LinkDetector;

var l = new LinkDetector();
console.log(l);
l.detect();
l.init();<commit_msg>finish oop<commit_after>/*var person = new Object();
person.name = "Gaohaoyang";
person.job = "FE";
person.sayName = function() {
    console.log(this.name);
}

var person = {
    name: "Gaohaoyang",
    job: "FE",
    sayName: function() {
        console.log(this.name);
    }
};

function foo(x, y) {
    if (typeof x === 'number' &&
        typeof y === 'number') {
        return x + y;
    } else {
        return 0;
    }
}
foo(1, 2); // 3

function add(a, b) {
    return a + b;
}

//function variable
var add = function(a, b) {
    // body...
};

// IEF(Immediately Executed Function)
(function() {
    // body...
})();

/*return function() {
    // body...
};*/

//NFE(Named Function Expression)
/*var add = function foo(a, b) {
    // body...
};*/

/*var num = add(1, 2);
console.log(num);

var add = function(a, b) {
    return a + b;
};*/

/*var func = function nfe() {};
console.log(func === nfe);*/
// 在 IE6~8，得到 false
// 在 IE9+ 及现代浏览器中 Uncaught ReferenceError: nfe is not defined
//

/*var func = new Function('a','b','console.log(a+b);');
func(1,2);//3

var func2 = Function('a','b','console.log(a+b);');
func2(1,2);//3*/

/*console.log(this.document === document); //true
console.log(this === window); //true

this.a = 91;
console.log(window.a); //91*/

/*function f1 () {
    return this;
}
console.log(f1() === window);//true, global object

function f2 () {
    "use strict";//使用严格模式
    return this;
}
console.log(f1() === undefined);//true*/

/*var o = {
    prop: 37,
    f: function() {
        return this.prop;
    }
};
console.log(o.f()); // logs 37
var o = {
    prop: 37
};

function independent() {
    return this.prop;
}
o.f = independent;
console.log(o.f()); // logs 37*/

/*var o = {
    f: function() {
        return this.a + this.b;
    }
};
var p = Object.create(o);
p.a = 1;
p.b = 2;
console.log(p.f()); //3*/
/*function modulus() {
    return Math.sqrt(this.re * this.re + this.im * this.im);
}
var o = {
    re: 1,
    im: -1,
    get phase() {
        return Math.atan2(this.im, this.re);
    }
};
Object.defineProperty(o, 'modulus', {
    get: modulus,
    enumerable: true,
    configurable: true
});
console.log(o.phase, o.modulus); // -0.78 1.4142*/

/*function MyClass() {
    this.a = 25;
}
var o = new MyClass();
console.log(o.a); //25

//new MyClass() 的时候，MyClass()中的this会指向一个空对象，这个对象的原型会指向 MyClass.prototype。MyClass()没有返回值或者返回为基本类型时，默认将this返回。
//
function C2() {
    this.a = 26;
    return {
        a: 24
    };
}

o = new C2();
console.log(o.a); //24

//因为返回了对象，将这个对象作为返回值*/

/*function add(c, d) {
    return this.a + this.b + c + d;
}
var o = {
    a: 1,
    b: 3
};
add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16
add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34
function bar() {
    console.log(Object.prototype.toString.call(this));
}
bar.call(7); // "[object Number]"*/

/*function f() {
    return this.a;
}
var g = f.bind({
    a: "test"
});
console.log(g()); // test
var o = {
    a: 37,
    f: f,
    g: g
};
console.log(o.f(), o.g()); // 37, test*/

// 绑定之后再调用时，仍然会按绑定时的内容走，所以 o.g() 结果是 test
//

/*function foo(x, y, z) {
    arguments.length; // 2
    arguments[0]; // 1
    arguments[0] = 10;
    x; // change to 10

    arguments[2] = 100;
    z; // still undefined!!!
    arguments.callee === foo; // true
}

foo(1, 2);
foo.length; // 3
foo.name; //"foo"*/

/*function foo(x, y) {
    console.log(x, y, this);
}

foo.call(100, 1, 2); //1 2 Number {[[PrimitiveValue]]: 100}
foo.apply(true, [3, 4]); //3 4 Boolean {[[PrimitiveValue]]: true}
foo.apply(null); //undefined undefined Window
foo.apply(undefined); //undefined undefined Window*/

/*this.x = 9;
var module = {
    x: 81,
    getX: function() {
        return console.log(this.x);
    }
};

module.getX(); //81

var getX = module.getX;
getX(); //9

var boundGetX = getX.bind(module);
boundGetX(); //81*/

/*function add(a, b, c) {
    return a + b + c;
}

var func = add.bind(undefined, 100);
func(1, 2); //103

var fun2 = fun.bind(undefined, 200);
func2(10); //310*/

/*function foo() {
    this.b = 100;
    return this.a;
}

console.log(foo()); //undefined

var func = foo.bind({
    a: 1
});

console.log(func()); //1
console.log(new func()); //foo {b: 100}*/

/*function outer() {
    var localVal = 30;
    return localVal;
}

console.log(outer()); //30

function outer2() {
    var localVal = 30;
    return function() {
        return localVal;
    };
}

var func = outer2();
console.log(func()); //30

! function() {
    var localData = "localData here";
    document.addEventListener('click',
        function() {
            console.log(localData);
        });
}();

! function() {
    var localData = "localData here";
    var url = "http://www.baidu.com/";
    $.ajax({
        url: url,
        success: function() {
            // do sth...
            console.log(localData);
        }
    });
}()
*/

/*document.body.innerHTML = "
aaa
" + "
bbb

ccc
";
for (var i = 1; i < 4; i++) {
    document.getElementById('div' + i).
    addEventListener('click', function() {
        alert(i); // all are 4!
    });
}*/

/*document.body.innerHTML = "
aaa
" + "
bbb

ccc
";
for (var i = 1; i < 4; i++) {
    ! function(i) {
        document.getElementById('div' + i).
        addEventListener('click', function() {
            alert(i); // 1, 2, 3
        });
    }(i);
}*/

/*(function() {
    var _userId = 9527;
    var _typeId = "item";
    var exp = {};

    function converter(userId) {
        return +userId;
    }

    exp.getUserId = function() {
        return converter(_userId);
    };

    exp.getTypeId = function() {
        return _typeId;
    };

    window.a = exp;
})();

console.log(a.getUserId()); //9527
console.log(a.getTypeId()); //item

console.log(a._userId); //undefined
console.log(a._typeId); //undefined
console.log(converter); //Uncaught ReferenceError: converter is not defined*/

/////////////////////////////////////////////////////////////////
//************************OOP********************************* //
/////////////////////////////////////////////////////////////////

/*function Foo() {
    this.y = 2;
}
console.log(typeof Foo.prototype); //object

Foo.prototype.x = 1;
var obj3 = new Foo();

console.log(obj3.y); //2
console.log(obj3.x); //1*/

//例

/*function Person(name, age) {
    this.name = name;
    this.age = age;
}

Person.prototype.LEGS_NUM = 2;
Person.prototype.ARMS_NUM = 2;

Person.prototype.hi = function() {
    console.log('Hi, my name is ' + this.name + ". I'm " + this.age + ' years old now');
};

Person.prototype.walking = function() {
    console.log(this.name + ' is walking...');
};

function Student(name, age, className) {
    Person.call(this, name, age); //使 Person 中的 this 指向 Student
    this.className = className;
}

Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;

Student.prototype.hi = function() {
    console.log('Hi, my name is ' + this.name + ". I'm " + this.age + ' years old now, and from ' + this.className + ".");
};

Student.prototype.learn = function(subject) {
    console.log(this.name + ' is learning ' + subject + ' at ' + this.className + '.');
}

//test
var gao = new Student('Gao', '24', 'Class 3123');
console.log(gao);
gao.hi(); //Hi, my name is Gao. I'm 24 years old now, and from Class 3123.
gao.LEGS_NUM; //2
gao.walking(); //Gao is walking...
gao.learn('JavaScript'); //Gao is learning JavaScript at Class 3123.

Student.prototype.x = 101;
console.log(gao.x); //101

Student.prototype = {
    y: 2
};
console.log(gao.x); //101
console.log(gao.y); //undefined

var ying = new Student('Ying', 24, 'UI');
console.log(ying.x); //undefined
console.log(ying.y); //2*/

/*Object.prototype.x = 1;
var obj = {};
console.log(obj.x); //1
console.log(obj);

for (var k in obj) {
    console.log('result--->' + k);
}
// result--->x

for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
        console.log("result--->" + key);
    }
}

Object.defineProperty(Object.prototype, 'x', {
    writable: true,
    value: 1
});
var obj = {};
console.log(obj.x);//1
console.log(obj);
for (var k in obj) {
    console.log('result--->' + k);
}
// nothing output here*/

/*console.log([1, 2] instanceof Array); //true
console.log([1, 2] instanceof Object); //true
console.log(new Object() instanceof Array); //false*/

/*function Person() {}

function Student() {}

Student.prototype = Person.prototype; //1

Student.prototype = new Person(); //2

Student.prototype = Object.create(Person.prototype); //3

Student.prototype.constructor = Student;

if (!Object.create) {
    Object.create = function(proto) {
        function F() {}
        F.prototype = proto;
        return new F;
    };
}*/

//---------------模拟重载------------------

/*function Person() {
    var args = arguments;
    if (typeof args[0] === 'object' && args[0]) {
        if (args[0].name) {
            this.name = args[0].name;
        }
        if(args[0].age){
            this.age = args[0].age;
        }
    } else {
        if (args[0]) {
            this.name = args[0];
        }
        if (args[1]) {
            this.age = args[1];
        }
    }
}

//重写 toString 方法
Person.prototype.toString = function() {
    console.log('name='+this.name+', age='+this.age);
};

var gao = new Person({name:'Gao',age:24});
gao.toString();

var ying = new Person('Ying',25);
ying.toString();*/

//-------------------调用子类方法-----------------------

/*function Person(name) {
    this.name = name;
}

function Student(name, className) {
    this.className = className;
    Person.call(this, name); // 调用基类的构造器
}

var gao = new Student('Gao', '3123');
console.log(gao); // Student {className: "3123", name: "Gao"}

Person.prototype.init = function() {};

Student.prototype.init = function() {
    // do sth...
    Person.prototype.init.apply(this, arguments); // 同时也想调用父类被覆盖的方法
};*/

//---------------------链式调用---------------------------

/*function ClassManager() {}
ClassManager.prototype.addClass = function(str) {
    console.log('Class: ' + str + ' added');
    return this;
};

var manager = new ClassManager();
manager.addClass('classA').addClass('classB').addClass('classC');
// Class: classA added
// Class: classB added
// Class: classC added*/

//---------------------抽象类--------------------------

/*function DetectorBase() {
    throw new Error('Abstract class can not be invoked directly!');
}

DetectorBase.detect = function() {
    console.log('Detection starting...');
}
DetectorBase.stop = function() {
    console.log('Detection stopped.');
};
DetectorBase.init = function() {
    throw new Error('Error');
}

var d = new DetectorBase();// Uncaught Error: Abstract class can not be invoked directly!

function LinkDetector() {}
LinkDetector.prototype = Object.create(DetectorBase.prototype);
LinkDetector.prototype.constructor = LinkDetector;

var l = new LinkDetector();
console.log(l); //LinkDetector {}__proto__: LinkDetector
l.detect(); //Uncaught TypeError: l.detect is not a function
l.init(); //Uncaught TypeError: l.init is not a function*/

var moduleA;
moduleA = function() {
    var prop = 1;

    function func() {}

    return {
        func: func,
        prop: prop
    };
};

var moduleA;

moduleA = new function() {
    var prop = 1;

    function func() {}

    this.func = func;
    this.prop = prop;
}<|endoftext|>


<commit_before>var _ = require('lodash');
var doctrine = require('doctrine');
var log = require('winston');

// A simple container of parsed tags with helpers
var Tags = function(content, tags) {
  // Sloppy implies support for jsdoc3 and closure compiler style types
  // Recoverable allows us to collect up information about the bad tags
  var parsed = doctrine.parse(content, { sloppy: true, recoverable: true, tags: tags });

  // Filter out the bad tags into a separate collection
  var badTags = this.badTags = [];
  this.tags = _.filter(parsed.tags, function(tag) {
    if ( tag.errors ) {
      badTags.push(tag);
    }
    return !tag.errors;
  });

  // Extract the description if necessary
  if ( parsed.description ) {
    var descriptionTag = this.getTag('description');
    if ( descriptionTag ) {
      descriptionTag.description = parsed.description + '\n' + descriptionTag.description;
    } else {
      this.tags.push({
        title: 'description',
        description: parsed.description
      });
    }
  }
};

Tags.prototype = {
  getTag: function(name, aliases) {
    var names = (aliases || []).concat(name);
    return _.find(this.tags, function(tag) { return _.contains(names, tag.title); });
  },

  getTags: function(name, aliases) {
    var names = (aliases || []).concat(name);
    return _.where(this.tags, function(tag) { return _.contains(names, tag.title); });
  },

  getType: function(tag) {
    try {
    var isOptional = tag.type.type === 'OptionalType';
    var mainType = isOptional ? tag.type.expression : tag.type;
    var mainTypeString = doctrine.type.stringify(mainType);
    var isUnion = mainType.type === 'UnionType';
    var typeList;
    if ( isUnion ) {
      typeList = _.map(mainType.elements, function(element) {
        return doctrine.type.stringify(element);
      });
    } else {
      typeList = [mainTypeString];
    }

    return {
      description: mainTypeString,
      optional: isOptional,
      typeList: typeList
    };
    } catch(e) {
      console.log(e);
      console.log(tag);
      throw e;
    }
  }
};

function formatBadTagErrorMessage(doc) {
  var message = 'Bad tags found in doc "' + doc.id + '" from file "' + doc.file + '" line ' + doc.startingLine + '\n';

  _.forEach(doc.tags.badTags, function(badTag) {
    var title = badTag.title || '<missing>';
    var description =
      badTag.name ||
      (_.isString(badTag.description) ? (badTag.description.substr(0, 20) + '...') : '<missing>');

    message += '  - Bad tag: "' + title + '" - "' + description + '"\n';
    _.forEach(badTag.errors, function(error) {
      message += '    * ' + error + '\n';
    });
  });

  return message + '\n';
}

var tags;
var plugin = module.exports = {
  name: 'doctrine-tag-parser',
  description: 'Parse the doc for tags using doctrine.',
  runAfter: ['parsing-tags'],
  runBefore: ['tags-parsed'],
  init: function(config) {
    tags = _.pluck(config.get('processing.tagDefinitions'), 'name');
    log.debug('Tags to parse:', tags);
  },
  process: function parseDocsWithDoctrine(docs) {
    _.forEach(docs, function(doc) {
      doc.tags = new Tags(doc.content, tags);
      if ( doc.tags.badTags.length > 0 ) {
        log.warn(formatBadTagErrorMessage(doc));
      }
    });
  }
};<commit_msg>fix(doctrine-tag-parser): don't rethrow error if tag type is bad<commit_after>var _ = require('lodash');
var doctrine = require('doctrine');
var log = require('winston');

// A simple container of parsed tags with helpers
var Tags = function(content, tags) {
  // Sloppy implies support for jsdoc3 and closure compiler style types
  // Recoverable allows us to collect up information about the bad tags
  var parsed = doctrine.parse(content, { sloppy: true, recoverable: true, tags: tags });

  // Filter out the bad tags into a separate collection
  var badTags = this.badTags = [];
  this.tags = _.filter(parsed.tags, function(tag) {
    if ( tag.errors ) {
      badTags.push(tag);
    }
    return !tag.errors;
  });

  // Extract the description if necessary
  if ( parsed.description ) {
    var descriptionTag = this.getTag('description');
    if ( descriptionTag ) {
      descriptionTag.description = parsed.description + '\n' + descriptionTag.description;
    } else {
      this.tags.push({
        title: 'description',
        description: parsed.description
      });
    }
  }
};

Tags.prototype = {
  getTag: function(name, aliases) {
    var names = (aliases || []).concat(name);
    return _.find(this.tags, function(tag) { return _.contains(names, tag.title); });
  },

  getTags: function(name, aliases) {
    var names = (aliases || []).concat(name);
    return _.where(this.tags, function(tag) { return _.contains(names, tag.title); });
  },

  getType: function(tag) {
    try {
    var isOptional = tag.type.type === 'OptionalType';
    var mainType = isOptional ? tag.type.expression : tag.type;
    var mainTypeString = doctrine.type.stringify(mainType);
    var isUnion = mainType.type === 'UnionType';
    var typeList;
    if ( isUnion ) {
      typeList = _.map(mainType.elements, function(element) {
        return doctrine.type.stringify(element);
      });
    } else {
      typeList = [mainTypeString];
    }

    return {
      description: mainTypeString,
      optional: isOptional,
      typeList: typeList
    };
    } catch(e) {
      console.log(e);
      console.log(tag);
    }
  }
};

function formatBadTagErrorMessage(doc) {
  var message = 'Bad tags found in doc "' + doc.id + '" from file "' + doc.file + '" line ' + doc.startingLine + '\n';

  _.forEach(doc.tags.badTags, function(badTag) {
    var title = badTag.title || '<missing>';
    var description =
      badTag.name ||
      (_.isString(badTag.description) ? (badTag.description.substr(0, 20) + '...') : '<missing>');

    message += '  - Bad tag: "' + title + '" - "' + description + '"\n';
    _.forEach(badTag.errors, function(error) {
      message += '    * ' + error + '\n';
    });
  });

  return message + '\n';
}

var tags;
var plugin = module.exports = {
  name: 'doctrine-tag-parser',
  description: 'Parse the doc for tags using doctrine.',
  runAfter: ['parsing-tags'],
  runBefore: ['tags-parsed'],
  init: function(config) {
    tags = _.pluck(config.get('processing.tagDefinitions'), 'name');
    log.debug('Tags to parse:', tags);
  },
  process: function parseDocsWithDoctrine(docs) {
    _.forEach(docs, function(doc) {
      doc.tags = new Tags(doc.content, tags);
      if ( doc.tags.badTags.length > 0 ) {
        log.warn(formatBadTagErrorMessage(doc));
      }
    });
  }
};<|endoftext|>


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

/**
 * WordPress dependencies
 */
import { createRegistry } from '@wordpress/data';

/**
 * Internal dependencies
 */
import API from 'googlesitekit-api';
import { unsubscribeFromAll } from 'tests/js/utils';
import { createNotificationsStore } from '../data/create-notifications-store';
import { createSettingsStore } from '../data/create-settings-store';
import { createInfoStore } from './create-info-store';
import { createModuleStore } from './create-module-store';
import { createSubmitChangesStore } from './create-submit-changes-store';

const SETTING_SLUG = 'testSetting';
const MODULE_SLUG = 'base';
const TEST_STORE_NAME = 'test/' + MODULE_SLUG;

describe( 'createModuleStore store', () => {
	const settingSlugs = [ SETTING_SLUG ];

	let registry;
	let storeDefinition;

	beforeAll( () => {
		API.setUsingCache( false );
	} );

	beforeEach( () => {
		registry = createRegistry();

		storeDefinition = createModuleStore( MODULE_SLUG, { storeName: TEST_STORE_NAME, settingSlugs, registry } );

		registry.registerStore( storeDefinition.STORE_NAME, storeDefinition );
	} );

	afterAll( () => {
		API.setUsingCache( true );
	} );

	afterEach( () => {
		unsubscribeFromAll( registry );
	} );

	describe( 'name', () => {
		it( 'returns the correct default store name', () => {
			expect( storeDefinition.STORE_NAME ).toEqual( TEST_STORE_NAME );
		} );
	} );

	describe( 'actions', () => {
		it.each( [
			[ 'createNotificationsStore', createNotificationsStore( 'modules', MODULE_SLUG, 'notifications' ) ],
			[ 'createSettingsStore', createSettingsStore( 'modules', MODULE_SLUG, 'settings', { settingSlugs, registry } ) ],
			[ 'createSubmitChangesStore', createSubmitChangesStore() ],
		] )( 'includes all actions from %s store', ( partialStoreName, partialStore ) => {
			expect( Object.keys( storeDefinition.actions ) ).toEqual(
				expect.arrayContaining( Object.keys( partialStore.actions ) )
			);
		} );
	} );

	describe( 'selectors', () => {
		it.each( [
			[ 'createInfoStore', createInfoStore( MODULE_SLUG, { storeName: TEST_STORE_NAME } ) ],
			[ 'createNotificationsStore', createNotificationsStore( 'modules', MODULE_SLUG, 'notifications' ) ],
			[ 'createSettingsStore', createSettingsStore( 'modules', MODULE_SLUG, 'settings', { settingSlugs, registry } ) ],
			[ 'createSubmitChangesStore', createSubmitChangesStore() ],
		] )( 'includes all actions from %s store', ( partialStoreName, partialStore ) => {
			expect( Object.keys( storeDefinition.selectors ) ).toEqual(
				expect.arrayContaining( Object.keys( partialStore.selectors ) )
			);
		} );
	} );
} );
<commit_msg>Update assets/js/googlesitekit/modules/create-module-store.test.js<commit_after>/**
 * Module datastore functions tests.
 *
 * Site Kit by Google, Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * WordPress dependencies
 */
import { createRegistry } from '@wordpress/data';

/**
 * Internal dependencies
 */
import API from 'googlesitekit-api';
import { unsubscribeFromAll } from 'tests/js/utils';
import { createNotificationsStore } from '../data/create-notifications-store';
import { createSettingsStore } from '../data/create-settings-store';
import { createInfoStore } from './create-info-store';
import { createModuleStore } from './create-module-store';
import { createSubmitChangesStore } from './create-submit-changes-store';

const SETTING_SLUG = 'testSetting';
const MODULE_SLUG = 'base';
const TEST_STORE_NAME = `test/${ MODULE_SLUG }`;

describe( 'createModuleStore store', () => {
	const settingSlugs = [ SETTING_SLUG ];

	let registry;
	let storeDefinition;

	beforeAll( () => {
		API.setUsingCache( false );
	} );

	beforeEach( () => {
		registry = createRegistry();

		storeDefinition = createModuleStore( MODULE_SLUG, { storeName: TEST_STORE_NAME, settingSlugs, registry } );

		registry.registerStore( storeDefinition.STORE_NAME, storeDefinition );
	} );

	afterAll( () => {
		API.setUsingCache( true );
	} );

	afterEach( () => {
		unsubscribeFromAll( registry );
	} );

	describe( 'name', () => {
		it( 'returns the correct default store name', () => {
			expect( storeDefinition.STORE_NAME ).toEqual( TEST_STORE_NAME );
		} );
	} );

	describe( 'actions', () => {
		it.each( [
			[ 'createNotificationsStore', createNotificationsStore( 'modules', MODULE_SLUG, 'notifications' ) ],
			[ 'createSettingsStore', createSettingsStore( 'modules', MODULE_SLUG, 'settings', { settingSlugs, registry } ) ],
			[ 'createSubmitChangesStore', createSubmitChangesStore() ],
		] )( 'includes all actions from %s store', ( partialStoreName, partialStore ) => {
			expect( Object.keys( storeDefinition.actions ) ).toEqual(
				expect.arrayContaining( Object.keys( partialStore.actions ) )
			);
		} );
	} );

	describe( 'selectors', () => {
		it.each( [
			[ 'createInfoStore', createInfoStore( MODULE_SLUG, { storeName: TEST_STORE_NAME } ) ],
			[ 'createNotificationsStore', createNotificationsStore( 'modules', MODULE_SLUG, 'notifications' ) ],
			[ 'createSettingsStore', createSettingsStore( 'modules', MODULE_SLUG, 'settings', { settingSlugs, registry } ) ],
			[ 'createSubmitChangesStore', createSubmitChangesStore() ],
		] )( 'includes all actions from %s store', ( partialStoreName, partialStore ) => {
			expect( Object.keys( storeDefinition.selectors ) ).toEqual(
				expect.arrayContaining( Object.keys( partialStore.selectors ) )
			);
		} );
	} );
} );
<|endoftext|>


<commit_before>$(function() {

    var switchButton = $(".toggleSideBar");
    var sidePane = switchButton.closest("div.sidePane");
    var templateWrapper = $('#templateWrapper');
    var speed = 300;
    var animation = {};

    sidePane.data('isOpened', true);

    sidePane.css({
        '-webkit-transition': 'none !important',
        '-moz-transition':    'none !important',
        '-o-transition':      'none !important',
        '-ms-transition':     'none !important',
        'transition':         'none !important'
    });

    // closing bugfix
    sidePane.width(sidePane.width());

    if(sidePane.data('closed')){
        sidePane.data('isOpened', false);
        sidePane.find('.sideContent').css('display','none');
        sidePane.css({
            'transition': 'none'
        });
        sidePane.css({right: (sidePane.outerWidth(true)*-1) + "px"});
    }
    sidePane.width(sidePane.width());
    sidePane.show(0);

    switchButton.on('click', function() {
        var isOpened = sidePane.data('isOpened');
        var align = sidePane.hasClass('right') ? 'right' : 'left';
        if(isOpened) {
            animation[align] =  "-" + sidePane.outerWidth(true) + "px"; //, "swing"];
            sidePane.animate(animation,speed, function() {
                templateWrapper.removeClass("sidePaneOpened");
                sidePane.data('isOpened', !isOpened);
                sidePane.find('.sideContent').css('display','none');
            });
        } else {
            templateWrapper.addClass("sidePaneOpened");
            animation[align] = "0px";
            sidePane.find(".sideContent").css('display','block');
            sidePane.animate(animation, speed, function() {
                sidePane.data('isOpened', !isOpened);
            });
        }
    });
});
<commit_msg>Add fullscreen template region "align" and "closed" properties<commit_after>$(function() {

    var switchButton = $(".toggleSideBar");
    var sidePane = switchButton.closest("div.sidePane");
    var templateWrapper = $('.templateWrapper');
    var speed = 300;
    var animation = {};

    sidePane.data('isOpened', true);

    sidePane.css({
        '-webkit-transition': 'none !important',
        '-moz-transition':    'none !important',
        '-o-transition':      'none !important',
        '-ms-transition':     'none !important',
        'transition':         'none !important'
    });

    // closing bugfix
    sidePane.width(sidePane.width());

    if(sidePane.data('closed')) {
        sidePane.data('isOpened', false);
        sidePane.find('.sideContent').css('display', 'none');
        sidePane.css({
            'transition': 'none'
        });

        if(sidePane.hasClass("right")) {
            sidePane.css({right: (sidePane.outerWidth(true) * -1) + "px"});
        } else {
            sidePane.css({left: (sidePane.outerWidth(true) * -1) + "px"});
        }

    }
    sidePane.width(sidePane.width());
    sidePane.show(0);

    switchButton.on('click', function() {
        var isOpened = sidePane.data('isOpened');
        var align = sidePane.hasClass('right') ? 'right' : 'left';
        var onProgress = function(now, fx) {
            sidePane.trigger("animate");
        };
        if(isOpened) {
            animation[align] = "-" + sidePane.outerWidth(true) + "px"; //, "swing"];

            sidePane.animate(animation, {
                duration: speed,
                progress: onProgress,
                complete: function() {
                    templateWrapper.removeClass("sidePaneOpened");
                    sidePane.data('isOpened', !isOpened);
                    sidePane.find('.sideContent').css('display', 'none');
                    sidePane.trigger("animate");
                    sidePane.trigger("switchSidepane");
                }
            });
        } else {
            templateWrapper.addClass("sidePaneOpened");
            animation[align] = "0px";
            sidePane.find(".sideContent").css('display', 'block');
            sidePane.animate(animation, {
                duration: speed,
                progress: onProgress,
                complete: function() {
                    sidePane.data('isOpened', !isOpened);
                    sidePane.trigger("animate");
                    sidePane.trigger("switchSidepane");
                }
            });
        }
    });
});
<|endoftext|>


<commit_before>var RestClient = require('rest-facade').Client;
var ArgumentError = require('./exceptions').ArgumentError;
var utils = require('./utils');

/**
 * Simple facade for consuming a REST API endpoint.
 * @external RestClient
 * @see https://github.com/ngonzalvez/rest-facade
 */

/**
 * @class ClientsManager
 * Auth0 Clients Manager.
 * @constructor
 *
 * @param {Object} options            The client options.
 * @param {String} options.token      The API access token.
 * @param {String} [options.region]   The code for the region in use.
 * @param {String} [options.domain]   The API domain for the region in use.
 */
var ClientsManager = function (options) {
  if (options === null || typeof options !== 'object') {
    throw new ArgumentError('Must provide client options');
  }

  if (options.baseUrl === null || options.baseUrl === undefined) {
    throw new ArgumentError('Must provide a base URL for the API');
  }

  if ('string' !== typeof options.baseUrl || options.baseUrl.length === 0) {
    throw new ArgumentError('The provided base URL is invalid');
  }

  if (options.accessToken === null || options.accessToken === undefined) {
    throw new ArgumentError('Must provide an access token');
  }

  if ('string' !== typeof options.accessToken|| options.accessToken.length === 0) {
    throw new ArgumentError('Invalid access token');
  }

  /**
   * Options object for the Rest Client instance.
   *
   * @type {Object}
   */
  clientOptions = {
    headers: headers,
    query: { convertCase: 'snakeCase', repeatParams: false }
  };

  /**
   * Provides an abstraction layer for consuming the
   * [Auth0 Clients endpoint]{@link https://auth0.com/docs/api/v2#!/Clients}.
   *
   * @type {external:RestClient}
   */
  this.resource = new RestClient(options.baseUrl + '/clients/:clientId', clientOptions);
};

/**
 * Create an Auth0 client.
 *
 * @method    create
 * @memberOf  ClientsManager
 * @return    {Promise}
 */
utils.wrapPropertyMethod(ClientsManager, 'create', 'resource.create');

/**
 * Get all Auth0 clients.
 *
 * @method  getAll
 * @memberOf  ClientsManager
 * @return  {Promise}               Returns a promise if no callback is received.
 */
utils.wrapPropertyMethod(ClientsManager, 'getAll', 'resource.getAll');

/**
 * Get an Auth0 client.
 *
 * @method  get
 * @memberOf  ClientsManager
 * @return  {Promise}
 */
utils.wrapPropertyMethod(ClientsManager, 'get', 'resource.get');

/**
 * Update an Auth0 client.
 *
 * @method    update
 * @memberOf  ClientsManager
 * @return    {Promise}
 */
utils.wrapPropertyMethod(ClientsManager, 'update', 'resource.patch');

/**
 * Delete an Auth0 client.
 *
 * @method    delete
 * @memberOf  ClientsManager
 * @return    {Promise}
 */
utils.wrapPropertyMethod(ClientsManager, 'delete', 'resource.delete');

module.exports = ClientsManager;
<commit_msg>Fix headers not being passed properly in clients manager.<commit_after>var RestClient = require('rest-facade').Client;
var ArgumentError = require('./exceptions').ArgumentError;
var utils = require('./utils');

/**
 * Simple facade for consuming a REST API endpoint.
 * @external RestClient
 * @see https://github.com/ngonzalvez/rest-facade
 */

/**
 * @class ClientsManager
 * Auth0 Clients Manager.
 * @constructor
 *
 * @param {Object} options            The client options.
 * @param {String} options.token      The API access token.
 * @param {String} [options.region]   The code for the region in use.
 * @param {String} [options.domain]   The API domain for the region in use.
 */
var ClientsManager = function (options) {
  if (options === null || typeof options !== 'object') {
    throw new ArgumentError('Must provide client options');
  }

  if (options.baseUrl === null || options.baseUrl === undefined) {
    throw new ArgumentError('Must provide a base URL for the API');
  }

  if ('string' !== typeof options.baseUrl || options.baseUrl.length === 0) {
    throw new ArgumentError('The provided base URL is invalid');
  }

  /**
   * Options object for the Rest Client instance.
   *
   * @type {Object}
   */
  clientOptions = {
    headers: options.headers,
    query: { convertCase: 'snakeCase', repeatParams: false }
  };

  /**
   * Provides an abstraction layer for consuming the
   * [Auth0 Clients endpoint]{@link https://auth0.com/docs/api/v2#!/Clients}.
   *
   * @type {external:RestClient}
   */
  this.resource = new RestClient(options.baseUrl + '/clients/:clientId', clientOptions);
};

/**
 * Create an Auth0 client.
 *
 * @method    create
 * @memberOf  ClientsManager
 * @return    {Promise}
 */
utils.wrapPropertyMethod(ClientsManager, 'create', 'resource.create');

/**
 * Get all Auth0 clients.
 *
 * @method  getAll
 * @memberOf  ClientsManager
 * @return  {Promise}               Returns a promise if no callback is received.
 */
utils.wrapPropertyMethod(ClientsManager, 'getAll', 'resource.getAll');

/**
 * Get an Auth0 client.
 *
 * @method  get
 * @memberOf  ClientsManager
 * @return  {Promise}
 */
utils.wrapPropertyMethod(ClientsManager, 'get', 'resource.get');

/**
 * Update an Auth0 client.
 *
 * @method    update
 * @memberOf  ClientsManager
 * @return    {Promise}
 */
utils.wrapPropertyMethod(ClientsManager, 'update', 'resource.patch');

/**
 * Delete an Auth0 client.
 *
 * @method    delete
 * @memberOf  ClientsManager
 * @return    {Promise}
 */
utils.wrapPropertyMethod(ClientsManager, 'delete', 'resource.delete');

module.exports = ClientsManager;
<|endoftext|>


<commit_before>  var post = require('jpost');

  module.exports = function EnviLog(json, next){
    console.log(json);
    json.guid = '4aa22bd0-50a1-436a-a3c1-2b4062381a21';

    post('https://envilog.herokuapp.com/', json, function(err, res){

      if(next){
        next();
      }
    });
  };
<commit_msg>Fix time<commit_after>  var post = require('jpost');

  module.exports = function EnviLog(json, next){
    json.guid = '4aa22bd0-50a1-436a-a3c1-2b4062381a21';

    console.log(json);
    post('https://envilog.herokuapp.com/', json, function(err, res){

      if(next){
        next();
      }
    });
  };
<|endoftext|>


<commit_before>// jscs:disable
var path = require('path');
var webpack = require('webpack');

module.exports = {
  devtool: 'eval',
  entry:  {
    main: ['./src/client.js'],
    editor: ['./src/routes/Edit'],
    post: ['./src/routes/Post'],
  },
  output: {
     path: __dirname + '/build/static',
     filename: '[name].js',
     chunkFilename: '[id].chunk.js',
     publicPath: '/build/static/'
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin('common.js',  2),
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        unused: true,
        dead_code: true,
        warnings: false,
        screw_ie8: true,
      }
    }),
    new webpack.NoErrorsPlugin(),
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify('production'),
    })
  ],
  module: {
    loaders: [{
      test: /\.js$/,
      loader: 'babel-loader?presets[]=es2015&presets[]=react&presets[]=stage-0',
      include: path.join(__dirname, 'src')
    }]
  }
};
<commit_msg>update sourcemap for production<commit_after>// jscs:disable
var path = require('path');
var webpack = require('webpack');

module.exports = {
  devtool: false,
  entry:  {
    main: ['./src/client.js'],
    editor: ['./src/routes/Edit'],
    post: ['./src/routes/Post'],
  },
  output: {
     path: __dirname + '/build/static',
     filename: '[name].js',
     chunkFilename: '[id].chunk.js',
     publicPath: '/build/static/'
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin('common.js',  2),
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        unused: true,
        dead_code: true,
        warnings: false,
        screw_ie8: true,
      }
    }),
    new webpack.NoErrorsPlugin(),
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify('production'),
    })
  ],
  module: {
    loaders: [{
      test: /\.js$/,
      loader: 'babel-loader?presets[]=es2015&presets[]=react&presets[]=stage-0',
      include: path.join(__dirname, 'src')
    }]
  }
};
<|endoftext|>


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

	let service = ['api', 'persistence', '$window', '$location', '$state', '$rootScope', '$timeout', '$cookies', '$interval', function(api, persistence, $window, $location, $state, $rootScope, $timeout, _$cookies, _$interval) {

		this.loginRedirect = function(provider, target) {

			persistence.save('afterAuth', target || "");

			api.authentication.getAuthRedirect({provider: provider}).$promise.then(function(data) {
				console.log("Redirect data:", data);

				$window.location.href = data.redirectUrl;
			}).catch(function(e) {
				$state.go("authError", {errorMessage: e.data.errorMessage, statusText: e.data.responseCodeType});
			})
		}

		this.providerCallback = function(provider, params) {
			let next = persistence.load('afterAuth');
			persistence.save('afterAuth', '');
            next = next || "/";
            next = next.replace("#!", "");

            params.provider = provider;

            api.authentication.getAuthResult(params).$promise.then(function(user) {
                console.debug("Logged in user:", user);
                console.debug("Redirecting to", next);

                $rootScope.user = user;
                $rootScope.user.$promise.then(() => {
					setupUserConsistencyCheck();
                });

                if (user.firstLogin && '/' == next) {
					$state.go("accountSettings", {location: "replace"});
                } else {
					$location.replace();
					$location.url(next);
                }

            }).catch(function(error) {
				$state.go("authError", {errorMessage: error.data.errorMessage, statusText: error.data.responseCodeType}, {location: "replace"});
				cancelUserConsistencyCheck()
            });

		}

		this.linkRedirect = function(provider) {
			persistence.save('afterAuth', '/account');

			api.authentication.getLinkRedirect({provider: provider}).$promise.then(function(data) {
				console.log("Redirect data:", data);

				$window.location.href = data.redirectUrl;
			})

		}

		let interval = null;

		this.logout = function() {
			let p = api.authentication.logout({}).$promise;

			p.then(function() {
				$rootScope.user = null;

			}).catch(function(e) {
				console.error("Failed to log out:", e)

			})
			cancelUserConsistencyCheck();
			return p;
		}

		let updateUserPreferences = function() {
			$rootScope.userPreferences = api.user.getUserPreferences();
			return $rootScope.userPreferences.$promise;
		}

		this.updateUser = function() {
			return new Promise(function(resolve, reject) {
				let userResource = api.currentUser.get();
				if (!$rootScope.user) {
					$rootScope.user = userResource;
				}

				userResource.$promise.then(function(user) {
					return new Promise(function(_resolve) {
						$timeout(function() {
							$rootScope.user = user;
							setupUserConsistencyCheck();
							$rootScope.$apply();
							_resolve();
						});
					}).then(updateUserPreferences).then(function() {
						$rootScope.checkForWebSocket(); // Setting $rootScope.user above removes the user snapshot, so ping WebSocket!
						resolve(user);
					});

				}).catch(function(){
					cancelUserConsistencyCheck();
					reject();
				});
			});
		}

		this.login = function(userPrototype) {
			// expects the user object to contain an email and password property.
			return new Promise(function(resolve, reject){
				api.authentication.login(userPrototype).$promise.then(function(u){
					$rootScope.user = u;
					setupUserConsistencyCheck();
					resolve();
				}).catch(function(e){
					$rootScope.user = {
						resolved: true,
						$promise: Promise.resolve({}),
					};
					cancelUserConsistencyCheck();
					reject(e);
				});
			});
		}

		let setupUserConsistencyCheck = function() {
			cancelUserConsistencyCheck();
			// Note: Had to use local storage rather than cookies for this because cookies sometimes did not update across browser tabs in chrome.
			// This is especially so when using third party authenticators for some reason.
			// We also need to make sure that we can in fact write to Local Storage before setting the timeout!
			if (persistence.save("currentUserId", $rootScope.user._id)) {

				interval = setInterval(function() {
					let currentId = persistence.load("currentUserId")
					if (currentId != $rootScope.user._id) {
						cancelUserConsistencyCheck();
						$rootScope.modals.userConsistencyError.show();
						// we want to know how often this happens.
						api.logger.log({
							type: "USER_CONSISTENCY_WARNING_SHOWN",
							userAgent: navigator.userAgent,
						});
						$rootScope.user = api.currentUser.get();
						$rootScope.$apply();
					}
				}, 1000)
			} else {
				console.error("Cannot perform user consistency checking!");
				api.logger.log({
					type: "USER_CONSISTENCY_CHECKING_FAILED",
					userAgent: navigator.userAgent,
				});
			}
		}

		let cancelUserConsistencyCheck = function() {
			persistence.save("currentUserId", null)
			if (interval) {
				clearInterval(interval);
				interval = null;
			}
		}
	}];

	// this should not be used in the router resolver property as it will only return once.
	// TODO should this be deprecated?
	let promiseLoggedIn = ['auth', '$rootScope', function(auth, $rootScope) {
		return $rootScope.user.$promise.catch(function(r) {
			if (r.status == 401)
				return Promise.reject("require_login");
			return Promise.reject("Something went wrong:", r);
		});
	}];

	return {
		service: service,
		promiseLoggedIn: promiseLoggedIn,
	}
});<commit_msg>Manage rejected Auth promise when not logged in.<commit_after>/**
 * Copyright 2014 Ian Davies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 * 		http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
define([], function() {

	let service = ['api', 'persistence', '$window', '$location', '$state', '$rootScope', '$timeout', '$cookies', '$interval', function(api, persistence, $window, $location, $state, $rootScope, $timeout, _$cookies, _$interval) {

		this.loginRedirect = function(provider, target) {

			persistence.save('afterAuth', target || "");

			api.authentication.getAuthRedirect({provider: provider}).$promise.then(function(data) {
				console.log("Redirect data:", data);

				$window.location.href = data.redirectUrl;
			}).catch(function(e) {
				$state.go("authError", {errorMessage: e.data.errorMessage, statusText: e.data.responseCodeType});
			})
		}

		this.providerCallback = function(provider, params) {
			let next = persistence.load('afterAuth');
			persistence.save('afterAuth', '');
            next = next || "/";
            next = next.replace("#!", "");

            params.provider = provider;

            api.authentication.getAuthResult(params).$promise.then(function(user) {
                console.debug("Logged in user:", user);
                console.debug("Redirecting to", next);

                $rootScope.user = user;
                $rootScope.user.$promise.then(() => {
					setupUserConsistencyCheck();
                });

                if (user.firstLogin && '/' == next) {
					$state.go("accountSettings", {location: "replace"});
                } else {
					$location.replace();
					$location.url(next);
                }

            }).catch(function(error) {
				$state.go("authError", {errorMessage: error.data.errorMessage, statusText: error.data.responseCodeType}, {location: "replace"});
				cancelUserConsistencyCheck()
            });

		}

		this.linkRedirect = function(provider) {
			persistence.save('afterAuth', '/account');

			api.authentication.getLinkRedirect({provider: provider}).$promise.then(function(data) {
				console.log("Redirect data:", data);

				$window.location.href = data.redirectUrl;
			})

		}

		let interval = null;

		this.logout = function() {
			let p = api.authentication.logout({}).$promise;

			p.then(function() {
				$rootScope.user = null;

			}).catch(function(e) {
				console.error("Failed to log out:", e)

			})
			cancelUserConsistencyCheck();
			return p;
		}

		let updateUserPreferences = function() {
			$rootScope.userPreferences = api.user.getUserPreferences();
			return $rootScope.userPreferences.$promise;
		}

		this.updateUser = function() {
			return new Promise(function(resolve, reject) {
				let userResource = api.currentUser.get();
				if (!$rootScope.user) {
					$rootScope.user = userResource;
				}

				userResource.$promise.then(function(user) {
					return new Promise(function(_resolve) {
						$timeout(function() {
							$rootScope.user = user;
							setupUserConsistencyCheck();
							$rootScope.$apply();
							_resolve();
						});
					}).then(updateUserPreferences).then(function() {
						$rootScope.checkForWebSocket(); // Setting $rootScope.user above removes the user snapshot, so ping WebSocket!
						resolve(user);
					});

				}).catch(function(){
					cancelUserConsistencyCheck();
					reject();
				});
			}).catch(function(error) {
				console.log('You are not logged in.');
				console.log(error);
			});
		}

		this.login = function(userPrototype) {
			// expects the user object to contain an email and password property.
			return new Promise(function(resolve, reject){
				api.authentication.login(userPrototype).$promise.then(function(u){
					$rootScope.user = u;
					setupUserConsistencyCheck();
					resolve();
				}).catch(function(e){
					$rootScope.user = {
						resolved: true,
						$promise: Promise.resolve({}),
					};
					cancelUserConsistencyCheck();
					reject(e);
				});
			});
		}

		let setupUserConsistencyCheck = function() {
			cancelUserConsistencyCheck();
			// Note: Had to use local storage rather than cookies for this because cookies sometimes did not update across browser tabs in chrome.
			// This is especially so when using third party authenticators for some reason.
			// We also need to make sure that we can in fact write to Local Storage before setting the timeout!
			if (persistence.save("currentUserId", $rootScope.user._id)) {

				interval = setInterval(function() {
					let currentId = persistence.load("currentUserId")
					if (currentId != $rootScope.user._id) {
						cancelUserConsistencyCheck();
						$rootScope.modals.userConsistencyError.show();
						// we want to know how often this happens.
						api.logger.log({
							type: "USER_CONSISTENCY_WARNING_SHOWN",
							userAgent: navigator.userAgent,
						});
						$rootScope.user = api.currentUser.get();
						$rootScope.$apply();
					}
				}, 1000)
			} else {
				console.error("Cannot perform user consistency checking!");
				api.logger.log({
					type: "USER_CONSISTENCY_CHECKING_FAILED",
					userAgent: navigator.userAgent,
				});
			}
		}

		let cancelUserConsistencyCheck = function() {
			persistence.save("currentUserId", null)
			if (interval) {
				clearInterval(interval);
				interval = null;
			}
		}
	}];

	// this should not be used in the router resolver property as it will only return once.
	// TODO should this be deprecated?
	let promiseLoggedIn = ['auth', '$rootScope', function(auth, $rootScope) {
		return $rootScope.user.$promise.catch(function(r) {
			if (r.status == 401)
				return Promise.reject("require_login");
			return Promise.reject("Something went wrong:", r);
		});
	}];

	return {
		service: service,
		promiseLoggedIn: promiseLoggedIn,
	}
});<|endoftext|>


<commit_before>App.Router.map(function(){
    this.resource('taskList', {path: '/tasks'}, function() {
        this.route('search');
    });

    // route disabled for now, let the backend handle the hours spent
    // this.resource('myTaskList', {path: '/my/tasks'});
    this.resource('task', {path: '/tasks/:task_id'}, function(){

    });
    this.resource('taskEdit', {path: '/tasks/:task_id/edit'});
    this.resource('projectTask', {path: '/:task_id'}, function(){});
    this.resource('taskNew', {path: '/tasks/new/:project_id'});

});

// Tasks

App.ProjectTasksIndexRoute = Em.Route.extend({
    model: function(params) {
        return Em.A();
    },

    setupController: function(controller, model) {
        this._super(controller, model);
        var project = this.modelFor('project');
        var tasks = App.Task.find({project: project.get('id')});
        tasks.addObserver('isLoaded', function() {
            tasks.forEach(function(record) {
                if (record.get('isLoaded')) {
                    controller.get('content').pushObject(record);
                }
            });
        });
    },
});

App.TaskRoute = Em.Route.extend(App.ScrollToTop, {
    model: function(params) {
        return App.Task.find(params.task_id);
    },

    actions: {
        applyForTask: function() {
            var route = this;
            var store = route.get('store');
            var taskMember = store.createRecord(App.TaskMember);
            var task = this.modelFor('task');
            var view = App.TaskMemberApplyView.create();

			if (!this.controllerFor('task').get('isMember')){
				Bootstrap.ModalPane.popup({
					heading: gettext('Apply for task'),
					bodyViewClass: view,
					primary: gettext('Apply'),
					secondary: gettext('Cancel'),
					callback: function(opts, e) {
						e.preventDefault();
						if (opts.primary) {
							taskMember.set('motivation', view.get('motivation'));
							taskMember.set('task', task);
							taskMember.set('created', new Date());
							taskMember.save();

			                                if (route.get('tracker')) {
			                                    route.get('tracker').trackEvent("Apply for task", {task: task.get('title')});
			                                }

						}
						if (opts.secondary) {
							taskMember.deleteRecord();
						}
					}
				});
			}
        },
        uploadFile: function(task) {
            var route = this;
            var controller = this.controllerFor('taskFileNew');
            var view = App.TaskFileNewView.create();
            view.set('controller', controller);
            var store = route.get('store');
            var file = store.createRecord(App.TaskFile);
            controller.set('model', file);
            file.set('task', task);

            Bootstrap.ModalPane.popup({
                classNames: ['modal', 'large'],
                headerViewClass: Ember.View.extend({
                    tagName: 'p',
                    classNames: ['modal-title'],
                    template: Ember.Handlebars.compile('{{view.parentView.heading}}')
                }),
                heading: task.get('title'),
                bodyViewClass: view,
                primary: 'Save',
                secondary: 'Cancel',
                callback: function(opts, e) {
                    e.preventDefault();
                    if (opts.primary) {
                        file.save();
                    }
                    if (opts.secondary) {
                        file.deleteRecord();
                    }
                }
            });
        },
        editTaskMember: function(taskMember) {
            var route = this;
            var controller = this.controllerFor('taskMemberEdit');
            controller.set('model', taskMember);
            var view = App.TaskMemberEdit.create();
            view.set('controller', controller);

            Bootstrap.ModalPane.popup({
                headerViewClass: Ember.View.extend({
                    tagName: 'p',
                    classNames: ['modal-title'],
                    template: Ember.Handlebars.compile('{{view.parentView.heading}}')
                }),
                heading: taskMember.get('member.full_name'),
                bodyViewClass: view,
                primary: 'Save',
                secondary: 'Cancel',
                callback: function(opts, e) {
                    e.preventDefault();
                    if (opts.primary) {
                        taskMember.save();
                    }
                    if (opts.secondary) {
                        taskMember.rollback();
                    }
                }
            });
        }
    }
});

App.TaskListIndexRoute = Em.Route.extend(App.UsedCountrySelectViewMixin, App.TrackRouteActivateMixin, {
    trackEventName: 'Browse tasks',
    setupController: function(controller, model) {
        this._super(controller, model);
        App.UsedSkill.find().then(function(skill_list){
            App.UsedSkillSelectView.reopen({
                content: skill_list
            });
        });
    },

});

App.TaskIndexRoute = Em.Route.extend(App.WallRouteMixin, {
    parentId: function(){
        return this.modelFor('task').get('id');
    }.property(),
    parentType: 'task'
});

App.TaskNewRoute = Em.Route.extend({
    model: function(params){
        var task = this.get('store').createRecord(App.Task);
        task.set('project', App.Project.find(params.project_id));
        return task;
    }
});

App.TaskEditRoute = Em.Route.extend({
    model: function(params) {
        return App.Task.find(params.task_id);
    },
});

/**
 * My Tasks: manage your tasks
 *
 */

App.MyTaskListRoute = Em.Route.extend(App.ScrollToTop, {
    model: function(params) {
        return App.MyTaskMember.find();
    }
});

<commit_msg>Update routes.js<commit_after>App.Router.map(function(){
    this.resource('taskList', {path: '/tasks'}, function() {
        this.route('search');
    });

    // route disabled for now, let the backend handle the hours spent
    // this.resource('myTaskList', {path: '/my/tasks'});
    this.resource('task', {path: '/tasks/:task_id'}, function(){

    });
    this.resource('taskEdit', {path: '/tasks/:task_id/edit'});
    this.resource('projectTask', {path: '/:task_id'}, function(){});
    this.resource('taskNew', {path: '/tasks/new/:project_id'});

});

// Tasks

App.ProjectTasksIndexRoute = Em.Route.extend({
    model: function(params) {
        return Em.A();
    },

    setupController: function(controller, model) {
        this._super(controller, model);
        var project = this.modelFor('project');
        var tasks = App.Task.find({project: project.get('id')});
        tasks.addObserver('isLoaded', function() {
            tasks.forEach(function(record) {
                if (record.get('isLoaded')) {
                    controller.get('content').pushObject(record);
                }
            });
        });
    },
});

App.TaskRoute = Em.Route.extend(App.ScrollToTop, {
    model: function(params) {
        return App.Task.find(params.task_id);
    },

    actions: {
        applyForTask: function() {
            var route = this;
            var store = route.get('store');
            var taskMember = store.createRecord(App.TaskMember);
            var task = this.modelFor('task');
            var view = App.TaskMemberApplyView.create();

			if (!this.controllerFor('task').get('isMember')){
				Bootstrap.ModalPane.popup({
					heading: gettext('Apply for task'),
					bodyViewClass: view,
					primary: gettext('Apply'),
					secondary: gettext('Cancel'),
					callback: function(opts, e) {
						e.preventDefault();
						if (opts.primary) {
							taskMember.set('motivation', view.get('motivation'));
							taskMember.set('task', task);
							taskMember.set('created', new Date());
							taskMember.save();

			                                if (route.get('tracker')) {
			                                    route.get('tracker').trackEvent("Apply for task", {task: task.get('title')});
			                                }

						}
						if (opts.secondary) {
							taskMember.deleteRecord();
						}
					}
				});
			}
        },
        uploadFile: function(task) {
            var route = this;
            var controller = this.controllerFor('taskFileNew');
            var view = App.TaskFileNewView.create();
            view.set('controller', controller);
            var store = route.get('store');
            var file = store.createRecord(App.TaskFile);
            controller.set('model', file);
            file.set('task', task);

            Bootstrap.ModalPane.popup({
                classNames: ['modal', 'large'],
                headerViewClass: Ember.View.extend({
                    tagName: 'p',
                    classNames: ['modal-title'],
                    template: Ember.Handlebars.compile('{{view.parentView.heading}}')
                }),
                heading: task.get('title'),
                bodyViewClass: view,
                primary: 'Save',
                secondary: 'Cancel',
                callback: function(opts, e) {
                    e.preventDefault();
                    if (opts.primary) {
                        file.save();
                    }
                    if (opts.secondary) {
                        file.deleteRecord();
                    }
                }
            });
        },
        editTaskMember: function(taskMember) {
            var route = this;
            var controller = this.controllerFor('taskMemberEdit');
            controller.set('model', taskMember);
            var view = App.TaskMemberEdit.create();
            view.set('controller', controller);

            Bootstrap.ModalPane.popup({
                headerViewClass: Ember.View.extend({
                    tagName: 'p',
                    classNames: ['modal-title'],
                    template: Ember.Handlebars.compile('{{view.parentView.heading}}')
                }),
                heading: taskMember.get('member.full_name'),
                bodyViewClass: view,
                primary: 'Save',
                secondary: 'Cancel',
                callback: function(opts, e) {
                    e.preventDefault();
                    if (opts.primary) {
                        taskMember.save();
                    }
                    if (opts.secondary) {
                        taskMember.rollback();
                    }
                }
            });
        }
    }
});

App.TaskListIndexRoute = Em.Route.extend(App.UsedCountrySelectViewMixin, App.TrackRouteActivateMixin, {
    trackEventName: 'Browse tasks',
    setupController: function(controller, model) {
        this._super(controller, model);
        App.UsedSkill.find().then(function(skill_list){
            App.UsedSkillSelectView.reopen({
                content: skill_list
            });
        });
    }
});

App.TaskIndexRoute = Em.Route.extend(App.WallRouteMixin, {
    parentId: function(){
        return this.modelFor('task').get('id');
    }.property(),
    parentType: 'task'
});

App.TaskNewRoute = Em.Route.extend({
    model: function(params){
        var task = this.get('store').createRecord(App.Task);
        task.set('project', App.Project.find(params.project_id));
        return task;
    }
});

App.TaskEditRoute = Em.Route.extend({
    model: function(params) {
        return App.Task.find(params.task_id);
    }
});

/**
 * My Tasks: manage your tasks
 *
 */

App.MyTaskListRoute = Em.Route.extend(App.ScrollToTop, {
    model: function(params) {
        return App.MyTaskMember.find();
    }
});

<|endoftext|>


<commit_before>/*!
 * exprest4
 * Copyright (c) 2016 Hiromitsu Fujita <bow.fujita@gmail.com>
 * MIT License
 */

'use strict';

var fs = require('fs')
  , path = require('path')
  , util = require('util')
  , methods = require('methods')
  , _ = require('underscore')
;

var DEFAULT_OPTS = {
      path: path.join(process.cwd(), 'controllers')
    , url: '/'
    }
;

function load(app, url, file)
{
  var name = [
        url.replace(/^\/+/, '/').replace(/\/+$/, '')
      , path.basename(file, '.js')
      ].join('/')
    , controller = require(file)
    , config = controller.__exprest
    , error = function() {
        return new Error(name+' controller: '+util.format.apply(util, arguments)+' in '+file);
      }
  ;

  if (!config) {
    throw error('No __exprest defined');
  }
  if (!_.isObject(config)) {
    throw error('Invalid __exprest');
  }
  if (!config.routes) {
    throw error('No __exprest.routes defined');
  }
  if (!_.isArray(config.routes)) {
    throw error('Invalid __exprest.routes');
  }

  config.routes.forEach(function(route, idx) {
    var method = (route.method || 'get').toLowerCase();
    if (!_.find(methods, function(verb) { return verb === method })) {
      throw error('Unknown method "%s" in __exprest.routes[%d].method', method, idx);
    }

    var action = route.action
    if (!action) {
      throw error('No __exprest.routes[%d].action defined', idx);
    }

    var handler = controller[action];
    if (!_.isFunction(handler)) {
      throw error('No %s() implemented', action);
    }

    var vpath = route.path ? [name, route.path].join('/') : name;
    if (_.isFunction(route.middleware)) {
      app[method](vpath, route.middleware, handler);
    }
    else {
      app[method](vpath, handler);
    }
  });
}

module.exports.route = function(app, opts) {
  opts = _.extend(DEFAULT_OPTS, opts || {});
  fs.readdirSync(opts.path).forEach(function(file) {
    load(app, opts.url, path.join(opts.path, file));
  });
}
<commit_msg>[Bug] DEFAULT_OPTS was overwritten by opts.<commit_after>/*!
 * exprest4
 * Copyright (c) 2016 Hiromitsu Fujita <bow.fujita@gmail.com>
 * MIT License
 */

'use strict';

var fs = require('fs')
  , path = require('path')
  , util = require('util')
  , methods = require('methods')
  , _ = require('underscore')
;

var DEFAULT_OPTS = {
      path: path.join(process.cwd(), 'controllers')
    , url: '/'
    }
;

function load(app, url, file)
{
  var name = [
        url.replace(/^\/+/, '/').replace(/\/+$/, '')
      , path.basename(file, '.js')
      ].join('/')
    , controller = require(file)
    , config = controller.__exprest
    , error = function() {
        return new Error(name+' controller: '+util.format.apply(util, arguments)+' in '+file);
      }
  ;

  if (!config) {
    throw error('No __exprest defined');
  }
  if (!_.isObject(config)) {
    throw error('Invalid __exprest');
  }
  if (!config.routes) {
    throw error('No __exprest.routes defined');
  }
  if (!_.isArray(config.routes)) {
    throw error('Invalid __exprest.routes');
  }

  config.routes.forEach(function(route, idx) {
    var method = (route.method || 'get').toLowerCase();
    if (!_.find(methods, function(verb) { return verb === method })) {
      throw error('Unknown method "%s" in __exprest.routes[%d].method', method, idx);
    }

    var action = route.action
    if (!action) {
      throw error('No __exprest.routes[%d].action defined', idx);
    }

    var handler = controller[action];
    if (!_.isFunction(handler)) {
      throw error('No %s() implemented', action);
    }

    var vpath = route.path ? [name, route.path].join('/') : name;
    if (_.isFunction(route.middleware)) {
      app[method](vpath, route.middleware, handler);
    }
    else {
      app[method](vpath, handler);
    }
  });
}

module.exports.route = function(app, opts) {
  opts = _.extend({}, DEFAULT_OPTS, opts || {});
  fs.readdirSync(opts.path).forEach(function(file) {
    load(app, opts.url, path.join(opts.path, file));
  });
}
<|endoftext|>


<commit_before>/* =============================================================

	Form Saver v2.0
	A simple script that lets users save and reuse form data.
	http://gomakethings.com

	Free to use under the MIT License.
	http://gomakethings.com/mit/

 * ============================================================= */

(function() {

	'use strict';

	if ( 'querySelector' in document && 'addEventListener' in window && window.localStorage ) {

		// Variables
		var forms = document.forms;
		var formSave = document.querySelectorAll('.form-save-data');
		var formRemove = document.querySelectorAll('.form-delete-data');

		// Save form data
		[].forEach.call(formSave, function (save) {
			save.addEventListener('click', function(e) {

				e.preventDefault();

				// Variables
				var form = save.form;
				var formSaverID = form.id === null || form.id === '' ? 'formsaver-' + document.URL : 'formsaver-' + form.id;
				var formSaverData = {};
				var formFields = form.elements;
				var formStatus = form.querySelectorAll('.form-status');

				// Add field data to array
				[].forEach.call(formFields, function (field) {
					if ( !buoy.hasClass(field, 'form-no-save') ) {
						if ( field.type == 'radio' || field.type == 'checkbox' ) {
							if ( field.checked === true ) {
								formSaverData[field.name + field.value] = 'on';
							}
						} else if ( field.type != 'hidden' && field.type != 'submit' ) {
							if ( field.value !== null && field.value !== '' ) {
								formSaverData[field.name] = field.value;
							}
						}
					}
				});

				// Display save success message
				[].forEach.call(formStatus, function (status) {
					if ( save.getAttribute('data-message') === null ) {
						status.innerHTML = '
Saved!
';
					} else {
						status.innerHTML = '
' + save.getAttribute('data-message') + '
';
					}
				});

				// Save form data in localStorage
				localStorage.setItem( formSaverID, JSON.stringify(formSaverData) );

				// If no form ID is provided, generate friendly console message encouraging one to be added
				if ( form.id === null || form.id === '' ) {
					console.log('FORM SAVER WARNING: This form has no ID attribute. This can create conflicts if more than one form is included on a page, or if the URL changes or includes a query string or hash values.');
				}

			}, false);
		});

		// Delete form data
		[].forEach.call(formRemove, function (remove) {
			remove.addEventListener('click', function(e) {

				e.preventDefault();

				// Variables
				var form = remove.form;
				var formSaverID = form.id === null || form.id === '' ? 'formsaver-' + document.URL : 'formsaver-' + form.id;
				var formStatus = form.querySelectorAll('.form-status');
				var formMessage = remove.getAttribute('data-message') === null ? '
Deleted!
' : '
' + remove.getAttribute('data-message') + '
';

				// Remove form data
				localStorage.removeItem(formSaverID);

				// Display delete success message
				if ( remove.getAttribute('data-clear') == 'true' ) {
					sessionStorage.setItem(formSaverID + '-formSaverMessage', formMessage);
					location.reload(false);
				} else {
					[].forEach.call(formStatus, function (status) {
						status.innerHTML = formMessage;
					});
				}

			}, false);
		});

		// Get form data on page load
		[].forEach.call(forms, function (form) {

			// Variables
			var formSaverID = form.id === null || form.id === '' ? 'formsaver-' + document.URL : 'formsaver-' + form.id;
			var formSaverData = JSON.parse( localStorage.getItem(formSaverID) );
			var formFields = form.elements;
			var formStatus = form.querySelectorAll('.form-status');

			// Populate form with data from localStorage
			[].forEach.call(formFields, function (field) {
				if ( formSaverData !== null ) {
					if ( field.type == 'radio' || field.type == 'checkbox' ) {
						if ( formSaverData[field.name + field.value] == 'on' ) {
							field.checked = true;
						}
					} else if ( field.type != 'hidden' && field.type != 'submit' ) {
						if ( formSaverData[field.name] !== null && formSaverData[field.name] !== undefined ) {
							field.value = formSaverData[field.name];
						}
					}
				}
			});

			// If page was reloaded and delete success message exists, display it
			[].forEach.call(formStatus, function (status) {
				status.innerHTML = sessionStorage.getItem(formSaverID + '-formSaverMessage');
				sessionStorage.removeItem(formSaverID + '-formSaverMessage');
			});

		});

	}

})();<commit_msg>Fixed typo in console warning<commit_after>/* =============================================================

	Form Saver v2.0
	A simple script that lets users save and reuse form data.
	http://gomakethings.com

	Free to use under the MIT License.
	http://gomakethings.com/mit/

 * ============================================================= */

(function() {

	'use strict';

	if ( 'querySelector' in document && 'addEventListener' in window && window.localStorage ) {

		// Variables
		var forms = document.forms;
		var formSave = document.querySelectorAll('.form-save-data');
		var formRemove = document.querySelectorAll('.form-delete-data');

		// Save form data
		[].forEach.call(formSave, function (save) {
			save.addEventListener('click', function(e) {

				e.preventDefault();

				// Variables
				var form = save.form;
				var formSaverID = form.id === null || form.id === '' ? 'formsaver-' + document.URL : 'formsaver-' + form.id;
				var formSaverData = {};
				var formFields = form.elements;
				var formStatus = form.querySelectorAll('.form-status');

				// Add field data to array
				[].forEach.call(formFields, function (field) {
					if ( !buoy.hasClass(field, 'form-no-save') ) {
						if ( field.type == 'radio' || field.type == 'checkbox' ) {
							if ( field.checked === true ) {
								formSaverData[field.name + field.value] = 'on';
							}
						} else if ( field.type != 'hidden' && field.type != 'submit' ) {
							if ( field.value !== null && field.value !== '' ) {
								formSaverData[field.name] = field.value;
							}
						}
					}
				});

				// Display save success message
				[].forEach.call(formStatus, function (status) {
					if ( save.getAttribute('data-message') === null ) {
						status.innerHTML = '
Saved!
';
					} else {
						status.innerHTML = '
' + save.getAttribute('data-message') + '
';
					}
				});

				// Save form data in localStorage
				localStorage.setItem( formSaverID, JSON.stringify(formSaverData) );

				// If no form ID is provided, generate friendly console message encouraging one to be added
				if ( form.id === null || form.id === '' ) {
					console.log('FORM SAVER WARNING: This form has no ID attribute. This can create conflicts if more than one form is included on a page, or if the URL changes or includes a query string or hash value.');
				}

			}, false);
		});

		// Delete form data
		[].forEach.call(formRemove, function (remove) {
			remove.addEventListener('click', function(e) {

				e.preventDefault();

				// Variables
				var form = remove.form;
				var formSaverID = form.id === null || form.id === '' ? 'formsaver-' + document.URL : 'formsaver-' + form.id;
				var formStatus = form.querySelectorAll('.form-status');
				var formMessage = remove.getAttribute('data-message') === null ? '
Deleted!
' : '
' + remove.getAttribute('data-message') + '
';

				// Remove form data
				localStorage.removeItem(formSaverID);

				// Display delete success message
				if ( remove.getAttribute('data-clear') == 'true' ) {
					sessionStorage.setItem(formSaverID + '-formSaverMessage', formMessage);
					location.reload(false);
				} else {
					[].forEach.call(formStatus, function (status) {
						status.innerHTML = formMessage;
					});
				}

			}, false);
		});

		// Get form data on page load
		[].forEach.call(forms, function (form) {

			// Variables
			var formSaverID = form.id === null || form.id === '' ? 'formsaver-' + document.URL : 'formsaver-' + form.id;
			var formSaverData = JSON.parse( localStorage.getItem(formSaverID) );
			var formFields = form.elements;
			var formStatus = form.querySelectorAll('.form-status');

			// Populate form with data from localStorage
			[].forEach.call(formFields, function (field) {
				if ( formSaverData !== null ) {
					if ( field.type == 'radio' || field.type == 'checkbox' ) {
						if ( formSaverData[field.name + field.value] == 'on' ) {
							field.checked = true;
						}
					} else if ( field.type != 'hidden' && field.type != 'submit' ) {
						if ( formSaverData[field.name] !== null && formSaverData[field.name] !== undefined ) {
							field.value = formSaverData[field.name];
						}
					}
				}
			});

			// If page was reloaded and delete success message exists, display it
			[].forEach.call(formStatus, function (status) {
				status.innerHTML = sessionStorage.getItem(formSaverID + '-formSaverMessage');
				sessionStorage.removeItem(formSaverID + '-formSaverMessage');
			});

		});

	}

})();<|endoftext|>


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

import { Component } from 'react'

/**
 * A component theme holds the flairs and presenters for a component.
 */
export type ComponentTheme = {
  // A flair is a unique string that maps to a set of CSS classes.
  flairs:{|
    [string]:string|string[],
    default:string
  |},
  // Presenters bundled with the theme.
  presenters:{|
    [string]:Component,
    default:string
  |}
}
<commit_msg>Enhance theme descriptor<commit_after>// Licensed under the Apache License, Version 2.0 (the “License”); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an “AS IS” BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

import { Component } from 'react'

/**
 * A component theme holds the flairs and presenters for a component.
 */
export type ComponentTheme = {|
  // A flair is a unique string that maps to a set of CSS classes.
  flairs:{|
    [string]:string|string[],
    default?:string
  |},
  // Presenters bundled with the theme.
  presenters:{|
    [string]:Component,
    default?:string
  |}
|}
<|endoftext|>


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

export default function Container(props) {

  const {
    children,
    onContainerKeyDown
  } = props;

  return (
    <div
      className={'Fusionbox-container'}
      onKeyDown={onContainerKeyDown}
      role={'combobox'}
      style={{
        position: 'relative'
      }}
      >
      {children}
    </div>
  );

}

Container.propTypes = {
  children: PropTypes.node.isRequired,
  onContainerKeyDown: PropTypes.func.isRequired
};
<commit_msg>Fix code style<commit_after>import React, { PropTypes } from 'react';

export default function Container(props) {

  const {
    children,
    onContainerKeyDown
  } = props;

  return (
    <div
      className={'Fusionbox-container'}
      onKeyDown={onContainerKeyDown}
      role={'combobox'}
      style={{
        position: 'relative'
      }}>
      {children}
    </div>
  );

}

Container.propTypes = {
  children: PropTypes.node.isRequired,
  onContainerKeyDown: PropTypes.func.isRequired
};
<|endoftext|>


<commit_before>import webpack from 'webpack';
import path from 'path';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import WebpackMd5Hash from 'webpack-md5-hash';
import HtmlWebpackPlugin from 'html-webpack-plugin';

const GLOBALS = {
  'process.env.NODE_ENV': JSON.stringify('production'),
  __DEV__: false
};

export default {
  debug: true,
  devtool: 'source-map', // more info:https://webpack.github.io/docs/build-performance.html#sourcemaps and https://webpack.github.io/docs/configuration.html#devtool
  noInfo: true, // set to false to see a list of every file being bundled.
  entry: ['babel-polyfill', 'whatwg-fetch', './src/index'],
  target: 'web', // necessary per https://webpack.github.io/docs/testing.html#compile-and-test
  output: {
    path: `${__dirname}/dist`,
    publicPath: '/',
    filename: '[name].[chunkhash].js'
  },
  plugins: [
    // Hash the files using MD5 so that their names change when the content changes.
    new WebpackMd5Hash(),

    // Optimize the order that items are bundled. This assures the hash is deterministic.
    new webpack.optimize.OccurenceOrderPlugin(),

    // Tells React to build in prod mode. https://facebook.github.io/react/downloads.html
    new webpack.DefinePlugin(GLOBALS),

    // Generate an external css file with a hash in the filename
    new ExtractTextPlugin('[name].[contenthash].css'),

    // Generate HTML file that contains references to generated bundles. See here for how this works: https://github.com/ampedandwired/html-webpack-plugin#basic-usage
    new HtmlWebpackPlugin({
      template: 'src/index.ejs',
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeRedundantAttributes: true,
        useShortDoctype: true,
        removeEmptyAttributes: true,
        removeStyleLinkTypeAttributes: true,
        keepClosingSlash: true,
        minifyJS: true,
        minifyCSS: true,
        minifyURLs: true
      },
      inject: true,
      // Note that you can add custom options here if you need to handle other custom logic in index.html
      // To track JavaScript errors via TrackJS, sign up for a free trial at TrackJS.com and enter your token below.
      trackJSToken: ''
    }),

    // Eliminate duplicate packages when generating bundle
    new webpack.optimize.DedupePlugin(),

    // Minify JS
    new webpack.optimize.UglifyJsPlugin()
  ],
  module: {
    loaders: [
      {test: /\.js$/, include: path.join(__dirname, 'src'), loaders: ['babel']},
      {test: /\.eot(\?v=\d+.\d+.\d+)?$/, loader: 'file'},
      {test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000&mimetype=application/font-woff"},
      {test: /\.ttf(\?v=\d+.\d+.\d+)?$/, loader: 'file-loader?limit=10000&mimetype=application/octet-stream'},
      {test: /\.svg(\?v=\d+.\d+.\d+)?$/, loader: 'file-loader?limit=10000&mimetype=image/svg+xml'},
      {test: /\.(jpe?g|png|gif)$/i, loaders: ['file']},
      {test: /\.ico$/, loader: 'file-loader?name=[name].[ext]'},
      {
        test: /(\.css|\.scss)$/,
        include: path.join(__dirname, 'src'),
        loader: ExtractTextPlugin.extract('css?sourceMap!sass?sourceMap')
      }
    ]
  }
};<commit_msg>remove GLOBAL variable<commit_after>import webpack from 'webpack';
import path from 'path';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import WebpackMd5Hash from 'webpack-md5-hash';
import HtmlWebpackPlugin from 'html-webpack-plugin';

export default {
  debug: true,
  devtool: 'source-map', // more info:https://webpack.github.io/docs/build-performance.html#sourcemaps and https://webpack.github.io/docs/configuration.html#devtool
  noInfo: true, // set to false to see a list of every file being bundled.
  entry: ['babel-polyfill', 'whatwg-fetch', './src/index'],
  target: 'web', // necessary per https://webpack.github.io/docs/testing.html#compile-and-test
  output: {
    path: `${__dirname}/dist`,
    publicPath: '/',
    filename: '[name].[chunkhash].js'
  },
  plugins: [
    // Hash the files using MD5 so that their names change when the content changes.
    new WebpackMd5Hash(),

    // Optimize the order that items are bundled. This assures the hash is deterministic.
    new webpack.optimize.OccurenceOrderPlugin(),

    // Tells React to build in prod mode. https://facebook.github.io/react/downloads.html
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify('production'),
      __DEV__: false
    }),

    // Generate an external css file with a hash in the filename
    new ExtractTextPlugin('[name].[contenthash].css'),

    // Generate HTML file that contains references to generated bundles. See here for how this works: https://github.com/ampedandwired/html-webpack-plugin#basic-usage
    new HtmlWebpackPlugin({
      template: 'src/index.ejs',
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeRedundantAttributes: true,
        useShortDoctype: true,
        removeEmptyAttributes: true,
        removeStyleLinkTypeAttributes: true,
        keepClosingSlash: true,
        minifyJS: true,
        minifyCSS: true,
        minifyURLs: true
      },
      inject: true,
      // Note that you can add custom options here if you need to handle other custom logic in index.html
      // To track JavaScript errors via TrackJS, sign up for a free trial at TrackJS.com and enter your token below.
      trackJSToken: ''
    }),

    // Eliminate duplicate packages when generating bundle
    new webpack.optimize.DedupePlugin(),

    // Minify JS
    new webpack.optimize.UglifyJsPlugin()
  ],
  module: {
    loaders: [
      {test: /\.js$/, include: path.join(__dirname, 'src'), loaders: ['babel']},
      {test: /\.eot(\?v=\d+.\d+.\d+)?$/, loader: 'file'},
      {test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000&mimetype=application/font-woff"},
      {test: /\.ttf(\?v=\d+.\d+.\d+)?$/, loader: 'file-loader?limit=10000&mimetype=application/octet-stream'},
      {test: /\.svg(\?v=\d+.\d+.\d+)?$/, loader: 'file-loader?limit=10000&mimetype=image/svg+xml'},
      {test: /\.(jpe?g|png|gif)$/i, loaders: ['file']},
      {test: /\.ico$/, loader: 'file-loader?name=[name].[ext]'},
      {
        test: /(\.css|\.scss)$/,
        include: path.join(__dirname, 'src'),
        loader: ExtractTextPlugin.extract('css?sourceMap!sass?sourceMap')
      }
    ]
  }
};<|endoftext|>


<commit_before>'use strict';

import React from 'react/addons';

var Header = React.createClass({
    render() {
        return (

                        <button type="button" className="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
                            Toggle navigation

                        </button>
                        React and Parse

                        <form className="navbar-form navbar-right">
                            Login
                            Register
                        </form>

        );
    }
});

export default Header;
<commit_msg>sessions Header<commit_after>'use strict';

import React from 'react/addons';
import _                from 'lodash';

var Header = React.createClass({
    render() {

        if ( _.isEmpty(localStorage.getItem('key')) ) {
            var login = Login
            var register = Register
        }else{
            var logout = Logout
        }

        return (

                        <button type="button" className="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
                            Toggle navigation

                        </button>
                        React and Parse

                        <form className="navbar-form navbar-right">
                            {login}
                            {register}
                            {logout}
                        </form>

        );
    }
});

export default Header;
<|endoftext|>