<commit_before>/**
*
* Docbase engine
* Appbase
* Henrique Sa, Feb '15
* MIT license
*
*/

!(function ($, angular){

    var jWindow = $(window);
    var angApp;

    var exports = this;
    var Docbase = exports.Docbase = {};
    var Events = Docbase.events = {};
    var Route = Docbase.route = {};

    /**
    * Github offers an API with a very strict, non-increasable limit for the client side.
    * Docbase uses this API to make a map of your markdown files, and then fetches
    * them through get requests to GitHub Pages, not the API. As there is a small chance
    * the GitHub quota will be exceeded before the docs are mapped, keep a map file (JSON)
    * in the root of your site so that can be fetched.
    * Only use HTML5 mode if you're hosting it yourself, requires server config.
    */

    Docbase.methods = ['file', 'github'];

    Docbase.run = function(options) {
        var defaults = {
            method: 'github',
            path: 'docs',
            map: {
                file: 'map.json',
                path: 'docs'
            },
            github: {
                /*user: 'user',
                repo: 'repo',*/
                path: '/',
                branch: 'gh-pages'
            },
            html5mode: false,
            indexType: 'html',
            indexSrc: '/html/main.html',
            flatdocHtml: '/html/flatdoc.html',
            angularAppName: 'docbaseApp'
        };

        options = $.extend({}, defaults, options);

        if(options.method === 'github') {
            if(!options.github.user || !options.github.repo) {
                throw 'Missing GitHub user/repo info.';
            }
        }

        // Removes trailing '/'s.
        Docbase.methods.forEach(function(method){
            var properties = options[method];
            Object.keys(properties).forEach(function(key){
                var value = properties[key];
                value = value.charAt(0) === '/' ? value.substring(1) : value;
                value = endsWith(value, '/') ? value.substring(0, value.length-1) : value;
                properties[key] = value;
            });
        });

        Docbase.options = options;

        Events.bind();

        angApp = angular
            .module(options.angularAppName, ['ngRoute'])
            .controller('URLCtrl', ['$scope', '$routeParams', '$location', '$timeout', Route.URLCtrl])
            .controller('MainCtrl', Route.mainCtrl)
            .config(['$routeProvider', '$locationProvider', Route.config]);

        Docbase[options.method](options[options.method]);
    }

    Docbase.github = function(options) {
        githubTree(options, function(error, map){
            if(error) {
                Docbase.file(Docbase.options.file);
            } else if(checkSchema(map)){
                Docbase.map = map;
                jWindow.trigger('mapped');
                Events.bind();
            } else {
                throw 'GitHub tree mapping error.';
            }
        });
    }

    Docbase.file = function(options) {
        $.get(options.path + '/' + options.file)
        .success(function(map){
            if(checkSchema(map)){
                var v = Object.keys(map);
                if(v.length &&  map[v[0]][0].files.length && map[v[0]][0].files[0].name){
                    Docbase.map = map;
                    jWindow.trigger('mapped');
                    Events.bind();
                } else {
                    throw 'Map does not have a file entry. Check the documentation';
                }
            } else {
                throw 'Map file schema error. Check the documentation.';
            }
        })
        .error(function(error){
            throw error;
        });
    }

    Events.switchBind = function(state){
        jWindow[state]('flatdoc:ready', Events.parseTitle);
        jWindow[state]('ajaxError', Events.ajaxError);
    }

    Events.bind = function(){
        Events.switchBind('on');
    };

    Events.unbind = function(){
        Events.switchBind('off');
    }

    Events.ready = function(){
        jWindow.trigger('docbase:ready');
    }

    Events.ajaxError = function(event, request){
        if(request.status === 403 && Docbase.options.method === 'github') {
            throw 'GitHub API quota exceeded.';
        }
    }

    /**
    * Parses title object, looking for specs such as three columns.
    * Simply make your fiirst markdown title an object to customize it.
    * Use double quotes on the markdown.
    * Example: {"title": "Actual title", "threeColumns": false}
    */
    Events.parseTitle = function(){
        var element = $('[role~="flatdoc-content"] h1:first');
        var menuTitle = $( '#' + element.attr('id') + '-link' );

        var content = element.html();
        try {
            content = content.replace(/\u201D/g, '"');
            content = content.replace(/\u201C/g, '"');
            content = JSON.parse(content);

            element.html(content.title);
            menuTitle.html(content.title);

            if(content.threeColumns) {
                $('body').removeClass('no-literate');
            } else {
                $('body').addClass('no-literate');
            }

        } catch (e) {/* No JSON object found, keep title as-is */};

        Events.ready();
    };

    Route.config = function($routeProvider, $locationProvider){
        var flatdocURL = Docbase.options.flatdocHtml;
        var mainURL = Docbase.options.indexSrc;

        if(Docbase.indexType === 'markdown') {
            mainURL = flatdocURL;
        }

        $routeProvider
        .when('/:version/:folder/:file', {
            templateUrl: flatdocURL,
            controller: 'URLCtrl'
        })
        .when('/:version/:folder', {
            templateUrl: flatdocURL,
            controller: 'URLCtrl'
        })
        .when('/:version', {
            templateUrl: flatdocURL,
            controller: 'URLCtrl'
        })
        .when('/', {
            templateUrl: mainURL,
            controller: 'MainCtrl'
        })
        .otherwise({
            redirectTo: '/'
        });

        $locationProvider.html5Mode(Docbase.options.html5mode);
    }

    Route.fetch = function(file){
        var options = Docbase.options;
        Flatdoc.run({
          fetcher: Flatdoc.file(options.path + file + '.md')
        });
    };

    // Route.github = function(path){
    //     var options = Docbase.options.github;
    //     var ghRepo = options.user + '/' + options.repo;
    //     var ghPath = options.path + path + '.md';
    //     var branch = options.branch;

    //     Flatdoc.run({
    //         fetcher: Flatdoc.github(ghRepo, ghPath, branch)
    //     });
    // };

    Route.URLCtrl = function($scope, $routeParams, $location, $timeout){
        if(Docbase.map) {
            mapLoaded();
        } else {
            jWindow.on('mapped', mapLoaded);
        }

        function mapLoaded(){
            var map = Docbase.map;
            var currentVersion = $routeParams.version;
            var versions = Object.keys(map);

            $timeout(function(){
                $scope.versions = versions;
                $scope.currentVersion = currentVersion || versions[versions.length-1];
                $scope.map = map;
            });

            var location = Route.updatePath($routeParams);
            $location.path(location.path);

            if(!location.fail){
                Route.fetch(location.path);
            }
        }
    };

    Route.mainCtrl = function(){
        if(Docbase.indexType === 'markdown') {
            var path = Docbase.indexSrc;
            if(endsWith(path, '.md')){
                path = path.substring(0, path.length-3);
            }
            if(path.charAt(0) !== '/'){
                path = '/' + path;
            }
            Route.fetch(path);
        }
    }

    Route.updatePath = function(params){
        var map = Docbase.map;
        var version = params.version;
        var folder = params.folder;
        var file = params.file;

        if(!map[version]){
            console.error('Version not mapped.');
            return {path: '/', fail: true};
        }

        var mapFolder;
        if(folder){
            mapFolder = map[version].filter(function(folders){
                return folders.name === folder;
            });
            if(!mapFolder.length){
                console.error('Folder not mapped.');
                return {path: '/' + version, fail: true};
            }
        }
        if(file){
            var mapFile = mapFolder[0].files.filter(function(files){
                return files.name === file;
            });
            if(!mapFile.length){
                console.error('File not mapped.');
                return {path: '/' + version + '/' + file, fail: true};
            }
        }

        folder = folder || map[version][0].name;
        var folderObj = map[version].filter(function(each){
            return each.name === folder;
        })[0];
        file = file || folderObj.files[0].name;

        var path = '/' + version + '/' + folder + '/' + file;

        return {path: path, fail: false};
    }

    function checkSchema(map) {
        return validate = schema({
            '*': Array.of(schema({
                name: String,
                label: String,
                files: Array.of(schema({
                    name: String,
                    label: String
                }))
            }))
        })(map);
    }

    function githubTree(options, callback){
        var full_path = options.path;

        var path = full_path.split('/');
        var deleted = path.splice(path.length-1, 1);
        path.join('/');
        deleted = deleted[0];

        var baseurl = 'https://api.github.com/repos/'
                    + options.user + '/' + options.repo + '/';

        var url = baseurl  + 'contents/' + path;

        $.get(url, {ref: options.branch})
        .success(function(data){
            var sha = data.filter(function(each){
                return each.name === deleted;
            })[0].sha;

            $.get(baseurl + 'git/trees/' + sha + '?recursive=1')
            .success(function(tree) {
                tree = tree.tree.filter(function(each){
                    return endsWith(each.path, '.md');
                });

                var map = {};

                tree.forEach(function(each){
                    var sub_path = each.path.split('/');
                    /* assuming sub_path[0] is the version,
                     * sub_path[1] is the folder,
                     * and sub_path[2] is the file.
                     */
                    if(sub_path.length >= 3){
                        var version = sub_path[0];
                        var folder = sub_path[1];
                        var file = sub_path[2].substring(0, sub_path[2].length-3);

                        // Version is new
                        if(!map[version]){
                            map[version] = [];
                        }

                        // Folder is new
                        if( !map[version].filter(function(a){ return a.name === folder }).length ) {
                            map[version].push({ label: folder, name: folder, files: [] });
                        }

                        // Add file
                        map[version].forEach(function(each){
                            if(each.name === folder)
                                each.files.push({name: file, label: file});
                        });
                    }
                });

                callback(null, map);

            })
            .error(function(error){
                callback(error);
            });
        })
        .error(function(error){
            callback(error);
        });
    }

    /**
    * endsWith polyfill, from MDN
    * Created by Ripter, last edited by Mathias Bynens
    */
    function endsWith(subjectString, searchString, position){
      if(position === undefined || position > subjectString.length){
        position = subjectString.length;
      }
      position -= searchString.length;
      var lastIndex = subjectString.indexOf(searchString, position);
      return lastIndex !== -1 && lastIndex === position;
    }
})(window.jQuery, window.angular);<commit_msg>Fixed bug on markdown home<commit_after>/**
*
* Docbase engine
* Appbase
* Henrique Sa, Feb '15
* MIT license
*
*/

!(function ($, angular){

    var jWindow = $(window);
    var angApp;

    var exports = this;
    var Docbase = exports.Docbase = {};
    var Events = Docbase.events = {};
    var Route = Docbase.route = {};

    /**
    * Github offers an API with a very strict, non-increasable limit for the client side.
    * Docbase uses this API to make a map of your markdown files, and then fetches
    * them through get requests to GitHub Pages, not the API. As there is a small chance
    * the GitHub quota will be exceeded before the docs are mapped, keep a map file (JSON)
    * in the root of your site so that can be fetched.
    * Only use HTML5 mode if you're hosting it yourself, requires server config.
    */

    Docbase.methods = ['file', 'github'];

    Docbase.run = function(options) {
        var defaults = {
            method: 'github',
            path: 'docs',
            map: {
                file: 'map.json',
                path: 'docs'
            },
            github: {
                /*user: 'user',
                repo: 'repo',*/
                path: '/',
                branch: 'gh-pages'
            },
            html5mode: false,
            indexType: 'html',
            indexSrc: '/html/main.html',
            flatdocHtml: '/html/flatdoc.html',
            angularAppName: 'docbaseApp'
        };

        options = $.extend({}, defaults, options);

        if(options.method === 'github') {
            if(!options.github.user || !options.github.repo) {
                throw 'Missing GitHub user/repo info.';
            }
        }

        // Removes trailing '/'s.
        Docbase.methods.forEach(function(method){
            var properties = options[method];
            Object.keys(properties).forEach(function(key){
                var value = properties[key];
                value = value.charAt(0) === '/' ? value.substring(1) : value;
                value = endsWith(value, '/') ? value.substring(0, value.length-1) : value;
                properties[key] = value;
            });
        });

        Docbase.options = options;

        Events.bind();

        angApp = angular
            .module(options.angularAppName, ['ngRoute'])
            .controller('URLCtrl', ['$scope', '$routeParams', '$location', '$timeout', Route.URLCtrl])
            .controller('MainCtrl', ['$location', Route.mainCtrl])
            .config(['$routeProvider', '$locationProvider', Route.config]);

        Docbase[options.method](options[options.method]);
    }

    Docbase.github = function(options) {
        githubTree(options, function(error, map){
            if(error) {
                Docbase.file(Docbase.options.file);
            } else if(checkSchema(map)){
                Docbase.map = map;
                jWindow.trigger('mapped');
                Events.bind();
            } else {
                throw 'GitHub tree mapping error.';
            }
        });
    }

    Docbase.file = function(options) {
        $.get(options.path + '/' + options.file)
        .success(function(map){
            if(checkSchema(map)){
                var v = Object.keys(map);
                if(v.length &&  map[v[0]][0].files.length && map[v[0]][0].files[0].name){
                    Docbase.map = map;
                    jWindow.trigger('mapped');
                    Events.bind();
                } else {
                    throw 'Map does not have a file entry. Check the documentation';
                }
            } else {
                throw 'Map file schema error. Check the documentation.';
            }
        })
        .error(function(error){
            throw error;
        });
    }

    Events.switchBind = function(state){
        jWindow[state]('flatdoc:ready', Events.parseTitle);
        jWindow[state]('ajaxError', Events.ajaxError);
    }

    Events.bind = function(){
        Events.switchBind('on');
    };

    Events.unbind = function(){
        Events.switchBind('off');
    }

    Events.ready = function(){
        jWindow.trigger('docbase:ready');
    }

    Events.ajaxError = function(event, request){
        if(request.status === 403 && Docbase.options.method === 'github') {
            throw 'GitHub API quota exceeded.';
        }
    }

    /**
    * Parses title object, looking for specs such as three columns.
    * Simply make your fiirst markdown title an object to customize it.
    * Use double quotes on the markdown.
    * Example: {"title": "Actual title", "threeColumns": false}
    */
    Events.parseTitle = function(){
        var element = $('[role~="flatdoc-content"] h1:first');
        var menuTitle = $( '#' + element.attr('id') + '-link' );

        var content = element.html();
        try {
            content = content.replace(/\u201D/g, '"');
            content = content.replace(/\u201C/g, '"');
            content = JSON.parse(content);

            element.html(content.title);
            menuTitle.html(content.title);

            if(content.threeColumns) {
                $('body').removeClass('no-literate');
            } else {
                $('body').addClass('no-literate');
            }

        } catch (e) {/* No JSON object found, keep title as-is */};

        Events.ready();
    };

    Route.config = function($routeProvider, $locationProvider){
        var flatdocURL = Docbase.options.flatdocHtml;
        var mainURL = Docbase.options.indexSrc;

        if(Docbase.options.indexType === 'markdown') {
            mainURL = flatdocURL;
        }

        $routeProvider
        .when('/:version/:folder/:file', {
            templateUrl: flatdocURL,
            controller: 'URLCtrl'
        })
        .when('/:version/:folder', {
            templateUrl: flatdocURL,
            controller: 'URLCtrl'
        })
        .when('/:version', {
            templateUrl: flatdocURL,
            controller: 'URLCtrl'
        })
        .when('/', {
            templateUrl: mainURL,
            controller: 'MainCtrl'
        })
        .otherwise({
            redirectTo: '/'
        });

        $locationProvider.html5Mode(Docbase.options.html5mode);
    }

    Route.fetch = function(file){
        var options = Docbase.options;
        Flatdoc.run({
          fetcher: Flatdoc.file(options.path + file + '.md')
        });
    };

    // Route.github = function(path){
    //     var options = Docbase.options.github;
    //     var ghRepo = options.user + '/' + options.repo;
    //     var ghPath = options.path + path + '.md';
    //     var branch = options.branch;

    //     Flatdoc.run({
    //         fetcher: Flatdoc.github(ghRepo, ghPath, branch)
    //     });
    // };

    Route.URLCtrl = function($scope, $routeParams, $location, $timeout){
        if(Docbase.map) {
            mapLoaded();
        } else {
            jWindow.on('mapped', mapLoaded);
        }

        function mapLoaded(){
            var map = Docbase.map;
            var currentVersion = $routeParams.version;
            var versions = Object.keys(map);

            $timeout(function(){
                $scope.versions = versions;
                $scope.currentVersion = currentVersion || versions[versions.length-1];
                $scope.map = map;
            });

            var location = Route.updatePath($routeParams);
            $location.path(location.path);

            if(!location.fail){
                Route.fetch(location.path);
            }
        }
    };

    Route.mainCtrl = function($location){
        if(Docbase.options.indexType === 'markdown') {
            var path = Docbase.options.indexSrc;
            if(endsWith(path, '.md')){
                path = path.substring(0, path.length-3);
            }
            if(path.charAt(0) !== '/'){
                path = '/' + path;
            }
            $location.path(path);
        }
    }

    Route.updatePath = function(params){
        var map = Docbase.map;
        var version = params.version;
        var folder = params.folder;
        var file = params.file;

        if(!map[version]){
            console.error('Version not mapped.');
            return {path: '/', fail: true};
        }

        var mapFolder;
        if(folder){
            mapFolder = map[version].filter(function(folders){
                return folders.name === folder;
            });
            if(!mapFolder.length){
                console.error('Folder not mapped.');
                return {path: '/' + version, fail: true};
            }
        }
        if(file){
            var mapFile = mapFolder[0].files.filter(function(files){
                return files.name === file;
            });
            if(!mapFile.length){
                console.error('File not mapped.');
                return {path: '/' + version + '/' + file, fail: true};
            }
        }

        folder = folder || map[version][0].name;
        var folderObj = map[version].filter(function(each){
            return each.name === folder;
        })[0];
        file = file || folderObj.files[0].name;

        var path = '/' + version + '/' + folder + '/' + file;

        return {path: path, fail: false};
    }

    function checkSchema(map) {
        return validate = schema({
            '*': Array.of(schema({
                name: String,
                label: String,
                files: Array.of(schema({
                    name: String,
                    label: String
                }))
            }))
        })(map);
    }

    function githubTree(options, callback){
        var full_path = options.path;

        var path = full_path.split('/');
        var deleted = path.splice(path.length-1, 1);
        path.join('/');
        deleted = deleted[0];

        var baseurl = 'https://api.github.com/repos/'
                    + options.user + '/' + options.repo + '/';

        var url = baseurl  + 'contents/' + path;

        $.get(url, {ref: options.branch})
        .success(function(data){
            var sha = data.filter(function(each){
                return each.name === deleted;
            })[0].sha;

            $.get(baseurl + 'git/trees/' + sha + '?recursive=1')
            .success(function(tree) {
                tree = tree.tree.filter(function(each){
                    return endsWith(each.path, '.md');
                });

                var map = {};

                tree.forEach(function(each){
                    var sub_path = each.path.split('/');
                    /* assuming sub_path[0] is the version,
                     * sub_path[1] is the folder,
                     * and sub_path[2] is the file.
                     */
                    if(sub_path.length >= 3){
                        var version = sub_path[0];
                        var folder = sub_path[1];
                        var file = sub_path[2].substring(0, sub_path[2].length-3);

                        // Version is new
                        if(!map[version]){
                            map[version] = [];
                        }

                        // Folder is new
                        if( !map[version].filter(function(a){ return a.name === folder }).length ) {
                            map[version].push({ label: folder, name: folder, files: [] });
                        }

                        // Add file
                        map[version].forEach(function(each){
                            if(each.name === folder)
                                each.files.push({name: file, label: file});
                        });
                    }
                });

                callback(null, map);

            })
            .error(function(error){
                callback(error);
            });
        })
        .error(function(error){
            callback(error);
        });
    }

    /**
    * endsWith polyfill, from MDN
    * Created by Ripter, last edited by Mathias Bynens
    */
    function endsWith(subjectString, searchString, position){
      if(position === undefined || position > subjectString.length){
        position = subjectString.length;
      }
      position -= searchString.length;
      var lastIndex = subjectString.indexOf(searchString, position);
      return lastIndex !== -1 && lastIndex === position;
    }
})(window.jQuery, window.angular);<|endoftext|>


<commit_before>var Slide = {
	width: function() {
		return $(window).width();
	},
	height: function() {
		return $(window).height();
	},
	syncSize: function() {
		var size = Frame.height() / 30;
	    $("body").css("font-size", size + 'px');
	    $(".frame").css("width", Frame.width() + 'px');
	    $(".frame").css("height", Frame.height() + 'px');

		/*
		$(".fit").each(function() {
			if (!$(this).data('dimensions')) {
				!$(this).data('dimensions', {
					width: $(this).width(),
					height: $(this).height(),
					parent: $(this).parent()
				});
			}
			var width = $(this).data('dimensions').width;
			var height = $(this).data('dimensions').height;

			var ratio = width/height;
			var parent = $(this).data('dimensions').parent;
			var new_width = 0;
			var new_height = 0;

			if (width > height) {
				if (parent.width() > parent.height()) {
					new_height = parent.height();
					new_width = Math.round(new_height * ratio);

				} else {
					new_width = parent.width();
					new_height = new_width / ratio;
				}
			} else {
				if (parent.width() > parent.height()) {
					new_height = parent.height();
					new_width = new_height / ratio;
				} else {
					new_width = parent.width();
					new_height = new_width * ratio;
				}
			}
			$(this).width(new_width);
			$(this).height(new_height);
			console.log("" + new_width + "x" + new_height + " parent: " + parent.width() + "x" + parent.height() + " parent_id: " + parent.attr("id"));
		});*/

		//Align vertically centered elements
		$(".center_vertically").each(function() {
			var pos = ($(this).parent().height() - $(this).height()) / 2;
			$(this).css("position","absolute");
			$(this).css("top", pos + "px");
		});
	}
}

$(window).ready(function(){
	Frame.syncSize();
});
$(window).resize(function(){
	console.log("resize event")
	Frame.syncSize();
});

functian toggleNavigationMenu() {
  if ($(".frame_menu").is(":visible")){
    $("#menu").hide("slow", function () {
      frame.layout();
    });
  } else {
    $("#menu").show("slow", function () {frame.layout();});
  }
}

/*$(window).ready(function(){
	Slide.syncSize();
});
$(window).resize(function(){
	Slide.syncSize();
});

$("#content").click(function(){
	alert("this.width()");
})*/
<commit_msg>fix indentation and white-space<commit_after>var Slide = {
  width: function() {
    return $(window).width();
  },
  height: function() {
    return $(window).height();
  },
  syncSize: function() {
    var size = Frame.height() / 30;
    $("body").css("font-size", size + 'px');
    $(".frame").css("width", Frame.width() + 'px');
    $(".frame").css("height", Frame.height() + 'px');

//     $(".fit").each(function() {
//       if (!$(this).data('dimensions')) {
//         $(this).data('dimensions', {
//           width: $(this).width(),
//                      height: $(this).height(),
//                      parent: $(this).parent()
//         });
//       }
//       var width = $(this).data('dimensions').width;
//       var height = $(this).data('dimensions').height;
//
//       var ratio = width/height;
//       var parent = $(this).data('dimensions').parent;
//       var new_width = 0;
//       var new_height = 0;
//
//       if (width > height) {
//         if (parent.width() > parent.height()) {
//           new_height = parent.height();
//           new_width = Math.round(new_height * ratio);
//         } else {
//           new_width = parent.width();
//           new_height = new_width / ratio;
//         }
//       } else {
//         if (parent.width() > parent.height()) {
//           new_height = parent.height();
//           new_width = new_height / ratio;
//         } else {
//           new_width = parent.width();
//           new_height = new_width * ratio;
//         }
//       }
//       $(this).width(new_width);
//       $(this).height(new_height);
//       console.log("" + new_width + "x" + new_height + " parent: " + parent.width() + "x" + parent.height() + " parent_id: " + parent.attr("id"));
//     });

    //Align vertically centered elements
    $(".center_vertically").each(function() {
      var pos = ($(this).parent().height() - $(this).height()) / 2;
      $(this).css("top", pos + "px");
    });
  }
}

$(window).ready(function(){
  Frame.syncSize();
});
$(window).resize(function(){
  console.log("resize event")
  Frame.syncSize();
});

functian toggleNavigationMenu() {
  if ($(".frame_menu").is(":visible")){
    $("#menu").hide("slow", function () {
      frame.layout();
    });
  } else {
    $("#menu").show("slow", function () {frame.layout();});
  }
}

/*$(window).ready(function(){
  Slide.syncSize();
});
$(window).resize(function(){
  Slide.syncSize();
});

$("#content").click(function(){
  alert("this.width()");
})*/
<|endoftext|>


<commit_before>//  Iron Router - for useage see https://github.com/EventedMind/iron-router

Router.configure({
  layoutTemplate: 'layout'
});

Router.map(function () {

});//<end-routes>
<commit_msg>fixes layout edge case<commit_after>//  Iron Router - for useage see https://github.com/EventedMind/iron-router

Router.configure({
  layoutTemplate: 'mainLayout'
});

Router.map(function () {

});//<end-routes>
<|endoftext|>


<commit_before>var regexCache = {
	post: {}
};

hexo.extend.helper.register('is_post', function() {
	var permalink = this.config.permalink;
	var r = regexCache.post[permalink];
	if (!r){
		var rUrl = permalink
				.replace(':lang', '[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*')
				.replace(':id', '\\d+')
				.replace(':category', '(\\w+\\/?)+')
				.replace(':year', '\\d{4}')
				.replace(/:(month|day)/g, '\\d{2}')
				.replace(/:i_(month|day)/g, '\\d{1,2}')
				.replace(/:title/, '[^\\/]+');
		r = regexCache.post[permalink] = new RegExp(rUrl);
	}
	return r.test(this.path);
});
<commit_msg>Add list_categories helper<commit_after>var regexCache = {
	post: {}
};

hexo.extend.helper.register('is_post', function() {
	var permalink = this.config.permalink;
	var r = regexCache.post[permalink];
	if (!r) {
		var rUrl = permalink
			.replace(':lang', '[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*')
			.replace(':id', '\\d+')
			.replace(':category', '(\\w+\\/?)+')
			.replace(':year', '\\d{4}')
			.replace(/:(month|day)/g, '\\d{2}')
			.replace(/:i_(month|day)/g, '\\d{1,2}')
			.replace(/:title/, '[^\\/]+');
		r = regexCache.post[permalink] = new RegExp(rUrl);
	}
	return r.test(this.path);
});

hexo.extend.helper.register('list_categories', function(categories, options) {
	/* jshint validthis: true */
	if (!options && (!categories || !categories.hasOwnProperty('length'))) {
		options = categories;
		categories = this.site.categories;
	}

	if (!categories || !categories.length) return '';
	options = options || {};

	var style = options.hasOwnProperty('style') ? options.style : 'list';
	var showCount = options.hasOwnProperty('show_count') ? options.show_count :
		true;
	var className = options.class || 'category';
	var depth = options.depth ? parseInt(options.depth, 10) : 0;
	var orderby = options.orderby || 'name';
	var order = options.order || 1;
	var transform = options.transform;
	var separator = options.hasOwnProperty('separator') ? options.separator :
		', ';
	var showCurrent = options.show_current || false;
	var childrenIndicator = options.hasOwnProperty('children_indicator') ?
		options.children_indicator : false;
	var result = '';
	var self = this;

	function prepareQuery(parent) {
		var query = {};

		if (parent) {
			query.parent = parent;
		} else {
			query.parent = {
				$exists: false
			};
		}

		return categories.find(query).sort(orderby, order).filter(function(
			cat) {
			return cat.length;
		});
	}

	function hierarchicalList(level, parent) {
		var result = '';

		prepareQuery(parent).forEach(function(cat, i) {
			var child;
			if (!depth || level + 1 < depth) {
				child = hierarchicalList(level + 1, cat._id);
			}

			var isCurrent = false;
			if (showCurrent && self.page) {
				for (var j = 0; j < cat.length; j++) {
					var post = cat.posts.data[j];
					if (post && post._id === self.page._id) {
						isCurrent = true;
						break;
					}
				}

				// special case: category page
				if (!isCurrent && self.page.base) {
					if (self.page.base.indexOf(cat.path) === 0) {
						isCurrent = true;
					}
				}
			}

			var additionalClassName = '';
			if (child && childrenIndicator) {
				additionalClassName = ' ' + childrenIndicator;
			}

			result += '
';

			result += '';
			result += transform ? transform(cat.name) : cat.name;
			result += '';

			if (showCount) {
				result += '' + cat
					.length + '';
			}

			if (child) {
				result += '
' + child +
					'
';
			}

			result += '
';
		});

		return result;
	}

	function flatList(level, parent) {
		var result = '';

		prepareQuery(parent).forEach(function(cat, i) {
			if (i || level) result += separator;

			result += '';
			result += transform ? transform(cat.name) : cat.name;

			if (showCount) {
				result += '' + cat.length +
					'';
			}

			result += '';

			if (!depth || level + 1 < depth) {
				result += flatList(level + 1, cat._id);
			}
		});

		return result;
	}

	if (style === 'list') {
		result += '
' + hierarchicalList(0) +
			'
';
	} else {
		result += flatList(0);
	}

	return result;
});
<|endoftext|>


<commit_before>var express = require('express')
var router = express.Router()

var QUERIES = [
  "_id", "department", "division", "campus", "term", "section",
  "term", "postrequisite", "tutorials", "breadth", "time", "instructor",
  "location", "size", "rating"
]

var courseSchema = new mongoose.Schema({
  course_id: String,
  code: String,
  name: String,
  description: String,
  division: String,
  prerequisites: String,
  exlusions: String,
  course_level: String,
  breadth: Array,
  campus: String,
  term: String,
  apsc_elec: String,
  meeting_sections: Array
})
var courses = new mongoose.model("courses", courseSchema)

router.get('/', function(req, res) {

  var query = req.query
  var clean = true
  var keys = []

  for (var key in query) {
    if (QUERIES.indexOf(key.toLowerCase()) < 0) {
      clean = false
    }
    keys.push(key)
  }

  var response = [];

  if (!clean) {
    res.send("yo")
  } else {
    for (var i = 0; i < keys.length; i++) {
      var key = keys[i].toLowerCase()
      var quer = query[key]
      if (key = "_id") {
        response.push(getIdQuery(quer))
      }
    }
  }

})

function getIdQuery(key, quer) {
  return courses.find({
    key: quer
  })
}

module.exports = router
<commit_msg>schema COOL<commit_after>var express = require('express')
var router = express.Router()

var QUERIES = [
  "_id", "department", "division", "campus", "term", "section",
  "term", "postrequisite", "tutorials", "breadth", "time", "instructor",
  "location", "size", "rating"
]

var timesSchema = new mongoose.Schema({
  day: String,
  start: String,
  end: String,
  location: String
})

var meetingSchema = new mongoose.Schema({
  lectures: [sectionSchema],
  tutorials: [sectionSchema],
  practicals: [sectionSchema]
})

var courseSchema = new mongoose.Schema({
  course_id: String,
  code: String,
  name: String,
  description: String,
  division: String,
  prerequisites: String,
  exlusions: String,
  course_level: String,
  breadth: [Number],
  campus: String,
  term: String,
  apsc_elec: String,
  meeting_sections: [meetingSchema]
})

var courses = new mongoose.model("courses", courseSchema)

router.get('/', function(req, res) {

  var query = req.query
  var clean = true
  var keys = []

  for (var key in query) {
    if (QUERIES.indexOf(key.toLowerCase()) < 0) {
      clean = false
    }
    keys.push(key)
  }

  var response = [];

  if (!clean) {
    res.send("yo")
  } else {
    for (var i = 0; i < keys.length; i++) {
      var key = keys[i].toLowerCase()
      var quer = query[key]
      if (key = "_id") {
        response.push(getIdQuery(quer))
      }
    }
  }

})

function getIdQuery(key, quer) {
  return courses.find({
    key: quer
  })
}

module.exports = router
<|endoftext|>


<commit_before>'use_strict';

const express  = require('express');
const router   = express.Router();
const pg       = require('pg').native;
const moment   = require('moment');
const _        = require('underscore');

const PG_URL = process.env.DATABASE_URL;
const client = new pg.Client(PG_URL);

client.connect(function(err) {
  if (err) console.error(err);

  // GET: list of all courses
  router.get('/', function(req, res, next) {
    const query = client.query('SELECT title, abbr FROM course');
    query.on('end', function(result) {
      const data = result.rows;

      res.json(data);
    });
  });

  // GET: Lookup a course by abbreviation
  router.get('/:abbr', function(req, res, next) {
    const sql = 'SELECT * FROM course ' +
                'LEFT JOIN section ' +
                'ON course.id = section.course_id ' +
                'WHERE course.abbr = $1';

    const query = client.query({
      text: sql,
      values: [req.params.abbr],
      name: 'course join section',
    });

    query.on('end', function(result) {
      const data = result.rows;

      var jsonResponse = {
        title: data[0].title,
        abbr: data[0].abbr,
        credits: data[0].credits,
        description: data[0].description,
        sections: [ ],
      };

      // Disabling JSCS so it wont complain about database column names
      // jscs:disable
      data.forEach(function(section, index, array) {
        // Make modifications to section data here
        if (section.days) {
          const days = section.days
          .toString()
          .replace(',', '');
        }
        const session = section.session === 'null' ? '' : section.session;
        const startDate = moment(section.start_date)
        .format('YYYY-MM-DD');
        const endDate = moment(section.endDate)
        .format('YYYY-MM-DD');

        jsonResponse.sections[index] = {
          term: section.term,
          startDate: startDate,
          endDate: endDate,
          session: session,
          crn: section.crn,
          sectionNumber: section.section,
          credits: section.credits,
          instructor: section.instructor,
          days: days,
          startTime: section.start_time,
          endTime: section.end_time,
          location: section.location,
          campus: section.campus,
          type: section.type,
          status: section.status,
          enrollmentCap: section.cap,
          enrolled: section.enrolled,
          waitlisted: section.wl_current,
          waitlistCap: section.wl_cap,
          fees: section.fees,
          restrictions: section.restrictions,
          comments: section.comments,
        };
      });
      // jscs:enable

      res.json(jsonResponse);
    });
  });
});

module.exports = router;
<commit_msg>Added comments<commit_after>// courses.js

// Specify strict mode for 'secure' code
'use_strict';

// Import dependencies and initilize global constants

// Web framework tools
const express  = require('express');
const router   = express.Router();

// PostgreSQL client library for Node.js
const pg       = require('pg').native;

// Library for date formatting
const moment   = require('moment');

// What does this do?
const _        = require('underscore');

// PostgreSQL URL and client
const PG_URL = process.env.DATABASE_URL;
const client = new pg.Client(PG_URL);

// =============================================================================
// MIDDLEWARE FOR ALL REQUESTS

client.connect(function(err) {
  if (err) console.error(err);

  // GET: list of all courses
  router.get('/', function(req, res, next) {
    const query = client.query('SELECT title, abbr FROM course');
    query.on('end', function(result) {
      const data = result.rows;

      res.json(data);
    });
  });

  // GET: Lookup a course by abbreviation
  router.get('/:abbr', function(req, res, next) {
    const sql = 'SELECT * FROM course ' +
                'LEFT JOIN section ' +
                'ON course.id = section.course_id ' +
                'WHERE course.abbr = $1';

    const query = client.query({
      text: sql,
      values: [req.params.abbr],
      name: 'course join section',
    });

    query.on('end', function(result) {
      const data = result.rows;

      var jsonResponse = {
        title: data[0].title,
        abbr: data[0].abbr,
        credits: data[0].credits,
        description: data[0].description,
        sections: [ ],
      };

      // Disabling JSCS so it wont complain about database column names
      // jscs:disable
      data.forEach(function(section, index, array) {
        // Make modifications to section data here
        if (section.days) {
          const days = section.days
          .toString()
          .replace(',', '');
        }
        const session = section.session === 'null' ? '' : section.session;
        const startDate = moment(section.start_date)
        .format('YYYY-MM-DD');
        const endDate = moment(section.endDate)
        .format('YYYY-MM-DD');

        jsonResponse.sections[index] = {
          term: section.term,
          startDate: startDate,
          endDate: endDate,
          session: session,
          crn: section.crn,
          sectionNumber: section.section,
          credits: section.credits,
          instructor: section.instructor,
          days: days,
          startTime: section.start_time,
          endTime: section.end_time,
          location: section.location,
          campus: section.campus,
          type: section.type,
          status: section.status,
          enrollmentCap: section.cap,
          enrolled: section.enrolled,
          waitlisted: section.wl_current,
          waitlistCap: section.wl_cap,
          fees: section.fees,
          restrictions: section.restrictions,
          comments: section.comments,
        };
      });
      // jscs:enable

      res.json(jsonResponse);
    });
  });
});

module.exports = router;
<|endoftext|>


<commit_before>const Promise = require("bluebird");
const Redis = require("ioredis");
const lockingCache = require("locking-cache");
const R = require("ramda");
const request = require("request-promise");

const Hashtag = require("../models/Hashtag");
const bookshelf = require("../db/bookshelf_init");

const FORGETTABLE_URL =
  process.env.FORGETTABLE_URL || "http://forgettable:8080";
const REDIS_URL = process.env.REDIS_URL || "redis://redis/";

const redis = new Redis(REDIS_URL);

const lockedFetch = lockingCache({
  maxAge: 1000 * 20
});

function getUserStats(hashtag) {
  const { knex } = bookshelf;

  const subquery = knex("changesets_hashtags")
    .join("hashtags", "hashtags.id", "changesets_hashtags.hashtag_id")
    .select("changeset_id")
    .where("hashtags.hashtag", hashtag);

  return knex
    .select(
      "user_id",
      "name",
      knex.raw("COUNT(*) as changesets"),
      knex.raw("SUM(road_km_mod + road_km_add) as roads"),
      knex.raw("SUM(building_count_add + building_count_mod) as buildings"),
      knex.raw(
        `SUM(building_count_add + building_count_mod +
                          road_count_add + road_count_mod +
                          waterway_count_add + poi_count_add) as edits`
      ),
      knex.raw("MAX(changesets.created_at) as created_at")
    )
    .from("changesets")
    .join("users", "changesets.user_id", "users.id")
    .where("changesets.id", "in", subquery)
    .groupBy("name", "user_id")
    .then(rows =>
      R.map(
        row => ({
          name: row.name,
          user_id: row.user_id,
          edits: Number(row.edits),
          changesets: Number(row.changesets),
          roads: Number(Number(row.roads).toFixed(3)),
          buildings: parseInt(row.buildings, 10),
          created_at: row.created_at
        }),
        rows
      )
    );
}

const getCachedUserStats = lockedFetch((hashtag, lock) =>
  lock(`user-stats:${hashtag}`, unlock =>
    getUserStats(hashtag)
      .then(stats => unlock(null, stats))
      .catch(err => unlock(err))
  )
);

module.exports = [
  {
    method: "GET",
    path: "/hashtags/{id}/users",
    handler: (req, res) => getCachedUserStats(req.params.id, res)
  },
  {
    method: "GET",
    path: "/hashtags/{id}/map",
    handler: (req, res) =>
      redis
        .lrange(`osmstats::map::#${R.toLower(req.params.id)}`, 0, -1)
        .then(elements => elements.map(JSON.parse))
        .then(res)
        .catch(res)
  },
  {
    method: "GET",
    path: "/hashtags",
    handler: (req, res) =>
      Promise.all([
        Hashtag.fetchAll({ columns: ["hashtag"] }),
        request(`${FORGETTABLE_URL}/nmostprobable?distribution=hashtags&N=5`)
      ])
        .then(results => {
          const hashtags = results[0];
          const distribution = JSON.parse(results[1]);
          const serialized = hashtags.toJSON();
          const hashtaglist = R.map(R.prop("hashtag"), serialized);
          return {
            hashtags: hashtaglist,
            trending: R.map(R.prop("bin"), distribution.data.data)
          };
        })
        .then(res)
        .catch(res)
  }
];
<commit_msg>Limit user counts to 10k<commit_after>const Promise = require("bluebird");
const Redis = require("ioredis");
const lockingCache = require("locking-cache");
const R = require("ramda");
const request = require("request-promise");

const Hashtag = require("../models/Hashtag");
const bookshelf = require("../db/bookshelf_init");

const FORGETTABLE_URL =
  process.env.FORGETTABLE_URL || "http://forgettable:8080";
const REDIS_URL = process.env.REDIS_URL || "redis://redis/";

const redis = new Redis(REDIS_URL);

const lockedFetch = lockingCache({
  maxAge: 1000 * 20
});

function getUserStats(hashtag) {
  const { knex } = bookshelf;

  const subquery = knex("changesets_hashtags")
    .join("hashtags", "hashtags.id", "changesets_hashtags.hashtag_id")
    .select("changeset_id")
    .where("hashtags.hashtag", hashtag);

  return knex
    .select(
      "user_id",
      "name",
      knex.raw("COUNT(*) as changesets"),
      knex.raw("SUM(road_km_mod + road_km_add) as roads"),
      knex.raw("SUM(building_count_add + building_count_mod) as buildings"),
      knex.raw(
        `SUM(building_count_add + building_count_mod +
                          road_count_add + road_count_mod +
                          waterway_count_add + poi_count_add) as edits`
      ),
      knex.raw("MAX(changesets.created_at) as created_at")
    )
    .from("changesets")
    .join("users", "changesets.user_id", "users.id")
    .where("changesets.id", "in", subquery)
    .groupBy("name", "user_id")
    .limit(10000)
    .then(rows =>
      R.map(
        row => ({
          name: row.name,
          user_id: row.user_id,
          edits: Number(row.edits),
          changesets: Number(row.changesets),
          roads: Number(Number(row.roads).toFixed(3)),
          buildings: parseInt(row.buildings, 10),
          created_at: row.created_at
        }),
        rows
      )
    );
}

const getCachedUserStats = lockedFetch((hashtag, lock) =>
  lock(`user-stats:${hashtag}`, unlock =>
    getUserStats(hashtag)
      .then(stats => unlock(null, stats))
      .catch(err => unlock(err))
  )
);

module.exports = [
  {
    method: "GET",
    path: "/hashtags/{id}/users",
    handler: (req, res) => getCachedUserStats(req.params.id, res)
  },
  {
    method: "GET",
    path: "/hashtags/{id}/map",
    handler: (req, res) =>
      redis
        .lrange(`osmstats::map::#${R.toLower(req.params.id)}`, 0, -1)
        .then(elements => elements.map(JSON.parse))
        .then(res)
        .catch(res)
  },
  {
    method: "GET",
    path: "/hashtags",
    handler: (req, res) =>
      Promise.all([
        Hashtag.fetchAll({ columns: ["hashtag"] }),
        request(`${FORGETTABLE_URL}/nmostprobable?distribution=hashtags&N=5`)
      ])
        .then(results => {
          const hashtags = results[0];
          const distribution = JSON.parse(results[1]);
          const serialized = hashtags.toJSON();
          const hashtaglist = R.map(R.prop("hashtag"), serialized);
          return {
            hashtags: hashtaglist,
            trending: R.map(R.prop("bin"), distribution.data.data)
          };
        })
        .then(res)
        .catch(res)
  }
];
<|endoftext|>


<commit_before>const express = require('express')
const { getListing } = require('./api/listing')
const { handleError, ExpressRedirectError } = require('../utils/errors')

module.exports = serverOpts => {
  const error404 = (req, res) => handleError(serverOpts, res, new ExpressRedirectError('Nobody here but is chickens.', 404))
  const app = express()
  app.get(['/', '/size-', '/size-:size'], error404)
  app.get('/size-:size/*', (req, res) => {
    const page = parseInt(req.query.page || '1', 10)
    return getListing({
      webRoot: app.path(),
      basePath: serverOpts.baseDir,
      directory: req.params['0'],
      page: page,
      pageSize: 50
    })
      .then(data => {
        data.size = req.params.size || '300'
        return data
      })
      .then(data => res.render('listing', data))
      .catch(e => handleError(serverOpts, res, e))
  })
  app.get(['/*', '/size-/*'], (req, res) => {
    let newPath = `/listing/size-300/${req.params[0]}`
    res.redirect(302, newPath)
  })
  return app
}
<commit_msg>force page parameter to be in range<commit_after>const express = require('express')
const { getListing } = require('./api/listing')
const { handleError, ExpressRedirectError } = require('../utils/errors')

module.exports = serverOpts => {
  const error404 = (req, res) => handleError(serverOpts, res, new ExpressRedirectError('Nobody here but is chickens.', 404))
  const app = express()
  app.get(['/', '/size-', '/size-:size'], error404)
  app.get('/size-:size/*', (req, res) => {
    const page = parseInt(req.query.page || '1', 10)
    return getListing({
        webRoot: app.path(),
        basePath: serverOpts.baseDir,
        directory: req.params['0'],
        page: page,
        pageSize: 50
      })
      .then(data => {
        data.size = req.params.size || '300'
        console.log(data.pages.current, page)
        if (data.pages.current !== page) {
          const dest = [app.path(), `size-${data.size}`, `${req.params['0']}?page=${data.pages.current}`]
          throw new ExpressRedirectError(dest.join('/'))
        }
        return data
      })
      .then(data => res.render('listing', data))
      .catch(e => handleError(serverOpts, res, e))
  })
  app.get(['/*', '/size-/*'], (req, res) => {
    let newPath = `/listing/size-300/${req.params[0]}`
    res.redirect(302, newPath)
  })
  return app
}
<|endoftext|>


<commit_before>// GATT Device Information Service UUIDs
var DEVICE_INFO_SERVICE_UUID           = '0000180a-0000-1000-8000-00805f9b34fb';
var MANUFACTURER_NAME_STRING_CHRC_UUID = '00002a29-0000-1000-8000-00805f9b34fb';
var SERIAL_NUMBER_STRING_CHRC_UUID     = '00002a25-0000-1000-8000-00805f9b34fb';
var HARDWARE_REVISION_STRING_CHRC_UUID = '00002a27-0000-1000-8000-00805f9b34fb';
var FIRMWARE_REVISION_STRING_CHRC_UUID = '00002a26-0000-1000-8000-00805f9b34fb';
var SOFTWARE_REVISION_STRING_CHRC_UUID = '00002a28-0000-1000-8000-00805f9b34fb';
var PNP_ID_CHRC_UUID                   = '00002a50-0000-1000-8000-00805f9b34fb';

// The currently displayed service and characteristics.
var deviceInfoService;
var characteristicMap = {};

// A mapping from device addresses to device names for found devices that expose
// a Device Information service.
var deviceInfoDevicesMap = {};

/**
 * Updates the UI based on the selected service.
 * @param {chrome.bluetoothLowEnergy.Service} service The selected GATT service
 *     to display.
 */
function selectService(service) {
  // Hide or show the appropriate elements based on whether or not
  // |serviceId| is undefined.
  UI.getInstance().resetState(!service);

  deviceInfoService = service;
  characteristicMap = {};

  if (!service) {
    console.log('No service selected.');
    return;
  }

  console.log('GATT service selected: ' + service.instanceId);

  // Get the characteristics of the selected service.
  chrome.bluetoothLowEnergy.getCharacteristics(service.instanceId,
                                               function (chrcs) {
    if (chrome.runtime.lastError) {
      console.log(chrome.runtime.lastError.message);
      return;
    }

    // Make sure that the same service is still selected.
    if (service.instanceId != deviceInfoService.instanceId)
      return;

    if (chrcs.length == 0) {
      console.log('Service has no characteristics: ' + service.instanceId);
      return;
    }

    chrcs.forEach(function (chrc) {
      var fieldId;
      var valueDisplayFunction = UI.getInstance().setStringValue;

      if (chrc.uuid == MANUFACTURER_NAME_STRING_CHRC_UUID) {
        console.log('Setting Manufacturer Name String Characteristic: ' +
                    chrc.instanceId);
        fieldId = 'manufacturer-name-string';
      } else if (chrc.uuid == SERIAL_NUMBER_STRING_CHRC_UUID) {
        console.log('Setting Serial Number String Characteristic: ' +
                    chrc.instanceId);
        fieldId = 'serial-number-string';
      } else if (chrc.uuid == HARDWARE_REVISION_STRING_CHRC_UUID) {
        console.log('Setting Hardware Revision String Characteristic: ' +
                    chrc.instanceId);
        fieldId = 'hardware-revision-string';
      } else if (chrc.uuid == FIRMWARE_REVISION_STRING_CHRC_UUID) {
        console.log('Setting Firmware Revision String Characteristic: ' +
                    chrc.instanceId);
        fieldId = 'firmware-revision-string';
      } else if (chrc.uuid == SOFTWARE_REVISION_STRING_CHRC_UUID) {
        console.log('Setting Software Revision String Characteristic: ' +
                    chrc.instanceId);
        fieldId = 'software-revision-string';
      } else if (chrc.uuid == PNP_ID_CHRC_UUID) {
        console.log('Setting PnP ID Characteristic: ' + chrc.instanceId);
        fieldId = 'pnp-id';
        valueDisplayFunction = UI.getInstance().setPnpIdValue;
      }

      if (fieldId === undefined) {
        console.log('Ignoring characteristic "' + chrc.instanceId +
                    '" with UUID ' + chrc.uuid);
        return;
      }

      characteristicMap[fieldId] = chrc;

      // Read the value of the characteristic and store it.
      chrome.bluetoothLowEnergy.readCharacteristicValue(chrc.instanceId,
                                                        function (readChrc) {
        if (chrome.runtime.lastError) {
          console.log(chrome.runtime.lastError.message);
          return;
        }

        // Make sure that the same characteristic is still selected.
        if (!characteristicMap.hasOwnProperty(fieldId) ||
            characteristicMap[fieldId].instanceId != readChrc.instanceId)
          return;

        characteristicMap[fieldId] = readChrc;
        valueDisplayFunction(fieldId, readChrc.value);
      });
    });
  });
}

/**
 * This is the entry point of the application. Initialize UI state and set up
 * the relevant Bluetooth Low Energy event listeners.
 */
function main() {
  // Set up the UI to look like no device was initially selected.
  selectService(undefined);

  // Request information about the local Bluetooth adapter to be displayed in
  // the UI.
  var updateAdapterState = function(adapterState) {
    UI.getInstance().setAdapterState(adapterState.address, adapterState.name);
  };

  chrome.bluetooth.getAdapterState(function (adapterState) {
    if (chrome.runtime.lastError)
      console.log(chrome.runtime.lastError.message);

    updateAdapterState(adapterState);
  });

  chrome.bluetooth.onAdapterStateChanged.addListener(updateAdapterState);

  var storeDevice = function(deviceAddress, device) {
    var resetUI = false;
    if (device == null) {
      delete deviceInfoDevicesMap[deviceAddress];
      resetUI = true;
    } else {
      deviceInfoDevicesMap[deviceAddress] =
          (device.name ? device.name : device.address);
    }

    // Update the selector UI with the new device list.
    UI.getInstance().updateDeviceSelector(deviceInfoDevicesMap, resetUI);
  };

  // Initialize |deviceInfoDevicesMap|.
  chrome.bluetooth.getDevices(function (devices) {
    if (chrome.runtime.lastError) {
      console.log(chrome.runtime.lastError.message);
    }

    if (devices) {
      devices.forEach(function (device) {
        // See if the device exposes a Device Information service.
        chrome.bluetoothLowEnergy.getServices(device.address,
                                              function (services) {
          if (chrome.runtime.lastError) {
            console.log(chrome.runtime.lastError.message);
            return;
          }

          if (!services)
            return;

          var found = false;
          services.forEach(function (service) {
            if (service.uuid == DEVICE_INFO_SERVICE_UUID) {
              console.log('Found Device Information service!');
              found = true;
            }
          });

          if (!found)
            return;

          console.log('Found device with Device Information service: ' +
                      device.address);
          storeDevice(device.address, device);
        });
      });
    }
  });

  // Set up the device selector.
  var deviceSelector = document.getElementById('device-selector');
  deviceSelector.onchange = function () {
    var selectedValue = deviceSelector[deviceSelector.selectedIndex].value;

    // If |selectedValue| is empty, unselect everything.
    if (!selectedValue) {
      selectService(undefined);
      return;
    }

    // Request all GATT services of the selected device to see if it still has
    // a Device Information service and pick the first one to display.
    chrome.bluetoothLowEnergy.getServices(selectedValue, function (services) {
      if (chrome.runtime.lastError) {
        console.log(chrome.runtime.lastError.message);
        selectService(undefined);
        return;
      }

      var foundService = undefined;
      services.forEach(function (service) {
        if (service.uuid == DEVICE_INFO_SERVICE_UUID)
          foundService = service;
      });

      selectService(foundService);
    });
  };

  // Track GATT services as they are added.
  chrome.bluetoothLowEnergy.onServiceAdded.addListener(function (service) {
    // Ignore, if the service is not a Device Information service.
    if (service.uuid != DEVICE_INFO_SERVICE_UUID)
      return;

    // Add the device of the service to the device map and update the UI.
    console.log('New Device Information service added: ' + service.instanceId);
    if (deviceInfoDevicesMap.hasOwnProperty(service.deviceAddress))
      return;

    // Looks like it's a brand new device. Get information about the device so
    // that we can display the device name in the drop-down menu.
    chrome.bluetooth.getDevice(service.deviceAddress, function (device) {
      if (chrome.runtime.lastError) {
        console.log(chrome.runtime.lastError.message);
        return;
      }

      storeDevice(device.address, device);
    });
  });

  // Track GATT services as they are removed.
  chrome.bluetoothLowEnergy.onServiceRemoved.addListener(function (service) {
    // Ignore, if the service is not a Device Information service.
    if (service.uuid != DEVICE_INFO_SERVICE_UUID)
      return;

    // See if this is the currently selected service. If so, unselect it.
    console.log('Device Information service removed: ' + service.instanceId);
    var selectedRemoved = false;
    if (deviceInfoService && deviceInfoService.instanceId == service.instanceId) {
      console.log('The selected service disappeared!');
      selectService(undefined);
      selectedRemoved = true;
    }

    // Remove the associated device from the map only if it has no other Device
    // Information services exposed (this will usually be the case)
    if (!deviceInfoDevicesMap.hasOwnProperty(service.deviceAddress))
      return;

    chrome.bluetooth.getDevice(service.deviceAddress, function (device) {
      if (chrome.runtime.lastError) {
        console.log(chrome.runtime.lastError.message);
        return;
      }

      chrome.bluetoothLowEnergy.getServices(device.address,
                                            function (services) {
        if (chrome.runtime.lastError) {
          // Error obtaining services. Remove the device from the map.
          console.log(chrome.runtime.lastError.message);
          storeDevice(device.address, null);
          return;
        }

        var found = false;
        for (var i = 0; i < services.length; i++) {
          if (services[i].uuid == DEVICE_INFO_SERVICE_UUID) {
            found = true;
            break;
          }
        }

        if (found)
          return;

        console.log('Removing device: ' + device.address);
        storeDevice(device.address, null);
      });
    });
  });

  // Track GATT services as they change.
  chrome.bluetoothLowEnergy.onServiceChanged.addListener(function (service) {
    // This only matters if the selected service changed.
    if (!deviceInfoService || service.instanceId != deviceInfoService.instanceId)
      return;

    console.log('The selected service has changed');

    // Reselect the service to force an updated.
    selectService(service);
  });
}

document.addEventListener('DOMContentLoaded', main);
<commit_msg>Factured the bluetooth logic into a module.<commit_after>var main = (function() {
  // GATT Device Information Service UUIDs
  var DEVICE_INFO_SERVICE_UUID      = '0000180a-0000-1000-8000-00805f9b34fb';
  var MANUFACTURER_NAME_STRING_UUID = '00002a29-0000-1000-8000-00805f9b34fb';
  var SERIAL_NUMBER_STRING_UUID     = '00002a25-0000-1000-8000-00805f9b34fb';
  var HARDWARE_REVISION_STRING_UUID = '00002a27-0000-1000-8000-00805f9b34fb';
  var FIRMWARE_REVISION_STRING_UUID = '00002a26-0000-1000-8000-00805f9b34fb';
  var SOFTWARE_REVISION_STRING_UUID = '00002a28-0000-1000-8000-00805f9b34fb';
  var PNP_ID_UUID                   = '00002a50-0000-1000-8000-00805f9b34fb';

  function DeviceInfoDemo() {
    // A mapping from device addresses to device names for found devices that
    // expose a Battery service.
    this.deviceMap_ = {};

    // The currently selected service and its characteristics.
    this.service_ = null;
    this.chrcMap_ = {};
  }

  /**
   * Sets up the UI for the given service.
   */
  DeviceInfoDemo.prototype.selectService = function(service) {
    // Hide or show the appropriate elements based on whether or not
    // |serviceId| is undefined.
    UI.getInstance().resetState(!service);

    this.service_ = service;
    this.chrcMap_ = {};

    if (!service) {
      console.log('No service selected.');
      return;
    }

    console.log('GATT service selected: ' + service.instanceId);

    // Get the characteristics of the selected service.
    var self = this;
    chrome.bluetoothLowEnergy.getCharacteristics(service.instanceId,
                                                 function (chrcs) {
      if (chrome.runtime.lastError) {
        console.log(chrome.runtime.lastError.message);
        return;
      }

      // Make sure that the same service is still selected.
      if (service.instanceId != self.service_.instanceId)
        return;

      if (chrcs.length == 0) {
        console.log('Service has no characteristics: ' + service.instanceId);
        return;
      }

      chrcs.forEach(function (chrc) {
        var fieldId;
        var valueDisplayFunction = UI.getInstance().setStringValue;

        if (chrc.uuid == MANUFACTURER_NAME_STRING_UUID) {
          console.log('Setting Manufacturer Name String Characteristic: ' +
                      chrc.instanceId);
          fieldId = 'manufacturer-name-string';
        } else if (chrc.uuid == SERIAL_NUMBER_STRING_UUID) {
          console.log('Setting Serial Number String Characteristic: ' +
                      chrc.instanceId);
          fieldId = 'serial-number-string';
        } else if (chrc.uuid == HARDWARE_REVISION_STRING_UUID) {
          console.log('Setting Hardware Revision String Characteristic: ' +
                      chrc.instanceId);
          fieldId = 'hardware-revision-string';
        } else if (chrc.uuid == FIRMWARE_REVISION_STRING_UUID) {
          console.log('Setting Firmware Revision String Characteristic: ' +
                      chrc.instanceId);
          fieldId = 'firmware-revision-string';
        } else if (chrc.uuid == SOFTWARE_REVISION_STRING_UUID) {
          console.log('Setting Software Revision String Characteristic: ' +
                      chrc.instanceId);
          fieldId = 'software-revision-string';
        } else if (chrc.uuid == PNP_ID_UUID) {
          console.log('Setting PnP ID Characteristic: ' + chrc.instanceId);
          fieldId = 'pnp-id';
          valueDisplayFunction = UI.getInstance().setPnpIdValue;
        }

        if (fieldId === undefined) {
          console.log('Ignoring characteristic "' + chrc.instanceId +
                      '" with UUID ' + chrc.uuid);
          return;
        }

        self.chrcMap_[fieldId] = chrc;

        // Read the value of the characteristic and store it.
        chrome.bluetoothLowEnergy.readCharacteristicValue(chrc.instanceId,
                                                          function (readChrc) {
          if (chrome.runtime.lastError) {
            console.log(chrome.runtime.lastError.message);
            return;
          }

          // Make sure that the same characteristic is still selected.
          if (!self.chrcMap_.hasOwnProperty(fieldId) ||
              self.chrcMap_[fieldId].instanceId != readChrc.instanceId)
            return;

          self.chrcMap_[fieldId] = readChrc;
          valueDisplayFunction(fieldId, readChrc.value);
        });
      });
    });
  };

  DeviceInfoDemo.prototype.init = function() {
    // Set up the UI to look like no device was initially selected.
    this.selectService(null);

    // Request information about the local Bluetooth adapter to be displayed in
    // the UI.
    var updateAdapterState = function(adapterState) {
      UI.getInstance().setAdapterState(adapterState.address, adapterState.name);
    };

    chrome.bluetooth.getAdapterState(function (adapterState) {
      if (chrome.runtime.lastError)
        console.log(chrome.runtime.lastError.message);

      updateAdapterState(adapterState);
    });

    chrome.bluetooth.onAdapterStateChanged.addListener(updateAdapterState);

    // Store the |this| to be used by API callbacks below.
    var self = this;

    // Helper functions used below.
    var isKnownDevice = function(deviceAddress) {
      return self.deviceMap_.hasOwnProperty(deviceAddress);
    };

    var storeDevice = function(deviceAddress, device) {
      var resetUI = false;
      if (device == null) {
        delete self.deviceMap_[deviceAddress];
        resetUI = true;
      } else {
        self.deviceMap_[deviceAddress] =
            (device.name ? device.name : device.address);
      }

      // Update the selector UI with the new device list.
      UI.getInstance().updateDeviceSelector(self.deviceMap_, resetUI);
    };

    // Initialize the device map.
    chrome.bluetooth.getDevices(function (devices) {
      if (chrome.runtime.lastError) {
        console.log(chrome.runtime.lastError.message);
      }

      if (devices) {
        devices.forEach(function (device) {
          // See if the device exposes a Device Information service.
          chrome.bluetoothLowEnergy.getServices(device.address,
                                                function (services) {
            if (chrome.runtime.lastError) {
              console.log(chrome.runtime.lastError.message);
              return;
            }

            if (!services)
              return;

            var found = false;
            services.forEach(function (service) {
              if (service.uuid == DEVICE_INFO_SERVICE_UUID) {
                console.log('Found Device Information service!');
                found = true;
              }
            });

            if (!found)
              return;

            console.log('Found device with Device Information service: ' +
                        device.address);
            storeDevice(device.address, device);
          });
        });
      }
    });

    // Set up the device selector.
    UI.getInstance().setDeviceSelectionHandler(function(selectedValue) {
      // If |selectedValue| is empty, unselect everything.
      if (!selectedValue) {
        self.selectService(null);
        return;
      }

      // Request all GATT services of the selected device to see if it still has
      // a Device Information service and pick the first one to display.
      chrome.bluetoothLowEnergy.getServices(selectedValue, function (services) {
        if (chrome.runtime.lastError) {
          console.log(chrome.runtime.lastError.message);
          self.selectService(null);
          return;
        }

        var foundService = null;
        services.forEach(function (service) {
          if (service.uuid == DEVICE_INFO_SERVICE_UUID)
            foundService = service;
        });

        self.selectService(foundService);
      });
    });

    // Track GATT services as they are added.
    chrome.bluetoothLowEnergy.onServiceAdded.addListener(function (service) {
      // Ignore, if the service is not a Device Information service.
      if (service.uuid != DEVICE_INFO_SERVICE_UUID)
        return;

      // Add the device of the service to the device map and update the UI.
      console.log('New Device Information service added: ' + service.instanceId);
      if (isKnownDevice(service.deviceAddress))
        return;

      // Looks like it's a brand new device. Get information about the device so
      // that we can display the device name in the drop-down menu.
      chrome.bluetooth.getDevice(service.deviceAddress, function (device) {
        if (chrome.runtime.lastError) {
          console.log(chrome.runtime.lastError.message);
          return;
        }

        storeDevice(device.address, device);
      });
    });

    // Track GATT services as they are removed.
    chrome.bluetoothLowEnergy.onServiceRemoved.addListener(function (service) {
      // Ignore, if the service is not a Device Information service.
      if (service.uuid != DEVICE_INFO_SERVICE_UUID)
        return;

      // See if this is the currently selected service. If so, unselect it.
      console.log('Device Information service removed: ' + service.instanceId);
      var selectedRemoved = false;
      if (self.service_ && self.service_.instanceId == service.instanceId) {
        console.log('The selected service disappeared!');
        self.selectService(null);
        selectedRemoved = true;
      }

      // Remove the associated device from the map only if it has no other Device
      // Information services exposed (this will usually be the case)
      if (!isKnownDevice(service.deviceAddress))
        return;

      chrome.bluetooth.getDevice(service.deviceAddress, function (device) {
        if (chrome.runtime.lastError) {
          console.log(chrome.runtime.lastError.message);
          return;
        }

        chrome.bluetoothLowEnergy.getServices(device.address,
                                              function (services) {
          if (chrome.runtime.lastError) {
            // Error obtaining services. Remove the device from the map.
            console.log(chrome.runtime.lastError.message);
            storeDevice(device.address, null);
            return;
          }

          var found = false;
          for (var i = 0; i < services.length; i++) {
            if (services[i].uuid == DEVICE_INFO_SERVICE_UUID) {
              found = true;
              break;
            }
          }

          if (found)
            return;

          console.log('Removing device: ' + device.address);
          storeDevice(device.address, null);
        });
      });
    });

    // Track GATT services as they change.
    chrome.bluetoothLowEnergy.onServiceChanged.addListener(function (service) {
      // This only matters if the selected service changed.
      if (!self.service_ || service.instanceId != self.service_.instanceId)
        return;

      console.log('The selected service has changed');

      // Reselect the service to force an updated.
      self.selectService(service);
    });
  };

  return {
    DeviceInfoDemo: DeviceInfoDemo
  };
})();

document.addEventListener('DOMContentLoaded', function() {
  var demo = new main.DeviceInfoDemo();
  demo.init();
});
<|endoftext|>


<commit_before>var palettes = require('../palettes.json');

exports.randomPalette = function(req, res) {
	// get a random palette from the top ones
	var randomPalette = palettes[Math.floor(palettes.length * Math.random())];
	res.json( palettes, {randomPalette});
	return {randomPalette};
}<commit_msg>test 2<commit_after>var palettes = require('../palettes.json');

exports.randomPalette = function(req, res) {
	// get a random palette from the top ones
	var randomPalette = palettes[Math.floor(palettes.length * Math.random())];
	res.json(randomPalette);
	return randomPalette;
}<|endoftext|>


<commit_before>var npm = require('npm');
var _ = require('lodash');
var getPluginsMetaData = require('../lib/getPluginsMetaData');
var subdevices = require('../lib/subdevices');

exports.plugins = function(req, res){
  getPluginsMetaData()
  .then(function(plugins){
    res.render('plugins', { title: 'Skynet Gateway Plugins', plugins: plugins });
  })
  .otherwise(function(err){
    res.send(500, err);
  });
};

exports.subdevices = function(req, res){
  subdevices.getRecords()
  .then(function(instances){
    res.render('subdevices', { title: 'Skynet Gateway Plugins', subdevices: instances });
  })
  .otherwise(function(err){
    res.send(500, err);
  });
};
<commit_msg>fix title<commit_after>var npm = require('npm');
var _ = require('lodash');
var getPluginsMetaData = require('../lib/getPluginsMetaData');
var subdevices = require('../lib/subdevices');

exports.plugins = function(req, res){
  getPluginsMetaData()
  .then(function(plugins){
    res.render('plugins', { title: 'Skynet Gateway Plugins', plugins: plugins });
  })
  .otherwise(function(err){
    res.send(500, err);
  });
};

exports.subdevices = function(req, res){
  subdevices.getRecords()
  .then(function(instances){
    res.render('subdevices', { title: 'Skynet Gateway Sub-devices', subdevices: instances });
  })
  .otherwise(function(err){
    res.send(500, err);
  });
};
<|endoftext|>


<commit_before>const express = require('express');
const router = express.Router();

var School = require("../models/school");

//index
router.get("/schools", function (req, res){
	School.find({}, function (err, schools){
		if(err) return res.status(500).send(err);
		res.send(schools);
	});
});

//show
router.get("/schools/:id", function (req, res){
	var id = req.params.id;

	School.findById(id, function (err, school) {
 		if(err) return res.status(500).send(err);
  	if(!school) return res.status(404).send({ err: "school not found"});
  	res.send(school);
  });
});

// //create
// router.post("/schools", function (req, res){
// });

// //update
// router.put("/schools/:id", function (req, res){
// 	var id = req.params.id;
// });

// //delete
// router.delete("/teachers/:id", function (req, res){
// 	var id = req.params.id;
// });

module.exports = router;<commit_msg>[추가] school search<commit_after>const express = require('express');
const router = express.Router();

var School = require("../models/school");

//search
router.get("/schools/search", function (req, res){
  var query = {};
  var _region1 = req.query.region1;
  var _region2 = req.query.region2;

  if(_region1) query.region1 = _region1;
  if(_region2) query.region2 = _region2;

  console.log(query);

  School.find(query, function (err, schools){
    if(err){
      console.err(err);
      return res.status(500).send(err);
    }
    if(schools.length === 0) return res.status(404).send({});

    return res.send(schools);
  });
});

//index
router.get("/schools", function (req, res){
	School.find({}, function (err, schools){
		if(err){
      console.log(err);
      return res.status(500).send(err);
    }
		res.send(schools);
	});
});

//show
router.get("/schools/:id", function (req, res){
	var id = req.params.id;

	School.findById(id, function (err, school) {
 		if(err) return res.status(500).send(err);
  	if(!school) return res.status(404).send({ err: "school not found"});
  	res.send(school);
  });
});

// //create
// router.post("/schools", function (req, res){
// });

// //update
// router.put("/schools/:id", function (req, res){
// 	var id = req.params.id;
// });

// //delete
// router.delete("/teachers/:id", function (req, res){
// 	var id = req.params.id;
// });

module.exports = router;<|endoftext|>


<commit_before>import router from 'koa-router';
import render from './../utils/render';
import mixList from './../controller/mixList';
import tagModel from './../models/Tags';
import goodsModel from './../models/Goods';
import articlesModel from './../models/Articles';

let R = router();

R.get('/', function *(next) {
  let hot = yield tagModel.ranking(6);
  let goodFetch = yield goodsModel.fetch({'state.display':true});
  let articleFetch = yield articlesModel.fetch({'state.display':true});
  let list = mixList(goodFetch,articleFetch);
  yield render('index',{
    title: '首页',
    desc:'',
    hot:hot,
    list:list
  },this);
});

export default R;
<commit_msg>增加搜索条件<commit_after>import router from 'koa-router';
import render from './../utils/render';
import mixList from './../controller/mixList';
import tagModel from './../models/Tags';
import goodsModel from './../models/Goods';
import articlesModel from './../models/Articles';

let R = router();

R.get('/', function *(next) {
  let query = this.request.query;
  let search = query.keyword ? {$or:[{nickName:{$regex:regex}},{email:{$regex:regex}},{phone:{$regex:regex}}]} : {};
  let hot = yield tagModel.ranking(6);
  let goodFetch = yield goodsModel.fetch({'state.display':true});
  let articleFetch = yield articlesModel.fetch({'state.display':true});
  let list = mixList(goodFetch,articleFetch);
  yield render('index',{
    title: '首页',
    desc:'',
    hot:hot,
    list:list
  },this);
});

export default R;
<|endoftext|>


<commit_before>/**
 * @file Helper functions to deal with access rights for books.
 * @copyright This file is part of Fidus Writer.
 *
 * Copyright (C) 2013 Takuto Kojima, Johannes Wilm.
 *
 * @license This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses.
 *
 */

(function () {
    var exports = this,
    /**
  * Helper functions to deal with book access rights. TODO
  * @namespace bookaccessrightsHelpers
  */
        bookaccessrightsHelpers = {};

    bookaccessrightsHelpers.createAccessRightsDialog = function (bookIds) {
        var dialogHeader = gettext('Share your book with others');
        var book_collaborators = {}, theAccessRights, theTeamMembers, i,
                len;

        theAccessRights = window.theAccessRights;

        len = theAccessRights.length

        theTeamMembers = window.theTeamMembers;

        for (i = 0; i < len; i++) {
            if (_.include(bookIds, theAccessRights[i].book_id)) {
                if ('undefined' == typeof (book_collaborators[
                    theAccessRights[i].user_id])) {
                    book_collaborators[theAccessRights[i].user_id] =
                        theAccessRights[i];
                    book_collaborators[theAccessRights[i].user_id].count =
                        1;
                } else {
                    if (book_collaborators[theAccessRights[i].user_id].rights !=
                        theAccessRights[i].rights);
                    book_collaborators[theAccessRights[i].user_id].rights =
                        'r';
                    book_collaborators[theAccessRights[i].user_id].count +=
                        1;
                }
            }
        }
        book_collaborators = _.select(book_collaborators, function (obj) {
            return obj.count == bookIds.length;
        });

        var dialogBody = tmp_book_access_right_overview({
            'dialogHeader': dialogHeader,
            'contacts': theTeamMembers,
            'collaborators': tmp_book_collaborators({
                'collaborators': book_collaborators
            })
        });
        $('body').append(dialogBody);
        var diaButtons = {};
        diaButtons[gettext('Submit')] = function () {
            //apply the current state to server
            var collaborators = [],
                rights = [];
            $('#share-member .collaborator-tr').each(function () {
                collaborators[collaborators.length] = $(this).attr(
                    'data-id');
                rights[rights.length] = $(this).attr('data-right');
            });
            bookaccessrightsHelpers.submitAccessRight(bookIds,
                collaborators, rights);
            $(this).dialog('close');
        };
        diaButtons[gettext('Cancel')] = function () {
            $(this).dialog("close");
        }
        $('#access-rights-dialog').dialog({
            draggable: false,
            resizable: false,
            top: 10,
            width: 820,
            height: 540,
            modal: true,
            buttons: diaButtons,
            create: function () {
                var $the_dialog = $(this).closest(".ui-dialog");
                $the_dialog.find(".ui-button:first-child").addClass(
                    "fw-button fw-dark");
                $the_dialog.find(".ui-button:last").addClass(
                    "fw-button fw-orange");
            },
            close: function () {
                $('#access-rights-dialog').dialog('destroy').remove();
            }
        });
        $('.fw-checkable').bind('click', function () {
            $.setCheckableLabel($(this));
        });
        $('#add-share-member').bind('click', function () {
            var $selected_members = $(
                '#my-contacts .fw-checkable.checked');
            var selected_data = [];
            $selected_members.each(function () {
                var member_id = $(this).attr('data-id');
                var $collaborator = $('#collaborator-' + member_id);
                if (0 == $collaborator.size()) {
                    selected_data[selected_data.length] = {
                        'user_id': member_id,
                        'user_name': $(this).attr('data-name'),
                        'avatar': $(this).attr('data-avatar'),
                        'rights': 'r'
                    }
                } else if ('d' == $collaborator.attr('data-right')) {
                    $collaborator.removeClass('d').addClass('r').attr(
                        'data-right', 'r');
                }
            });
            $('#my-contacts .checkable-label.checked').removeClass(
                'checked');
            $('#share-member table tbody').append(tmp_book_collaborators({
                'collaborators': selected_data
            }));
            bookaccessrightsHelpers.collaboratorFunctionsEvent();
        });
        bookaccessrightsHelpers.collaboratorFunctionsEvent();
    };

    bookaccessrightsHelpers.collaboratorFunctionsEvent = function () {
        $('.edit-right').unbind('click');
        $('.edit-right').each(function () {
            $.addDropdownBox($(this), $(this).siblings('.fw-pulldown'));
        });
        var $spans = $(
            '.edit-right-wrapper .fw-pulldown-item, .delete-collaborator');
        $spans.unbind('click');
        $spans.bind('click', function () {
            var new_right = $(this).attr('data-right');
            $(this).closest('.collaborator-tr').attr('class',
                'collaborator-tr ' + new_right);
            $(this).closest('.collaborator-tr').attr('data-right',
                new_right);
        });
    };

    bookaccessrightsHelpers.submitAccessRight = function (books,
        collaborators, rights) {
        var post_data = {
            'books[]': books,
            'collaborators[]': collaborators,
            'rights[]': rights
        }
        $.ajax({
            url: '/book/accessright/save/',
            data: post_data,
            type: 'POST',
            dataType: 'json',
            success: function (response) {
                theAccessRights = response.access_rights;
                $.addAlert('success', gettext(
                    'Access rights have been saved'));
            },
            error: function (jqXHR, textStatus, errorThrown) {
                console.log(jqXHR.responseText);
            }
        });
    };

    exports.bookaccessrightsHelpers = bookaccessrightsHelpers;

}).call(this);<commit_msg>reenable book write access sharing<commit_after>/**
 * @file Helper functions to deal with access rights for books.
 * @copyright This file is part of Fidus Writer.
 *
 * Copyright (C) 2013 Takuto Kojima, Johannes Wilm.
 *
 * @license This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses.
 *
 */

(function () {
    var exports = this,
    /**
  * Helper functions to deal with book access rights. TODO
  * @namespace bookaccessrightsHelpers
  */
        bookaccessrightsHelpers = {};

    bookaccessrightsHelpers.createAccessRightsDialog = function (bookIds) {
        var dialogHeader = gettext('Share your book with others');
        var book_collaborators = {}, theAccessRights, theTeamMembers, i,
                len;

        theAccessRights = window.theAccessRights;

        len = theAccessRights.length

        theTeamMembers = window.theTeamMembers;

        for (i = 0; i < len; i++) {
            if (_.include(bookIds, theAccessRights[i].book_id)) {
                if ('undefined' == typeof (book_collaborators[
                    theAccessRights[i].user_id])) {
                    book_collaborators[theAccessRights[i].user_id] =
                        theAccessRights[i];
                    book_collaborators[theAccessRights[i].user_id].count =
                        1;
                } else {
                    if (book_collaborators[theAccessRights[i].user_id].rights !=
                        theAccessRights[i].rights);
                    book_collaborators[theAccessRights[i].user_id].rights =
                        'r';
                    book_collaborators[theAccessRights[i].user_id].count +=
                        1;
                }
            }
        }
        book_collaborators = _.select(book_collaborators, function (obj) {
            return obj.count == bookIds.length;
        });

        var dialogBody = tmp_book_access_right_overview({
            'dialogHeader': dialogHeader,
            'contacts': theTeamMembers,
            'collaborators': tmp_book_collaborators({
                'collaborators': book_collaborators
            })
        });
        $('body').append(dialogBody);
        var diaButtons = {};
        diaButtons[gettext('Submit')] = function () {
            //apply the current state to server
            var collaborators = [],
                rights = [];
            $('#share-member .collaborator-tr').each(function () {
                collaborators[collaborators.length] = $(this).attr(
                    'data-id');
                rights[rights.length] = $(this).attr('data-right');
            });
            bookaccessrightsHelpers.submitAccessRight(bookIds,
                collaborators, rights);
            $(this).dialog('close');
        };
        diaButtons[gettext('Cancel')] = function () {
            $(this).dialog("close");
        }
        $('#access-rights-dialog').dialog({
            draggable: false,
            resizable: false,
            top: 10,
            width: 820,
            height: 540,
            modal: true,
            buttons: diaButtons,
            create: function () {
                var $the_dialog = $(this).closest(".ui-dialog");
                $the_dialog.find(".ui-button:first-child").addClass(
                    "fw-button fw-dark");
                $the_dialog.find(".ui-button:last").addClass(
                    "fw-button fw-orange");
            },
            close: function () {
                $('#access-rights-dialog').dialog('destroy').remove();
            }
        });
        $('.fw-checkable').bind('click', function () {
            $.setCheckableLabel($(this));
        });
        $('#add-share-member').bind('click', function () {
            var $selected_members = $(
                '#my-contacts .fw-checkable.checked');
            var selected_data = [];
            $selected_members.each(function () {
                var member_id = $(this).attr('data-id');
                var $collaborator = $('#collaborator-' + member_id);
                if (0 == $collaborator.size()) {
                    selected_data[selected_data.length] = {
                        'user_id': member_id,
                        'user_name': $(this).attr('data-name'),
                        'avatar': $(this).attr('data-avatar'),
                        'rights': 'r'
                    }
                } else if ('d' == $collaborator.attr('data-right')) {
                    $collaborator.removeClass('d').addClass('r').attr(
                        'data-right', 'r');
                }
            });
            $('#my-contacts .checkable-label.checked').removeClass(
                'checked');
            $('#share-member table tbody').append(tmp_book_collaborators({
                'collaborators': selected_data
            }));
            bookaccessrightsHelpers.collaboratorFunctionsEvent();
        });
        bookaccessrightsHelpers.collaboratorFunctionsEvent();
    };

    bookaccessrightsHelpers.collaboratorFunctionsEvent = function () {
        $('.edit-right').unbind('click');
        $('.edit-right').each(function () {
            $.addDropdownBox($(this), $(this).siblings('.fw-pulldown'));
        });
        var $spans = $(
            '.edit-right-wrapper .fw-pulldown-item, .delete-collaborator');
        $spans.unbind('mousedown');
        $spans.bind('mousedown', function () {
            var new_right = $(this).attr('data-right');
            $(this).closest('.collaborator-tr').attr('class',
                'collaborator-tr ' + new_right);
            $(this).closest('.collaborator-tr').attr('data-right',
                new_right);
        });
    };

    bookaccessrightsHelpers.submitAccessRight = function (books,
        collaborators, rights) {
        var post_data = {
            'books[]': books,
            'collaborators[]': collaborators,
            'rights[]': rights
        }
        $.ajax({
            url: '/book/accessright/save/',
            data: post_data,
            type: 'POST',
            dataType: 'json',
            success: function (response) {
                theAccessRights = response.access_rights;
                $.addAlert('success', gettext(
                    'Access rights have been saved'));
            },
            error: function (jqXHR, textStatus, errorThrown) {
                console.log(jqXHR.responseText);
            }
        });
    };

    exports.bookaccessrightsHelpers = bookaccessrightsHelpers;

}).call(this);<|endoftext|>


<commit_before>$(function () {
    var $document;

    $document = $(document);

    $document.on('click', '.popover > a', function (event) {
        event.preventDefault();

        var $body = $('body');
        var $link = $(event.target);
        var $popover = $link.parent();
        var $content = $popover.find('.popover-content');

        $body.css({ 'overflow': 'hidden' });

        $popover.addClass('active');

        $content.on('scroll touchmove mousewheel', function (e) {
            e.stopPropagation();
        });

        var popoverPos = ( $popover.outerWidth() / 2 ) - ( $content.outerWidth() / 2 );
        $content.css({ left: popoverPos });

        $document.one('click scroll touchmove mousewheel', function (event) {
            if (!$(event.target).is('.popover-content *')) {
                event.stopImmediatePropagation();
                event.preventDefault();
            }

            $body.css({ 'overflow': 'visible' });

            $popover.removeClass('active');
            $body.click();
        });
    });
});
<commit_msg>add wheel event<commit_after>$(function () {
    var $document;

    $document = $(document);

    $document.on('click', '.popover > a', function (event) {
        event.preventDefault();

        var $body = $('body');
        var $link = $(event.target);
        var $popover = $link.parent();
        var $content = $popover.find('.popover-content');

        $body.css({ 'overflow': 'hidden' });

        $popover.addClass('active');

        $content.on('scroll touchmove mousewheel wheel', function (e) {
            e.stopPropagation();
        });

        var popoverPos = ( $popover.outerWidth() / 2 ) - ( $content.outerWidth() / 2 );
        $content.css({ left: popoverPos });

        $document.one('click scroll touchmove mousewheel wheel', function (event) {
            if (!$(event.target).is('.popover-content *')) {
                event.stopImmediatePropagation();
                event.preventDefault();
            }

            $body.css({ 'overflow': 'visible' });

            $popover.removeClass('active');
            $body.click();
        });
    });
});
<|endoftext|>