<commit_before>'use strict';

var install = module.exports = {};

var lang        = require('../util/lang');
var fs          = require('fs-sync');
var semver      = require('semver');
var async       = require('async');
var request     = require('request');
var node_fs     = require('fs');
var node_path   = require('path');
var targz       = require('tar.gz');

// No argument overloading and fault tolerance
// @param {Object} options
// - key: {string} cortex.dependencies
// - dir: {path}
// - modules: {Array.<string>} ['a@0.0.1', 'b@0.0.2]
install.run = function (options, callback) {
    var cache = {
        callbacks: {}
    };

    async.parallel(
        options.modules.map(function (module) {
            return function (done) {
                var splitted = module.split('@');

                install.install({
                    name: splitted[0],
                    version: splitted[1] || 'latest',
                    cache: cache,
                    dir: options.dir,
                    key: options.key

                }, done);
            };
        }),

        function (err) {

        }
    );
};

// Only download and extract a single module
// @param {Object} options
// - name:
// - version:
// - dir: {path}
// @param {function()} callback
install.download = function (options, calback) {
    async.waterfall([

        // Get module information
        function (done) {
            var version_ = options.version;

            if(install.is_explicit_version(version_)){
                // 获取tarball地址
                install.get_module_info_by_version(options, done);

            }else{
                install.get_module_info_by_range({
                    name: options.name,
                    range: version_

                }, done);
            }
        },

        // Download tarball
        function (data, done) {
            var root = node_path.join(options.dir, data.name, data.version);
            var filename = get_filename(data.tarball);
            var filepath = node_path.join(root, filename);

            var stream = fs.createWriteStream(filepath);

            stream.on('close', function () {
                done(null, {
                    pkg: data.pkg,
                    file: filepath,
                    extract_dir: root
                });
            });

            request.get(tarball).pipe(stream);
        },

        // extract tarball
        function (data, done) {
            new targz().extract(data.file, data.extract_dir, function (err) {
                if (err) {
                    return done(err);
                }

                done(null, data);
            });
        }

    ], callback);
};

// 'a.b', {a: {b: 1}} -> 1
// 'a.b', {a: 1}, false -> false
// 'a.b', undefined -> 'a.b'
function assign (namespaces, obj, default_value, maintain){
    if(arguments.length === 2){
        default_value = param;
    }

    // 'a.b' -> ['a', 'b'];
    var hierarchies = maintain ? [namespaces] : namespaces.split('.');
    var i = 0;
    var len = hierarchies.length;
    var key;
    var value = obj;

    for(; i < len; i ++){
        key = hierarchies[i];

        if( key in value ){
            value = value[key];
        }else{

            // 'a.b', {a: 1} -> 'a.b'
            return default_value;
        }
    }

    // 'a.b', {a: {b: 1}} -> 1
    return value;
}

// Install a single module
// - download
// - extract
// - install dependencies
// @param {Object} options
// - cache: {Object}
// - name:
// - version:
// - key:
// - dir
install.install = function (options, callback) {
    var module = options.name + '@' + options.version;
    var callbacks = options.cache.callbacks;
    var module_callbacks = callbacks[module];

    if(!module_callbacks){
        module_callbacks = callbacks[module] = [];
        install._register_install(options, function (err, data) {
            var cbs = callbacks[module];

            callbacks[module] = {
                error: err,
                data: data
            };

            cbs.forEach(function (cb) {
                cb(err, data);
            });

            cbs.length = 0;
        });
    }

    if( Array.isArray(module_callbacks) ){
        callbacks.push(module_callbacks);
    }else{
        callback(module_callbacks.error, module_callbacks.data);
    }
};

// Parameters same as `install.install`
install._register_install = function (options, callback) {
    install.donwload(options, function (err, data) {
        var dependencies = assign(data.pkg, options.key, {});
        var parallel = [];

        lang.each(dependencies, function (name, version) {
            parallel.push(function (done) {
                install.install({
                    cache: options.cache,
                    name: name,
                    version: version,
                    dir: options.dir,
                    key: options,key
                }, done)
            });
        });

        async.parallel(parallel, function (err) {
            callback(err);
        });
    });
};

install.is_explicit_version = function(version){
    return semver.valid(version);
};

// Get the latest matched version
// @param {Object} versions
// {
//     '0.1.2': ...,
//     '0.2.3': ...
// }
// @param {string} pattern npm flavored sematic version
install.get_matched_version = function (versions, pattern) {

    // Ordered by version DESC
    var choices = Object.keys(versions).sort(semver.rcompare);
    var matched = null;

    if(choices.length){
        if(pattern === 'latest'){
            matched = choices[0];
        }else{
            choices.some(function (version) {
                if( semver.satisfies(version, pattern) ){
                    matched = version;
                    return true;
                }
            });
        }
    }

    return matched;
};

function santitize_tarball_url(url){
    return url.replace(/\/registry\/_design\/[a-z]+\/_rewrite/i, '');
};

var REGEX_MATCH_FILENAME = /[^\/]+$/;

function get_filename(url){
    return url.match(REGEX_MATCH_FILENAME)[0];
};

// @param {Object} options
// - name: {string}
// - range: {string} npm flavored semver range
install.get_module_info_by_range = function (options, callback) {
    var name = options.name;

    this.db.get(this.db.escape(options.name), function (err, res, json) {
        if(err){
            return callback(err, res, json);
        }

        var versions = json.versions;
        var matched_version = install.get_matched_version(versions, options.range);

        if(!matched_version){
            return callback(
                'No version of module "' +
                options.name +
                '" matched "' +
                options.range +
                '".'
            );
        }

        var pkg = versions[matched_version];
        var tarball = pkg.dist.tarball;

        callback(null, res, {
            pkg: pkg,
            name: name,
            version: matched_version,
            tarball: santitize_tarball_url(tarball)
        });
    });
};

// @param {string} version semver
// @param {Object} options
// - registry
install.get_module_info_by_version = function (options, callback) {
    var name = options.name;
    var version = options.version;

    this.db.get(this.db.escape(name) + '/' + version, function (err, res, json) {
        if(err){
            return callback(err, res, json);
        }

        callback(null, res, {
            pkg: json,
            name: name,
            version: version,
            tarball: santitize_tarball_url(json.dist.tarball)
        });
    });
};

<commit_msg>redesign the return value of `data` parameter of callback<commit_after>'use strict';

var install = module.exports = {};

var lang        = require('../util/lang');
var fs          = require('fs-sync');
var semver      = require('semver');
var async       = require('async');
var request     = require('request');
var node_fs     = require('fs');
var node_path   = require('path');
var targz       = require('tar.gz');

// No argument overloading and fault tolerance
// @param {Object} options
// - dependency_key: {string} cortex.dependencies
// - dir: {path}
// - modules: {Array.<string>} ['a@0.0.1', 'b@0.0.2]
install.run = function (options, callback) {
    var cache = {
        callbacks: {},
        ranges: {},
        dependencies: {},
        packages: {},
        origins: {}
    };

    async.parallel(
        options.modules.map(function (module) {
            return function (done) {
                var splitted = module.split('@');
                var name = splitted[0];
                var version = splitted[1];

                install._cache_origin_modules(cache, name, version);

                install.install({
                    name: name,
                    version: version,
                    cache: cache,
                    dir: options.dir,
                    dependency_key: options.dependency_key

                }, done);
            };
        }),

        function (err) {
            if(err){
                return callback(err);
            }

            delete cache.callbacks;

            callback(null, cache);
        }
    );
};

// Only download and extract a single module
// @param {Object} options
// - name:
// - version:
// - dir: {path}
// - cache
// @param {function()} callback
install.download = function (options, calback) {
    async.waterfall([

        // Get module information
        function (done) {
            var version_ = options.version;

            if(install.is_explicit_version(version_)){
                // 获取tarball地址
                install.get_module_info_by_version(options, done);

            }else{
                install.get_module_info_by_range(options, done);
            }
        },

        // Download tarball
        function (data, done) {
            install._cache_package(options.cache, data.name, data.version, data.pkg);

            var root = node_path.join(options.dir, data.name, data.version);
            var filename = get_filename(data.tarball);
            var filepath = node_path.join(root, filename);

            var stream = fs.createWriteStream(filepath);

            stream.on('close', function () {
                done(null, {
                    pkg: data.pkg,
                    file: filepath,
                    extract_dir: root
                });
            });

            request.get(tarball).pipe(stream);
        },

        // extract tarball
        function (data, done) {
            new targz().extract(data.file, data.extract_dir, function (err) {
                if (err) {
                    return done(err);
                }

                done(null, data);
            });
        }

    ], callback);
};

// Install a single module
// - download
// - extract
// - install dependencies

// @param {Object} options
// - cache: {Object}
// - name:
// - version:
// - key:
// - dir
install.install = function (options, callback) {
    var module = options.name + '@' + options.version;
    var callbacks = options.cache.callbacks;
    var module_callbacks = callbacks[module];

    if(!module_callbacks){
        module_callbacks = callbacks[module] = [];
        install._register_install(options, function (err, data) {
            var cbs = callbacks[module];

            callbacks[module] = {
                error: err,
                data: data
            };

            cbs.forEach(function (cb) {
                cb(err, data);
            });

            cbs.length = 0;
        });
    }

    if( Array.isArray(module_callbacks) ){
        callbacks.push(module_callbacks);
    }else{
        callback(module_callbacks.error, module_callbacks.data);
    }
};

install._cache_package = function (cache, name, exact_version, pkg) {
    var packages = cache.packages;

    if(!packages[name]){
        packages[name] = {};
    }

    packages[name][exact_version] = pkg;
};

install._cache_dependencies = function (cache, name, exact_version, dependencies) {
    var deps = cache.dependencies;

    if(!deps[name]){
        deps[name] = {};
    }

    deps[name][exact_version] = dependencies;
};

install._cache_range = function (cache, name, range, exact_version) {
    var ranges = cache.ranges;

    if(!ranges[name]){
        ranges[name] = {};
    }

    ranges[name][range] = exact_version;
};

install._cache_origin_modules = function (cache, name, version) {
    var origins = cache.origins;

    if(!origins[name]){
        origins[name] = [];
    }

    origins[name].push(version);
};

// Parameters same as `install.install`
install._register_install = function (options, callback) {
    install.donwload(options, function (err, data) {
        var dependencies = lang.object_member_by_namespaces(data.pkg, options.dependency_key, {});
        var parallel = [];

        install._cache_dependencies(options.cache, data.name, data.version, dependencies);

        lang.each(dependencies, function (name, version) {
            parallel.push(function (done) {
                install.install({
                    cache: options.cache,
                    name: name,
                    version: version,
                    dir: options.dir,
                    dependency_key: options.dependency_key
                }, done);
            });
        });

        async.parallel(parallel, function (err) {
            callback(err);
        });
    });
};

install.is_explicit_version = function(version){
    return semver.valid(version);
};

// Get the latest matched version
// @param {Object} versions
// {
//     '0.1.2': ...,
//     '0.2.3': ...
// }
// @param {string} pattern npm flavored sematic version
install.get_matched_version = function (versions, pattern) {

    // Ordered by version DESC
    var choices = Object.keys(versions).sort(semver.rcompare);
    var matched = null;

    if(choices.length){
        if(pattern === 'latest'){
            matched = choices[0];
        }else{
            choices.some(function (version) {
                if( semver.satisfies(version, pattern) ){
                    matched = version;
                    return true;
                }
            });
        }
    }

    return matched;
};

function santitize_tarball_url(url){
    return url.replace(/\/registry\/_design\/[a-z]+\/_rewrite/i, '');
};

var REGEX_MATCH_FILENAME = /[^\/]+$/;

function get_filename(url){
    return url.match(REGEX_MATCH_FILENAME)[0];
};

// @param {Object} options
// - name: {string}
// - range: {string} npm flavored semver range
install.get_module_info_by_range = function (options, callback) {
    var name = options.name;

    this.db.get(this.db.escape(options.name), function (err, res, json) {
        if(err){
            return callback(err, res, json);
        }

        var versions = json.versions;
        var matched_version = install.get_matched_version(versions, options.version);

        if(!matched_version){
            return callback(
                'No version of module "' +
                options.name +
                '" matched "' +
                options.version +
                '".'
            );
        }

        install._cache_range(options.cache, options.name, options.version, matched_version);

        var pkg = versions[matched_version];
        var tarball = pkg.dist.tarball;

        callback(null, res, {
            pkg: pkg,
            name: name,
            version: matched_version,
            tarball: santitize_tarball_url(tarball)
        });
    });
};

// @param {string} version semver
// @param {Object} options
// - registry
install.get_module_info_by_version = function (options, callback) {
    var name = options.name;
    var version = options.version;

    this.db.get(this.db.escape(name) + '/' + version, function (err, res, json) {
        if(err){
            return callback(err, res, json);
        }

        callback(null, res, {
            pkg: json,
            name: name,
            version: version,
            tarball: santitize_tarball_url(json.dist.tarball)
        });
    });
};

<|endoftext|>


<commit_before>var jive = require('jive-sdk');
var Q = require("q");
var https = require("https");
var url = require('url');

var JiveFacade = require("../../../common/JiveApiFacade");
var JiveOauth = require("../../../common/JiveOauth");
var StrategyBuilder = require("./StrategySetBuilder");
var placeStore = require("../../../common/PlaceStore");

var builder = new StrategyBuilder();
var stratSetScaffolding = builder.issues().issueComments();

function linkedPlaceSkeleton(linked, action){
    var place = linked.placeID;
    var jiveToken = linked.jive.access_token;
    var jiveRefresh = linked.jive.refresh_token;
    var gitHubToken = linked.github.token.access_token;
    var jiveUrl = linked.jiveUrl;
    var repo = linked.github.repo;
    var repoOwner = linked.github.repoOwner;
    var jiveAuth = new JiveOauth(jiveToken, jiveRefresh, function (newTokens, community) {
        jive.logger.debug(newTokens);
    });

    return jive.community.findByJiveURL(jiveUrl).then(function (community) {
        var japi = new JiveFacade(community, jiveAuth);
        if (!repo || !repoOwner) {
            jive.logger.error("Missing repo information for " + linked.placeUrl)
        }
        else {
            var setupOptions = {
                jiveApi: japi,
                placeID: place,
                owner: repoOwner,
                repo: repo,
                gitHubToken: gitHubToken,
                placeUrl: linked.placeUrl
            };
            return action(setupOptions);
        }
    });
}

function decorateLinkedPlaceWithStategies(linked) {
    linked.setupStrategies = stratSetScaffolding.build();
}

function setUpLinkedPlace(linked){
    decorateLinkedPlaceWithStategies(linked);
    return linkedPlaceSkeleton(linked, linked.setupStrategies.setup);
}

function teardownLinkedPlace(linked) {
    return linkedPlaceSkeleton(linked, linked.setupStrategies.teardown);
}

var linkedPlaces;

exports.onBootstrap = function() {
    placeStore.getAllPlaces().then(function (places) {
        linkedPlaces = places;
        linkedPlaces.forEach(setUpLinkedPlace);
    });
};

exports.onConfigurationChange = function(req, res){
    var url_parts = url.parse(req.url, true);
    var queryPart = url_parts.query;
    var placeUrl = queryPart["place"];

    placeStore.invalidateCache(placeUrl).then(function (newLinkedPlace) {
        var tempCollection = [];
        var toTeardown;
        linkedPlaces.forEach(function (place) {
            if(place.placeUrl !== newLinkedPlace.placeUrl){
                tempCollection.push(place);
            }else{//found it
                toTeardown = place;
            }
        });
        tempCollection.push(newLinkedPlace);
        linkedPlaces = tempCollection;
        if(toTeardown) {
            return teardownLinkedPlace(toTeardown).then(function () {
                setUpLinkedPlace(newLinkedPlace);
            });
        }else{
            return setUpLinkedPlace(newLinkedPlace);
        }

    }).catch(function (error) {
        jive.logger.error(error);
        res.writeHead(200, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({success:false}));
    });
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({success:true}));
};<commit_msg>Refresh tokens in github service<commit_after>var jive = require('jive-sdk');
var Q = require("q");
var https = require("https");
var url = require('url');

var JiveFacade = require("../../../common/JiveApiFacade");
var JiveOauth = require("../../../common/JiveOauth");
var StrategyBuilder = require("./StrategySetBuilder");
var placeStore = require("../../../common/PlaceStore");

var builder = new StrategyBuilder();
var stratSetScaffolding = builder.issues().issueComments();

function linkedPlaceSkeleton(linked, action){
    var place = linked.placeID;
    var jiveToken = linked.jive.access_token;
    var jiveRefresh = linked.jive.refresh_token;
    var gitHubToken = linked.github.token.access_token;
    var jiveUrl = linked.jiveUrl;
    var repo = linked.github.repo;
    var repoOwner = linked.github.repoOwner;
    var jiveAuth = new JiveOauth(jiveToken, jiveRefresh, function (newTokens, community) {
        jive.logger.info("Refreshing Jive tokens for: "+ linked.placeUrl);
        linked.jive.access_token = newTokens.access_token;
        linked.jive.refresh_token = newTokens.refresh_token;
        linked.jive.expires_in = newTokens.expires_in;
        jiveAuth = new JiveOauth(newTokens.access_token, newTokens.refresh_token, this)
        return placeStore.save(linked.placeUrl,{jive:linked.jive});
    });

    return jive.community.findByJiveURL(jiveUrl).then(function (community) {
        var japi = new JiveFacade(community, jiveAuth);
        if (!repo || !repoOwner) {
            jive.logger.error("Missing repo information for " + linked.placeUrl)
        }
        else {
            var setupOptions = {
                jiveApi: japi,
                placeID: place,
                owner: repoOwner,
                repo: repo,
                gitHubToken: gitHubToken,
                placeUrl: linked.placeUrl
            };
            return action(setupOptions);
        }
    });
}

function decorateLinkedPlaceWithStategies(linked) {
    linked.setupStrategies = stratSetScaffolding.build();
}

function setUpLinkedPlace(linked){
    decorateLinkedPlaceWithStategies(linked);
    return linkedPlaceSkeleton(linked, linked.setupStrategies.setup);
}

function teardownLinkedPlace(linked) {
    return linkedPlaceSkeleton(linked, linked.setupStrategies.teardown);
}

var linkedPlaces;

exports.onBootstrap = function() {
    placeStore.getAllPlaces().then(function (places) {
        linkedPlaces = places;
        linkedPlaces.forEach(setUpLinkedPlace);
    });
};

exports.onConfigurationChange = function(req, res){
    var url_parts = url.parse(req.url, true);
    var queryPart = url_parts.query;
    var placeUrl = queryPart["place"];

    placeStore.invalidateCache(placeUrl).then(function (newLinkedPlace) {
        var tempCollection = [];
        var toTeardown;
        linkedPlaces.forEach(function (place) {
            if(place.placeUrl !== newLinkedPlace.placeUrl){
                tempCollection.push(place);
            }else{//found it
                toTeardown = place;
            }
        });
        tempCollection.push(newLinkedPlace);
        linkedPlaces = tempCollection;
        if(toTeardown) {
            return teardownLinkedPlace(toTeardown).then(function () {
                setUpLinkedPlace(newLinkedPlace);
            });
        }else{
            return setUpLinkedPlace(newLinkedPlace);
        }

    }).catch(function (error) {
        jive.logger.error(error);
        res.writeHead(200, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({success:false}));
    });
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({success:true}));
};<|endoftext|>


<commit_before>const { Client, Collection } = require("discord.js");
const { readdirSync, readFileSync } = require("fs");
const { inspect } = require("util");
const SwgohClientStub = require("swgoh-client-stub");

const Bot = {};

// Attach the config to the Bot so we can use it anywhere
Bot.config = require("./config.js");

const client = new Client({
    intents: Bot.config.botIntents,
    partials: Bot.config.partials
});

// Attach the character and team files to the Bot so I don't have to reopen em each time
Bot.abilityCosts = JSON.parse(readFileSync("data/abilityCosts.json", "utf-8"));
Bot.acronyms     = JSON.parse(readFileSync("data/acronyms.json", "utf-8"));
Bot.arenaJumps   = JSON.parse(readFileSync("data/arenaJumps.json", "utf-8"));
Bot.charLocs     = JSON.parse(readFileSync("data/charLocations.json", "utf-8"));
Bot.characters   = JSON.parse(readFileSync("data/characters.json", "utf-8"));
Bot.factions     = [...new Set(Bot.characters.reduce((a, b) => a.concat(b.factions), []))];
Bot.missions     = JSON.parse(readFileSync("data/missions.json", "utf-8"));
Bot.resources    = JSON.parse(readFileSync("data/resources.json", "utf-8"));
Bot.shipLocs     = JSON.parse(readFileSync("data/shipLocations.json", "utf-8"));
Bot.ships        = JSON.parse(readFileSync("data/ships.json", "utf-8"));
Bot.squads       = JSON.parse(readFileSync("data/squads.json", "utf-8"));

const gameData   = JSON.parse(readFileSync("data/gameData.json", "utf-8"));

// Load in various general functions for the bot
require("./modules/functions.js")(Bot, client);

// Load in stuff for the events command
require("./modules/eventFuncs.js")(Bot, client);

// Load in stuff for patrons and such
require("./modules/patreonFuncs.js")(Bot, client);

// Languages
Bot.languages = {};
Bot.swgohLangList = ["ENG_US", "GER_DE", "SPA_XM", "FRE_FR", "RUS_RU", "POR_BR", "KOR_KR", "ITA_IT", "TUR_TR", "CHS_CN", "CHT_CN", "IND_ID", "JPN_JP", "THA_TH"];
client.reloadLanguages();

client.commands  = new Collection();
client.aliases   = new Collection();
client.slashcmds = new Collection();

Bot.evCountdowns = {};

Bot.talkedRecently = new Set();

const init = async () => {
    const { MongoClient } = require("mongodb");
    Bot.mongo = await MongoClient.connect(Bot.config.mongodb.url, { useNewUrlParser: true, useUnifiedTopology: true } );
    // Set up the caching
    Bot.cache   = require("./modules/cache.js")(Bot.mongo);
    Bot.userReg = require("./modules/users.js")(Bot);

    Bot.statCalculator = require("swgoh-stat-calc");
    Bot.statCalculator.setGameData(gameData);

    if (Bot.config.swapiConfig) {
        // Load up the api connector/ helpers
        const ApiSwgohHelp = require("api-swgoh-help");
        Bot.swgoh = (Bot.config.fakeSwapiConfig && Bot.config.fakeSwapiConfig.enabled) ?
            new ApiSwgohHelp(Bot.config.fakeSwapiConfig.options) :
            new ApiSwgohHelp(Bot.config.swapiConfig);
        Bot.swgohAPI = require("./modules/swapi.js")(Bot);

        if (Bot.config.fakeSwapiConfig?.clientStub) {
            // Do stuff
            Bot.swapiStub = new SwgohClientStub(Bot.config.fakeSwapiConfig.clientStub);
        }
    }

    const Logger = require("./modules/Logger.js");
    Bot.logger = new Logger(Bot, client);

    // Here we load **commands** into memory, as a collection, so they're accessible
    // here and everywhere else.
    const cmdFiles = readdirSync("./commands/");
    const cmdError = [];
    cmdFiles.forEach(file => {
        try {
            if (!file.endsWith(".js")) return;
            const commandName = file.split(".")[0];
            const result = client.loadCommand(commandName);
            if (result) cmdError.push(`Unable to load command: ${commandName}`);
        } catch (e) {
            Bot.logger.warn(`[INIT] Unable to load command ${file}: ${e}`);
        }
    });
    if (cmdError.length) {
        Bot.logger.warn("cmdLoad: " + cmdError.join("\n"));
    }

    const slashFiles = readdirSync("./slash/");
    const slashError = [];
    slashFiles.forEach(file => {
        try {
            if (!file.endsWith(".js")) return;
            const commandName = file.split(".")[0];
            const result = client.loadSlash(commandName);
            if (result) slashError.push(`Unable to load command: ${commandName}`);
        } catch (err) {
            return console.error(err);
        }
    });
    if (slashError.length) {
        Bot.logger.warn("slashLoad: " + slashError.join("\n"));
    }

    // Then we load events, which will include our message and ready event.
    const evtFiles = readdirSync("./events/");
    evtFiles.forEach(file => {
        const eventName = file.split(".")[0];
        const event = require(`./events/${file}`);
        if (["ready", "interactionCreate", "messageCreate", "guildMemberAdd", "guildMemberRemove"].includes(eventName)) {
            client.on(eventName, event.bind(null, Bot, client));
        } else {
            client.on(eventName, event.bind(null, Bot));
        }
        delete require.cache[require.resolve(`./events/${file}`)];
    });

    process.on("uncaughtException", (err) => {
        const errorMsg = err.stack?.replace(new RegExp(`${process.cwd()}`, "g"), ".");
        console.error(`[${Bot.myTime()}] Uncaught Exception: ${errorMsg}`);

        // If it's that error, don't bother showing it again
        try {
            if (!errorMsg?.startsWith("Error: RSV2 and RSV3 must be clear") && Bot.config.logs.logToChannel) {
                client.channels.cache.get(Bot.config.logs.channel)?.send("```inspect(errorMsg)```",{split: true});
            }
        } catch (e) {
            // Don't bother doing anything
        }
        // Always best practice to let the code crash on uncaught exceptions.
        // Because you should be catching them anyway.
        process.exit(1);
    });

    process.on("unhandledRejection", (err) => {
        const errorMsg = err.stack.replace(new RegExp(process.cwd(), "g"), ".");

        // If it's something I can't do anything about, ignore it
        const ignoreArr = [
            "Internal Server Error",                // Something on Discord's end
            "The user aborted a request",           // Pretty sure this is also on Discord's end
            "Cannot send messages to this user",    // A user probably has the bot blocked or doesn't allow DMs (No way to check for that)
            "Unknown Message"                       // Not sure, but seems to happen when someone deletes a message that the bot is trying to reply to?
        ];
        const errStr = ignoreArr.find(elem => errorMsg.includes(elem));
        if (errStr) {
            return console.error(`[${Bot.myTime()}] Uncaught Promise Error: ${errStr}`);
        }

        if (errorMsg.includes("ShardClientUtil._handleMessage") && errorMsg.includes("client is not defined")) {
            Bot.logger.error("The following error probably has to do with a 'client' inside a broadcastEval");
        }
        // console.log(err);
        console.error(`[${Bot.myTime()}] Uncaught Promise Error: ${errorMsg}`);
        try {
            if (Bot.config.logs.logToChannel) {
                client.channels.cache.get(Bot.config.logs.channel)?.send(`\`\`\`${inspect(errorMsg)}\`\`\``,{split: true});
            }
        } catch (e) {
            // Don't bother doing anything
        }
    });
};

init();
client.login(Bot.config.token);
<commit_msg>Remove options from mongo connection. (Apparently not needed since 3.7 or so)<commit_after>const { Client, Collection } = require("discord.js");
const { readdirSync, readFileSync } = require("fs");
const { inspect } = require("util");
const SwgohClientStub = require("swgoh-client-stub");

const Bot = {};

// Attach the config to the Bot so we can use it anywhere
Bot.config = require("./config.js");

const client = new Client({
    intents: Bot.config.botIntents,
    partials: Bot.config.partials
});

// Attach the character and team files to the Bot so I don't have to reopen em each time
Bot.abilityCosts = JSON.parse(readFileSync("data/abilityCosts.json", "utf-8"));
Bot.acronyms     = JSON.parse(readFileSync("data/acronyms.json", "utf-8"));
Bot.arenaJumps   = JSON.parse(readFileSync("data/arenaJumps.json", "utf-8"));
Bot.charLocs     = JSON.parse(readFileSync("data/charLocations.json", "utf-8"));
Bot.characters   = JSON.parse(readFileSync("data/characters.json", "utf-8"));
Bot.factions     = [...new Set(Bot.characters.reduce((a, b) => a.concat(b.factions), []))];
Bot.missions     = JSON.parse(readFileSync("data/missions.json", "utf-8"));
Bot.resources    = JSON.parse(readFileSync("data/resources.json", "utf-8"));
Bot.shipLocs     = JSON.parse(readFileSync("data/shipLocations.json", "utf-8"));
Bot.ships        = JSON.parse(readFileSync("data/ships.json", "utf-8"));
Bot.squads       = JSON.parse(readFileSync("data/squads.json", "utf-8"));

const gameData   = JSON.parse(readFileSync("data/gameData.json", "utf-8"));

// Load in various general functions for the bot
require("./modules/functions.js")(Bot, client);

// Load in stuff for the events command
require("./modules/eventFuncs.js")(Bot, client);

// Load in stuff for patrons and such
require("./modules/patreonFuncs.js")(Bot, client);

// Languages
Bot.languages = {};
Bot.swgohLangList = ["ENG_US", "GER_DE", "SPA_XM", "FRE_FR", "RUS_RU", "POR_BR", "KOR_KR", "ITA_IT", "TUR_TR", "CHS_CN", "CHT_CN", "IND_ID", "JPN_JP", "THA_TH"];
client.reloadLanguages();

client.commands  = new Collection();
client.aliases   = new Collection();
client.slashcmds = new Collection();

Bot.evCountdowns = {};

Bot.talkedRecently = new Set();

const init = async () => {
    const { MongoClient } = require("mongodb");
    Bot.mongo = await MongoClient.connect(Bot.config.mongodb.url);
    // Set up the caching
    Bot.cache   = require("./modules/cache.js")(Bot.mongo);
    Bot.userReg = require("./modules/users.js")(Bot);

    Bot.statCalculator = require("swgoh-stat-calc");
    Bot.statCalculator.setGameData(gameData);

    if (Bot.config.swapiConfig) {
        // Load up the api connector/ helpers
        const ApiSwgohHelp = require("api-swgoh-help");
        Bot.swgoh = (Bot.config.fakeSwapiConfig && Bot.config.fakeSwapiConfig.enabled) ?
            new ApiSwgohHelp(Bot.config.fakeSwapiConfig.options) :
            new ApiSwgohHelp(Bot.config.swapiConfig);
        Bot.swgohAPI = require("./modules/swapi.js")(Bot);

        if (Bot.config.fakeSwapiConfig?.clientStub) {
            // Do stuff
            Bot.swapiStub = new SwgohClientStub(Bot.config.fakeSwapiConfig.clientStub);
        }
    }

    const Logger = require("./modules/Logger.js");
    Bot.logger = new Logger(Bot, client);

    // Here we load **commands** into memory, as a collection, so they're accessible
    // here and everywhere else.
    const cmdFiles = readdirSync("./commands/");
    const cmdError = [];
    cmdFiles.forEach(file => {
        try {
            if (!file.endsWith(".js")) return;
            const commandName = file.split(".")[0];
            const result = client.loadCommand(commandName);
            if (result) cmdError.push(`Unable to load command: ${commandName}`);
        } catch (e) {
            Bot.logger.warn(`[INIT] Unable to load command ${file}: ${e}`);
        }
    });
    if (cmdError.length) {
        Bot.logger.warn("cmdLoad: " + cmdError.join("\n"));
    }

    const slashFiles = readdirSync("./slash/");
    const slashError = [];
    slashFiles.forEach(file => {
        try {
            if (!file.endsWith(".js")) return;
            const commandName = file.split(".")[0];
            const result = client.loadSlash(commandName);
            if (result) slashError.push(`Unable to load command: ${commandName}`);
        } catch (err) {
            return console.error(err);
        }
    });
    if (slashError.length) {
        Bot.logger.warn("slashLoad: " + slashError.join("\n"));
    }

    // Then we load events, which will include our message and ready event.
    const evtFiles = readdirSync("./events/");
    evtFiles.forEach(file => {
        const eventName = file.split(".")[0];
        const event = require(`./events/${file}`);
        if (["ready", "interactionCreate", "messageCreate", "guildMemberAdd", "guildMemberRemove"].includes(eventName)) {
            client.on(eventName, event.bind(null, Bot, client));
        } else {
            client.on(eventName, event.bind(null, Bot));
        }
        delete require.cache[require.resolve(`./events/${file}`)];
    });

    process.on("uncaughtException", (err) => {
        const errorMsg = err.stack?.replace(new RegExp(`${process.cwd()}`, "g"), ".");
        console.error(`[${Bot.myTime()}] Uncaught Exception: ${errorMsg}`);

        // If it's that error, don't bother showing it again
        try {
            if (!errorMsg?.startsWith("Error: RSV2 and RSV3 must be clear") && Bot.config.logs.logToChannel) {
                client.channels.cache.get(Bot.config.logs.channel)?.send("```inspect(errorMsg)```",{split: true});
            }
        } catch (e) {
            // Don't bother doing anything
        }
        // Always best practice to let the code crash on uncaught exceptions.
        // Because you should be catching them anyway.
        process.exit(1);
    });

    process.on("unhandledRejection", (err) => {
        const errorMsg = err.stack.replace(new RegExp(process.cwd(), "g"), ".");

        // If it's something I can't do anything about, ignore it
        const ignoreArr = [
            "Internal Server Error",                // Something on Discord's end
            "The user aborted a request",           // Pretty sure this is also on Discord's end
            "Cannot send messages to this user",    // A user probably has the bot blocked or doesn't allow DMs (No way to check for that)
            "Unknown Message"                       // Not sure, but seems to happen when someone deletes a message that the bot is trying to reply to?
        ];
        const errStr = ignoreArr.find(elem => errorMsg.includes(elem));
        if (errStr) {
            return console.error(`[${Bot.myTime()}] Uncaught Promise Error: ${errStr}`);
        }

        if (errorMsg.includes("ShardClientUtil._handleMessage") && errorMsg.includes("client is not defined")) {
            Bot.logger.error("The following error probably has to do with a 'client' inside a broadcastEval");
        }
        // console.log(err);
        console.error(`[${Bot.myTime()}] Uncaught Promise Error: ${errorMsg}`);
        try {
            if (Bot.config.logs.logToChannel) {
                client.channels.cache.get(Bot.config.logs.channel)?.send(`\`\`\`${inspect(errorMsg)}\`\`\``,{split: true});
            }
        } catch (e) {
            // Don't bother doing anything
        }
    });
};

init();
client.login(Bot.config.token);
<|endoftext|>


<commit_before>
function popoutContent(){

	var header_height = removeHeader();
	fixHeight(header_height);
}

function removeHeader(){
	var header = document.getElementsByClassName("d2l-popup-title")[0];
	var header_height = header.offsetHeight;

	header.parentNode.removeChild(header);

	return header_height;
}

function fixHeight(header_height) {
	//Readjust height of div to compensate for removed header
	var popup_body = document.getElementsByClassName('d2l-popup-body')[0];
	var popup_body_height = popup_body.offsetHeight;
	var view_height = popup_body_height + header_height;
	popup_body.style.height = view_height + "px";

	var content_body = document.getElementsByClassName('d2l-fileviewer-rendered-pdf')[0];
	if (content_body != null) {
		content_body.style.height = (view_height - 6) + "px";
	}
}

popoutContent();
<commit_msg>resizing window now works<commit_after>'use strict';

function popoutContent(){

	var header_height = removeHeader();
	fixHeight(header_height);
}

function removeHeader(){
	var header = document.getElementsByClassName("d2l-popup-title")[0];
	var header_height = header.offsetHeight;
	header.parentNode.removeChild(header);
	return header_height;
}

function fixHeight(header_height = 0) {
	//Readjust height of view
	var popup_body = document.getElementsByClassName('d2l-popup-body')[0];
	var popup_body_height = popup_body.offsetHeight;
	var view_height = popup_body_height + header_height; //header_height is for the first time only
	popup_body.style.height = view_height + "px";

	//Readjust height of fileviewer
	var content_body = document.getElementsByClassName('d2l-fileviewer-rendered-pdf')[0];
	if (content_body != null) {
		content_body.style.height = (view_height - 6) + "px";
	}
}

var timeoutId = 0;
window.addEventListener('resize', function(){

	if (timeoutId){
	    clearTimeout(timeoutId);
	}
	timeoutId = setTimeout(function() {
	    console.log('resize');
	    fixHeight();
	    timeoutId = 0;
	}, 200);
}, false);

popoutContent();
<|endoftext|>


<commit_before>
openerp.hr_timesheet_sheet = function(instance) {
    var QWeb = instance.web.qweb;
    var _t = instance.web._t;

    instance.hr_timesheet_sheet.WeeklyTimesheet = instance.web.form.FormWidget.extend(instance.web.form.ReinitializeWidgetMixin, {
        events: {
            "click .oe_timesheet_weekly_account a": "go_to",
        },
        init: function() {
            this._super.apply(this, arguments);
            this.set({
                sheets: [],
                date_to: false,
                date_from: false,
            });
            this.updating = false;
            this.field_manager.on("field_changed:timesheet_ids", this, this.query_sheets);
            this.field_manager.on("field_changed:date_from", this, function() {
                this.set({"date_from": instance.web.str_to_date(this.field_manager.get_field_value("date_from"))});
            });
            this.field_manager.on("field_changed:date_to", this, function() {
                this.set({"date_to": instance.web.str_to_date(this.field_manager.get_field_value("date_to"))});
            });
            this.field_manager.on("field_changed:user_id", this, function() {
                this.set({"user_id": this.field_manager.get_field_value("user_id")});
            });
            this.on("change:sheets", this, this.update_sheets);
            this.res_o2m_drop = new instance.web.DropMisordered();
            this.render_drop = new instance.web.DropMisordered();
            this.description_line = _t("/");
        },
        go_to: function(event) {
            var id = JSON.parse($(event.target).data("id"));
            this.do_action({
                type: 'ir.actions.act_window',
                res_model: "account.analytic.account",
                res_id: id,
                views: [[false, 'form']],
                target: 'current'
            });
        },
        query_sheets: function() {
            var self = this;
            if (self.updating)
                return;
            var commands = this.field_manager.get_field_value("timesheet_ids");
            this.res_o2m_drop.add(new instance.web.Model(this.view.model).call("resolve_2many_commands", ["timesheet_ids", commands, [],
                    new instance.web.CompoundContext()]))
                .done(function(result) {
                self.querying = true;
                self.set({sheets: result});
                self.querying = false;
            });
        },
        update_sheets: function() {
            var self = this;
            if (self.querying)
                return;
            self.updating = true;
            self.field_manager.set_values({timesheet_ids: self.get("sheets")}).done(function() {
                self.updating = false;
            });
        },
        initialize_field: function() {
            instance.web.form.ReinitializeWidgetMixin.initialize_field.call(this);
            var self = this;
            self.on("change:sheets", self, self.initialize_content);
            self.on("change:date_to", self, self.initialize_content);
            self.on("change:date_from", self, self.initialize_content);
            self.on("change:user_id", self, self.initialize_content);
        },
        initialize_content: function() {
            var self = this;
            if (self.setting)
                return;
            // don't render anything until we have date_to and date_from
            if (!self.get("date_to") || !self.get("date_from"))
                return;
            this.destroy_content();

            // it's important to use those vars to avoid race conditions
            var dates;
            var accounts;
            var account_names;
            var default_get;
            return this.render_drop.add(new instance.web.Model("hr.analytic.timesheet").call("default_get", [
                ['account_id','general_account_id', 'journal_id','date','name','user_id','product_id','product_uom_id','to_invoice','amount','unit_amount'],
                new instance.web.CompoundContext({'user_id': self.get('user_id')})]).then(function(result) {
                default_get = result;
                // calculating dates
                dates = [];
                var start = self.get("date_from");
                var end = self.get("date_to");
                while (start <= end) {
                    dates.push(start);
                    start = start.clone().addDays(1);
                }
                // group by account
                accounts = _(self.get("sheets")).chain()
                .map(function(el) {
                    // much simpler to use only the id in all cases
                    if (typeof(el.account_id) === "object")
                        el.account_id = el.account_id[0];
                    return el;
                })
                .groupBy("account_id").value();

                var account_ids = _.map(_.keys(accounts), function(el) { return el === "false" ? false : Number(el) });

                return new instance.web.Model("hr.analytic.timesheet").call("multi_on_change_account_id", [[], account_ids,
                    new instance.web.CompoundContext({'user_id': self.get('user_id')})]).then(function(accounts_defaults) {
                    accounts = _(accounts).chain().map(function(lines, account_id) {
                        account_defaults = _.extend({}, default_get, (accounts_defaults[account_id] || {}).value || {});
                        // group by days
                        account_id = account_id === "false" ? false :  Number(account_id);
                        var index = _.groupBy(lines, "date");
                        var days = _.map(dates, function(date) {
                            var day = {day: date, lines: index[instance.web.date_to_str(date)] || []};
                            // add line where we will insert/remove hours
                            var to_add = _.find(day.lines, function(line) { return line.name === self.description_line });
                            if (to_add) {
                                day.lines = _.without(day.lines, to_add);
                                day.lines.unshift(to_add);
                            } else {
                                day.lines.unshift(_.extend(_.clone(account_defaults), {
                                    name: self.description_line,
                                    unit_amount: 0,
                                    date: instance.web.date_to_str(date),
                                    account_id: account_id,
                                }));
                            }
                            return day;
                        });
                        return {account: account_id, days: days, account_defaults: account_defaults};
                    }).value();

                    // we need the name_get of the analytic accounts
                    return new instance.web.Model("account.analytic.account").call("name_get", [_.pluck(accounts, "account"),
                        new instance.web.CompoundContext()]).then(function(result) {
                        account_names = {};
                        _.each(result, function(el) {
                            account_names[el[0]] = el[1];
                        });
                        accounts = _.sortBy(accounts, function(el) {
                            return account_names[el.account];
                        });
                    });;
                });
            })).then(function(result) {
                // we put all the gathered data in self, then we render
                self.dates = dates;
                self.accounts = accounts;
                self.account_names = account_names;
                self.default_get = default_get;
                //real rendering
                self.display_data();
            });
        },
        destroy_content: function() {
            if (this.dfm) {
                this.dfm.destroy();
                this.dfm = undefined;
            }
        },
        display_data: function() {
            var self = this;
            self.$el.html(QWeb.render("hr_timesheet_sheet.WeeklyTimesheet", {widget: self}));
            _.each(self.accounts, function(account) {
                _.each(_.range(account.days.length), function(day_count) {
                    if (!self.get('effective_readonly')) {
                        self.get_box(account, day_count).val(self.sum_box(account, day_count)).change(function() {
                            var num = Number($(this).val());
                            if (isNaN(num)) {
                                $(this).val(self.sum_box(account, day_count));
                            } else {
                                account.days[day_count].lines[0].unit_amount += num - self.sum_box(account, day_count);
                                self.display_totals();
                                self.sync();
                            }
                        });
                    } else {
                        self.get_box(account, day_count).html(self.sum_box(account, day_count));
                    }
                });
            });
            self.display_totals();
            self.$(".oe_timesheet_weekly_adding button").click(_.bind(this.init_add_account, this));
        },
        init_add_account: function() {
            var self = this;
            if (self.dfm)
                return;
            self.$(".oe_timesheet_weekly_add_row").show();
            self.dfm = new instance.web.form.DefaultFieldManager(self);
            self.dfm.extend_field_desc({
                account: {
                    relation: "account.analytic.account",
                },
            });
            self.account_m2o = new instance.web.form.FieldMany2One(self.dfm, {
                attrs: {
                    name: "account",
                    type: "many2one",
                    domain: [
                        ['type','in',['normal', 'contract']],
                        ['state', '<>', 'close'],
                        ['use_timesheets','=',1],
                        ['id', 'not in', _.pluck(self.accounts, "account")],
                    ],
                    context: {
                        default_use_timesheets: 1,
                        default_type: "contract",
                    },
                    modifiers: '{"required": true}',
                },
            });
            self.account_m2o.prependTo(self.$(".oe_timesheet_weekly_add_row td"));
            self.$(".oe_timesheet_weekly_add_row button").click(function() {
                var id = self.account_m2o.get_value();
                if (id === false) {
                    self.dfm.set({display_invalid_fields: true});
                    return;
                }
                var ops = self.generate_o2m_value();
                new instance.web.Model("hr.analytic.timesheet").call("on_change_account_id", [[], id]).then(function(res) {
                    var def = _.extend({}, self.default_get, res.value, {
                        name: self.description_line,
                        unit_amount: 0,
                        date: instance.web.date_to_str(self.dates[0]),
                        account_id: id,
                    });
                    ops.push(def);
                    self.set({"sheets": ops});
                });
            });
        },
        get_box: function(account, day_count) {
            return this.$('[data-account="' + account.account + '"][data-day-count="' + day_count + '"]');
        },
        get_total: function(account) {
            return this.$('[data-account-total="' + account.account + '"]');
        },
        get_day_total: function(day_count) {
            return this.$('[data-day-total="' + day_count + '"]');
        },
        get_super_total: function() {
            return this.$('.oe_timesheet_weekly_supertotal');
        },
        sum_box: function(account, day_count) {
            var line_total = 0;
            _.each(account.days[day_count].lines, function(line) {
                line_total += line.unit_amount;
            });
            return line_total;
        },
        display_totals: function() {
            var self = this;
            var day_tots = _.map(_.range(self.dates.length), function() { return 0 });
            var super_tot = 0;
            _.each(self.accounts, function(account) {
                var acc_tot = 0;
                _.each(_.range(self.dates.length), function(day_count) {
                    var sum = self.sum_box(account, day_count);
                    acc_tot += sum;
                    day_tots[day_count] += sum;
                    super_tot += sum;
                });
                self.get_total(account).html(acc_tot);
            });
            _.each(_.range(self.dates.length), function(day_count) {
                self.get_day_total(day_count).html(day_tots[day_count]);
            });
            self.get_super_total().html(super_tot);
        },
        sync: function() {
            var self = this;
            self.setting = true;
            self.set({sheets: this.generate_o2m_value()});
            self.setting = false;
        },
        generate_o2m_value: function() {
            var self = this;
            var ops = [];

            _.each(self.accounts, function(account) {
                var auth_keys = _.extend(_.clone(account.account_defaults), {
                    name: true, unit_amount: true, date: true, account_id:true,
                });
                _.each(account.days, function(day) {
                    _.each(day.lines, function(line) {
                        if (line.unit_amount !== 0) {
                            var tmp = _.clone(line);
                            tmp.id = undefined;
                            _.each(line, function(v, k) {
                                if (v instanceof Array) {
                                    tmp[k] = v[0];
                                }
                            });
                            // we have to remove some keys, because analytic lines are shitty
                            _.each(_.keys(tmp), function(key) {
                                if (auth_keys[key] === undefined) {
                                    tmp[key] = undefined;
                                }
                            });
                            ops.push(tmp);
                        }
                    });
                });
            });
            return ops;
        },
    });

    instance.web.form.custom_widgets.add('weekly_timesheet', 'instance.hr_timesheet_sheet.WeeklyTimesheet');

};
<commit_msg>[IMP]Introduce float_time concept in Timesheet Widget.<commit_after>
openerp.hr_timesheet_sheet = function(instance) {
    var QWeb = instance.web.qweb;
    var _t = instance.web._t;

    instance.hr_timesheet_sheet.WeeklyTimesheet = instance.web.form.FormWidget.extend(instance.web.form.ReinitializeWidgetMixin, {
        events: {
            "click .oe_timesheet_weekly_account a": "go_to",
        },
        init: function() {
            this._super.apply(this, arguments);
            this.set({
                sheets: [],
                date_to: false,
                date_from: false,
            });
            this.updating = false;
            this.field_manager.on("field_changed:timesheet_ids", this, this.query_sheets);
            this.field_manager.on("field_changed:date_from", this, function() {
                this.set({"date_from": instance.web.str_to_date(this.field_manager.get_field_value("date_from"))});
            });
            this.field_manager.on("field_changed:date_to", this, function() {
                this.set({"date_to": instance.web.str_to_date(this.field_manager.get_field_value("date_to"))});
            });
            this.field_manager.on("field_changed:user_id", this, function() {
                this.set({"user_id": this.field_manager.get_field_value("user_id")});
            });
            this.on("change:sheets", this, this.update_sheets);
            this.res_o2m_drop = new instance.web.DropMisordered();
            this.render_drop = new instance.web.DropMisordered();
            this.description_line = _t("/");
        },
        go_to: function(event) {
            var id = JSON.parse($(event.target).data("id"));
            this.do_action({
                type: 'ir.actions.act_window',
                res_model: "account.analytic.account",
                res_id: id,
                views: [[false, 'form']],
                target: 'current'
            });
        },
        query_sheets: function() {
            var self = this;
            if (self.updating)
                return;
            var commands = this.field_manager.get_field_value("timesheet_ids");
            this.res_o2m_drop.add(new instance.web.Model(this.view.model).call("resolve_2many_commands", ["timesheet_ids", commands, [],
                    new instance.web.CompoundContext()]))
                .done(function(result) {
                self.querying = true;
                self.set({sheets: result});
                self.querying = false;
            });
        },
        update_sheets: function() {
            var self = this;
            if (self.querying)
                return;
            self.updating = true;
            self.field_manager.set_values({timesheet_ids: self.get("sheets")}).done(function() {
                self.updating = false;
            });
        },
        initialize_field: function() {
            instance.web.form.ReinitializeWidgetMixin.initialize_field.call(this);
            var self = this;
            self.on("change:sheets", self, self.initialize_content);
            self.on("change:date_to", self, self.initialize_content);
            self.on("change:date_from", self, self.initialize_content);
            self.on("change:user_id", self, self.initialize_content);
        },
        initialize_content: function() {
            var self = this;
            if (self.setting)
                return;
            // don't render anything until we have date_to and date_from
            if (!self.get("date_to") || !self.get("date_from"))
                return;
            this.destroy_content();

            // it's important to use those vars to avoid race conditions
            var dates;
            var accounts;
            var account_names;
            var default_get;
            return this.render_drop.add(new instance.web.Model("hr.analytic.timesheet").call("default_get", [
                ['account_id','general_account_id', 'journal_id','date','name','user_id','product_id','product_uom_id','to_invoice','amount','unit_amount'],
                new instance.web.CompoundContext({'user_id': self.get('user_id')})]).then(function(result) {
                default_get = result;
                // calculating dates
                dates = [];
                var start = self.get("date_from");
                var end = self.get("date_to");
                while (start <= end) {
                    dates.push(start);
                    start = start.clone().addDays(1);
                }
                // group by account
                accounts = _(self.get("sheets")).chain()
                .map(function(el) {
                    // much simpler to use only the id in all cases
                    if (typeof(el.account_id) === "object")
                        el.account_id = el.account_id[0];
                    return el;
                })
                .groupBy("account_id").value();

                var account_ids = _.map(_.keys(accounts), function(el) { return el === "false" ? false : Number(el) });

                return new instance.web.Model("hr.analytic.timesheet").call("multi_on_change_account_id", [[], account_ids,
                    new instance.web.CompoundContext({'user_id': self.get('user_id')})]).then(function(accounts_defaults) {
                    accounts = _(accounts).chain().map(function(lines, account_id) {
                        account_defaults = _.extend({}, default_get, (accounts_defaults[account_id] || {}).value || {});
                        // group by days
                        account_id = account_id === "false" ? false :  Number(account_id);
                        var index = _.groupBy(lines, "date");
                        var days = _.map(dates, function(date) {
                            var day = {day: date, lines: index[instance.web.date_to_str(date)] || []};
                            // add line where we will insert/remove hours
                            var to_add = _.find(day.lines, function(line) { return line.name === self.description_line });
                            if (to_add) {
                                day.lines = _.without(day.lines, to_add);
                                day.lines.unshift(to_add);
                            } else {
                                day.lines.unshift(_.extend(_.clone(account_defaults), {
                                    name: self.description_line,
                                    unit_amount: 0,
                                    date: instance.web.date_to_str(date),
                                    account_id: account_id,
                                }));
                            }
                            return day;
                        });
                        return {account: account_id, days: days, account_defaults: account_defaults};
                    }).value();

                    // we need the name_get of the analytic accounts
                    return new instance.web.Model("account.analytic.account").call("name_get", [_.pluck(accounts, "account"),
                        new instance.web.CompoundContext()]).then(function(result) {
                        account_names = {};
                        _.each(result, function(el) {
                            account_names[el[0]] = el[1];
                        });
                        accounts = _.sortBy(accounts, function(el) {
                            return account_names[el.account];
                        });
                    });;
                });
            })).then(function(result) {
                // we put all the gathered data in self, then we render
                self.dates = dates;
                self.accounts = accounts;
                self.account_names = account_names;
                self.default_get = default_get;
                //real rendering
                self.display_data();
            });
        },
        destroy_content: function() {
            if (this.dfm) {
                this.dfm.destroy();
                this.dfm = undefined;
            }
        },
        is_valid_value:function(value){
            var split_value = value.split(":");
            var wrong_value = true;
            if (split_value.length > 2)return false;
            _.detect(split_value,function(num){
                if(isNaN(num)){
                    wrong_value = false;
                }
            })
            return wrong_value;
        },
        display_data: function() {
            var self = this;
            self.$el.html(QWeb.render("hr_timesheet_sheet.WeeklyTimesheet", {widget: self}));
            _.each(self.accounts, function(account) {
                _.each(_.range(account.days.length), function(day_count) {
                    if (!self.get('effective_readonly')) {
                        self.get_box(account, day_count).val(self.sum_box(account, day_count, true)).change(function() {
                            var num = $(this).val();
                            if (self.is_valid_value(num)){
                                num = Number(self.parse_client(num));
                            }
                            if (isNaN(num)) {
                                $(this).val(self.sum_box(account, day_count, true));
                            } else {
                                account.days[day_count].lines[0].unit_amount += num - self.sum_box(account, day_count);
                                self.display_totals();
                                self.sync();
                                 if(!isNaN($(this).val())){
                                    $(this).val(self.sum_box(account, day_count, true));
                                }
                            }
                        });
                    } else {
                        self.get_box(account, day_count).html(self.sum_box(account, day_count, true));
                    }
                });
            });
            self.display_totals();
            self.$(".oe_timesheet_weekly_adding button").click(_.bind(this.init_add_account, this));
        },
        init_add_account: function() {
            var self = this;
            if (self.dfm)
                return;
            self.$(".oe_timesheet_weekly_add_row").show();
            self.dfm = new instance.web.form.DefaultFieldManager(self);
            self.dfm.extend_field_desc({
                account: {
                    relation: "account.analytic.account",
                },
            });
            self.account_m2o = new instance.web.form.FieldMany2One(self.dfm, {
                attrs: {
                    name: "account",
                    type: "many2one",
                    domain: [
                        ['type','in',['normal', 'contract']],
                        ['state', '<>', 'close'],
                        ['use_timesheets','=',1],
                        ['id', 'not in', _.pluck(self.accounts, "account")],
                    ],
                    context: {
                        default_use_timesheets: 1,
                        default_type: "contract",
                    },
                    modifiers: '{"required": true}',
                },
            });
            self.account_m2o.prependTo(self.$(".oe_timesheet_weekly_add_row td"));
            self.$(".oe_timesheet_weekly_add_row button").click(function() {
                var id = self.account_m2o.get_value();
                if (id === false) {
                    self.dfm.set({display_invalid_fields: true});
                    return;
                }
                var ops = self.generate_o2m_value();
                new instance.web.Model("hr.analytic.timesheet").call("on_change_account_id", [[], id]).then(function(res) {
                    var def = _.extend({}, self.default_get, res.value, {
                        name: self.description_line,
                        unit_amount: 0,
                        date: instance.web.date_to_str(self.dates[0]),
                        account_id: id,
                    });
                    ops.push(def);
                    self.set({"sheets": ops});
                });
            });
        },
        get_box: function(account, day_count) {
            return this.$('[data-account="' + account.account + '"][data-day-count="' + day_count + '"]');
        },
        get_total: function(account) {
            return this.$('[data-account-total="' + account.account + '"]');
        },
        get_day_total: function(day_count) {
            return this.$('[data-day-total="' + day_count + '"]');
        },
        get_super_total: function() {
            return this.$('.oe_timesheet_weekly_supertotal');
        },
        sum_box: function(account, day_count, setter) {
            var line_total = 0;
            _.each(account.days[day_count].lines, function(line) {
                line_total += line.unit_amount;
            });
            return (setter)?this.format_client(line_total):line_total;
        },
        display_totals: function() {
            var self = this;
            var day_tots = _.map(_.range(self.dates.length), function() { return 0 });
            var super_tot = 0;
            _.each(self.accounts, function(account) {
                var acc_tot = 0;
                _.each(_.range(self.dates.length), function(day_count) {
                    var sum = self.sum_box(account, day_count);
                    acc_tot += sum;
                    day_tots[day_count] += sum;
                    super_tot += sum;
                });
                self.get_total(account).html(self.format_client(acc_tot));
            });
            _.each(_.range(self.dates.length), function(day_count) {
                self.get_day_total(day_count).html(self.format_client(day_tots[day_count]));
            });
            self.get_super_total().html(self.format_client(super_tot));
        },
        sync: function() {
            var self = this;
            self.setting = true;
            self.set({sheets: this.generate_o2m_value()});
            self.setting = false;
        },
        //converts hour value to float
        parse_client: function(value) {
            return instance.web.parse_value(value, { type:"float_time" });
        },
        //converts float value to hour
        format_client:function(value){
            return instance.web.format_value(value, { type:"float_time" });
        },
        generate_o2m_value: function() {
            var self = this;
            var ops = [];

            _.each(self.accounts, function(account) {
                var auth_keys = _.extend(_.clone(account.account_defaults), {
                    name: true, unit_amount: true, date: true, account_id:true,
                });
                _.each(account.days, function(day) {
                    _.each(day.lines, function(line) {
                        if (line.unit_amount !== 0) {
                            var tmp = _.clone(line);
                            tmp.id = undefined;
                            _.each(line, function(v, k) {
                                if (v instanceof Array) {
                                    tmp[k] = v[0];
                                }
                            });
                            // we have to remove some keys, because analytic lines are shitty
                            _.each(_.keys(tmp), function(key) {
                                if (auth_keys[key] === undefined) {
                                    tmp[key] = undefined;
                                }
                            });
                            ops.push(tmp);
                        }
                    });
                });
            });
            return ops;
        },
    });

    instance.web.form.custom_widgets.add('weekly_timesheet', 'instance.hr_timesheet_sheet.WeeklyTimesheet');

};
<|endoftext|>


<commit_before>/*======================================================
************   Searchbar   ************
======================================================*/
var Searchbar = function (container, params) {
    var defaults = {
        input: null,
        clearButton: null,
        cancelButton: null,
        searchList: null,
        searchIn: '.item-title',
        searchBy: '',
        found: null,
        notFound: null,
        overlay: null,
        ignore: '.searchbar-ignore',
        customSearch: false
    };
    params = params || {};
    for (var def in defaults) {
        if (typeof params[def] === 'undefined' || params[def] === null) {
            params[def] = defaults[def];
        }
    }

    // Instance
    var s = this;

    // Params
    s.params = params;

    // Container
    container = $(container);
    s.container = container;

    // Active
    s.active = false;

    // Input
    s.input = s.params.input ? $(s.params.input) : s.container.find('input[type="search"]');
    s.clearButton = s.params.clearButton ? $(s.params.clearButton) : s.container.find('.searchbar-clear');
    s.cancelButton = s.params.cancelButton ? $(s.params.cancelButton) : s.container.find('.searchbar-cancel');

    // Search List
    s.searchList = $(s.params.searchList);
    s.ul = s.searchList.children('ul');

    // Is Virtual List
    s.isVirtualList = s.searchList.hasClass('virtual-list');

    // Is In Page
    s.pageContainer = s.container.parents('.page').eq(0);

    // Overlay
    if (!s.params.overlay) {
        s.overlay = s.pageContainer.length > 0 ? s.pageContainer.find('.searchbar-overlay') : $('.searchbar-overlay');
    }
    else {
        s.overlay = $(s.params.overlay);
    }
    // Found and not found
    if (!s.params.found) {
        s.found = s.pageContainer.length > 0 ? s.pageContainer.find('.searchbar-found') : $('.searchbar-found');
    }
    else {
        s.found = $(s.params.found);
    }
    if (!s.params.notFound) {
        s.notFound = s.pageContainer.length > 0 ? s.pageContainer.find('.searchbar-not-found') : $('.searchbar-not-found');
    }
    else {
        s.notFound = $(s.params.notFound);
    }

    // Cancel button
    var cancelMarginProp = app.rtl ? 'margin-left' : 'margin-right';
    if (s.cancelButton.length > 0) {
        s.cancelButton.transition(0).show();
        s.cancelButton.css(cancelMarginProp, -s.cancelButton[0].offsetWidth + 'px');
        setTimeout(function () {
            s.cancelButton.transition('');
        }, 0);
    }

    s.triggerEvent = function (eventName, eventData) {
        s.container.trigger(eventName, eventData);
        if (s.searchList.length > 0) s.searchList.trigger(eventName, eventData);
    };

    // Enable/disalbe
    s.enable = function () {
        function _enable() {
            if (s.searchList.length && !s.container.hasClass('searchbar-active')) s.overlay.addClass('searchbar-overlay-active');
            s.container.addClass('searchbar-active');
            if (s.cancelButton.length > 0) s.cancelButton.css(cancelMarginProp, '0px');
            s.triggerEvent('enableSearch');
            s.active = true;
        }
        if (app.device.ios) {
            setTimeout(function () {
                _enable();
            }, 400);
        }
        else {
            _enable();
        }
    };

    s.disable = function () {
        s.input.val('').trigger('change');
        s.container.removeClass('searchbar-active searchbar-not-empty');
        if (s.cancelButton.length > 0) s.cancelButton.css(cancelMarginProp, -s.cancelButton[0].offsetWidth + 'px');

        if (s.searchList.length) s.overlay.removeClass('searchbar-overlay-active');
        function _disable() {
            s.input.blur();
            s.triggerEvent('disableSearch');
            s.active = false;
        }
        if (app.device.ios) {
            setTimeout(function () {
                _disable();
            }, 400);
        }
        else {
            _disable();
        }
    };

    // Clear
    s.clear = function () {
        s.input.val('').trigger('change').focus();
        s.triggerEvent('clearSearch');
    };

    // Search
    s.handleInput = function () {
        setTimeout(function () {
            var value = s.input.val().trim();
            if (s.searchList.length > 0 && (s.params.searchIn || s.isVirtualList)) s.search(value, true);
        }, 0);
    };

    var previousQuery;
    var virtualList;
    s.search = function (query, internal) {
        if (query.trim() === previousQuery) return;
        previousQuery = query.trim();

        if (!internal) {
            if (!s.active) {
                s.enable();
            }
            if (!internal) {
                s.input.val(query);
            }
        }
        // Add active/inactive classes on overlay
        if (query.length === 0) {
            s.container.removeClass('searchbar-not-empty');
            if (s.searchList.length && s.container.hasClass('searchbar-active')) s.overlay.addClass('searchbar-overlay-active');
        }
        else {
            s.container.addClass('searchbar-not-empty');
            if (s.searchList.length && s.container.hasClass('searchbar-active')) s.overlay.removeClass('searchbar-overlay-active');
        }

        if (s.params.externalSearch) {
            s.triggerEvent('search', {query: query});
            return;
        }

        var values = query.trim().toLowerCase().split(' ');
        var foundItems = [];
        if (s.isVirtualList) {
            virtualList = s.searchList[0].f7VirtualList;
            if (query.trim() === '') {
                virtualList.resetFilter();
                s.notFound.hide();
                s.found.show();
                return;
            }
            if (virtualList.params.searchAll) {
                foundItems = virtualList.params.searchAll(query, virtualList.items) || [];
            }
            else if (virtualList.params.searchByItem) {
                for (var i = 0; i < virtualList.items.length; i++) {
                    if(virtualList.params.searchByItem(query, i, virtualList.params.items[i])) {
                        foundItems.push(i);
                    }
                }
            }
        }
        else {
            if (s.ul.length === 0) {
                s.ul = s.searchList.children('ul');
            }
            s.ul.children('li').removeClass('hidden-by-searchbar').each(function (index, el) {
                el = $(el);
                var compareWithText = [];
                el.find(s.params.searchIn).each(function () {
                    compareWithText.push($(this).text().trim().toLowerCase());
                });
                compareWithText = compareWithText.join(' ');
                var wordsMatch = 0;
                for (var i = 0; i < values.length; i++) {
                    if (compareWithText.indexOf(values[i]) >= 0) wordsMatch++;
                }
                if (wordsMatch !== values.length && !(s.params.ignore && el.is(s.params.ignore))) {
                    el.addClass('hidden-by-searchbar');
                }
                else {
                    foundItems.push(el[0]);
                }
            });

            if (app.params.searchbarHideDividers) {
                s.searchList.find('.item-divider, .list-group-title').each(function () {
                    var title = $(this);
                    var nextElements = title.nextAll('li');
                    var hide = true;
                    for (var i = 0; i < nextElements.length; i++) {
                        var nextEl = $(nextElements[i]);
                        if (nextEl.hasClass('list-group-title') || nextEl.hasClass('item-divider')) break;
                        if (!nextEl.hasClass('hidden-by-searchbar')) {
                            hide = false;
                        }
                    }
                    var ignore = s.params.ignore && title.is(s.params.ignore);
                    if (hide && !ignore) title.addClass('hidden-by-searchbar');
                    else title.removeClass('hidden-by-searchbar');
                });
            }
            if (app.params.searchbarHideGroups) {
                s.searchList.find('.list-group').each(function () {
                    var group = $(this);
                    var ignore = s.params.ignore && group.is(s.params.ignore);
                    var notHidden = group.find('li:not(.hidden-by-searchbar)');
                    if (notHidden.length === 0 && !ignore) {
                        group.addClass('hidden-by-searchbar');
                    }
                    else {
                        group.removeClass('hidden-by-searchbar');
                    }
                });
            }
        }
        s.triggerEvent('search', {query: query, foundItems: foundItems});
        if (foundItems.length === 0) {
            s.notFound.show();
            s.found.hide();
        }
        else {
            s.notFound.hide();
            s.found.show();
        }
        if (s.isVirtualList) {
            virtualList.filterItems(foundItems);
        }
    };

    // Events
    function preventSubmit(e) {
        e.preventDefault();
    }

    s.attachEvents = function (destroy) {
        var method = destroy ? 'off' : 'on';
        s.container[method]('submit', preventSubmit);
        s.cancelButton[method]('click', s.disable);
        s.overlay[method]('click', s.disable);
        s.input[method]('focus', s.enable);
        s.input[method]('change keydown keypress keyup', s.handleInput);
        s.clearButton[method]('click', s.clear);
    };
    s.detachEvents = function() {
        s.attachEvents(true);
    };

    // Init Destroy
    s.init = function () {
        s.attachEvents();
    };
    s.destroy = function () {
        s.detachEvents();
        s = null;
    };

    // Init
    s.init();

    s.container[0].f7Searchbar = s;
    return s;

};
app.searchbar = function (container, params) {
    return new Searchbar(container, params);
};
app.initSearchbar = function (container) {
    container = $(container);
    var searchbar = container.hasClass('searchbar') ? container : container.find('.searchbar');
    if (searchbar.length === 0) return;
    if (!searchbar.hasClass('searchbar-init')) return;

    var sb = app.searchbar(searchbar, searchbar.dataset());

    function onBeforeRemove() {
        sb.destroy();
    }
    if (container.hasClass('page')) {
        container.once('pageBeforeRemove', onBeforeRemove);
    }
    else if (container.hasClass('navbar-inner')) {
        container.once('navbarBeforeRemove', onBeforeRemove);
    }
};<commit_msg>Fix search for groups<commit_after>/*======================================================
************   Searchbar   ************
======================================================*/
var Searchbar = function (container, params) {
    var defaults = {
        input: null,
        clearButton: null,
        cancelButton: null,
        searchList: null,
        searchIn: '.item-title',
        searchBy: '',
        found: null,
        notFound: null,
        overlay: null,
        ignore: '.searchbar-ignore',
        customSearch: false
    };
    params = params || {};
    for (var def in defaults) {
        if (typeof params[def] === 'undefined' || params[def] === null) {
            params[def] = defaults[def];
        }
    }

    // Instance
    var s = this;

    // Params
    s.params = params;

    // Container
    container = $(container);
    s.container = container;

    // Active
    s.active = false;

    // Input
    s.input = s.params.input ? $(s.params.input) : s.container.find('input[type="search"]');
    s.clearButton = s.params.clearButton ? $(s.params.clearButton) : s.container.find('.searchbar-clear');
    s.cancelButton = s.params.cancelButton ? $(s.params.cancelButton) : s.container.find('.searchbar-cancel');

    // Search List
    s.searchList = $(s.params.searchList);

    // Is Virtual List
    s.isVirtualList = s.searchList.hasClass('virtual-list');

    // Is In Page
    s.pageContainer = s.container.parents('.page').eq(0);

    // Overlay
    if (!s.params.overlay) {
        s.overlay = s.pageContainer.length > 0 ? s.pageContainer.find('.searchbar-overlay') : $('.searchbar-overlay');
    }
    else {
        s.overlay = $(s.params.overlay);
    }
    // Found and not found
    if (!s.params.found) {
        s.found = s.pageContainer.length > 0 ? s.pageContainer.find('.searchbar-found') : $('.searchbar-found');
    }
    else {
        s.found = $(s.params.found);
    }
    if (!s.params.notFound) {
        s.notFound = s.pageContainer.length > 0 ? s.pageContainer.find('.searchbar-not-found') : $('.searchbar-not-found');
    }
    else {
        s.notFound = $(s.params.notFound);
    }

    // Cancel button
    var cancelMarginProp = app.rtl ? 'margin-left' : 'margin-right';
    if (s.cancelButton.length > 0) {
        s.cancelButton.transition(0).show();
        s.cancelButton.css(cancelMarginProp, -s.cancelButton[0].offsetWidth + 'px');
        setTimeout(function () {
            s.cancelButton.transition('');
        }, 0);
    }

    s.triggerEvent = function (eventName, eventData) {
        s.container.trigger(eventName, eventData);
        if (s.searchList.length > 0) s.searchList.trigger(eventName, eventData);
    };

    // Enable/disalbe
    s.enable = function () {
        function _enable() {
            if (s.searchList.length && !s.container.hasClass('searchbar-active')) s.overlay.addClass('searchbar-overlay-active');
            s.container.addClass('searchbar-active');
            if (s.cancelButton.length > 0) s.cancelButton.css(cancelMarginProp, '0px');
            s.triggerEvent('enableSearch');
            s.active = true;
        }
        if (app.device.ios) {
            setTimeout(function () {
                _enable();
            }, 400);
        }
        else {
            _enable();
        }
    };

    s.disable = function () {
        s.input.val('').trigger('change');
        s.container.removeClass('searchbar-active searchbar-not-empty');
        if (s.cancelButton.length > 0) s.cancelButton.css(cancelMarginProp, -s.cancelButton[0].offsetWidth + 'px');

        if (s.searchList.length) s.overlay.removeClass('searchbar-overlay-active');
        function _disable() {
            s.input.blur();
            s.triggerEvent('disableSearch');
            s.active = false;
        }
        if (app.device.ios) {
            setTimeout(function () {
                _disable();
            }, 400);
        }
        else {
            _disable();
        }
    };

    // Clear
    s.clear = function () {
        s.input.val('').trigger('change').focus();
        s.triggerEvent('clearSearch');
    };

    // Search
    s.handleInput = function () {
        setTimeout(function () {
            var value = s.input.val().trim();
            if (s.searchList.length > 0 && (s.params.searchIn || s.isVirtualList)) s.search(value, true);
        }, 0);
    };

    var previousQuery;
    var virtualList;
    s.search = function (query, internal) {
        if (query.trim() === previousQuery) return;
        previousQuery = query.trim();

        if (!internal) {
            if (!s.active) {
                s.enable();
            }
            if (!internal) {
                s.input.val(query);
            }
        }
        // Add active/inactive classes on overlay
        if (query.length === 0) {
            s.container.removeClass('searchbar-not-empty');
            if (s.searchList.length && s.container.hasClass('searchbar-active')) s.overlay.addClass('searchbar-overlay-active');
        }
        else {
            s.container.addClass('searchbar-not-empty');
            if (s.searchList.length && s.container.hasClass('searchbar-active')) s.overlay.removeClass('searchbar-overlay-active');
        }

        if (s.params.externalSearch) {
            s.triggerEvent('search', {query: query});
            return;
        }

        var values = query.trim().toLowerCase().split(' ');
        var foundItems = [];
        if (s.isVirtualList) {
            virtualList = s.searchList[0].f7VirtualList;
            if (query.trim() === '') {
                virtualList.resetFilter();
                s.notFound.hide();
                s.found.show();
                return;
            }
            if (virtualList.params.searchAll) {
                foundItems = virtualList.params.searchAll(query, virtualList.items) || [];
            }
            else if (virtualList.params.searchByItem) {
                for (var i = 0; i < virtualList.items.length; i++) {
                    if(virtualList.params.searchByItem(query, i, virtualList.params.items[i])) {
                        foundItems.push(i);
                    }
                }
            }
        }
        else {
            s.searchList.find('li').removeClass('hidden-by-searchbar').each(function (index, el) {
                el = $(el);
                var compareWithText = [];
                el.find(s.params.searchIn).each(function () {
                    compareWithText.push($(this).text().trim().toLowerCase());
                });
                compareWithText = compareWithText.join(' ');
                var wordsMatch = 0;
                for (var i = 0; i < values.length; i++) {
                    if (compareWithText.indexOf(values[i]) >= 0) wordsMatch++;
                }
                if (wordsMatch !== values.length && !(s.params.ignore && el.is(s.params.ignore))) {
                    el.addClass('hidden-by-searchbar');
                }
                else {
                    foundItems.push(el[0]);
                }
            });

            if (app.params.searchbarHideDividers) {
                s.searchList.find('.item-divider, .list-group-title').each(function () {
                    var title = $(this);
                    var nextElements = title.nextAll('li');
                    var hide = true;
                    for (var i = 0; i < nextElements.length; i++) {
                        var nextEl = $(nextElements[i]);
                        if (nextEl.hasClass('list-group-title') || nextEl.hasClass('item-divider')) break;
                        if (!nextEl.hasClass('hidden-by-searchbar')) {
                            hide = false;
                        }
                    }
                    var ignore = s.params.ignore && title.is(s.params.ignore);
                    if (hide && !ignore) title.addClass('hidden-by-searchbar');
                    else title.removeClass('hidden-by-searchbar');
                });
            }
            if (app.params.searchbarHideGroups) {
                s.searchList.find('.list-group').each(function () {
                    var group = $(this);
                    var ignore = s.params.ignore && group.is(s.params.ignore);
                    var notHidden = group.find('li:not(.hidden-by-searchbar)');
                    if (notHidden.length === 0 && !ignore) {
                        group.addClass('hidden-by-searchbar');
                    }
                    else {
                        group.removeClass('hidden-by-searchbar');
                    }
                });
            }
        }
        s.triggerEvent('search', {query: query, foundItems: foundItems});
        if (foundItems.length === 0) {
            s.notFound.show();
            s.found.hide();
        }
        else {
            s.notFound.hide();
            s.found.show();
        }
        if (s.isVirtualList) {
            virtualList.filterItems(foundItems);
        }
    };

    // Events
    function preventSubmit(e) {
        e.preventDefault();
    }

    s.attachEvents = function (destroy) {
        var method = destroy ? 'off' : 'on';
        s.container[method]('submit', preventSubmit);
        s.cancelButton[method]('click', s.disable);
        s.overlay[method]('click', s.disable);
        s.input[method]('focus', s.enable);
        s.input[method]('change keydown keypress keyup', s.handleInput);
        s.clearButton[method]('click', s.clear);
    };
    s.detachEvents = function() {
        s.attachEvents(true);
    };

    // Init Destroy
    s.init = function () {
        s.attachEvents();
    };
    s.destroy = function () {
        s.detachEvents();
        s = null;
    };

    // Init
    s.init();

    s.container[0].f7Searchbar = s;
    return s;

};
app.searchbar = function (container, params) {
    return new Searchbar(container, params);
};
app.initSearchbar = function (container) {
    container = $(container);
    var searchbar = container.hasClass('searchbar') ? container : container.find('.searchbar');
    if (searchbar.length === 0) return;
    if (!searchbar.hasClass('searchbar-init')) return;

    var sb = app.searchbar(searchbar, searchbar.dataset());

    function onBeforeRemove() {
        sb.destroy();
    }
    if (container.hasClass('page')) {
        container.once('pageBeforeRemove', onBeforeRemove);
    }
    else if (container.hasClass('navbar-inner')) {
        container.once('navbarBeforeRemove', onBeforeRemove);
    }
};<|endoftext|>


<commit_before>var gulp = require('gulp');
var browserify = require('browserify');
var babelify = require('babelify');
var source = require('vinyl-source-stream');
var uglify = require('gulp-uglify');
var buffer = require('vinyl-buffer');
var filesize = require('gulp-filesize');
var eslint = require('gulp-eslint');
var mocha = require('gulp-mocha');
require('babel-core/register');

var paths = {
  allSrc: './src/**/*.js',
  allTests: './test/**/*.js',
};

gulp.task('build', function() {
  return browserify({
    entries: './src/wordsmith.js',
    extensions: ['.js'],
    debug: true
  })
      .transform('babelify', {presets: ['es2015']})
      .bundle()
      .pipe(source('wordsmith.min.js'))
      .pipe(buffer())
      .pipe(uglify())
      .pipe(filesize())
      .pipe(gulp.dest('dist'));
});

gulp.task('lint', function() {
  gulp.src(paths.allSrc)
      .pipe(eslint())
      .pipe(eslint.format());
});

gulp.task('lint-fail', function() {
  gulp.src(paths.allSrc)
      .pipe(eslint())
      .pipe(eslint.format())
      .pipe(eslint.failAfterError());
});

gulp.task('test-ci', ['test', 'lint-fail']);

gulp.task('test', function() {
  gulp.src(paths.allTests)
      .pipe(mocha());
});

gulp.task('watch', function() {
  gulp.watch(paths.allSrc, ['lint', 'test']);
});
<commit_msg> return the streams to potentially fix issue where gulp is returning 0 even though errors have occurred<commit_after>var gulp = require('gulp');
var browserify = require('browserify');
var babelify = require('babelify');
var source = require('vinyl-source-stream');
var uglify = require('gulp-uglify');
var buffer = require('vinyl-buffer');
var filesize = require('gulp-filesize');
var eslint = require('gulp-eslint');
var mocha = require('gulp-mocha');
require('babel-core/register');

var paths = {
  allSrc: './src/**/*.js',
  allTests: './test/**/*.js',
};

gulp.task('build', function() {
  return browserify({
    entries: './src/wordsmith.js',
    extensions: ['.js'],
    debug: true
  })
      .transform('babelify', {presets: ['es2015']})
      .bundle()
      .pipe(source('wordsmith.min.js'))
      .pipe(buffer())
      .pipe(uglify())
      .pipe(filesize())
      .pipe(gulp.dest('dist'));
});

gulp.task('lint', function() {
  return gulp.src(paths.allSrc)
      .pipe(eslint())
      .pipe(eslint.format());
});

gulp.task('lint-fail', function() {
  return gulp.src(paths.allSrc)
      .pipe(eslint())
      .pipe(eslint.format())
      .pipe(eslint.failAfterError());
});

gulp.task('test-ci', ['test', 'lint-fail']);

gulp.task('test', function() {
  return gulp.src(paths.allTests)
      .pipe(mocha());
});

gulp.task('watch', function() {
  gulp.watch(paths.allSrc, ['lint', 'test']);
});
<|endoftext|>