<commit_before>$.fn.exists = function() {
    return this.length > 0;
}

$.fn.hasAttr = function(name) {
   var attr = this.attr(name);
   return typeof attr !== 'undefined' && attr !== false;
};

window.t = typeof window.t !== "undefined" ? window.t : {
    models: {},
    collections: {},
    components: {},
    controllers: {},
    libraries: {
        Adapters: {}
    },
    app: {}
};
var t = typeof t !== "undefined" ? t : window.t;

t.libraries.App = Stapes.subclass({
    Views: {},
    controller: false,
    isCordova: false,
    appController: {},
    constructor: function(appController){
        var self = this;
        this.appController = t.libraries.Controller.subclass(appController);
        this.isCordova = !!window.cordova;
        if(this.isCordova){
            this.cordovaExclude();
            $(document).on("deviceready", function(){
                self.init();
            })
        }else{
            $(document).on("ready", function(){
                self.init();
            })
        }
    },
    showLoading: function(){
        $("t-loading").show().velocity({ opacity: 1 }, { duration: 800 });
    },
    hideLoading: function(){
        $("t-loading").velocity({ opacity: 0 }, { duration: 800, display: "none" });
    },
    init: function(){
        var self = this;
        this.loadViews();
        this.bodyFix();
        this.appController = new this.appController(self);
        this.bindControllerToPage(this.appController);
        this.initCollections();
        this.Views.on("ready", function(){
            self.Views.registerAllComponents();
            self.bindControllerToPage(self.appController);
            self.initRouter();
            self.appController.ready(self);
        })
    },
    _construct: function(controller, args){
        function Controller() {
            return controller.apply(this, args);
        }
        Controller.prototype = controller.prototype;
        return new Controller();
    },
    goTo: function(controller, method, args){
        t.controllers[controller].proto({
            __name: controller
        });
        var construct = true;
        if(this.controller){
            if(this.controller.__name === controller){
                construct = false;
            }
        }
        if(construct){
            this.controller = this._construct(t.controllers[controller], []);
        }
        this.controller[method].apply(t.app.controller, args);
    },
    initRouter: function(){
        var self = this;
        this.router = new Grapnel({ pushState: true });
        if(typeof this.appController.routes !== "undefined"){
            _.each(this.appController.routes, function(action, route){
                if(typeof action !== "function"){
                    var parts = action.split(".");
                    var controller = parts[0];
                    var method = typeof parts[1] !== "undefined" ? parts[1] : "index";
                    self.router.get(route, function(request){
                        self.goTo(controller, method, [request]);
                    });
                }else{
                    self.router.get(route, function(request){
                        action.apply(self.appController, [request]);
                    });
                }
            })
        }
    },
    navigate: function(route, showLoading){
        showLoading = typeof showLoading !== "undefined" ? showLoading : true;
        if(showLoading){
            this.showLoading();
        }
        this.router.navigate(route);
    },
    bindControllerToPage: function(controller){
        rivets.bind($("html"), controller);
    },
    cordovaExclude: function(){
        $("*[t-cordova-exclude]").each(function(){
            $(this).remove();
        });
    },
    initCollections: function(){
        _.each(t.models, function(model, name){
            // TODO: Check if collection is already initialised before attempting to create a new instance
            t.collections[name] = typeof t.collections[name] === "undefined" ? new t.libraries.Collection(model) : new t.collections[name](model);
            model.proto({
                collection: t.collections[name]
            });
        });
    },
    loadViews: function(){
        this.Views = new t.libraries.Views();
    },
    bodyFix: function(){
        $("body").width($(window).width());
        $("body").height($(window).height());
    }
});

t.libraries.Component = Stapes.subclass({
    attr: {},
    constructor: function($el, attrs){
        this.attr = attrs;
    },
    onClick: function(e, self){
        e.stopPropagation();
        var el = this;
        var event = typeof self.attr['t-on-click'] !== "undefined" ? self.attr['t-on-click'] : false;
        if(event){
            t.app.controller[event].apply(el, [e, t.app.controller]);
            return false;
        }
    },
    navigateTo: function(e, self){
        var href = $(this).attr("href");
        t.app.navigate(href);
        return false;
    }
});

t.libraries.View = Stapes.subclass({

});

t.libraries.Views = Stapes.subclass({
    constructor: function(dir){
        var self = this;
        this.dir = typeof dir !== "undefined" ? dir : "app/views/";
        this.staged = [];
        this.views = [];
        this.components = [];
        this.loadAllViews();
        this.on("views-loaded", function(){
            self.loadAllComponents();
        })
        this.on("components-loaded", function(){
            self.emit("ready");
        })

    },
    loadAllViews: function(){
        var self = this;
        var views = $("t-views").children("t-view[src]");
        var N = views.length;
        if(N > 0){
            views.each(function(){
                self.include($(this), self.dir, function($el){
                    self.views.push($el.attr("name"));
                    N -= 1;
                    if(N < 1){
                        self.emit("views-loaded");
                    }
                })
            })
        }else{
            self.emit("views-loaded");
        }
    },
    loadAllComponents: function(){
        var self = this;
        var components = $("t-views > t-components").children("t-component[src]");
        var N = components.length;
        if(N > 0){
            components.each(function(){
                self.include($(this), self.dir + "components/", function($el){
                    self.components.push($el.attr("name"));
                    N -= 1;
                    if(N < 1){
                        self.emit("components-loaded");
                    }
                })
            })
        }else{
            self.emit("components-loaded");
        }
    },
    include: function($el, dir, onComplete){
        var self = this;
        var src = $el.attr("src");
        src = dir + src + "?" + Date.now();
        $.get(src, function(html, status){
            var result = status === "error" ? false : true;
            if(!result){
                console.error("t Cannot include file: " + src);
            }else{
                html = self.comment(html);
                $el.html(html);
            }
            onComplete($el, result, html);
        })
    },
    comment: function(html){
        html = "<!--[[ " + html + " ]]-->";
        return html;
    },
    uncomment: function(html){
        html = typeof html !== "undefined" ? html : "";
        html = html.replace("<!--[[ ", "");
        html = html.replace(" ]]-->", "");
        return html;
    },
    registerAllComponents: function(){
        return this.registerComponents(this.components);
    },
    registerComponents: function(components){
        var self = this;
        _.each(components, function(name){
            var $component = $('t-components > t-component[name="' + name + '"]');
            self.registerComponent($component, name);
        })
    },
    registerComponent: function($component, name){
        var self = this;
        rivets.components[name] = {
            template: function(){
                return self.uncomment($component.html());
            },
            initialize: function(el){
                var $el = $(el);
                var attributes = self.getAttributes($el);

                var controllerName = self.componentControllerName(name);
                var componentController = typeof t.components[controllerName] !== "undefined" ? new t.components[controllerName]($el, attributes) : new t.libraries.Component($el, attributes);

                return componentController;
            }
        }
    },
    getAttributes: function($el){
        var attributes = [];
        $el.each(function(){
            $.each(this.attributes, function(){
                if(this.specified){
                    attributes[this.name] = this.value;
                }
            })
        });
        return attributes;
    },
    componentControllerName: function(name){
        var parts = name.split("-");
        _.each(parts, function(part, key){
            if(key > 0){
                parts[key] = part.charAt(0).toUpperCase() + part.slice(1);
            }
        })
        return parts.join("");
    },
    stage: function($view, controller, show, hide){
        show = typeof show !== "function" ? controller.show : show;
        hide = typeof hide !== "function" ? controller.hide : hide;

        var html = $view.html();
        html = this.uncomment(html);

        var name = $view.attr("name") + "-view";

        if($(name).exists()){
            var stagedID = parseInt($(name).attr("data-staged-id"));
            $(name).remove();
            this.staged[stagedID] = null;
        }

        var stagedID = this.staged.length;
        $view = $("<" + name + "/>").attr({
            "class": "view",
            "data-staged-id": stagedID
        }).html(html).hide();

        var view = new (t.libraries.View.subclass({
            id: stagedID,
            name: name,
            $view: $view,
            controller: controller,
            show: show,
            hide: hide
        }));

        view.$view.appendTo("t-canvas");

        this.staged.push(view);

        return view;
    },
    show: function(view){
        this.hideOthers(view);
        t.app.emit("view-show");
        view.show();
    },
    hideOthers: function(view){
        t.app.emit("view-hide");
        _.each(this.staged, function(View){
            if(View !== null){
                if(view.name !== View.name){
                    View.hide();
                }
            }
        });
    }
})

t.libraries.Controller = Stapes.subclass({
    __name: "app",
    ready: function(){

    },
    render: function(viewID, onShow, onHide){
        var $view = $('t-views > t-view[name="' + viewID + '"]');
        var view = t.app.Views.stage($view, this, onShow, onHide);
        rivets.bind(view.$view, this);
        t.app.Views.show(view);
    },
    show: function(){
        this.$view.fadeIn();
    },
    hide: function(){
        this.$view.fadeOut();
    },
    showLoading: function(){
        t.app.showLoading();
    },
    hideLoading: function(){
        t.app.hideLoading();
    },
    _construct: function(controller, args){
        function Controller() {
            return controller.apply(this, args);
        }
        Controller.prototype = controller.prototype;
        return new Controller();
    },
    goTo: function(controller, method, args){
        t.app.goTo(controller, method, args);
    },
    back: function(e, self){
        window.history.go(-1);
        return false;
    },
    navigateTo: function(e, self){
        var href = $(this).attr("href");
        t.app.navigate(href);
        return false;
    }
})

t.libraries.Model = Stapes.subclass({
    constructor: function(data){
        if(typeof data === "object"){
            this.extend(data);
        }
    }
});

t.libraries.Collection = Stapes.subclass({
    objects: [],
    adapter: function(){
        return {};
    },
    constructor: function(model){
        this.model = model;
        this.adapter = typeof this.adapter === "function" ? this.adapter() : this.adapter;
        this.clear();
    },
    clear: function(){
        this.objects = [];
        return this;
    },
    create: function(data, push){
        push = typeof push === "undefined" ? true : push;
        var object = new this.model(data);
        if(push){
            this.objects.push(object);
        }
        return object;
    },
    createObjects: function(items, empty){
        empty = typeof empty === undefined ? true : empty;
        var self = this;
        if(empty){
            this.objects = [];
        }
        _.each(items, function(item){
            self.create(item);
        })
    },
    query: function(method, data, callback){
        var self = this;
        if(typeof this.adapter.query === "function" ){
            this.adapter.query(method, data, function(data){
                self.callback("query", callback, data);
            });
        }else{
            this.callback("query", callback);
        }
    },
    get: function(onComplete, conditions){
        var self = this;
        if(typeof this.adapter.get === "function" ){
            this.adapter.get(function(data){
                if(data !== false){
                    var object = self.create(data, false);
                    self.callback("get", onComplete, object);
                }else{
                    self.callback("get", onComplete);
                }
            }, conditions)
        }else{
            this.callback("get", onComplete);
        }
        return this;
    },
    getAll: function(onComplete, conditions){
        var self = this;
        if(typeof this.adapter.getAll === "function" ){
            this.adapter.getAll(function(data){
                if(data !== false){
                    self.createObjects(data);
                    self.callback("getAll", onComplete, self.objects);
                }else{
                    self.callback("getAll", onComplete);
                }
            }, conditions)
        }else{
            this.callback("getAll", onComplete);
        }
        return this;
    },
    callback: function(event, callback, data){
        if(typeof callback === "function"){
            callback(data);
        }
        this.emit(event, data);
    },
    empty: function(){
        if(typeof this.objects === "undefined"){
            return true;
        }else if(this.objects.length < 1){
            return true;
        }else{
            return false;
        }
    }
});

t.libraries.Adapters.jsonFile = Stapes.subclass({
    src: "",
    localCache: false,
    constructor: function(src){
        this.src = src;
    },
    get: function(callback, conditions){
        var pullNew = true;
        if(this.localCache !== false){
            if(typeof conditions !== "undefined"){
                var data = _.findWhere(this.localCache, conditions);
            }else{
                var data = this.localCache;
            }
            if(typeof data !== "undefined"){
                pullNew = false;
                callback(data);
            }
        }
        if(pullNew){
            $.ajax({
                dataType: "json",
                url: this.src  + "?" + Date.now(),
                success: function(data){
                    if(typeof conditions !== "undefined"){
                        data = _.findWhere(data, conditions);
                        data = typeof data === "undefined" ? false : data;
                    }else{
                        data = data[0];
                    }
                    callback(data);
                },
                error: function(){
                    callback(false);
                }
            })
        }
    },
    getAll: function(callback, conditions){
        var self = this;
        $.ajax({
            dataType: "json",
            url: this.src  + "?" + Date.now(),
            success: function(data){
                if(typeof conditions !== "undefined"){
                    data = _.where(data, conditions);
                }
                self.localCache = data;
                callback(data);
            },
            error: function(){
                callback(false);
            }
        })
    }
})

t.libraries.Adapters.socket = Stapes.subclass({
    host: "",
    socket: false,
    modelName: "",
    constructor: function(modelName, forceNew){
        this.host = t.app.appController.socketHost;
        this.modelName = modelName;
        forceNew = typeof forceNew === "undefined" ? false : forceNew;

        if(forceNew){
            t.app.socket = io(this.host);
        }else{
            t.app.socket = typeof t.app.socket === "undefined" ? io(this.host) : t.app.socket;
        }
        this.socket = t.app.socket;
    },
    query: function(method, data, callback){
        var request ={
            data: data
        } ;
        request.action = this.modelName + ":" + method;
        this.socket.removeAllListeners(request.action);
        this.socket.emit(request.action, request);
        this.socket.on(request.action, function(response){
            callback(response);
        });
    },
    get: function(callback, conditions){
        var pullNew = true;
        callback(true);
    },
    getAll: function(callback, conditions){
        callback(true);
    }
})<commit_msg>no onClick on component prototype<commit_after>$.fn.exists = function() {
    return this.length > 0;
}

$.fn.hasAttr = function(name) {
   var attr = this.attr(name);
   return typeof attr !== 'undefined' && attr !== false;
};

window.t = typeof window.t !== "undefined" ? window.t : {
    models: {},
    collections: {},
    components: {},
    controllers: {},
    libraries: {
        Adapters: {}
    },
    app: {}
};
var t = typeof t !== "undefined" ? t : window.t;

t.libraries.App = Stapes.subclass({
    Views: {},
    controller: false,
    isCordova: false,
    appController: {},
    constructor: function(appController){
        var self = this;
        this.appController = t.libraries.Controller.subclass(appController);
        this.isCordova = !!window.cordova;
        if(this.isCordova){
            this.cordovaExclude();
            $(document).on("deviceready", function(){
                self.init();
            })
        }else{
            $(document).on("ready", function(){
                self.init();
            })
        }
    },
    showLoading: function(){
        $("t-loading").show().velocity({ opacity: 1 }, { duration: 800 });
    },
    hideLoading: function(){
        $("t-loading").velocity({ opacity: 0 }, { duration: 800, display: "none" });
    },
    init: function(){
        var self = this;
        this.loadViews();
        this.bodyFix();
        this.appController = new this.appController(self);
        this.bindControllerToPage(this.appController);
        this.initCollections();
        this.Views.on("ready", function(){
            self.Views.registerAllComponents();
            self.bindControllerToPage(self.appController);
            self.initRouter();
            self.appController.ready(self);
        })
    },
    _construct: function(controller, args){
        function Controller() {
            return controller.apply(this, args);
        }
        Controller.prototype = controller.prototype;
        return new Controller();
    },
    goTo: function(controller, method, args){
        t.controllers[controller].proto({
            __name: controller
        });
        var construct = true;
        if(this.controller){
            if(this.controller.__name === controller){
                construct = false;
            }
        }
        if(construct){
            this.controller = this._construct(t.controllers[controller], []);
        }
        this.controller[method].apply(t.app.controller, args);
    },
    initRouter: function(){
        var self = this;
        this.router = new Grapnel({ pushState: true });
        if(typeof this.appController.routes !== "undefined"){
            _.each(this.appController.routes, function(action, route){
                if(typeof action !== "function"){
                    var parts = action.split(".");
                    var controller = parts[0];
                    var method = typeof parts[1] !== "undefined" ? parts[1] : "index";
                    self.router.get(route, function(request){
                        self.goTo(controller, method, [request]);
                    });
                }else{
                    self.router.get(route, function(request){
                        action.apply(self.appController, [request]);
                    });
                }
            })
        }
    },
    navigate: function(route, showLoading){
        showLoading = typeof showLoading !== "undefined" ? showLoading : true;
        if(showLoading){
            this.showLoading();
        }
        this.router.navigate(route);
    },
    bindControllerToPage: function(controller){
        rivets.bind($("html"), controller);
    },
    cordovaExclude: function(){
        $("*[t-cordova-exclude]").each(function(){
            $(this).remove();
        });
    },
    initCollections: function(){
        _.each(t.models, function(model, name){
            // TODO: Check if collection is already initialised before attempting to create a new instance
            t.collections[name] = typeof t.collections[name] === "undefined" ? new t.libraries.Collection(model) : new t.collections[name](model);
            model.proto({
                collection: t.collections[name]
            });
        });
    },
    loadViews: function(){
        this.Views = new t.libraries.Views();
    },
    bodyFix: function(){
        $("body").width($(window).width());
        $("body").height($(window).height());
    }
});

t.libraries.Component = Stapes.subclass({
    attr: {},
    constructor: function($el, attrs){
        this.attr = attrs;
    },
    navigateTo: function(e, self){
        var href = $(this).attr("href");
        t.app.navigate(href);
        return false;
    }
});

t.libraries.View = Stapes.subclass({

});

t.libraries.Views = Stapes.subclass({
    constructor: function(dir){
        var self = this;
        this.dir = typeof dir !== "undefined" ? dir : "app/views/";
        this.staged = [];
        this.views = [];
        this.components = [];
        this.loadAllViews();
        this.on("views-loaded", function(){
            self.loadAllComponents();
        })
        this.on("components-loaded", function(){
            self.emit("ready");
        })

    },
    loadAllViews: function(){
        var self = this;
        var views = $("t-views").children("t-view[src]");
        var N = views.length;
        if(N > 0){
            views.each(function(){
                self.include($(this), self.dir, function($el){
                    self.views.push($el.attr("name"));
                    N -= 1;
                    if(N < 1){
                        self.emit("views-loaded");
                    }
                })
            })
        }else{
            self.emit("views-loaded");
        }
    },
    loadAllComponents: function(){
        var self = this;
        var components = $("t-views > t-components").children("t-component[src]");
        var N = components.length;
        if(N > 0){
            components.each(function(){
                self.include($(this), self.dir + "components/", function($el){
                    self.components.push($el.attr("name"));
                    N -= 1;
                    if(N < 1){
                        self.emit("components-loaded");
                    }
                })
            })
        }else{
            self.emit("components-loaded");
        }
    },
    include: function($el, dir, onComplete){
        var self = this;
        var src = $el.attr("src");
        src = dir + src + "?" + Date.now();
        $.get(src, function(html, status){
            var result = status === "error" ? false : true;
            if(!result){
                console.error("t Cannot include file: " + src);
            }else{
                html = self.comment(html);
                $el.html(html);
            }
            onComplete($el, result, html);
        })
    },
    comment: function(html){
        html = "<!--[[ " + html + " ]]-->";
        return html;
    },
    uncomment: function(html){
        html = typeof html !== "undefined" ? html : "";
        html = html.replace("<!--[[ ", "");
        html = html.replace(" ]]-->", "");
        return html;
    },
    registerAllComponents: function(){
        return this.registerComponents(this.components);
    },
    registerComponents: function(components){
        var self = this;
        _.each(components, function(name){
            var $component = $('t-components > t-component[name="' + name + '"]');
            self.registerComponent($component, name);
        })
    },
    registerComponent: function($component, name){
        var self = this;
        rivets.components[name] = {
            template: function(){
                return self.uncomment($component.html());
            },
            initialize: function(el){
                var $el = $(el);
                var attributes = self.getAttributes($el);

                var controllerName = self.componentControllerName(name);

                var componentController = typeof t.components[controllerName] !== "undefined" ? new t.components[controllerName]($el, attributes) : new t.libraries.Component($el, attributes);

                return componentController;
            }
        }
    },
    getAttributes: function($el){
        var attributes = [];
        $el.each(function(){
            $.each(this.attributes, function(){
                if(this.specified){
                    attributes[this.name] = this.value;
                }
            })
        });
        return attributes;
    },
    componentControllerName: function(name){
        var parts = name.split("-");
        _.each(parts, function(part, key){
            if(key > 0){
                parts[key] = part.charAt(0).toUpperCase() + part.slice(1);
            }
        })
        return parts.join("");
    },
    stage: function($view, controller, show, hide){
        show = typeof show !== "function" ? controller.show : show;
        hide = typeof hide !== "function" ? controller.hide : hide;

        var html = $view.html();
        html = this.uncomment(html);

        var name = $view.attr("name") + "-view";

        if($(name).exists()){
            var stagedID = parseInt($(name).attr("data-staged-id"));
            $(name).remove();
            this.staged[stagedID] = null;
        }

        var stagedID = this.staged.length;
        $view = $("<" + name + "/>").attr({
            "class": "view",
            "data-staged-id": stagedID
        }).html(html).hide();

        var view = new (t.libraries.View.subclass({
            id: stagedID,
            name: name,
            $view: $view,
            controller: controller,
            show: show,
            hide: hide
        }));

        view.$view.appendTo("t-canvas");

        this.staged.push(view);

        return view;
    },
    show: function(view){
        this.hideOthers(view);
        t.app.emit("view-show");
        view.show();
    },
    hideOthers: function(view){
        t.app.emit("view-hide");
        _.each(this.staged, function(View){
            if(View !== null){
                if(view.name !== View.name){
                    View.hide();
                }
            }
        });
    }
})

t.libraries.Controller = Stapes.subclass({
    __name: "app",
    ready: function(){

    },
    render: function(viewID, onShow, onHide){
        var $view = $('t-views > t-view[name="' + viewID + '"]');
        var view = t.app.Views.stage($view, this, onShow, onHide);
        rivets.bind(view.$view, this);
        t.app.Views.show(view);
    },
    show: function(){
        this.$view.fadeIn();
    },
    hide: function(){
        this.$view.fadeOut();
    },
    showLoading: function(){
        t.app.showLoading();
    },
    hideLoading: function(){
        t.app.hideLoading();
    },
    _construct: function(controller, args){
        function Controller() {
            return controller.apply(this, args);
        }
        Controller.prototype = controller.prototype;
        return new Controller();
    },
    goTo: function(controller, method, args){
        t.app.goTo(controller, method, args);
    },
    back: function(e, self){
        window.history.go(-1);
        return false;
    },
    navigateTo: function(e, self){
        var href = $(this).attr("href");
        t.app.navigate(href);
        return false;
    }
})

t.libraries.Model = Stapes.subclass({
    constructor: function(data){
        if(typeof data === "object"){
            this.extend(data);
        }
    }
});

t.libraries.Collection = Stapes.subclass({
    objects: [],
    adapter: function(){
        return {};
    },
    constructor: function(model){
        this.model = model;
        this.adapter = typeof this.adapter === "function" ? this.adapter() : this.adapter;
        this.clear();
    },
    clear: function(){
        this.objects = [];
        return this;
    },
    create: function(data, push){
        push = typeof push === "undefined" ? true : push;
        var object = new this.model(data);
        if(push){
            this.objects.push(object);
        }
        return object;
    },
    createObjects: function(items, empty){
        empty = typeof empty === undefined ? true : empty;
        var self = this;
        if(empty){
            this.objects = [];
        }
        _.each(items, function(item){
            self.create(item);
        })
    },
    query: function(method, data, callback){
        var self = this;
        if(typeof this.adapter.query === "function" ){
            this.adapter.query(method, data, function(data){
                self.callback("query", callback, data);
            });
        }else{
            this.callback("query", callback);
        }
    },
    get: function(onComplete, conditions){
        var self = this;
        if(typeof this.adapter.get === "function" ){
            this.adapter.get(function(data){
                if(data !== false){
                    var object = self.create(data, false);
                    self.callback("get", onComplete, object);
                }else{
                    self.callback("get", onComplete);
                }
            }, conditions)
        }else{
            this.callback("get", onComplete);
        }
        return this;
    },
    getAll: function(onComplete, conditions){
        var self = this;
        if(typeof this.adapter.getAll === "function" ){
            this.adapter.getAll(function(data){
                if(data !== false){
                    self.createObjects(data);
                    self.callback("getAll", onComplete, self.objects);
                }else{
                    self.callback("getAll", onComplete);
                }
            }, conditions)
        }else{
            this.callback("getAll", onComplete);
        }
        return this;
    },
    callback: function(event, callback, data){
        if(typeof callback === "function"){
            callback(data);
        }
        this.emit(event, data);
    },
    empty: function(){
        if(typeof this.objects === "undefined"){
            return true;
        }else if(this.objects.length < 1){
            return true;
        }else{
            return false;
        }
    }
});

t.libraries.Adapters.jsonFile = Stapes.subclass({
    src: "",
    localCache: false,
    constructor: function(src){
        this.src = src;
    },
    get: function(callback, conditions){
        var pullNew = true;
        if(this.localCache !== false){
            if(typeof conditions !== "undefined"){
                var data = _.findWhere(this.localCache, conditions);
            }else{
                var data = this.localCache;
            }
            if(typeof data !== "undefined"){
                pullNew = false;
                callback(data);
            }
        }
        if(pullNew){
            $.ajax({
                dataType: "json",
                url: this.src  + "?" + Date.now(),
                success: function(data){
                    if(typeof conditions !== "undefined"){
                        data = _.findWhere(data, conditions);
                        data = typeof data === "undefined" ? false : data;
                    }else{
                        data = data[0];
                    }
                    callback(data);
                },
                error: function(){
                    callback(false);
                }
            })
        }
    },
    getAll: function(callback, conditions){
        var self = this;
        $.ajax({
            dataType: "json",
            url: this.src  + "?" + Date.now(),
            success: function(data){
                if(typeof conditions !== "undefined"){
                    data = _.where(data, conditions);
                }
                self.localCache = data;
                callback(data);
            },
            error: function(){
                callback(false);
            }
        })
    }
})

t.libraries.Adapters.socket = Stapes.subclass({
    host: "",
    socket: false,
    modelName: "",
    constructor: function(modelName, forceNew){
        this.host = t.app.appController.socketHost;
        this.modelName = modelName;
        forceNew = typeof forceNew === "undefined" ? false : forceNew;

        if(forceNew){
            t.app.socket = io(this.host);
        }else{
            t.app.socket = typeof t.app.socket === "undefined" ? io(this.host) : t.app.socket;
        }
        this.socket = t.app.socket;
    },
    query: function(method, data, callback){
        var request ={
            data: data
        } ;
        request.action = this.modelName + ":" + method;
        this.socket.removeAllListeners(request.action);
        this.socket.emit(request.action, request);
        this.socket.on(request.action, function(response){
            callback(response);
        });
    },
    get: function(callback, conditions){
        var pullNew = true;
        callback(true);
    },
    getAll: function(callback, conditions){
        callback(true);
    }
})<|endoftext|>


<commit_before>var delimiters = {};
delimiters["("] = true; delimiters[")"] = true;
delimiters[";"] = true; delimiters["\n"] = true;

var whitespace = {};
whitespace[" "] = true; whitespace["\t"] = true; whitespace["\n"] = true;

var operators = {};
operators["+"] = "+"; operators["<"] = "<"; operators["="] = "==";
operators["and"] = "&&"; operators["or"] = "||";

var special = {};
special["set"] = compileSet;
special["if"] = compileIf;
special["function"] = compileFunction;

function makeStream(str) {
    return { pos: 0, string: str, len: str.length };
}

function peekChar(s) {
    if (s.pos < s.len)
        return s.string.charAt(s.pos);
}

function readChar(s) {
    var c = peekChar(s);

    if (c) {
        s.pos++;
        return c;
    }
}

function readWhitespace (s) {
    var c;

    while (true) {
        c = peekChar(s);
        if (c && whitespace[c])
            readChar(s);
        else break;
    }
}

function readAtom(s) {
    var c, str = "";

    while (true) {
        c = peekChar(s);
        if (c && !whitespace[c] && !delimiters[c]) {
            str += c;
            readChar(s);
        } else break;
    }

    return str;
}

function readList(s) {
    readChar(s); // (

    var c, l = [];

    while (true) {
        readWhitespace(s);
        c = peekChar(s)
        if (c && c != ")") {
            l.push(read(s));
        } else if (c) {
            readChar(s); // )
            break;
        } else {
            error("Expected ) at " + s.pos);
        }
    }

    return l;
}

function readComment(s) {
    var c;
    do { c = readChar(s); } while (c && c != "\n");
}

function readString(s) {
    readChar(s); // "

    var c, str = "";

    while (true) {
        c = peekChar(s);
        if (c && c != "\"") {
            if (c == "\\")
                str += readChar(s);
            str += readChar(s);
        } else if (c) {
            readChar(s); // "
            break;
        } else {
            error("Expected \" at " + s.pos);
        }
    }

    return str;
}

function read(s) {
    readWhitespace(s);

    var c = peekChar(s);

    switch (c) {
        case ";": readComment(s); return read(s);
        case "(": return readList(s);
        case ")": error("Unexpected ) at " + s.pos);
        case "\"": return readString(s);
        default: return readAtom(s);
    }
}

function readFromString(str) {
    return read(makeStream(str));
}

function isAtom(form) {
    return typeof form == "string";
}

function isCall(form) {
    return Array.isArray(form) && typeof form[0] == "string";
}

function isOperator(form) {
    return operators[form[0]] != null;
}

function isSpecial(form) {
    return special[form[0]] != null;
}

function compileAtom(form, isStatement) {
    return form.toString() + (isStatement ? ";" : "");
}

function compileCall(form, isStatement) {
    var i = 1, args = "";
    while (i < form.length) {
        var a = compile(form[i], false);
        args += a + (i < form.length - 1 ? "," : "");
        ++i;
    }
    return form[0] + "(" + args + ")" + (isStatement ? ";" : "");
}

function compileOperator(form) {
    if (form.length > 3)
        error("Too many arguments to operator " + form[0]);

    var a = compile(form[1], false);
    var b = compile(form[2], false);
    return "(" + a + operators[form[0]] + b + ")";
}

function compileSet(form, isStatement) {
    if (!isStatement)
        error("Cannot compile assignment as an expression")
    if (!isAtom(form[0]))
        error("Invalid left-hand side of assignment")
    return form[1] + "=" + compile(form[2], false) + ";";
}

function compileBranch(branch) {
    var i = 1, str = "if(" + compile(branch[0], false) + "){";
    while (i < branch.length) {
        str += compile(branch[i], true);
        ++i;
    }
    return str + "}";
}

function compileIf(form, isStatement) {
    if (!isStatement)
        error("Cannot compile if as an expression")
    var i = 1, str = "";
    while (i < form.length) {
        str += compileBranch(form[i]);
        if (i < form.length - 1)
            str += "else ";
        ++i;
    }
    return str + ";";
}

function compileFunction(form, isStatement) {
    // ignoring isStatement for now
    var name = form[1];
    var args = form[2];
    var body = form.slice(3);
    str = "function " + name + "(";

    var i = 0;
    while (i < args.length) {
        str += args[i];
        if (i < args.length - 1)
            str += ",";
        ++i;
    }

    str += "){"

    i = 0;
    while (i < body.length) {
        str += compile(body[i], true);
        ++i;
    }

    return str + "}";
}

function compile(form, isStatement) {
    isStatement = typeof isStatement == "undefined" ? true : isStatement;

    if (isAtom(form))
        return compileAtom(form, isStatement);
    else if (isCall(form)) {
        if (isOperator(form)) {
            if (isStatement)
                error("Cannot compile use of operator " + form[0] + " as a statement");
            return compileOperator(form);
        } else if (isSpecial(form)) {
            return special[form[0]](form, isStatement);
        } else return compilecall(form, isStatement);
    } else error("Unexpected form " + form.toString());
}

function error(msg) {
    throw new Error(msg);
}
<commit_msg>WIP on additional special forms<commit_after>fs = require('fs');

var delimiters = {};
delimiters["("] = true; delimiters[")"] = true;
delimiters[";"] = true; delimiters["\n"] = true;

var whitespace = {};
whitespace[" "] = true; whitespace["\t"] = true; whitespace["\n"] = true;

var operators = {};
operators["+"] = "+"; operators["<"] = "<"; operators["="] = "==";
operators["and"] = "&&"; operators["or"] = "||";

var special = {};
special["set"] = compileSet;
special["if"] = compileIf;
special["function"] = compileFunction;
special["get"] = compileGet;
special["define"] = compileDefine;
special["while"] = compileWhile;

function error(msg) {
    throw new Error(msg);
}

function makeStream(str) {
    return { pos: 0, string: str, len: str.length };
}

function readFile(filename) {
    return fs.readFileSync(filename, "utf8");
}

function peekChar(s) {
    if (s.pos < s.len)
        return s.string.charAt(s.pos);
}

function readChar(s) {
    var c = peekChar(s);

    if (c) {
        s.pos++;
        return c;
    }
}

function readWhitespace (s) {
    var c;

    while (true) {
        c = peekChar(s);
        if (c && whitespace[c])
            readChar(s);
        else break;
    }
}

function readAtom(s) {
    var c, str = "";

    while (true) {
        c = peekChar(s);
        if (c && !whitespace[c] && !delimiters[c]) {
            str += c;
            readChar(s);
        } else break;
    }

    return str;
}

function readList(s) {
    readChar(s); // (

    var c, l = [];

    while (true) {
        readWhitespace(s);
        c = peekChar(s)
        if (c && c != ")") {
            l.push(read(s));
        } else if (c) {
            readChar(s); // )
            break;
        } else {
            error("Expected ) at " + s.pos);
        }
    }

    return l;
}

function readComment(s) {
    var c;
    do { c = readChar(s); } while (c && c != "\n");
}

function readString(s) {
    readChar(s); // "

    var c, str = "";

    while (true) {
        c = peekChar(s);
        if (c && c != "\"") {
            if (c == "\\")
                str += readChar(s);
            str += readChar(s);
        } else if (c) {
            readChar(s); // "
            break;
        } else {
            error("Expected \" at " + s.pos);
        }
    }

    return str;
}

function read(s) {
    readWhitespace(s);

    var c = peekChar(s);

    switch (c) {
        case ";": readComment(s); return read(s);
        case "(": return readList(s);
        case ")": error("Unexpected ) at " + s.pos);
        case "\"": return readString(s);
        default: return readAtom(s);
    }
}

function readFromString(str) {
    return read(makeStream(str));
}

function isAtom(form) {
    return typeof form == "string";
}

function isCall(form) {
    return Array.isArray(form) && typeof form[0] == "string";
}

function isOperator(form) {
    return operators[form[0]] != null;
}

function isSpecial(form) {
    return special[form[0]] != null;
}

function compileAtom(form, isStatement) {
    return form.toString() + (isStatement ? ";" : "");
}

function compileCall(form, isStatement) {
    return form[0] + compileArgs(form.slice(1)) + (isStatement ? ";" : "");
}

function compileOperator(form) {
    if (form.length > 3)
        error("Too many arguments to operator " + form[0]);

    var a = compile(form[1], false);
    var b = compile(form[2], false);
    return "(" + a + operators[form[0]] + b + ")";
}

function compileSet(form, isStatement) {
    if (!isStatement)
        error("Cannot compile assignment as an expression");
    if (!isAtom(form[0]))
        error("Invalid left-hand side of assignment");
    if (form.length < 3)
        error("Missing right-hand side in assignment");
    return compile(form[1], false) + "=" + compile(form[2], false) + ";";
}

function compileArgs(forms, areLiteral) {
    var i = 0, str = "(";
    while (i < forms.length) {
        if (areLiteral)
            str += forms[i];
        else
            str += compile(forms[i], false);
        if (i < forms.length - 1)
            str += ",";
        ++i;
    }
    return str + ")";
}

function compileBody(forms) {
    var i = 0, str = "{";
    while (i < forms.length) {
        str += compile(forms[i], true);
        ++i;
    }
    return str + "}";
}

function compileBranch(branch) {
    var body = branch.slice(1);
    return "if(" + compile(branch[0], false) + ")" + compileBody(body);
}

function compileIf(form, isStatement) {
    if (!isStatement)
        error("Cannot compile if as an expression");
    var i = 1, str = "";
    while (i < form.length) {
        str += compileBranch(form[i]);
        if (i < form.length - 1)
            str += "else ";
        ++i;
    }
    return str + ";";
}

function compileFunction(form, isStatement) {
    // ignoring isStatement for now
    var name = form[1];
    var args = compileArgs(form[2], true);
    var body = compileBody(form.slice(3));
    return "function " + name + args + body + ";";
}

function compileGet(form, isStatement) {
    return form[1] + "[" + form[2] + "]" + (isStatement ? ";" : "");
}

function compileDefine(form, isStatement) {
    if (!isStatement)
        error("Cannot compile definition as an expression");

    if (typeof form[2] == "undefined")
        return "var " + form[1] + ";";
    else return "var " + form[1] + "=" + form[2] + ";";
}

function compileWhile(form, isStatement) {
    if (!isStatement)
        error("Cannot compile while loop as an expression");
    var condition = compile(form[1], false);
    var body = compileBody(form.slice(2));
    return "while(" + condition + ")" + body + ";";
}

function compile(form, isStatement) {
    isStatement = typeof isStatement == "undefined" ? true : isStatement;

    if (isAtom(form))
        return compileAtom(form, isStatement);
    else if (isCall(form)) {
        if (isOperator(form)) {
            if (isStatement)
                error("Cannot compile use of operator " + form[0] + " as a statement");
            return compileOperator(form);
        } else if (isSpecial(form)) {
            return special[form[0]](form, isStatement);
        } else return compileCall(form, isStatement);
    } else error("Unexpected form " + form.toString());
}

function compileFile(filename) {
    var s = makeStream(readFile(filename));
    var form, output = "";
    while (true) {
        form = read(s);
        if (form)
            output += compile(form, true);
        else
            break;
    }
    return output;
}
<|endoftext|>


<commit_before>"use strict";
var ls = {//window.addEventListener("storage",function(e){console.log(e)},false)
    get: function (key) {
        key = localStorage.getItem(key);
        return key ? JSON.parse(key) : null;
    },
    si: function (k, v) {
        localStorage.setItem(k, JSON.stringify(v));
    },
    set: function (key, value) {
        switch (typeof key) {
            case "string":
                return value ? (ls.si(key, value), true) : false;
            case "object":
                for (let i in key) {
                    ls.si(i, key[i])
                };
                return true;
        }
    },
    put: function (key, value) {
        var d = ls.get(key);
        if (d) {
            for (let i in value) {
                d[i] = value[i]
            }
            value = d;
        }
        ls.si(key, value);
    }
};
var dbs = {
    sina: {
        key: "id",
        idx: [],//name nm unique
        init: function () {
            ls.get("sina") || ls.set("sina", {});
            ext.ajax("http://m.weibo.cn/home/me?format=cards").then(
                function (res) {
                    res = JSON.parse(res.response)[0].card_group[0].user;
                    iDB.init("sina", res.id, 1).then(function () {
                        var f = ls.get("sina")[res.id];
                        if (!f) {
                            f = {};
                            f[res.id] = [1, false, Math.ceil(res.mblogNum / 10)];
                            ls.put("sina", f);
                            f = f[res.id];
                        }
                        dbs.sina.get(res.id, f[0], f[2], f[1])

                    })
                },
                function (status) {
                    (status == 0) && ext.tabs.create({
                        url: "https://passport.weibo.cn/signin/welcome"
                    })
                })
        },
        format: function (dat, flag) {

            (flag !== false) && (dat = dat.mblog);

            var uid = dat.user.id,
                re = {
                    tim: dat.created_timestamp,
                    id: dat.id,
                    bid: dat.bid,
                    mid: dat.mid,
                    src: dat.source
                };
            dat.text && (re.txt = dat.text);
            dat.url_struct && (re.url = dat.url_struct.map(i => i.ori_url));
            dat.topic_struct && (re.tags = dat.topic_struct.map(i => i.topic_title));
            dat.pics && (re.pics = dat.pics.map(i => i.url.replace(/(^.*\/).*(\/.*$)/, "$1large$2")));
            dat.comments_count && (re.cmt_n = dat.comments_count);
            dat.like_count && (re.like = dat.like_count);
            dat.reposts_count && (re.rt_n = dat.reposts_count);

            flag !== false && re.cmt_n && dbs.sina.cmtget(uid, re.id)

            dat.retweeted_status && (re.rt = dbs.sina.format(dat.retweeted_status, false));

            if (flag === true) {
                iDB.put("sina", uid, re);
            } else {
                return re
            }
        },
        cmtget: function (uid, cid, page = 1, cmts = { id: uid, cmts: [] }) {
            var l = ls.get("sina_cmts") || {}, s = new Set(l[uid] || null);
            if (!s.has(cid)) {
                s.add(cid);
                l[uid] = Array.from(s);
                ls.set("sina_cmts", l);
            }

            ext.ajax(`http://m.weibo.cn/${uid}/${cid}/rcMod?format=cards&type=comment&hot=1&page=${page}`).then(
                function (xml) {
                    xml = JSON.parse(xml.response)[0];
                    if (xml.card_group) {

                        xml.card_group.forEach(function (i) {
                            var c = {
                                tim: new Date(i.created_at).getTime() / 1000,
                                src: i.source,
                                id: i.id,
                                usr: {
                                    id: i.user.id,
                                    name: i.user.screen_name
                                }
                            };
                            i.text && (c.txt = i.text);
                            i.reply_id && (c.re_id = i.reply_id);
                            i.reply_text && (c.re_txt = i.reply_text);
                            i.pic && (c.pic = i.pic.url);
                            i.like && (c.like = i.like_counts);
                            cmts.cmts.push(c);
                        });
                        if (xml.loadMore) {
                            (setTimeout(function () {
                                cmtget(uid, cid, ++page, cmts);
                            }, ext.delay(3)))
                        } else {
                            iDB.put("sina", uid, cmts);
                            var l = ls.get("sina_cmts") || {}, s = new Set(l[uid] || null);
                            if (s.has(cid)) {
                                s.delete(cid);
                                l[uid] = Array.from(s);
                                ls.set("sina_cmts", l);
                            }
                        }
                    }
                });

        },
        get: function (id, i = 1, k, flag) {
            var don = function () {
                if (flag || i >= k) {
                    t[id] = [1, true, k, new Date().getTime()];
                    ls.put("sina", t);
                } else {
                    ls.set(new Date().toJSON(), "DONE");
                    dbs.sina.get(id, i, k, flag);
                }
            };
            var mor = function () {
                t[id] = [++i, flag, k];
                ls.put("sina", t);
                (setTimeout(function () {
                    dbs.sina.get(id, i, k, flag);
                }, ext.delay(5)))
            };
            if (i > 0) {
                var t = {};
                ext.ajax(`http://m.weibo.cn/index/my?format=cards&page=${i}`).then(function (data) {
                    var j = 0;
                    data = JSON.parse(data.response);
                    while (data[j] && data[j].mod_type != "mod/pagelist") {
                        j++
                    }
                    data = data[j] ? data[j].card_group : null;
                    if (data) {
                        data = data.map(dbs.sina.format);
                        if (i < k && data.length < 10) {//
                            don();
                        } else if (flag) {//check data
                            iDB.get("sina", id, data[0].id).then(function (res) {
                                if (res[0]) {
                                    i && don()
                                } else {
                                    iDB.put("sina", id, data);
                                    mor()
                                }
                            });
                        } else {
                            iDB.put("sina", id, data);
                            mor();
                        }
                    } else {
                        don()
                    }
                })
            }
        },
        out: function (id) {
            var usr = ls.get("sina")[id];
            if (usr) {
                var dat = {
                    usr: [id, usr[2], new Date().toJSON()],
                    blogs: []
                };
                iDB.obj("sina", dat.usr[0], "readonly").then(function (obj) {
                    obj = obj.openCursor();
                    var nxt = function (evt) {
                        evt = evt.target.result;
                        if (evt) {
                            dat.blogs.push(evt.value);
                            evt.continue();
                            evt.onsuccess = nxt;
                        } else {
                            ext.tabs.create({
                                url: "data:application/json," + JSON.stringify(dat)
                            })
                        }
                    }
                    obj.onsuccess = nxt;

                })
            } else {
                console.log("Nothing...")
            }
        },
        clean: function () { }
    }
};
var iDB = {
    init: function (dbnm, tb, ver) {
        return new Promise(function (thn, cth) {
            var re = indexedDB.open(dbnm, ver || 1);
            re.onsuccess = function (evt) {
                thn(dbs[dbnm].re = evt.target.result);
            }
            re.onupgradeneeded = function (evt) {
                var tmp = dbs[dbnm];
                var db = evt.target.result;
                var obj = db.createObjectStore(tb, { keyPath: tmp.key });
                if (tmp.idx) {
                    for (let i of tmp.idx) {
                        obj.createIndex(i[0], i[1] || i[0], { unique: i[2] })
                    }
                }
            }
        });

    },
    d: function (data) {
        return Array.isArray(data) ? data : [data];
    },
    obj: function (dbnm, tb, method) {

        return new Promise(function (thn, cth) {
            if (dbs[dbnm].re) {
                thn(dbs[dbnm].re.transaction([tb], method).objectStore(tb));
            } else {
                iDB.init(dbnm, tb).then(re => thn(re.transaction([tb], method).objectStore(tb)));
            }
        })
    },
    add: function (dbnm, tb, data) {
        iDB.obj(dbnm, tb, "readwrite").then(obj => { for (let i of iDB.d(data)) { obj.add(i) } });
    },
    put: function (dbnm, tb, data) {
        iDB.obj(dbnm, tb, "readwrite").then(obj => {
            for (let i of iDB.d(data)) {
                obj.get(i[obj.keyPath]).onsuccess = function (evt) {
                    evt = evt.target.result;
                    if (evt) {
                        for (let j in evt) {
                            i[j] = evt[j]
                        }
                    }
                    obj.put(i);
                }
            }
        });
    },
    del: function (dbnm, tb, keys) {
        iDB.obj(dbnm, tb, "readwrite").then(obj => { for (let i of iDB.d(data)) { obj.delete(i) } });
    },
    get: function (dbnm, tb, keys) {
        return new Promise(function (thn, cth) {
            iDB.obj(dbnm, tb, "readonly").then(obj => {
                var res = {}, l;
                if (Array.isArray(keys)) {
                    l = keys.length;
                } else {
                    l = 1;
                    keys = [keys];
                }
                var n = 0;

                for (let i in keys) {
                    obj.get(keys[i]).onsuccess = function (evt) {
                        res[i] = evt.target.result;
                        if (++n == l) {
                            thn(res)
                        }
                    }
                }
            })

        })

    }
};

(function () {

})();
<commit_msg>bugs fix<commit_after>"use strict";
var ls = {//window.addEventListener("storage",function(e){console.log(e)},false)
    get: function (key) {
        key = localStorage.getItem(key);
        return key ? JSON.parse(key) : null;
    },
    si: function (k, v) {
        localStorage.setItem(k, JSON.stringify(v));
    },
    set: function (key, value) {
        switch (typeof key) {
            case "string":
                return value ? (ls.si(key, value), true) : false;
            case "object":
                for (let i in key) {
                    ls.si(i, key[i])
                };
                return true;
        }
    },
    put: function (key, value) {
        var d = ls.get(key);
        if (d) {
            for (let i in value) {
                d[i] = value[i]
            }
            value = d;
        }
        ls.si(key, value);
    }
};
var dbs = {
    sina: {
        key: "id",
        idx: [],//name nm unique
        init: function () {
            ls.get("sina") || ls.set("sina", {});
            ext.ajax("http://m.weibo.cn/home/me?format=cards").then(
                function (res) {
                    res = JSON.parse(res.response)[0].card_group[0].user.id;
                    iDB.init("sina", res, 1).then(function () {
                        var f = ls.get("sina")[res];
                        if (!f) {
                            f = {};
                            f[res] = [1, false, Math.ceil(res.mblogNum / 10)];
                            ls.put("sina", f);
                            f = f[res];
                        }
                        dbs.sina.get(res, f[0], f[2], f[1]);
                        f = ls.get("sina_cmts");
                        if (f && f[res] && f[res].length) {
                            f[res].forEach(i => setTimeout(function () {
                                dbs.sina.cmtget(res, i)
                            }, ext.delay(1)));

                        }

                    })
                },
                function (status) {
                    (status == 0) && ext.tabs.create({
                        url: "https://passport.weibo.cn/signin/welcome"
                    })
                })
        },
        format: function (dat, flag) {

            (flag !== false) && (dat = dat.mblog);

            var uid = dat.user.id,
                re = {
                    tim: dat.created_timestamp,
                    id: dat.id,
                    bid: dat.bid,
                    mid: dat.mid,
                    src: dat.source
                };
            dat.text && (re.txt = dat.text);
            dat.url_struct && (re.url = dat.url_struct.map(i => i.ori_url));
            dat.topic_struct && (re.tags = dat.topic_struct.map(i => i.topic_title));
            dat.pics && (re.pics = dat.pics.map(i => i.url.replace(/(^.*\/).*(\/.*$)/, "$1large$2")));
            dat.comments_count && (re.cmt_n = dat.comments_count);
            dat.like_count && (re.like = dat.like_count);
            dat.reposts_count && (re.rt_n = dat.reposts_count);

            flag !== false && re.cmt_n && dbs.sina.cmtget(uid, re.id)

            dat.retweeted_status && (re.rt = dbs.sina.format(dat.retweeted_status, false));

            if (flag === true) {
                iDB.put("sina", uid, re);
            } else {
                return re
            }
        },
        cmtget: function (uid, cid, page = 1, cmts = { id: cid, cmts: [] }) {
            var l = ls.get("sina_cmts") || {}, s = new Set(l[uid] || null);
            if (!s.has(cid)) {
                s.add(cid);
                l[uid] = Array.from(s);
                ls.set("sina_cmts", l);
            }
            var del = function () {
                var l = ls.get("sina_cmts") || {}, s = new Set(l[uid] || null);
                if (s.has(cid)) {
                    s.delete(cid);
                    l[uid] = Array.from(s);
                    ls.set("sina_cmts", l);
                }
            };

            ext.ajax(`http://m.weibo.cn/${uid}/${cid}/rcMod?format=cards&type=comment&hot=1&page=${page}`).then(
                function (xml) {
                    xml = JSON.parse(xml.response)[0];
                    if (xml.card_group) {

                        xml.card_group.forEach(function (i) {
                            var c = {
                                tim: new Date(i.created_at).getTime() / 1000,
                                src: i.source,
                                id: i.id,
                                usr: {
                                    id: i.user.id,
                                    name: i.user.screen_name
                                }
                            };
                            i.text && (c.txt = i.text);
                            i.reply_id && (c.re_id = i.reply_id);
                            i.reply_text && (c.re_txt = i.reply_text);
                            i.pic && (c.pic = i.pic.url);
                            i.like && (c.like = i.like_counts);
                            cmts.cmts.push(c);
                        });
                        if (xml.loadMore) {
                            (setTimeout(function () {
                                dbs.sina.cmtget(uid, cid, ++page, cmts);
                            }, ext.delay(3)))
                        } else {
                            iDB.put("sina", uid, cmts);
                            del()
                        }
                    } else {
                        del()
                    }
                });

        },
        get: function (id, i = 1, k, flag) {
            var don = function () {
                if (flag || i >= k) {
                    t[id] = [1, true, k, new Date().getTime()];
                    ls.put("sina", t);
                } else {
                    ls.set(new Date().toJSON(), "DONE");
                    dbs.sina.get(id, i, k, flag);
                }
            };
            var mor = function () {
                t[id] = [++i, flag, k];
                ls.put("sina", t);
                (setTimeout(function () {
                    dbs.sina.get(id, i, k, flag);
                }, ext.delay(5)))
            };
            if (i > 0) {
                var t = {};
                ext.ajax(`http://m.weibo.cn/index/my?format=cards&page=${i}`).then(function (data) {
                    var j = 0;
                    data = JSON.parse(data.response);
                    while (data[j] && data[j].mod_type != "mod/pagelist") {
                        j++
                    }
                    data = data[j] ? data[j].card_group : null;
                    if (data) {
                        data = data.map(dbs.sina.format);
                        if (i < k && data.length < 10) {//
                            don();
                        } else if (flag) {//check data
                            iDB.get("sina", id, data[0].id).then(function (res) {
                                if (res[0]) {
                                    i && don()
                                } else {
                                    iDB.put("sina", id, data);
                                    mor()
                                }
                            });
                        } else {
                            iDB.put("sina", id, data);
                            mor();
                        }
                    } else {
                        don()
                    }
                })
            }
        },
        out: function (id) {
            var usr = ls.get("sina")[id];
            if (usr) {
                var dat = {
                    usr: [id, usr[2], new Date().toJSON()],
                    blogs: []
                };
                iDB.obj("sina", dat.usr[0], "readonly").then(function (obj) {
                    obj = obj.openCursor();
                    var nxt = function (evt) {
                        evt = evt.target.result;
                        if (evt) {
                            dat.blogs.push(evt.value);
                            evt.continue();
                            evt.onsuccess = nxt;
                        } else {
                            ext.tabs.create({
                                url: "data:application/json," + JSON.stringify(dat)
                            })
                        }
                    }
                    obj.onsuccess = nxt;

                })
            } else {
                console.log("Nothing...")
            }
        },
        clean: function () { }
    }
};
var iDB = {
    init: function (dbnm, tb, ver) {
        return new Promise(function (thn, cth) {
            var re = indexedDB.open(dbnm, ver || 1);
            re.onsuccess = function (evt) {
                thn(dbs[dbnm].re = evt.target.result);
            }
            re.onupgradeneeded = function (evt) {
                var tmp = dbs[dbnm];
                var db = evt.target.result;
                var obj = db.createObjectStore(tb, { keyPath: tmp.key });
                if (tmp.idx) {
                    for (let i of tmp.idx) {
                        obj.createIndex(i[0], i[1] || i[0], { unique: i[2] })
                    }
                }
            }
        });

    },
    d: function (data) {
        return Array.isArray(data) ? data : [data];
    },
    obj: function (dbnm, tb, method) {

        return new Promise(function (thn, cth) {
            if (dbs[dbnm].re) {
                thn(dbs[dbnm].re.transaction([tb], method).objectStore(tb));
            } else {
                iDB.init(dbnm, tb).then(re => thn(re.transaction([tb], method).objectStore(tb)));
            }
        })
    },
    add: function (dbnm, tb, data) {
        iDB.obj(dbnm, tb, "readwrite").then(obj => { for (let i of iDB.d(data)) { obj.add(i) } });
    },
    put: function (dbnm, tb, data) {
        iDB.obj(dbnm, tb, "readwrite").then(obj => {
            for (let i of iDB.d(data)) {
                obj.get(i[obj.keyPath]).onsuccess = function (evt) {
                    evt = evt.target.result;
                    if (evt) {
                        for (let j in evt) {
                            i[j] = evt[j]
                        }
                    }
                    obj.put(i);
                }
            }
        });
    },
    del: function (dbnm, tb, keys) {
        iDB.obj(dbnm, tb, "readwrite").then(obj => { for (let i of iDB.d(data)) { obj.delete(i) } });
    },
    get: function (dbnm, tb, keys) {
        return new Promise(function (thn, cth) {
            iDB.obj(dbnm, tb, "readonly").then(obj => {
                var res = {}, l;
                if (Array.isArray(keys)) {
                    l = keys.length;
                } else {
                    l = 1;
                    keys = [keys];
                }
                var n = 0;

                for (let i in keys) {
                    obj.get(keys[i]).onsuccess = function (evt) {
                        res[i] = evt.target.result;
                        if (++n == l) {
                            thn(res)
                        }
                    }
                }
            })

        })

    }
};

(function () {

})();
<|endoftext|>


<commit_before>/**
 * @author César Costas Carrera
 *
 * CURRICULUM VITAE
 */

export default {
  name: 'César Costas Carrera',
  role: 'Software Engineer (SE2)',
  color: '#84425d',
  contact: {
    phone: '+447920158374',
    email: 'costascarrera.cesar@gmail.com',
    sites: [
      'https://github.com/gatsbimantico',
      'https://stackoverflow.com/users/2308745/gatsbimantico'
    ],
  },
  summary: `
I am a frontend web developer with over ${Math.floor((new Date() - new Date('11/15/2013')) / 3.1536e+9) / 10} years of experience.
This CV currently under maintenance.
  `,/**
My passion for frontend development begun through data visualization working as a data analyst in a research project.
Since then I've worked on high traffic sites for brands like Loveholidays, Volkswagen or Pull&Bear.

I'm fully competent with modern frameworks (like React, Angular and Polymer), frontend utilities (like NodeJs, Gulp, Git, Docker), testing (functional and A/B tests) and agile methodologies (like Scrum or Khanban).
	`, */
  skills: [
    // 'PLACEHOLDER_FOR_A_QUOTE',
  ],
  experiences: [{

    is: 'Software Engineer Ⅱ',
    at: 'Ocado',
    on: { start: '2020 Jan', end: "now" },
    tools: {
      main: [
        { name: 'React', version: '16' },
        { name: 'Redux' },
        { name: 'styled-components' },
        { name: 'Enzime' },
        { name: 'RTL' },
        { name: 'Node', version: '10' },
        { name: 'Gitlab' },
        { name: 'Jira Cloud' },
      ],
    },
    portfolio: {
      released: [
        'https://groceries.morrisons.com/browse',
      ]
    },
    description: `
Ocado's development culture relies on high autonomy.

I lead the engineering team to work on
 legal aspects of the site as compliance with cookies,
 and pushed for initiatives to prevent the project from becoming legacy or be exposed to security holes.

I worked with my colleagues on edge frontend responsibilities like accessibility, performance, and developing features designed by the UX team.
    `

  }, {

    was: 'Frontend web developer',
    at: 'Loveholidays',
    on: { start: '2018 May', end: "2020 Jan" },
    tools: {
      main: [
        { name: 'React', version: 16 },
        { name: 'Redux' },
        { name: 'redux-sagas' },
        { name: 'styled-components' },
        { name: 'Enzime' },
        { name: 'Github' },
        { name: 'Jira Cloud' },
      ],
      others: [
        { name: 'Sass' },
        { name: 'Karma' },
        { name: 'Optimizely' },
        { name: 'Google Analytics' },
        { name: 'Google Optimize' },
      ],
    },
    portfolio: {
      released: [
        'https://loveholidays.com'
      ]
    },
    description: `
My time at Loveholidays was completely in sync with the needs of their business.
I joined to help scale the business internationally and moving from django into a React frontend.

I lead by example the experiments team from its inception with two developers until its end with three frontend teams with around 15 developers.

The values that I induced in the team were: Speed (quick tasks, big impact, fast pipeline), quality, standards (close to native and semantic), and performance.
    `,

  }, {

    was: 'Frontend web developer',
    at: 'Tribal worldwide',
    on: { start: '2017 Jan', end: '2018 May' },
    tools: {
      main: [
        { name: 'Polymer', version: '1' },
        { name: 'Redux' },
        { name: 'Mocha' },
        { name: 'Sass' },
        { name: 'Gulp', version: '4' },
        { name: 'jQuery', version: '3' },
        { name: 'Node', version: '6' },
        { name: 'Git' },
        { name: 'Jira' },
      ],
      others: [
        'Handlebars',
        'Wordpress',
        'Aem',
        'Jahia',
      ]
    },
    portfolio: {
      released: [
        'http://lipton.com',
        'http://cartedor.co.uk/maisoncartedor',
        'http://volkswagen.co.uk',
      ]
    },
    description: `
    Tribal is an hybrid Ad-Development agency that provides websites to their advertising clients.
    Each project is handled by a small team of 1 to 4 specialists.

    At Tribal I contributed to Wordpress, AEM and Polymer proyects, while mentoring a junior and an intern developers.

    I took the lead rooting for reusable components, unit tests and understanding the problem and client needs before coding.
    `,

  }, {

    was: 'Full stack web developer',
    at: 'Imatia innovation',
    on: { start: '2016 Jun', end: '2016 Dec' },
    tools: {
      main: [
        { name: 'Angular', version: '2' },
        { name: 'TypeScript', version: '2' },
        { name: 'Sass' },
        { name: 'Gulp', version: '3' },
        { name: 'Gitlab' },
        { name: 'Docker' },
      ],
      others: [
        { name: 'Node', version: '6' },
        'Java',
        'Scala',
        'Hadoop',
      ]
    },
    description: `
    `,

  }, {

    was: 'Full stack web developer',
    at: 'ViewNext',
    on: { start: '2015 Jun', end: '2016 Jun' },
    tools: {
      main: [
        { name: 'Java' },
        { name: 'JSP' },
        { name: 'SVN' },
        { name: 'jQuery', version: '1' },
        { name: 'Jira' },
      ],
      others: [
        { name: 'HTML', version: '4' },
        { name: 'CSS', version: '2' },
        { name: 'Angular', version: '1' },
        { name: 'Backbone' },
        'DB2',
      ]
    },
    portfolio: {
      dismissed: [
        'https://www.massimodutti.com/',
        'https://www.oysho.com/',
        'https://www.pullandbear.com/',
        'https://www.zarahome.com/',
        'https://www.stradivarius.com/',
        'https://www.bershka.com/',
        'https://www.uterque.com/',
        'https://www.lefties.com/'
      ]
    },
    description: `
    `,

  }, {

    was: 'Full stack web developer',
    at: 'University of Vigo',
    on: { start: '2013 Nov', end: '2015 May' },
    tools: {
      main: [
        { name: 'Ruby-on-Rails' },
        { name: 'jQuery', version: '1' },
        { name: 'D3js' },
      ],
      others: [
        { name: 'HTML', version: '5' },
        { name: 'CSS', version: '3' },
        'Java',
        'Weka',
        'RapidMiner',
        'Python',
      ]
    },
    description: `
    `,

  }],
  education: [{
/*
    titles: [
      'Time Management',
      'How to speak in public',
      'Strength Deployment Inventory'
    ], at: 'Tribal', on: '2018 - 2017'

  }, {
*/
    titles: [
      'Full Stack Web Development especialization'
    ], at: 'Coursera', on: 2016

  }, {
/*
    titles: [
      'Angular',
      'TDD',
      'eCommerce',
      'JavaEE'
    ], at: 'ViewNext', on: 2015

  }, {
*/
    titles: [
      'Intro to Machine Learning'
    ], at: 'Udacity', on: 2012

  }, {

    titles: [
      'BSC. Physics'
    ], at: 'University of Vigo', on: 2005

  }]
};
<commit_msg>Comment to make the years more semantic<commit_after>/**
 * @author César Costas Carrera
 *
 * CURRICULUM VITAE
 */

export default {
  name: 'César Costas Carrera',
  role: 'Software Engineer (SE2)',
  color: '#84425d',
  contact: {
    phone: '+447920158374',
    email: 'costascarrera.cesar@gmail.com',
    sites: [
      'https://github.com/gatsbimantico',
      'https://stackoverflow.com/users/2308745/gatsbimantico'
    ],
  },
  summary: `
I am a frontend web developer with over ${Math.floor((new Date() - new Date('11/15/2013')) / 3.1536e+9) / 10} years of experience.
This CV currently under maintenance.
  `,/**
7.0 - 7 years
7.1 - over 7 years
7.2 - over 7 years
7.3 - over 7 years
7.4 - over 7 years
7.5 - over 7 ½ years
7.6 - over 7 ½ years
7.7 - over 7 ½ years
7.8 - over 7 ½ years
7.9 - aproximately 8 years

My passion for frontend development begun through data visualization working as a data analyst in a research project.
Since then I've worked on high traffic sites for brands like Loveholidays, Volkswagen or Pull&Bear.

I'm fully competent with modern frameworks (like React, Angular and Polymer), frontend utilities (like NodeJs, Gulp, Git, Docker), testing (functional and A/B tests) and agile methodologies (like Scrum or Khanban).
	`, */
  skills: [
    // 'PLACEHOLDER_FOR_A_QUOTE',
  ],
  experiences: [{

    is: 'Software Engineer Ⅱ',
    at: 'Ocado',
    on: { start: '2020 Jan', end: "now" },
    tools: {
      main: [
        { name: 'React', version: '16' },
        { name: 'Redux' },
        { name: 'styled-components' },
        { name: 'Enzime' },
        { name: 'RTL' },
        { name: 'Node', version: '10' },
        { name: 'Gitlab' },
        { name: 'Jira Cloud' },
      ],
    },
    portfolio: {
      released: [
        'https://groceries.morrisons.com/browse',
      ]
    },
    description: `
Ocado's development culture relies on high autonomy.

I lead the engineering team to work on
 legal aspects of the site as compliance with cookies,
 and pushed for initiatives to prevent the project from becoming legacy or be exposed to security holes.

I worked with my colleagues on edge frontend responsibilities like accessibility, performance, and developing features designed by the UX team.
    `

  }, {

    was: 'Frontend web developer',
    at: 'Loveholidays',
    on: { start: '2018 May', end: "2020 Jan" },
    tools: {
      main: [
        { name: 'React', version: 16 },
        { name: 'Redux' },
        { name: 'redux-sagas' },
        { name: 'styled-components' },
        { name: 'Enzime' },
        { name: 'Github' },
        { name: 'Jira Cloud' },
      ],
      others: [
        { name: 'Sass' },
        { name: 'Karma' },
        { name: 'Optimizely' },
        { name: 'Google Analytics' },
        { name: 'Google Optimize' },
      ],
    },
    portfolio: {
      released: [
        'https://loveholidays.com'
      ]
    },
    description: `
My time at Loveholidays was completely in sync with the needs of their business.
I joined to help scale the business internationally and moving from django into a React frontend.

I lead by example the experiments team from its inception with two developers until its end with three frontend teams with around 15 developers.

The values that I induced in the team were: Speed (quick tasks, big impact, fast pipeline), quality, standards (close to native and semantic), and performance.
    `,

  }, {

    was: 'Frontend web developer',
    at: 'Tribal worldwide',
    on: { start: '2017 Jan', end: '2018 May' },
    tools: {
      main: [
        { name: 'Polymer', version: '1' },
        { name: 'Redux' },
        { name: 'Mocha' },
        { name: 'Sass' },
        { name: 'Gulp', version: '4' },
        { name: 'jQuery', version: '3' },
        { name: 'Node', version: '6' },
        { name: 'Git' },
        { name: 'Jira' },
      ],
      others: [
        'Handlebars',
        'Wordpress',
        'Aem',
        'Jahia',
      ]
    },
    portfolio: {
      released: [
        'http://lipton.com',
        'http://cartedor.co.uk/maisoncartedor',
        'http://volkswagen.co.uk',
      ]
    },
    description: `
    Tribal is an hybrid Ad-Development agency that provides websites to their advertising clients.
    Each project is handled by a small team of 1 to 4 specialists.

    At Tribal I contributed to Wordpress, AEM and Polymer proyects, while mentoring a junior and an intern developers.

    I took the lead rooting for reusable components, unit tests and understanding the problem and client needs before coding.
    `,

  }, {

    was: 'Full stack web developer',
    at: 'Imatia innovation',
    on: { start: '2016 Jun', end: '2016 Dec' },
    tools: {
      main: [
        { name: 'Angular', version: '2' },
        { name: 'TypeScript', version: '2' },
        { name: 'Sass' },
        { name: 'Gulp', version: '3' },
        { name: 'Gitlab' },
        { name: 'Docker' },
      ],
      others: [
        { name: 'Node', version: '6' },
        'Java',
        'Scala',
        'Hadoop',
      ]
    },
    description: `
    `,

  }, {

    was: 'Full stack web developer',
    at: 'ViewNext',
    on: { start: '2015 Jun', end: '2016 Jun' },
    tools: {
      main: [
        { name: 'Java' },
        { name: 'JSP' },
        { name: 'SVN' },
        { name: 'jQuery', version: '1' },
        { name: 'Jira' },
      ],
      others: [
        { name: 'HTML', version: '4' },
        { name: 'CSS', version: '2' },
        { name: 'Angular', version: '1' },
        { name: 'Backbone' },
        'DB2',
      ]
    },
    portfolio: {
      dismissed: [
        'https://www.massimodutti.com/',
        'https://www.oysho.com/',
        'https://www.pullandbear.com/',
        'https://www.zarahome.com/',
        'https://www.stradivarius.com/',
        'https://www.bershka.com/',
        'https://www.uterque.com/',
        'https://www.lefties.com/'
      ]
    },
    description: `
    `,

  }, {

    was: 'Full stack web developer',
    at: 'University of Vigo',
    on: { start: '2013 Nov', end: '2015 May' },
    tools: {
      main: [
        { name: 'Ruby-on-Rails' },
        { name: 'jQuery', version: '1' },
        { name: 'D3js' },
      ],
      others: [
        { name: 'HTML', version: '5' },
        { name: 'CSS', version: '3' },
        'Java',
        'Weka',
        'RapidMiner',
        'Python',
      ]
    },
    description: `
    `,

  }],
  education: [{
/*
    titles: [
      'Time Management',
      'How to speak in public',
      'Strength Deployment Inventory'
    ], at: 'Tribal', on: '2018 - 2017'

  }, {
*/
    titles: [
      'Full Stack Web Development especialization'
    ], at: 'Coursera', on: 2016

  }, {
/*
    titles: [
      'Angular',
      'TDD',
      'eCommerce',
      'JavaEE'
    ], at: 'ViewNext', on: 2015

  }, {
*/
    titles: [
      'Intro to Machine Learning'
    ], at: 'Udacity', on: 2012

  }, {

    titles: [
      'BSC. Physics'
    ], at: 'University of Vigo', on: 2005

  }]
};
<|endoftext|>


<commit_before>const mongoose = require('mongoose');
const nconf = require('./config/nconf');
const raccoon = require('raccoon');
const raccoonConnection = require('./config/raccoon.js');
// raccoon.connect(6379, nconf.get('REDIS_URL'));

// let options = {
//                 server: { socketOptions: { keepAlive: 1, connectTimeoutMS: 30000 } },
//                 replset: { socketOptions: { keepAlive: 1, connectTimeoutMS : 30000 } }
//               };

mongoose.connect(nconf.get('MONGODB_URI'));
mongoose.Promise = global.Promise;

var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {

  console.log('Connected to the db');
});

module.exports = db;
<commit_msg>fix MONGODBURI<commit_after>const mongoose = require('mongoose');
const nconf = require('./config/nconf');
const raccoon = require('raccoon');
const raccoonConnection = require('./config/raccoon.js');

mongoose.connect(nconf.get('MONGODB_URI'));
mongoose.Promise = global.Promise;

var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {

  console.log('Connected to the db');
});

module.exports = db;
<|endoftext|>