<commit_before>import Origin from "../origin"
import ValueMap from "../value-map"
import unstringTracifyArguments from "./unstringTracifyArguments"
import stringTraceUseValue from "./stringTraceUseValue"
import untrackedArgument from "./untrackedArgument"
import config from "../config"
import toString from "../untracedToString"
import cloneRegExp from "clone-regexp"
import debuggerStatementFunction from "../debuggerStatementFunction"

function FromJSString(options){
    var value = options.value
    while(value.isStringTraceString) {
        value = value.value
    }

    // Properties need to be non enumerable so they don't show up in
    // for...in loops
    Object.defineProperties(this, {
        origin: {
            enumerable: false,
            writable: true,
            value: options.origin
        },
        value: {
            enumerable: false,
            writable: true,
            value: value
        }
    })
}
Object.defineProperty(FromJSString.prototype, "isStringTraceString", {
    value: true,
    enumerable: false
})

function isArray(val){
    return val !== null && val.length !== undefined && val.map !== undefined;
}

function capitalizeFirstCharacter(str){
    return str.slice(0, 1).toUpperCase() + str.slice(1)
}

function countGroupsInRegExp(re){
    // http://stackoverflow.com/questions/16046620/regex-to-count-the-number-of-capturing-groups-in-a-regex
    return new RegExp(re.toString() + '|').exec('').length
}

// getOwnPropertyNames instead of for loop b/c props aren't enumerable
Object.getOwnPropertyNames(String.prototype).forEach(function(propertyName){
    if (propertyName === "toString") { return }
    // can't use .apply on valueOf function (" String.prototype.valueOf is not generic")
    if (propertyName === "valueOf") { return }

    if (propertyName === "indexOf" || propertyName === "charCodeAt") {
        return;
    }

    if (typeof String.prototype[propertyName] === "function") {
        Object.defineProperty(FromJSString.prototype, propertyName, {
            value: handlerFunction,
            enumerable: false
        })

        function handlerFunction(){
            var oldValue = this;
            var args = unstringTracifyArguments(arguments)
            var newVal;
            var error = Error();

            var argumentOrigins = Array.from(arguments).map(function(arg){
                if (arg instanceof FromJSString) {
                    return arg.origin;
                }
                if (typeof arg === "string"){
                    return untrackedArgument(arg, error)
                }
                var str = toString(arg, true)
                return {
                    value: str,
                    origin: new Origin({
                        error: {stack: ""},
                        inputValues: [],
                        value: str
                    })
                }
            })
            var inputValues = [oldValue.origin].concat(argumentOrigins)

            var oldString = oldValue.toString()

            var valueItems = null;
            if (propertyName === "replace") {
                var valueMap = new ValueMap();
                var inputMappedSoFar = ""

                var newVal = oldString.replace(args[0], function(){
                    var argumentsArray = Array.prototype.slice.apply(arguments, [])
                    var match = argumentsArray[0];
                    var submatches = argumentsArray.slice(1, argumentsArray.length - 2)
                    var offset = argumentsArray[argumentsArray.length - 2]
                    var string = argumentsArray[argumentsArray.length - 1]

                    submatches = submatches.map(function(submatch){
                        if (typeof submatch !== "string"){
                            return submatch
                        }

                        return makeTraceObject({
                            value: submatch,
                            origin: new Origin({
                                error,
                                value: submatch,
                                action: "Replace Call Submatch",
                                inputValues: [oldValue],
                                inputValuesCharacterIndex: [offset + match.indexOf(submatch)]
                            })
                        })
                    })

                    var newArgsArray = [
                        match,
                        ...submatches,
                        offset,
                        string
                    ];

                    var inputBeforeToKeep = oldString.substring(inputMappedSoFar.length, offset)
                    valueMap.appendString(inputBeforeToKeep , oldValue.origin, inputMappedSoFar.length)
                    inputMappedSoFar += inputBeforeToKeep

                    var replaceWith = null;
                    // confusing... args[1] is basically inputValues[2].value
                    if (typeof args[1] === "string" || typeof args[1] === "number") {
                        var value = args[1].toString();
                        value = value.replace(/\$([0-9]{1,2}|[$`&'])/g, function(dollarMatch, dollarSubmatch){
                            var submatchIndex = parseFloat(dollarSubmatch)
                            if (!isNaN(submatchIndex)){
                                var submatch = submatches[submatchIndex - 1] // $n is one-based, array is zero-based
                                if (submatch === undefined) {
                                    var maxSubmatchIndex = countGroupsInRegExp(args[0])
                                    var submatchIsDefinedInRegExp = submatchIndex < maxSubmatchIndex

                                    if (submatchIsDefinedInRegExp) {
                                        submatch = ""
                                    } else {
                                        submatch = "$" + dollarSubmatch
                                    }
                                }
                                return submatch
                            } else if (dollarSubmatch === "&"){
                                return match
                            } else {
                                throw "not handled!!"
                            }
                        })

                        replaceWith = {
                            value: value,
                            origin: inputValues[2]
                        }
                    } else if (typeof args[1] === "function"){
                        replaceWith = args[1].apply(this, newArgsArray)
                        if (replaceWith === undefined){
                            replaceWith = "undefined"
                        }
                        if (replaceWith === null) {
                            replaceWith = "null"
                        }
                        if (!replaceWith.origin) {
                            replaceWith = makeTraceObject({
                                value: toString(replaceWith),
                                origin: new Origin({
                                    error,
                                    value: toString(replaceWith),
                                    action: "Untracked replace match result",
                                    inputValues: []
                                })
                            })
                        } else {
                            replaceWith = {
                                value: replaceWith.value,
                                origin: replaceWith.origin
                            }
                        }
                    } else {
                        throw "not handled"
                    }
                    valueMap.appendString(replaceWith.value, replaceWith.origin, 0)

                    inputMappedSoFar += match

                    return replaceWith.value
                })

                valueMap.appendString(oldString.substring(inputMappedSoFar.length), oldValue.origin, inputMappedSoFar.length)

                valueItems = valueMap.serialize(inputValues)

            } else if (propertyName === "slice"){
                var valueMap = new ValueMap();
                var from = args[0]
                var to = args[1]

                if (to < 0) {
                    to = oldString.length + to;
                }

                newVal = oldString.slice(from, to)

                valueMap.appendString(newVal, oldValue.origin, from) // oldvalue.origin is inputValues[0]

                valueItems = valueMap.serialize(inputValues)
            } else if (propertyName === "substr"){
                var start = args[0]
                if (start < 0){
                    start = oldString.length + start
                }
                let length = args[1]
                if (length === undefined){
                    length = oldString.length - start;
                }

                newVal = oldString.substr(start, length)
                var valueMap = new ValueMap()
                valueMap.appendString(newVal, oldValue.origin, start)
                valueItems = valueMap.serialize(inputValues)

            } else if (propertyName === "substring"){
                var start = args[0]
                var end = args[1]

                if (start < 0 || isNaN(start)) {
                    start = 0;
                }
                if (end < 0 || isNaN(end)) {
                    end = oldString.length;
                }

                newVal = oldString.substring(start, end)
                var valueMap = new ValueMap()
                valueMap.appendString(newVal, oldValue.origin, start)
                valueItems = valueMap.serialize(inputValues)
            } else if (propertyName === "match") {
                var regExp = args[0]
                if (regExp.global) {
                    var matches = [];
                    var match;
                    while (match = regExp.exec(this)) {
                        matches.push(match[0])
                    }
                    if (matches.length === 0) {
                        return null;
                    }
                    return matches
                } else {
                    return regExp.exec(this)
                }
            } else if (propertyName === "split") {
                var separator = args[0]
                var limit = args[1]
                if (limit !== undefined) {
                    dontTrack()
                } else {
                    var res = oldString.split(args[0])

                    var separators = [];
                    if (typeof separator === "string") {
                        for (var i=0; i< res.length -1; i++) {
                            separators.push(separator)
                        }
                    } else if (separator instanceof RegExp) {
                        var regExp = cloneRegExp(separator, {global: true})
                        separators = oldString.match(regExp)
                        if (separators === null) {
                            separators = [];
                        }
                    } else {
                        debuggerStatementFunction();
                        dontTrack();
                    }

                    newVal = []
                    var currentCharIndex = 0;
                    res.forEach(function(str, i){
                        var inputValuesCharacterIndex = [currentCharIndex];
                        currentCharIndex += str.length;
                        if (separators[i]) {
                            currentCharIndex += separators[i].length;
                        }

                        newVal.push(makeTraceObject({
                            value: str,
                            origin: new Origin({
                                error,
                                value: str,
                                action: "Split Call",
                                inputValues,
                                inputValuesCharacterIndex
                            })
                        }))
                    })
                }
            } else {
                dontTrack()
            }

            function dontTrack(){
                if (config.logUntrackedStrings) {
                    console.trace("string not tracked after ",propertyName ,"call")
                }

                newVal = nativeStringObject.prototype[propertyName].apply(oldString, args);
            }

            var actionName = capitalizeFirstCharacter(propertyName) + " Call";

            if (typeof newVal === "string") {
                return makeTraceObject(
                    {
                        value: newVal,
                        origin: new Origin({
                            error,
                            value: newVal,
                            valueItems: valueItems,
                            inputValues: inputValues,
                            action: actionName
                        })
                    }
                )
            } else if (isArray(newVal)) {
                return newVal.map(function(val){
                    if (typeof val === "string"){
                        return makeTraceObject(
                            {
                                value: val,
                                origin: new Origin({
                                    error,
                                    value: val,
                                    inputValues: inputValues,
                                    action: actionName,
                                })
                            }
                        )
                    } else {
                        return val
                    }
                })
            } else {
                debuggerStatementFunction()
                return newVal
            }
        }
    }
})

Object.defineProperties(FromJSString.prototype, {
    valueOf: {
        value: function(){
            return this.value;
        },
        enumerable: false
    },
    toJSON: {
        value: function(){
            return this.value
        },
        enumerable: false
    },
    toString: {
        value: function(){
            return this.value
        },
        enumerable: false
    },
    indexOf: {
        value: function(search, fromIndex){
            if (search && search.isStringTraceString) {
                search = search.value
            }
            return this.value.indexOf(search, fromIndex)
        },
        enumerable: false
    },
    charCodeAt: {
        value: function(index){
            return this.value.charCodeAt(index)
        },
        enumerable: false
    }
})
Object.defineProperty(FromJSString.prototype, "length", {
    get: function(){
        return this.value.length;
    }
})

var traps = {
    get: function(target, name){
        if (typeof name !== "symbol" && !isNaN(name)) {
            return target.value[name]
        }

        if (name === "constructor") {
            return window.String
        }

        return target[name]
    },
    has: function(target, propName){
        throw new TypeError("Cannot use 'in' operator to search for '" + propName +"' in " + target.value)
    }
}

export function makeTraceObject(options){
    if (typeof options.value !== "string") {
        return options.value
    }
    if (options === undefined || options.value === undefined || options.origin === undefined) {
        throw "invalid options for makeTraceObject"
    }
    var stringTraceObject = new FromJSString({
        value: stringTraceUseValue(options.value),
        origin: options.origin
    })
    if (stringTraceObject.value.isStringTraceString) {
        debuggerStatementFunction()
    }

    // Make accessing characters by index work
    return new Proxy(stringTraceObject, traps);
}
<commit_msg>Separate localCompare from other FromJSString functions.<commit_after>import Origin from "../origin"
import ValueMap from "../value-map"
import unstringTracifyArguments from "./unstringTracifyArguments"
import stringTraceUseValue from "./stringTraceUseValue"
import untrackedArgument from "./untrackedArgument"
import config from "../config"
import toString from "../untracedToString"
import cloneRegExp from "clone-regexp"
import debuggerStatementFunction from "../debuggerStatementFunction"

function FromJSString(options){
    var value = options.value
    while(value.isStringTraceString) {
        value = value.value
    }

    // Properties need to be non enumerable so they don't show up in
    // for...in loops
    Object.defineProperties(this, {
        origin: {
            enumerable: false,
            writable: true,
            value: options.origin
        },
        value: {
            enumerable: false,
            writable: true,
            value: value
        }
    })
}
Object.defineProperty(FromJSString.prototype, "isStringTraceString", {
    value: true,
    enumerable: false
})

function isArray(val){
    return val !== null && val.length !== undefined && val.map !== undefined;
}

function capitalizeFirstCharacter(str){
    return str.slice(0, 1).toUpperCase() + str.slice(1)
}

function countGroupsInRegExp(re){
    // http://stackoverflow.com/questions/16046620/regex-to-count-the-number-of-capturing-groups-in-a-regex
    return new RegExp(re.toString() + '|').exec('').length
}

// getOwnPropertyNames instead of for loop b/c props aren't enumerable
Object.getOwnPropertyNames(String.prototype).forEach(function(propertyName){
    if (propertyName === "toString") { return }
    // can't use .apply on valueOf function (" String.prototype.valueOf is not generic")
    if (propertyName === "valueOf") { return }

    // these return numbers
    if (propertyName === "indexOf" || propertyName === "charCodeAt" || propertyName === "localeCompare") {
        return;
    }

    if (typeof String.prototype[propertyName] === "function") {
        Object.defineProperty(FromJSString.prototype, propertyName, {
            value: handlerFunction,
            enumerable: false
        })

        function handlerFunction(){
            var oldValue = this;
            var args = unstringTracifyArguments(arguments)
            var newVal;
            var error = Error();

            var argumentOrigins = Array.from(arguments).map(function(arg){
                if (arg instanceof FromJSString) {
                    return arg.origin;
                }
                if (typeof arg === "string"){
                    return untrackedArgument(arg, error)
                }
                var str = toString(arg, true)
                return {
                    value: str,
                    origin: new Origin({
                        error: {stack: ""},
                        inputValues: [],
                        value: str
                    })
                }
            })
            var inputValues = [oldValue.origin].concat(argumentOrigins)

            var oldString = oldValue.toString()

            var valueItems = null;
            if (propertyName === "replace") {
                var valueMap = new ValueMap();
                var inputMappedSoFar = ""

                var newVal = oldString.replace(args[0], function(){
                    var argumentsArray = Array.prototype.slice.apply(arguments, [])
                    var match = argumentsArray[0];
                    var submatches = argumentsArray.slice(1, argumentsArray.length - 2)
                    var offset = argumentsArray[argumentsArray.length - 2]
                    var string = argumentsArray[argumentsArray.length - 1]

                    submatches = submatches.map(function(submatch){
                        if (typeof submatch !== "string"){
                            return submatch
                        }

                        return makeTraceObject({
                            value: submatch,
                            origin: new Origin({
                                error,
                                value: submatch,
                                action: "Replace Call Submatch",
                                inputValues: [oldValue],
                                inputValuesCharacterIndex: [offset + match.indexOf(submatch)]
                            })
                        })
                    })

                    var newArgsArray = [
                        match,
                        ...submatches,
                        offset,
                        string
                    ];

                    var inputBeforeToKeep = oldString.substring(inputMappedSoFar.length, offset)
                    valueMap.appendString(inputBeforeToKeep , oldValue.origin, inputMappedSoFar.length)
                    inputMappedSoFar += inputBeforeToKeep

                    var replaceWith = null;
                    // confusing... args[1] is basically inputValues[2].value
                    if (typeof args[1] === "string" || typeof args[1] === "number") {
                        var value = args[1].toString();
                        value = value.replace(/\$([0-9]{1,2}|[$`&'])/g, function(dollarMatch, dollarSubmatch){
                            var submatchIndex = parseFloat(dollarSubmatch)
                            if (!isNaN(submatchIndex)){
                                var submatch = submatches[submatchIndex - 1] // $n is one-based, array is zero-based
                                if (submatch === undefined) {
                                    var maxSubmatchIndex = countGroupsInRegExp(args[0])
                                    var submatchIsDefinedInRegExp = submatchIndex < maxSubmatchIndex

                                    if (submatchIsDefinedInRegExp) {
                                        submatch = ""
                                    } else {
                                        submatch = "$" + dollarSubmatch
                                    }
                                }
                                return submatch
                            } else if (dollarSubmatch === "&"){
                                return match
                            } else {
                                throw "not handled!!"
                            }
                        })

                        replaceWith = {
                            value: value,
                            origin: inputValues[2]
                        }
                    } else if (typeof args[1] === "function"){
                        replaceWith = args[1].apply(this, newArgsArray)
                        if (replaceWith === undefined){
                            replaceWith = "undefined"
                        }
                        if (replaceWith === null) {
                            replaceWith = "null"
                        }
                        if (!replaceWith.origin) {
                            replaceWith = makeTraceObject({
                                value: toString(replaceWith),
                                origin: new Origin({
                                    error,
                                    value: toString(replaceWith),
                                    action: "Untracked replace match result",
                                    inputValues: []
                                })
                            })
                        } else {
                            replaceWith = {
                                value: replaceWith.value,
                                origin: replaceWith.origin
                            }
                        }
                    } else {
                        throw "not handled"
                    }
                    valueMap.appendString(replaceWith.value, replaceWith.origin, 0)

                    inputMappedSoFar += match

                    return replaceWith.value
                })

                valueMap.appendString(oldString.substring(inputMappedSoFar.length), oldValue.origin, inputMappedSoFar.length)

                valueItems = valueMap.serialize(inputValues)

            } else if (propertyName === "slice"){
                var valueMap = new ValueMap();
                var from = args[0]
                var to = args[1]

                if (to < 0) {
                    to = oldString.length + to;
                }

                newVal = oldString.slice(from, to)

                valueMap.appendString(newVal, oldValue.origin, from) // oldvalue.origin is inputValues[0]

                valueItems = valueMap.serialize(inputValues)
            } else if (propertyName === "substr"){
                var start = args[0]
                if (start < 0){
                    start = oldString.length + start
                }
                let length = args[1]
                if (length === undefined){
                    length = oldString.length - start;
                }

                newVal = oldString.substr(start, length)
                var valueMap = new ValueMap()
                valueMap.appendString(newVal, oldValue.origin, start)
                valueItems = valueMap.serialize(inputValues)

            } else if (propertyName === "substring"){
                var start = args[0]
                var end = args[1]

                if (start < 0 || isNaN(start)) {
                    start = 0;
                }
                if (end < 0 || isNaN(end)) {
                    end = oldString.length;
                }

                newVal = oldString.substring(start, end)
                var valueMap = new ValueMap()
                valueMap.appendString(newVal, oldValue.origin, start)
                valueItems = valueMap.serialize(inputValues)
            } else if (propertyName === "match") {
                var regExp = args[0]
                if (regExp.global) {
                    var matches = [];
                    var match;
                    while (match = regExp.exec(this)) {
                        matches.push(match[0])
                    }
                    if (matches.length === 0) {
                        return null;
                    }
                    return matches
                } else {
                    return regExp.exec(this)
                }
            } else if (propertyName === "split") {
                var separator = args[0]
                var limit = args[1]
                if (limit !== undefined) {
                    dontTrack()
                } else {
                    var res = oldString.split(args[0])

                    var separators = [];
                    if (typeof separator === "string") {
                        for (var i=0; i< res.length -1; i++) {
                            separators.push(separator)
                        }
                    } else if (separator instanceof RegExp) {
                        var regExp = cloneRegExp(separator, {global: true})
                        separators = oldString.match(regExp)
                        if (separators === null) {
                            separators = [];
                        }
                    } else {
                        debuggerStatementFunction();
                        dontTrack();
                    }

                    newVal = []
                    var currentCharIndex = 0;
                    res.forEach(function(str, i){
                        var inputValuesCharacterIndex = [currentCharIndex];
                        currentCharIndex += str.length;
                        if (separators[i]) {
                            currentCharIndex += separators[i].length;
                        }

                        newVal.push(makeTraceObject({
                            value: str,
                            origin: new Origin({
                                error,
                                value: str,
                                action: "Split Call",
                                inputValues,
                                inputValuesCharacterIndex
                            })
                        }))
                    })
                }
            } else {
                dontTrack()
            }

            function dontTrack(){
                if (config.logUntrackedStrings) {
                    console.trace("string not tracked after ",propertyName ,"call")
                }

                newVal = nativeStringObject.prototype[propertyName].apply(oldString, args);
            }

            var actionName = capitalizeFirstCharacter(propertyName) + " Call";

            if (typeof newVal === "string") {
                return makeTraceObject(
                    {
                        value: newVal,
                        origin: new Origin({
                            error,
                            value: newVal,
                            valueItems: valueItems,
                            inputValues: inputValues,
                            action: actionName
                        })
                    }
                )
            } else if (isArray(newVal)) {
                return newVal.map(function(val){
                    if (typeof val === "string"){
                        return makeTraceObject(
                            {
                                value: val,
                                origin: new Origin({
                                    error,
                                    value: val,
                                    inputValues: inputValues,
                                    action: actionName,
                                })
                            }
                        )
                    } else {
                        return val
                    }
                })
            } else {
                // this should not really happen, although I've possibly
                // missed some functions that return numbers
                debuggerStatementFunction()
                return newVal
            }
        }
    }
})

Object.defineProperties(FromJSString.prototype, {
    valueOf: {
        value: function(){
            return this.value;
        },
        enumerable: false
    },
    toJSON: {
        value: function(){
            return this.value
        },
        enumerable: false
    },
    toString: {
        value: function(){
            return this.value
        },
        enumerable: false
    },
    indexOf: {
        value: function(search, fromIndex){
            if (search && search.isStringTraceString) {
                search = search.value
            }
            return this.value.indexOf(search, fromIndex)
        },
        enumerable: false
    },
    charCodeAt: {
        value: function(index){
            return this.value.charCodeAt(index)
        },
        enumerable: false
    },
    localeCompare: {
        value: function(){
            return this.value.localeCompare.apply(this.value, arguments)
        },
        enumerable: false
    }
})
Object.defineProperty(FromJSString.prototype, "length", {
    get: function(){
        return this.value.length;
    }
})

var traps = {
    get: function(target, name){
        if (typeof name !== "symbol" && !isNaN(name)) {
            return target.value[name]
        }

        if (name === "constructor") {
            return window.String
        }

        return target[name]
    },
    has: function(target, propName){
        throw new TypeError("Cannot use 'in' operator to search for '" + propName +"' in " + target.value)
    }
}

export function makeTraceObject(options){
    if (typeof options.value !== "string") {
        return options.value
    }
    if (options === undefined || options.value === undefined || options.origin === undefined) {
        throw "invalid options for makeTraceObject"
    }
    var stringTraceObject = new FromJSString({
        value: stringTraceUseValue(options.value),
        origin: options.origin
    })
    if (stringTraceObject.value.isStringTraceString) {
        debuggerStatementFunction()
    }

    // Make accessing characters by index work
    return new Proxy(stringTraceObject, traps);
}
<|endoftext|>


<commit_before>var db = require('../modules/database');
var Q = require('q');

// Collections
var Games = db.collection('games');
var AchievementsIndex = db.collection('achievements_index');
var CategoriesIndex = db.collection('categories_index');
var DevelopersIndex = db.collection('developers_index');
var GenresIndex = db.collection('genres_index');
var DemosIndex = db.collection('demos_index');
var LanguagesIndex = db.collection('languages_index');
var MetacriticIndex = db.collection('metacritic_index');
var PlatformsIndex = db.collection('platforms_index');
var PublishersIndex = db.collection('publishers_index');
var RecommendationsIndex = db.collection('recommendations_index');

/**
 * Make a query promise and return the promise
 * @param collection
 * @param query
 * @returns {promise|*|Function|promise|promise|promise}
 */
function makeQueryPromise(collection,query){
    var d = Q.defer();
    collection.find(query, function(err, data){
        d.resolve(err || data);
    });
    return d.promise;
}
/**
 * Ensures alphanumeric only and builds match-any regex
 * @param value
 * @returns {string}
 */
function matchAny(value){
    return '.*' + value.replace(/\W/g, '') + '.*';
}

/**
 * Check if variable is a boolean
 * @param input
 * @returns {boolean}
 */
function isTrue(input) {
    return typeof input == 'string' ? input.toLowerCase() == 'true' : !!input;
}

/**
 * Get a game by query
 * @param params {{}}
 * @param callback function
 */
exports.getGame = function(params,callback){
    console.log('params',params);
    var limit = 25;
    var query = {};
    var queue = [];

    // Find by game title
    if(params.name){
        query.name = matchAny(params.name);
    }

    // Find games by genre
    if(params.genres){
        queue.push(makeQueryPromise(GenresIndex,{
            id: {
                $in: params.genres.split(',').map(function(x){
                    return parseInt(x, 10)
                })
            }
        }));
    }

    // Find games by category
    if(params.categories){
        queue.push(makeQueryPromise(CategoriesIndex,{
            id: {
                $in: params.categories.split(',').map(function(x){
                    return parseInt(x, 10)
                })
            }
        }));
    }

    // Find games by achievement count
    if(typeof params.achievements !== 'undefined'){
        var count = parseInt(params.achievements,10);
        if(!isNaN(count)){
            //TODO: support GTE/GT/LT/LTE/EQ
            queue.push(makeQueryPromise(AchievementsIndex,{
                $gte: {total: count}
            }));
        }
    }

    // Find by publisher
    if(params.publishers){
        queue.push(makeQueryPromise(PublishersIndex,{
            name: {$in: params.publishers.split(',')}
        }));
    }

    // Find by developer
    if(params.developers){
        queue.push(makeQueryPromise(DevelopersIndex,{
            name: {$in: params.developers.split(',')}
        }));
    }

    // Find by if it has a demo
    if(typeof params.demo !== 'undefined'){
        var boolean = isTrue(params.demo);
        if(boolean){
            queue.push(makeQueryPromise(DemosIndex,{
                hasDemo: true
            }));
        }
    }

    // Set new limit if it's a number
    if(params.limit){
        params.limit = parseInt(params.limit,10);
        limit = (!isNaN(params.limit))? Math.abs(params.limit) : limit;
    }

    console.log('queue',queue);
    Q.allSettled(queue).spread(function(){
        var lists = [];
        var i = 0;
        var len = arguments.length;
        // Extract all returned values
        while(i < len){
            var argument = arguments[i];
            argument.value.forEach(function(result){
                lists.push(result.games);
            });
            i++;
        }

        // Get total queries
        var total = arguments.length;
        var combined = [];
        // Concatenate all the results into 1 array
        combined = combined.concat.apply(combined, lists);

        var occurrences = {};
        var j = 0;
        var len_j = combined.length;
        // Count the occurrences of each ID
        while(j < len_j){
            var id = combined[j];
            if (occurrences[id]) {
                occurrences[id]++;
            } else {
                occurrences[id] = 1;
            }
            j++;
        }

        // Compared occurrences with the total to see which ones match what we're searching for
        var final = [];
        for(var item in occurrences){
            if(occurrences[item] === total){
                final.push(parseInt(item,10));
            }
        }

        // Fetch the game ID we end up with and return the results
        Games.find({
            name: new RegExp(query.name, 'i'),
            steam_appid: {$in: final}
        },function(err, data){
            callback(err || data);
        }).limit(limit || 25);
    }).done();
};<commit_msg>Added metacritic filter - Fixed achievements filter<commit_after>var db = require('../modules/database');
var Q = require('q');

// Collections
var Games = db.collection('games');
var AchievementsIndex = db.collection('achievements_index');
var CategoriesIndex = db.collection('categories_index');
var DevelopersIndex = db.collection('developers_index');
var GenresIndex = db.collection('genres_index');
var DemosIndex = db.collection('demos_index');
var LanguagesIndex = db.collection('languages_index');
var MetacriticIndex = db.collection('metacritic_index');
var PlatformsIndex = db.collection('platforms_index');
var PublishersIndex = db.collection('publishers_index');
var RecommendationsIndex = db.collection('recommendations_index');

/**
 * Make a query promise and return the promise
 * @param collection
 * @param query
 * @returns {promise|*|Function|promise|promise|promise}
 */
function makeQueryPromise(collection,query){
    var d = Q.defer();
    collection.find(query, function(err, data){
        d.resolve(err || data);
    });
    return d.promise;
}
/**
 * Ensures alphanumeric only and builds match-any regex
 * @param value
 * @returns {string}
 */
function matchAny(value){
    return '.*' + value.replace(/\W/g, '') + '.*';
}

/**
 * Check if variable is a boolean
 * @param input
 * @returns {boolean}
 */
function isTrue(input) {
    return typeof input == 'string' ? input.toLowerCase() == 'true' : !!input;
}

/**
 * Get a game by query
 * @param params {{}}
 * @param callback function
 */
exports.getGame = function(params,callback){
    console.log('params',params);
    var limit = 25;
    var query = {};
    var queue = [];

    // Find by game title
    if(params.name){
        query.name = matchAny(params.name);
    }

    // Find games by genre
    if(params.genres){
        queue.push(makeQueryPromise(GenresIndex,{
            id: {
                $in: params.genres.split(',').map(function(x){
                    return parseInt(x, 10)
                })
            }
        }));
    }

    // Find games by category
    if(params.categories){
        queue.push(makeQueryPromise(CategoriesIndex,{
            id: {
                $in: params.categories.split(',').map(function(x){
                    return parseInt(x, 10)
                })
            }
        }));
    }

    // Find games by achievement count
    if(typeof params.achievements !== 'undefined'){
        var count = parseInt(params.achievements,10);
        if(!isNaN(count)){
            //TODO: support GTE/GT/LT/LTE/EQ
            queue.push(makeQueryPromise(AchievementsIndex,{
                total: {$gte: count}
            }));
        }
    }

    // Find by publisher
    if(params.publishers){
        queue.push(makeQueryPromise(PublishersIndex,{
            name: {$in: params.publishers.split(',')}
        }));
    }

    // Find by developer
    if(params.developers){
        queue.push(makeQueryPromise(DevelopersIndex,{
            name: {$in: params.developers.split(',')}
        }));
    }

    // Find by if it has a demo
    if(typeof params.demo !== 'undefined'){
        var boolean = isTrue(params.demo);
        if(boolean){
            queue.push(makeQueryPromise(DemosIndex,{
                hasDemo: true
            }));
        }
    }

    // Find by Metacritic score
    if(typeof params.metacritic !== 'undefined'){
        var score = parseInt(params.metacritic,10);
        if(!isNaN(score)){
            //TODO: support GTE/GT/LT/LTE/EQ
            queue.push(makeQueryPromise(MetacriticIndex,{
                score: {$gte: score}
            }));
        }
    }

    // Set new limit if it's a number
    if(params.limit){
        params.limit = parseInt(params.limit,10);
        limit = (!isNaN(params.limit))? Math.abs(params.limit) : limit;
    }

    console.log('queue',queue);
    Q.allSettled(queue).spread(function(){
        var lists = [];
        var i = 0;
        var len = arguments.length;
        // Extract all returned values
        while(i < len){
            var argument = arguments[i];
            argument.value.forEach(function(result){
                lists.push(result.games);
            });
            i++;
        }

        // Get total queries
        var total = arguments.length;
        var combined = [];
        // Concatenate all the results into 1 array
        combined = combined.concat.apply(combined, lists);

        var occurrences = {};
        var j = 0;
        var len_j = combined.length;
        // Count the occurrences of each ID
        while(j < len_j){
            var id = combined[j];
            if (occurrences[id]) {
                occurrences[id]++;
            } else {
                occurrences[id] = 1;
            }
            j++;
        }

        // Compared occurrences with the total to see which ones match what we're searching for
        var final = [];
        for(var item in occurrences){
            if(occurrences[item] === total){
                final.push(parseInt(item,10));
            }
        }

        // Fetch the game ID we end up with and return the results
        Games.find({
            name: new RegExp(query.name, 'i'),
            steam_appid: {$in: final}
        },function(err, data){
            callback(err || data);
        }).limit(limit || 25);
    }).done();
};<|endoftext|>


<commit_before>var fs = require('fs')
  , async = require('async')
  , scoreScraper = require('../../lib/scraper-group.js')()
  , moment = require('moment-timezone')
  ;

module.exports = function(server) {

  var Game = server.model('Game')
    , utils = server.utils
    , _ = utils._
    ;

  /**
   * Changed games.
   */
  var changedGames = function(games) {
    // Transform the scores in Integer.
    games = _.map(games, function(g) {
      g.score[0] = parseInt(g.score[0]);
      g.score[1] = parseInt(g.score[1]);
      return g;
    });

    // Filter the played games.
    games = _.filter(games, function(g) { return !_.isNaN(parseInt(g.score[0])) });

    return games;
  }

  /**
   * Update all scores.
   */
  var updateScores = function(games, callback) {
    games = changedGames(games);
    if (games.length === 0) return callback(null, 0);

    var nbUpdated = 0;
    async.each(games, function(item, cb) {
      Game.updateScore(item, function(e, isUpdated) {
        if (isUpdated) nbUpdated += 1;
        cb(e);
      });
    }, function(e) {
      callback(e, nbUpdated);
    });
  }

  /**
   * Broadcast the games.
   */
  var broadcastGames = function(date) {
    Game.findByDate(date, function(e, games) {
      if (e) console.error('Error getting the games : ', e);
      else
        server.io.broadcast('games:update', games);
    });
  }

  /**
   * Broadcast the bets results.
   */
  var broadcastBets = function(date) {
    Game.getBetsPoints(date, function(e, bets) {
      if (e) console.error('Error getting the bets : ', e);
      else {
        server.io.broadcast('bets:update', bets);
      }
    });
  }

  /**
   * Scrap scores.
   */
  var scoreScraping = setInterval(function() {

    var date = utils.getDate();

    Game.groupByDate(date, function(e, groups) {
      if (e) return console.error('Error getting the groups of the day : ', e);

      console.log('groups to scrap : ', groups);
      async.concatSeries(groups, scoreScraper.scrap, function(e, results) {
        if (e) return console.log('Error scraping the results : ', e);

        updateScores(results, function(e, nbUpdated) {
          console.log('Scraping done, at  : ', new Date(), nbUpdated);
          if (e) console.error('Error updating the scores : ', e);
          if (!e && nbUpdated > 0) {
            broadcastGames(date);
            broadcastBets(date);
          }
        });

      });
    })

  }, server.config.scraping.dt);

  /**
   * Public methods.
   */
  return {

    newScore: function(game) {
      console.log(' ==> newScore called : ', new Date(), game);
      Game.updateScore(game, function(e, isUpdated) {
        if (e) console.log(' ==> newScore error : ', e);
        else console.log(' ==> newScore score updated : ', isUpdated);
        var date = utils.getDate();
        broadcastGames(date);
        broadcastBets(date);
      });
    }

  };

};
<commit_msg>fix scraping<commit_after>var fs = require('fs')
  , async = require('async')
  , scoreScraper = require('../../lib/scraper-group.js')()
  , moment = require('moment-timezone')
  ;

module.exports = function(server) {

  var Game = server.model('Game')
    , utils = server.utils
    , _ = utils._
    ;

  /**
   * Changed games.
   */
  var changedGames = function(games) {
    // Transform the scores in Integer.
    games = _.map(games, function(g) {
      g.score[0] = parseInt(g.score[0]);
      g.score[1] = parseInt(g.score[1]);
      return g;
    });

    // Filter the played games.
    games = _.filter(games, function(g) { return !_.isNaN(parseInt(g.score[0])) });

    return games;
  }

  /**
   * Update all scores.
   */
  var updateScores = function(games, callback) {
    games = changedGames(games);
    if (games.length === 0) return callback(null, 0);

    var nbUpdated = 0;
    async.each(games, function(item, cb) {
      Game.updateScore(item, function(e, isUpdated) {
        if (isUpdated) nbUpdated += 1;
        cb(e);
      });
    }, function(e) {
      callback(e, nbUpdated);
    });
  }

  /**
   * Broadcast the games.
   */
  var broadcastGames = function(date) {
    Game.findByDate(date, function(e, games) {
      if (e) console.error('Error getting the games : ', e);
      else
        server.io.broadcast('games:update', games);
    });
  }

  /**
   * Broadcast the bets results.
   */
  var broadcastBets = function(date) {
    Game.getBetsPoints(date, function(e, bets) {
      if (e) console.error('Error getting the bets : ', e);
      else {
        server.io.broadcast('bets:update', bets);
      }
    });
  }

  /**
   * Scrap scores.
   */
  var scoreScraping = setInterval(function() {

    var date = utils.getDate();

    Game.groupByDate(date, function(e, groups) {
      if (e) return console.error('Error getting the groups of the day : ', e);

      console.log('groups to scrap : ', groups);
      if (!groups)
        return;
      async.concatSeries(groups, scoreScraper.scrap, function(e, results) {
        if (e) return console.log('Error scraping the results : ', e);

        updateScores(results, function(e, nbUpdated) {
          console.log('Scraping done, at  : ', new Date(), nbUpdated);
          if (e) console.error('Error updating the scores : ', e);
          if (!e && nbUpdated > 0) {
            broadcastGames(date);
            broadcastBets(date);
          }
        });

      });
    })

  }, server.config.scraping.dt);

  /**
   * Public methods.
   */
  return {

    newScore: function(game) {
      console.log(' ==> newScore called : ', new Date(), game);
      Game.updateScore(game, function(e, isUpdated) {
        if (e) console.log(' ==> newScore error : ', e);
        else console.log(' ==> newScore score updated : ', isUpdated);
        var date = utils.getDate();
        broadcastGames(date);
        broadcastBets(date);
      });
    }

  };

};
<|endoftext|>


<commit_before>var init = function() {

	geoLocation();
	//getWeather();
	$.index.open();

};

	// this is the event listener for the button
$.refresh.addEventListener('click',function(){
	geoLocation();
});
var getWeather = function(coords) {
	var args = arguments[0] || {};

	//getting data
	var apiCall = Ti.Network.createHTTPClient();
	apiCall.open("GET", "http://api.wunderground.com/api/0686a531a29abea6/conditions/q/"+coords.latitude +","+coords.longitude+".json");

	//on a successful load of data
	apiCall.onload = function() {
		try {
			//this takes the data from weather.com and makes it useable
			var json = JSON.parse(this.responseText);
			//this is were we are selecting the certain information from weather.com
			Ti.API.info('Full Location' + json.current_observation.display_location.full);
			Ti.API.info('temp_f= ' + json.current_observation.temp_f);
			Ti.API.info('weather=' + json.current_observation.weather);
			Ti.API.info('Feels Like=' + json.current_observation.feelslike_f);
			Ti.API.info('icon' + json.current_observation.icon_url);
			Ti.API.info('humidity =' + json.current_observation.relative_humidity);
			//wind data
			Ti.API.info('Wind direction =' + json.current_observation.wind_dir + 'mph');
			Ti.API.info('humidity =' + json.current_observation.wind_mph);
			Ti.API.info('humidity =' + json.current_observation.windchill_f);
			//pushes the data onto the index xml labels/views
			$.city.text = json.current_observation.display_location.full;
			$.temp.text = "Temp= " + json.current_observation.temp_f;
			$.feelsLike.text = "Feels Like= " + json.current_observation.feelslike_f;
			$.windMPH.text = 'Wind Speed=' + json.current_observation.wind_mph;
			$.windDir.text = 'Wind Direction=' + json.current_observation.wind_dir;
			$.windChill.text = 'Wind Chill=' + json.current_observation.windchill_f;
			$.humidity.text = "Humidity= " + json.current_observation.relative_humidity;
			$.skys.text = json.current_observation.weather;
			$.weatherIcon.image = json.current_observation.icon_url;
			wear(json.current_observation);
		} catch(e) {
			Ti.API.info(e);
		}

	};

	//executes send for data
	apiCall.send();

};
//grabbing the current location
var geoLocation = function(){
if (Ti.Geolocation.locationServicesEnabled) {
    Titanium.Geolocation.purpose = 'Get Current Location';
    Titanium.Geolocation.getCurrentPosition(function(e) {
        if (e.error) {
            Ti.API.error('Error: ' + e.error);
        } else {
            Ti.API.info(e.coords);
            getWeather(e.coords);
            Ti.API.info('lat'+e.coords.latitude);
            Ti.API.info('long'+e.coords.longitude);
        }
    });
} else {
    alert('Please enable location services');
}
};

//this is the wear function that takes the current temp and spits out what to wear

var wear = function(data) {
	if (data.temp_f < 32 && data.feelslike_f < 32) {
		$.toWear.text = "Wear a winter jacket and pants";
	} else if (data.temp_f > 33 && data.temp_f < 60 && data.feelslike_f > 33 && data.feelslike_f < 60) {
		$.toWear.text = "Light jacket and pants";
	} else if (data.temp_f > 61 && data.temp_f < 75 && data.feelslike_f > 61 && data.feelslike_f < 75) {
		$.toWear.text = "T-shirts and jeans";
	} else if (data.temp_f > 76 && data.feelslike_f > 76) {
		$.toWear.text = "Shorts and no Shirts";
	}
};

init();
<commit_msg>added stuff back<commit_after>var init = function() {

	geoLocation();
	//getWeather();
	$.index.open();

};

	// this is the event listener for the button
$.refresh.addEventListener('click',function(){
	geoLocation();
});
var getWeather = function(coords) {
	var args = arguments[0] || {};

	//getting data
	var apiCall = Ti.Network.createHTTPClient();
	apiCall.open("GET", "http://api.wunderground.com/api/0686a531a29abea6/conditions/q/"+coords.latitude +","+coords.longitude+".json");

	//on a successful load of data
	apiCall.onload = function() {
		try {
			//this takes the data from weather.com and makes it useable
			var json = JSON.parse(this.responseText);
			//this is were we are selecting the certain information from weather.com
			Ti.API.info('Full Location' + json.current_observation.display_location.full);
			Ti.API.info('temp_f= ' + json.current_observation.temp_f);
			Ti.API.info('weather=' + json.current_observation.weather);
			Ti.API.info('Feels Like=' + json.current_observation.feelslike_f);
			Ti.API.info('icon' + json.current_observation.icon_url);
			Ti.API.info('humidity =' + json.current_observation.relative_humidity);
			//wind data
			Ti.API.info('Wind direction =' + json.current_observation.wind_dir + 'mph');
			Ti.API.info('humidity =' + json.current_observation.wind_mph);
			Ti.API.info('humidity =' + json.current_observation.windchill_f);
			//pushes the data onto the index xml labels/views
			$.city.text = json.current_observation.display_location.full;
			$.temp.text = "Temp= " + json.current_observation.temp_f;
			$.feelsLike.text = "Feels Like= " + json.current_observation.feelslike_f;
			$.windMPH.text = 'Wind Speed=' + json.current_observation.wind_mph;
			$.windDir.text = 'Wind Direction=' + json.current_observation.wind_dir;
			$.windChill.text = 'Wind Chill=' + json.current_observation.windchill_f;
			$.humidity.text = "Humidity= " + json.current_observation.relative_humidity;
			$.skys.text = json.current_observation.weather;
			$.weatherIcon.image = json.current_observation.icon_url;
			wear(json.current_observation);
		} catch(e) {
			Ti.API.info(e);
		}

	};

	//executes send for data
	apiCall.send();

};
//grabbing the current location
var geoLocation = function(){
if (Ti.Geolocation.locationServicesEnabled) {
    Titanium.Geolocation.purpose = 'Get Current Location';
    Titanium.Geolocation.getCurrentPosition(function(e) {
        if (e.error) {
            Ti.API.error('Error: ' + e.error);
        } else {
            Ti.API.info(e.coords);
            getWeather(e.coords);
            Ti.API.info('lat'+e.coords.latitude);
            Ti.API.info('long'+e.coords.longitude);
        }
    });
} else {
    alert('Please enable location services');
}
};

//this is the wear function that takes the current temp and spits out what to wear

var wear = function(data) {
	if (data.feelslike_f > 16 && data.feelslike_f < 37.9) {
		$.toWear.text = "Wear a winter jacket and pants plus socks, light hat.";
	}
	else if (data.feelslike_f > 15.9 && data.feelslike_f < -10) {
		$.toWear.text = "Heavy winter jacket, sweatshirt or fleese underneith jacket, wool socks, heavy gloves, and heavy winter hat. Maybe a heavy scarf if that's your style.";
	}
	else if ( data.feelslike_f > 38 && data.feelslike_f < 60.9) {
		$.toWear.text = "Light jacket and pants";
	}
	else if (data.feelslike_f > 61 && data.feelslike_f < 74.9) {
		$.toWear.text = "T-shirt and jeans";
	}
	else if (data.feelslike_f > 75 && data.feelslike_f < 89.9) {
		$.toWear.text = "Shorts and T-shirt";
	}
	else if (data.feelslike_f > 90 && data.feelslike_f < 110) {
		$.toWear.text = "Light shirt in both material and color, light shorts, and probably sunscreen";
	}
	else {
		$.toWear.text = "Stay indoors as often as possible";
	}
};

init();
<|endoftext|>


<commit_before>var args = arguments[0] || {};

var json;
var doneLoading = false;

var url = Alloy.Globals.rootWebServiceUrl;
var dataRetriever = setPathForLibDirectory('dataRetriever/dataRetriever');
var loadingSpinner = setPathForLibDirectory('loadingSpinner/loadingSpinner');
var spinner = new loadingSpinner();
/**
 * Analytics Specific Data
 */
var analyticsPageTitle = "Home";
var analyticsPageLevel = "Home";

function setAnalyticsPageTitle(title) {
	analyticsPageTitle = title;
}

function getAnalyticsPageTitle() {
	return analyticsPageTitle;
}

function setAnalyticsPageLevel(level) {
	analyticsPageLevel = level;
}

function getAnalyticsPageLevel() {
	return analyticsPageLevel;
}

this.setAnalyticsPageTitle = setAnalyticsPageTitle;
this.getAnalyticsPageTitle = getAnalyticsPageTitle;
this.setAnalyticsPageLevel = setAnalyticsPageLevel;
this.getAnalyticsPageLevel = getAnalyticsPageLevel;
//------------------------------------------------

function setPathForLibDirectory(libFile) {
	if ( typeof Titanium == 'undefined') {
		lib = require("../../lib/" + libFile);
	} else {
		lib = require(libFile);
	}
	return lib;
};

function openExhibits() {
	if(doneLoading){
		addSpinner();
		var controller = Alloy.createController("exhibitLanding", eval([json]));
		controller.setAnalyticsPageTitle("Exhibit Landing");
		Alloy.Globals.navController.open(controller);
		hideSpinner();
	}
}

function openMap() {
	if(doneLoading){
		addSpinner();
		var controller = Alloy.createController("map", eval([json]));
		Alloy.Globals.navController.open(controller);
		hideSpinner();
	}
}

function openInfo() {
	if(doneLoading){
		addSpinner();
		var controller = Alloy.createController("info", eval([json]));
		Alloy.Globals.navController.open(controller);
		hideSpinner();
	}
}

function addSpinner(){
	spinner.addTo($.index);
	spinner.show();
}

function hideSpinner(){
	spinner.hide();
}

function retrieveJson(jsonURL) {
	addSpinner();
	dataRetriever.fetchDataFromUrl(jsonURL, function(returnedData) {
		if (returnedData) {
			json = returnedData;
			var museum = json.data.museum;

			var jsonExhibitsLabel = museum.homepage_exhibits_label;
			if(jsonExhibitsLabel) $.exhibitsLabel.text = jsonExhibitsLabel;

			var jsonMapLabel = museum.homepage_map_label;
			if(jsonMapLabel) $.mapLabel.text = jsonMapLabel;

			var jsonInfoLabel = museum.homepage_info_label;
			if(jsonInfoLabel) $.infoLabel.text = jsonInfoLabel;

			var jsonIconUrl = museum.homepage_icon;
			if(jsonIconUrl) $.iconLink.image = jsonIconUrl;

			doneLoading = true;
			hideSpinner();
		}
	});
}

function enableMenuButtons() {
	$.exhibitsLink.addEventListener("click", function() {
		openExhibits();
	});
	$.mapLink.addEventListener("click", function() {
		openMap();
	});
	$.infoLink.addEventListener("click", function() {
		openInfo();
	});
}

function formatObjectSizes() {
	var font = {
		"fontFamily" : 'KGSummerSunshineShadow'
	};

	if (Titanium.Platform.osname == "ipad"){
		font["fontSize"] = "70dp";
		$.exhibitsLabel.font = font;
		$.mapLabel.font = font;
		$.infoLabel.font = font;

	} else {
		font["fontSize"] = "35dp";
		$.exhibitsLabel.font = font;
		$.mapLabel.font = font;
		$.infoLabel.font = font;
	}
}

function init(){
	retrieveJson(url);
	formatObjectSizes();
	enableMenuButtons();
}

var reload = function(){
	doneLoading = false;
	url = Alloy.Globals.rootWebServiceUrl;
	retrieveJson(url);
};

init();

// This is how you export functions/members from index
this.reload = reload;

Alloy.Globals.navController.open(this);
<commit_msg>Changed font on home page back to default, as per Gerald's request<commit_after>var args = arguments[0] || {};

var json;
var doneLoading = false;

var url = Alloy.Globals.rootWebServiceUrl;
var dataRetriever = setPathForLibDirectory('dataRetriever/dataRetriever');
var loadingSpinner = setPathForLibDirectory('loadingSpinner/loadingSpinner');
var spinner = new loadingSpinner();
/**
 * Analytics Specific Data
 */
var analyticsPageTitle = "Home";
var analyticsPageLevel = "Home";

function setAnalyticsPageTitle(title) {
	analyticsPageTitle = title;
}

function getAnalyticsPageTitle() {
	return analyticsPageTitle;
}

function setAnalyticsPageLevel(level) {
	analyticsPageLevel = level;
}

function getAnalyticsPageLevel() {
	return analyticsPageLevel;
}

this.setAnalyticsPageTitle = setAnalyticsPageTitle;
this.getAnalyticsPageTitle = getAnalyticsPageTitle;
this.setAnalyticsPageLevel = setAnalyticsPageLevel;
this.getAnalyticsPageLevel = getAnalyticsPageLevel;
//------------------------------------------------

function setPathForLibDirectory(libFile) {
	if ( typeof Titanium == 'undefined') {
		lib = require("../../lib/" + libFile);
	} else {
		lib = require(libFile);
	}
	return lib;
};

function openExhibits() {
	if(doneLoading){
		addSpinner();
		var controller = Alloy.createController("exhibitLanding", eval([json]));
		controller.setAnalyticsPageTitle("Exhibit Landing");
		Alloy.Globals.navController.open(controller);
		hideSpinner();
	}
}

function openMap() {
	if(doneLoading){
		addSpinner();
		var controller = Alloy.createController("map", eval([json]));
		Alloy.Globals.navController.open(controller);
		hideSpinner();
	}
}

function openInfo() {
	if(doneLoading){
		addSpinner();
		var controller = Alloy.createController("info", eval([json]));
		Alloy.Globals.navController.open(controller);
		hideSpinner();
	}
}

function addSpinner(){
	spinner.addTo($.index);
	spinner.show();
}

function hideSpinner(){
	spinner.hide();
}

function retrieveJson(jsonURL) {
	addSpinner();
	dataRetriever.fetchDataFromUrl(jsonURL, function(returnedData) {
		if (returnedData) {
			json = returnedData;
			var museum = json.data.museum;

			var jsonExhibitsLabel = museum.homepage_exhibits_label;
			if(jsonExhibitsLabel) $.exhibitsLabel.text = jsonExhibitsLabel;

			var jsonMapLabel = museum.homepage_map_label;
			if(jsonMapLabel) $.mapLabel.text = jsonMapLabel;

			var jsonInfoLabel = museum.homepage_info_label;
			if(jsonInfoLabel) $.infoLabel.text = jsonInfoLabel;

			var jsonIconUrl = museum.homepage_icon;
			if(jsonIconUrl) $.iconLink.image = jsonIconUrl;

			doneLoading = true;
			hideSpinner();
		}
	});
}

function enableMenuButtons() {
	$.exhibitsLink.addEventListener("click", function() {
		openExhibits();
	});
	$.mapLink.addEventListener("click", function() {
		openMap();
	});
	$.infoLink.addEventListener("click", function() {
		openInfo();
	});
}

function formatObjectSizes() {
	var font = {
		//"fontFamily" : 'KGSummerSunshineShadow'
		fontWeight : "bold"
	};

	if (Titanium.Platform.osname == "ipad"){
		font["fontSize"] = "85dp";
		$.exhibitsLabel.font = font;
		$.mapLabel.font = font;
		$.infoLabel.font = font;

	} else {
		font["fontSize"] = "45dp";
		$.exhibitsLabel.font = font;
		$.mapLabel.font = font;
		$.infoLabel.font = font;
	}
}

function init(){
	retrieveJson(url);
	formatObjectSizes();
	enableMenuButtons();
}

var reload = function(){
	doneLoading = false;
	url = Alloy.Globals.rootWebServiceUrl;
	retrieveJson(url);
};

init();

// This is how you export functions/members from index
this.reload = reload;

Alloy.Globals.navController.open(this);
<|endoftext|>


<commit_before>import warning from '../utils/warning'
import { default as defaultSchema } from '../plugins/schema'

// Maximum recursive calls for normalization
const MAX_CALLS = 50

/**
 * Refresh a reference to a node that have been modified in a transform.
 * @param  {Transform} transform
 * @param  {Node} node
 * @return {Node} newNode
 */

function _refreshNode(transform, node) {
  const { state } = transform
  const { document } = state

  if (node.kind == 'document') {
    return document
  }

  return document.getDescendant(node.key)
}

/**
 * Normalize all children of a node
 * @param  {Transform} transform
 * @param  {Schema} schema
 * @param  {Node} node
 * @return {Transform} transform
 */

function _normalizeChildrenWith(transform, schema, node) {
  if (!node.nodes) {
    return transform
  }

  return node.nodes.reduce(
    (t, child) => {
      return t.normalizeNodeWith(schema, child)
    },
    transform
  )
}

/**
 * Normalize a node without its children
 * @param  {Transform} transform
 * @param  {Schema} schema
 * @param  {Node} node
 * @return {Transform} transform
 */

function _normalizeNodeWith(transform, schema, node) {
  const failure = schema.__validate(node)

  // Node is valid?
  if (!failure) {
    return transform
  }

  const { value, rule } = failure

  // Normalize and get the new state
  transform = rule.normalize(transform, node, value)

  // Search for the updated node in the new state
  const newNode = _refreshNode(transform, node)

  // Node no longer exist, go back to normalize parents
  if (!newNode) {
    return transform
  }

  return _normalizeNodeWith(transform, schema, newNode)
}

/**
 * Normalize a node (itself and its children) using a schema.
 *
 * @param  {Transform} transform
 * @param  {Schema} schema
 * @param  {Node} node
 * @return {Transform}
 */

export function normalizeNodeWith(transform, schema, node) {
  let recursiveCount = 0

  // Auxiliary function, called recursively, with a maximum calls safety net.
  function _recur() {
    recursiveCount++
    if (recursiveCount > MAX_CALLS) {
      warning('Unexpected number of successive normalizations. Aborting.')
      return transform
    }
    // Iterate over its children
    transform = _normalizeChildrenWith(transform, schema, node)

    // Refresh the node reference, and normalize it
    node = _refreshNode(transform, node)
    if (node) {
      transform = _normalizeNodeWith(transform, schema, node)
    }

    return transform
  }

  return _recur(transform, schema, node)
}

/**
 * Normalize a node its parents using a schema.
 *
 * @param  {Transform} transform
 * @param  {Schema} schema
 * @param  {Node} node
 * @return {Transform}
 */

export function normalizeParentsWith(transform, schema, node) {
  transform = _normalizeNodeWith(transform, schema, node)

  // Normalize went back up to the document
  if (node.kind == 'document') {
    return transform
  }

  // We search for the new parent
  node = _refreshNode(transform, node)
  if (!node) {
    return transform
  }

  const { state } = transform
  const { document } = state
  const parent = document.getParent(node.key)

  return normalizeParentsWith(transform, schema, parent)
}

/**
 * Normalize state using a schema.
 *
 * @param  {Transform} transform
 * @param  {Schema} schema
 * @return {Transform} transform
 */

export function normalizeWith(transform, schema) {
  const { state } = transform
  const { document } = state

  // Schema was not rule to edit the document
  if (!schema.isNormalization) {
    return transform
  }

  return transform.normalizeNodeWith(schema, document)
}

/**
 * Normalize the state using the core schema.
 *
 * @param  {Transform} transform
 * @return {Transform} transform
 */

export function normalize(transform) {
    return transform
        .normalizeDocument()
        .normalizeSelection()
}

/**
 * Normalize only the document
 *
 * @param  {Transform} transform
 * @return {Transform} transform
 */

export function normalizeDocument(transform) {
  return transform.normalizeWith(defaultSchema)
}

/**
 * Normalize a node and its children using core schema
 *
 * @param  {Transform} transform
 * @param  {Node or String} key
 * @return {Transform} transform
 */

export function normalizeNodeByKey(transform, key) {
  const { state } = transform
  const { document } = state
  const node = document.key == key ? document : document.assertDescendant(key)

  return transform.normalizeNodeWith(defaultSchema, node)
}

/**
 * Normalize a node and its parent using core schema
 *
 * @param  {Transform} transform
 * @param  {Node or String} key
 * @return {Transform} transform
 */

export function normalizeParentsByKey(transform, key) {
  const { state } = transform
  const { document } = state
  const node = document.key == key ? document : document.assertDescendant(key)

  return transform.normalizeParentsWith(defaultSchema, node)
}

/**
 * Normalize only the selection.
 *
 * @param  {Transform} transform
 * @return {Transform} transform
 */

export function normalizeSelection(transform) {
  let { state } = transform
  let { document, selection } = state
  selection = selection.normalize(document)

  // If the selection is nulled (not normal)
  if (
    selection.isUnset ||
    !document.hasDescendant(selection.anchorKey) ||
    !document.hasDescendant(selection.focusKey)
  ) {
      warning('Selection was invalid and reset to start of the document')
      const firstText = document.getTexts().first()
      selection = selection.merge({
        anchorKey: firstText.key,
        anchorOffset: 0,
        focusKey: firstText.key,
        focusOffset: 0,
        isBackward: false
      })
  }

  state = state.merge({ selection })
  transform.state = state
  return transform
}
<commit_msg>Recursive safety fixed, and throw error instead<commit_after>import warning from '../utils/warning'
import { default as defaultSchema } from '../plugins/schema'

// Maximum recursive calls for normalization
const MAX_CALLS = 50

/**
 * Refresh a reference to a node that have been modified in a transform.
 * @param  {Transform} transform
 * @param  {Node} node
 * @return {Node} newNode
 */

function _refreshNode(transform, node) {
  const { state } = transform
  const { document } = state

  if (node.kind == 'document') {
    return document
  }

  return document.getDescendant(node.key)
}

/**
 * Normalize all children of a node
 * @param  {Transform} transform
 * @param  {Schema} schema
 * @param  {Node} node
 * @return {Transform} transform
 */

function _normalizeChildrenWith(transform, schema, node) {
  if (!node.nodes) {
    return transform
  }

  return node.nodes.reduce(
    (t, child) => {
      return t.normalizeNodeWith(schema, child)
    },
    transform
  )
}

/**
 * Normalize a node without its children
 * @param  {Transform} transform
 * @param  {Schema} schema
 * @param  {Node} node
 * @return {Transform} transform
 */

function _normalizeNodeWith(transform, schema, node) {
  let recursiveCount = 0

  // Auxiliary function, called recursively, with a maximum calls safety net.
  function _recur(_transform, _schema, _node) {
    const failure = _schema.__validate(_node)

    // Node is valid?
    if (!failure) {
      return _transform
    }

    const { value, rule } = failure

    // Normalize and get the new state
    _transform = rule.normalize(_transform, _node, value)

    // Search for the updated node in the new state
    const newNode = _refreshNode(_transform, _node)

    // Node no longer exist, go back to normalize parents
    if (!newNode) {
      return _transform
    }

    recursiveCount++
    if (recursiveCount > MAX_CALLS) {
      throw new Error('Unexpected number of successive normalizations. Aborting.')
    }

    return _recur(_transform, _schema, _node)
  }

  return _recur(transform, schema, node)
}

/**
 * Normalize a node (itself and its children) using a schema.
 *
 * @param  {Transform} transform
 * @param  {Schema} schema
 * @param  {Node} node
 * @return {Transform}
 */

export function normalizeNodeWith(transform, schema, node) {
  // Iterate over its children
  transform = _normalizeChildrenWith(transform, schema, node)

  // Refresh the node reference, and normalize it
  node = _refreshNode(transform, node)
  if (node) {
    transform = _normalizeNodeWith(transform, schema, node)
  }

  return transform
}

/**
 * Normalize a node its parents using a schema.
 *
 * @param  {Transform} transform
 * @param  {Schema} schema
 * @param  {Node} node
 * @return {Transform}
 */

export function normalizeParentsWith(transform, schema, node) {
  transform = _normalizeNodeWith(transform, schema, node)

  // Normalize went back up to the document
  if (node.kind == 'document') {
    return transform
  }

  // We search for the new parent
  node = _refreshNode(transform, node)
  if (!node) {
    return transform
  }

  const { state } = transform
  const { document } = state
  const parent = document.getParent(node.key)

  return normalizeParentsWith(transform, schema, parent)
}

/**
 * Normalize state using a schema.
 *
 * @param  {Transform} transform
 * @param  {Schema} schema
 * @return {Transform} transform
 */

export function normalizeWith(transform, schema) {
  const { state } = transform
  const { document } = state

  // Schema was not rule to edit the document
  if (!schema.isNormalization) {
    return transform
  }

  return transform.normalizeNodeWith(schema, document)
}

/**
 * Normalize the state using the core schema.
 *
 * @param  {Transform} transform
 * @return {Transform} transform
 */

export function normalize(transform) {
    return transform
        .normalizeDocument()
        .normalizeSelection()
}

/**
 * Normalize only the document
 *
 * @param  {Transform} transform
 * @return {Transform} transform
 */

export function normalizeDocument(transform) {
  return transform.normalizeWith(defaultSchema)
}

/**
 * Normalize a node and its children using core schema
 *
 * @param  {Transform} transform
 * @param  {Node or String} key
 * @return {Transform} transform
 */

export function normalizeNodeByKey(transform, key) {
  const { state } = transform
  const { document } = state
  const node = document.key == key ? document : document.assertDescendant(key)

  return transform.normalizeNodeWith(defaultSchema, node)
}

/**
 * Normalize a node and its parent using core schema
 *
 * @param  {Transform} transform
 * @param  {Node or String} key
 * @return {Transform} transform
 */

export function normalizeParentsByKey(transform, key) {
  const { state } = transform
  const { document } = state
  const node = document.key == key ? document : document.assertDescendant(key)

  return transform.normalizeParentsWith(defaultSchema, node)
}

/**
 * Normalize only the selection.
 *
 * @param  {Transform} transform
 * @return {Transform} transform
 */

export function normalizeSelection(transform) {
  let { state } = transform
  let { document, selection } = state
  selection = selection.normalize(document)

  // If the selection is nulled (not normal)
  if (
    selection.isUnset ||
    !document.hasDescendant(selection.anchorKey) ||
    !document.hasDescendant(selection.focusKey)
  ) {
      warning('Selection was invalid and reset to start of the document')
      const firstText = document.getTexts().first()
      selection = selection.merge({
        anchorKey: firstText.key,
        anchorOffset: 0,
        focusKey: firstText.key,
        focusOffset: 0,
        isBackward: false
      })
  }

  state = state.merge({ selection })
  transform.state = state
  return transform
}
<|endoftext|>


<commit_before>var mongoose = require('mongoose')
    , User = mongoose.model('User')
    , Account = mongoose.model('Account')

//Setup for logging in via twitter
var login = function (req, res) {

    if (req.session.returnTo) {
        res.redirect(req.session.returnTo)
        delete req.session.returnTo
        return
    }
    return res.redirect('/home')
}

exports.authCallback = login
exports.session = login

exports.index = function (req, res) {
    if (!user) var user
    if (req.user)
        user = req.user
    else
        var user = ""
    res.render('home/index', {
        title: 'Index',
        user: user
    })
}

exports.login = function (req, res) {
    if (!user) var user
    if (req.user)
        user = req.user
    else
        var user = ""

    msg = req.flash('loginMessage')
    res.render("users/login", {
        title: 'Login',
        user: user,
        message: msg
   })
}

exports.logout = function (req, res) {
    req.logout()
    user=""
    res.redirect("login")
}

exports.display = function (req, res) {

    if (!req.user) return res.redirect("login")

    user = req.user

    Account
        .findOne({ email : user.email })
        .exec(function (err, accts) {
            if (err) return next(err)
            if (!accts) accts = new Account
            res.render('users/index', {
                title: user.username + "'s Dashboard - Bridges",
                user: user,
                acct: accts
            })
        })

}

exports.deletePerson = function (req, res) {

    user = req.user
    console.log(user)
    /*
    User
        .findOne({email: user.email})
        .exec(function (err, user) {
            if (err) return next(err)
                user.remove()
        })
    Account
        .findOne({email: user.email})
        .exec(function(err, acct) {
            if (err) return next(err)
                acct.remove()
        })*/
}

exports.getkey = function (req, res) {
    user = req.user
    user.generateKey()
    user.save()
    res.send(user.apikey)
}

//set up the signup
exports.signup = function (req, res) {
    res.render('users/signup', {
        title: 'Sign up',
        user: new User()
    })
}

exports.create = function (req, res) {
    var user = new User(req.body)
    user.provider = 'local'
    user.save(function (err) {
        if (err) {
            return res.render('users/signup', {
                    errors: (err.errors),
                    user: user,
                    title: 'Sign up'
             })
        }

        // manually login the user once successfully signed up
        req.logIn(user, function(err) {
            if (err) return next(err)
                return res.redirect('/')
        })
    })
}

exports.user = function (req, res, next, id) {
    User
        .findOne({ _id : id })
        .exec(function (err, user) {
            if (err) return next(err)
            if (!user) return next(new Error('Failed to load User ' + id))
                req.profile = user
            next()
        })
}
<commit_msg>delete user working properly<commit_after>var mongoose = require('mongoose')
    , User = mongoose.model('User')
    , Account = mongoose.model('Account')
    , Assignment = mongoose.model("Assignment")
//Setup for logging in via twitter
var login = function (req, res) {

    if (req.session.returnTo) {
        res.redirect(req.session.returnTo)
        delete req.session.returnTo
        return
    }
    return res.redirect('/home')
}

exports.authCallback = login
exports.session = login

exports.index = function (req, res) {
    if (!user) var user
    if (req.user)
        user = req.user
    else
        var user = ""
    res.render('home/index', {
        title: 'Index',
        user: user
    })
}

exports.login = function (req, res) {
    if (!user) var user
    if (req.user)
        user = req.user
    else
        var user = ""

    msg = req.flash('loginMessage')
    res.render("users/login", {
        title: 'Login',
        user: user,
        message: msg
   })
}

exports.logout = function (req, res) {
    req.logout()
    user=""
    res.redirect("login")
}

exports.display = function (req, res) {

    if (!req.user) return res.redirect("login")

    user = req.user

    Account
        .findOne({ email : user.email })
        .exec(function (err, accts) {
            if (err) return next(err)
            if (!accts) accts = new Account
            res.render('users/index', {
                title: user.username + "'s Dashboard - Bridges",
                user: user,
                acct: accts
            })
        })

}

exports.deletePerson = function (req, res) {

    user = req.user
    console.log("Deleting user: " + user.email)

    User
        .findOne({email: user.email})
        .exec(function (err, user) {
            if (err) return next(err)
            if (user) user.remove()
        })
    Assignment
        .find({email: user.email})
        .exec(function(err, assign) {
            if (err) return next(err)
            for (i in assign) {
                console.log(assign[i].assignmentID)
                assign[i].remove()
            }
            return res.redirect("login")
        })
    Account
        .find({email: user.email})
        .exec(function(err, acct) {
            if (err) return next(err)
            for (i in acct) {
                console.log(acct[i].domain)
                acct[i].remove()
            }
            return res.redirect("login")
        })
}

exports.getkey = function (req, res) {
    console.log(req.user)
    user = req.user
    user.generateKey()
    user.save()
    res.send(user.apikey)
}

//set up the signup
exports.signup = function (req, res) {
    res.render('users/signup', {
        title: 'Sign up',
        user: new User()
    })
}

exports.create = function (req, res) {
    console.log("Creating user: "+ req.body.email)
    var user = new User(req.body)
    user.provider = 'local'
    user.save(function (err) {
        if (err) {
            return res.render('users/signup', {
                    errors: (err.errors),
                    user: user,
                    title: 'Sign up'
             })
        }

        // manually login the user once successfully signed up
        req.logIn(user, function(err) {
            if (err) return next(err)
                return res.redirect('/')
        })
    })
}

exports.user = function (req, res, next, id) {
    User
        .findOne({ _id : id })
        .exec(function (err, user) {
            if (err) return next(err)
            if (!user) return next(new Error('Failed to load User ' + id))
                req.profile = user
            next()
        })
}
<|endoftext|>


<commit_before>// @flow

import React from 'react';
import type { Node } from 'react';
import withStyles from '../styles/withStyles';
import { duration } from '../styles/transitions';
import Transition from '../internal/Transition';
import type { TransitionCallback } from '../internal/Transition';

const reflow = elem => elem.offsetHeight;

export const styles = (theme: Object) => ({
  container: {
    height: 0,
    overflow: 'hidden',
    transition: theme.transitions.create('height'),
  },
  entered: {
    height: 'auto',
    transitionDuration: '0ms',
  },
});

export type TransitionDuration = number | { enter?: number, exit?: number } | 'auto';

type ProvidedProps = {
  classes: Object,
  transitionDuration: TransitionDuration,
  theme: Object,
};

export type Props = {
  /**
   * The content node to be collapsed.
   */
  children?: Node,
  /**
   * Useful to extend the style applied to components.
   */
  classes?: Object,
  /**
   * If `true`, the component will transition in.
   */
  in?: boolean,
  /**
   * Callback fired before the component is entering.
   */
  onEnter?: TransitionCallback,
  /**
   * Callback fired when the component is entering.
   */
  onEntering?: TransitionCallback,
  /**
   * Callback fired when the component has entered.
   */
  onEntered?: TransitionCallback,
  /**
   * Callback fired before the component is exiting.
   */
  onExit?: TransitionCallback,
  /**
   * Callback fired when the component is exiting.
   */
  onExiting?: TransitionCallback,
  /**
   * Callback fired when the component has exited.
   */
  onExited?: TransitionCallback,
  /**
   * @ignore
   */
  theme?: Object,
  /**
   * The duration for the transition, in milliseconds.
   * You may specify a single timeout for all transitions, or individually with an object.
   *
   * Set to 'auto' to automatically calculate transition time based on height.
   */
  transitionDuration?: TransitionDuration,
};

class Collapse extends React.Component<ProvidedProps & Props> {
  static defaultProps = {
    in: false,
    transitionDuration: duration.standard,
  };

  wrapper = null;

  autoTransitionDuration = undefined;

  handleEnter = element => {
    element.style.height = '0px';
    if (this.props.onEnter) {
      this.props.onEnter(element);
    }
  };

  handleEntering = element => {
    const { transitionDuration, theme } = this.props;
    const wrapperHeight = this.wrapper ? this.wrapper.clientHeight : 0;

    if (transitionDuration === 'auto') {
      const duration2 = theme.transitions.getAutoHeightDuration(wrapperHeight);
      element.style.transitionDuration = `${duration2}ms`;
      this.autoTransitionDuration = duration2;
    } else if (typeof transitionDuration === 'number') {
      element.style.transitionDuration = `${transitionDuration}ms`;
    } else if (transitionDuration) {
      element.style.transitionDuration = `${transitionDuration.enter}ms`;
    } else {
      // The propType will warn in this case.
    }

    element.style.height = `${wrapperHeight}px`;

    if (this.props.onEntering) {
      this.props.onEntering(element);
    }
  };

  handleEntered = element => {
    element.style.transitionDuration = '0ms'; // safari fix
    element.style.height = 'auto';
    reflow(element);
    if (this.props.onEntered) {
      this.props.onEntered(element);
    }
  };

  handleExit = element => {
    const wrapperHeight = this.wrapper ? this.wrapper.clientHeight : 0;
    element.style.height = `${wrapperHeight}px`;
    if (this.props.onExit) {
      this.props.onExit(element);
    }
  };

  handleExiting = element => {
    const { transitionDuration, theme } = this.props;
    const wrapperHeight = this.wrapper ? this.wrapper.clientHeight : 0;

    if (transitionDuration) {
      if (transitionDuration === 'auto') {
        const duration2 = theme.transitions.getAutoHeightDuration(wrapperHeight);
        element.style.transitionDuration = `${duration2}ms`;
        this.autoTransitionDuration = duration2;
      } else if (typeof transitionDuration === 'number') {
        element.style.transitionDuration = `${transitionDuration}ms`;
      } else if (transitionDuration) {
        element.style.transitionDuration = `${transitionDuration.exit}ms`;
      } else {
        // The propType will warn in this case.
      }
    }

    element.style.height = '0px';
    if (this.props.onExiting) {
      this.props.onExiting(element);
    }
  };

  handleRequestTimeout = () => {
    if (this.props.transitionDuration === 'auto') {
      return this.autoTransitionDuration || 0;
    }
    return this.props.transitionDuration;
  };

  render() {
    const {
      children,
      classes,
      onEnter,
      onEntering,
      onExit,
      onExiting,
      transitionDuration,
      theme,
      ...other
    } = this.props;

    return (
      <Transition
        onEntering={this.handleEntering}
        onEnter={this.handleEnter}
        onEntered={this.handleEntered}
        enteredClassName={classes.entered}
        onExiting={this.handleExiting}
        onExit={this.handleExit}
        onRequestTimeout={this.handleRequestTimeout}
        {...other}
      >

 {
              this.wrapper = node;
            }}
          >
            {children}

      </Transition>
    );
  }
}

export default withStyles(styles, {
  withTheme: true,
  name: 'MuiCollapse',
})(Collapse);
<commit_msg>Omit onEntered prop from other (#8499)<commit_after>// @flow

import React from 'react';
import type { Node } from 'react';
import withStyles from '../styles/withStyles';
import { duration } from '../styles/transitions';
import Transition from '../internal/Transition';
import type { TransitionCallback } from '../internal/Transition';

const reflow = elem => elem.offsetHeight;

export const styles = (theme: Object) => ({
  container: {
    height: 0,
    overflow: 'hidden',
    transition: theme.transitions.create('height'),
  },
  entered: {
    height: 'auto',
    transitionDuration: '0ms',
  },
});

export type TransitionDuration = number | { enter?: number, exit?: number } | 'auto';

type ProvidedProps = {
  classes: Object,
  transitionDuration: TransitionDuration,
  theme: Object,
};

export type Props = {
  /**
   * The content node to be collapsed.
   */
  children?: Node,
  /**
   * Useful to extend the style applied to components.
   */
  classes?: Object,
  /**
   * If `true`, the component will transition in.
   */
  in?: boolean,
  /**
   * Callback fired before the component is entering.
   */
  onEnter?: TransitionCallback,
  /**
   * Callback fired when the component is entering.
   */
  onEntering?: TransitionCallback,
  /**
   * Callback fired when the component has entered.
   */
  onEntered?: TransitionCallback,
  /**
   * Callback fired before the component is exiting.
   */
  onExit?: TransitionCallback,
  /**
   * Callback fired when the component is exiting.
   */
  onExiting?: TransitionCallback,
  /**
   * Callback fired when the component has exited.
   */
  onExited?: TransitionCallback,
  /**
   * @ignore
   */
  theme?: Object,
  /**
   * The duration for the transition, in milliseconds.
   * You may specify a single timeout for all transitions, or individually with an object.
   *
   * Set to 'auto' to automatically calculate transition time based on height.
   */
  transitionDuration?: TransitionDuration,
};

class Collapse extends React.Component<ProvidedProps & Props> {
  static defaultProps = {
    in: false,
    transitionDuration: duration.standard,
  };

  wrapper = null;

  autoTransitionDuration = undefined;

  handleEnter = element => {
    element.style.height = '0px';
    if (this.props.onEnter) {
      this.props.onEnter(element);
    }
  };

  handleEntering = element => {
    const { transitionDuration, theme } = this.props;
    const wrapperHeight = this.wrapper ? this.wrapper.clientHeight : 0;

    if (transitionDuration === 'auto') {
      const duration2 = theme.transitions.getAutoHeightDuration(wrapperHeight);
      element.style.transitionDuration = `${duration2}ms`;
      this.autoTransitionDuration = duration2;
    } else if (typeof transitionDuration === 'number') {
      element.style.transitionDuration = `${transitionDuration}ms`;
    } else if (transitionDuration) {
      element.style.transitionDuration = `${transitionDuration.enter}ms`;
    } else {
      // The propType will warn in this case.
    }

    element.style.height = `${wrapperHeight}px`;

    if (this.props.onEntering) {
      this.props.onEntering(element);
    }
  };

  handleEntered = element => {
    element.style.transitionDuration = '0ms'; // safari fix
    element.style.height = 'auto';
    reflow(element);
    if (this.props.onEntered) {
      this.props.onEntered(element);
    }
  };

  handleExit = element => {
    const wrapperHeight = this.wrapper ? this.wrapper.clientHeight : 0;
    element.style.height = `${wrapperHeight}px`;
    if (this.props.onExit) {
      this.props.onExit(element);
    }
  };

  handleExiting = element => {
    const { transitionDuration, theme } = this.props;
    const wrapperHeight = this.wrapper ? this.wrapper.clientHeight : 0;

    if (transitionDuration) {
      if (transitionDuration === 'auto') {
        const duration2 = theme.transitions.getAutoHeightDuration(wrapperHeight);
        element.style.transitionDuration = `${duration2}ms`;
        this.autoTransitionDuration = duration2;
      } else if (typeof transitionDuration === 'number') {
        element.style.transitionDuration = `${transitionDuration}ms`;
      } else if (transitionDuration) {
        element.style.transitionDuration = `${transitionDuration.exit}ms`;
      } else {
        // The propType will warn in this case.
      }
    }

    element.style.height = '0px';
    if (this.props.onExiting) {
      this.props.onExiting(element);
    }
  };

  handleRequestTimeout = () => {
    if (this.props.transitionDuration === 'auto') {
      return this.autoTransitionDuration || 0;
    }
    return this.props.transitionDuration;
  };

  render() {
    const {
      children,
      classes,
      onEnter,
      onEntering,
      onEntered,
      onExit,
      onExiting,
      transitionDuration,
      theme,
      ...other
    } = this.props;

    return (
      <Transition
        onEntering={this.handleEntering}
        onEnter={this.handleEnter}
        onEntered={this.handleEntered}
        enteredClassName={classes.entered}
        onExiting={this.handleExiting}
        onExit={this.handleExit}
        onRequestTimeout={this.handleRequestTimeout}
        {...other}
      >

 {
              this.wrapper = node;
            }}
          >
            {children}

      </Transition>
    );
  }
}

export default withStyles(styles, {
  withTheme: true,
  name: 'MuiCollapse',
})(Collapse);
<|endoftext|>


<commit_before>/*
Class: ResponsiveHandler
Monitor changes in breakpoints for responsive sites.
*/
/* global define, clearTimeout, setTimeout, window */
define(['jquery', 'tmclasses/tmclasses'], function(__jQuery, __tmclasses){
	var __ResponsiveHandler = __tmclasses.create({
		init: function(){
			var _this = this;
			this.__parent(arguments);
			if(__jQuery){
				__jQuery(window).on('resize', function(_event){
					_this.handleResize(_event);
				});
			}
			this.current = this.determineBreakPoint();
		}
		,properties: {
			/*
			Property: breakpoints
			Map of break point names to values.  Must be in order from smallest to greatest.
			*/
			breakpoints: {
				'nvp': 48
				,'wvp': 100
			}
			/*
			Property: container
			Element to get value for break point from
			*/
			,container: __jQuery && __jQuery('html')
			,current: null
			,delay: 100
			,getBreakPoint: function(_re){
				var _breakpoint;
				if(_re || !this.current){
					_breakpoint = this.determineBreakPoint();
					if(this.current !== _breakpoint){
						this.current = this.determineBreakPoint();
					}
				}
				return this.current;
			}
			,getResizeData: function(_re){
				var _current = this.current;
				return {
					breakPoint: this.getBreakPoint(_re)
					,lastBreakPoint: _current
				};
			}
			,handleResize: function(_event){
				var _this = this;
				clearTimeout(this.timeout);
				this.timeout = setTimeout(function(){
					var _resizeData = _this.getResizeData(true);
					if(_resizeData.breakPoint !== _resizeData.lastBreakPoint){
						_resizeData.event = _event;
						_this.pub('change', _resizeData);
					}
					_this.pub('resize');
				}, this.delay);
			}
			,method: 'lineHeight'
			,determineBreakPoint: function(){
				var _currentValue, _maxPoint, _point, _pointValue;
				switch(this.method){
					case 'lineHeight':
						_currentValue = this.container.css('line-height');
						if(_currentValue.indexOf('px') > -1){
							_currentValue = parseFloat(_currentValue, 10) / 10;
						}
					break;
					case 'width':
						_currentValue = this.container.width();
						if(_currentValue.indexOf('px') > -1){
							_currentValue = parseFloat(_currentValue, 10);
						}
					break;
				}
				for(_point in this.breakpoints){
					if(this.breakpoints.hasOwnProperty(_point)){
						_pointValue = this.breakpoints[_point];
						if(_currentValue <= _pointValue){
							_maxPoint = _point;
							break;
						}
					}
				}
				return _maxPoint;
			}
			,timeout: null
		}
	});
	return __ResponsiveHandler;
});
<commit_msg>ua/ResponsiveHandler: added `isNVP()` method, which is used by 'ui/ExpandGallery'<commit_after>/*
Class: ResponsiveHandler
Monitor changes in breakpoints for responsive sites.
*/
/* global define, clearTimeout, setTimeout, window */
define(['jquery', 'tmclasses/tmclasses'], function(__jQuery, __tmclasses){
	var __ResponsiveHandler = __tmclasses.create({
		init: function(){
			var _this = this;
			this.__parent(arguments);
			if(__jQuery){
				__jQuery(window).on('resize', function(_event){
					_this.handleResize(_event);
				});
			}
			this.current = this.determineBreakPoint();
		}
		,properties: {
			/*
			Property: breakpoints
			Map of break point names to values.  Must be in order from smallest to greatest.
			*/
			breakpoints: {
				'nvp': 48
				,'wvp': 100
			}
			/*
			Property: container
			Element to get value for break point from
			*/
			,container: __jQuery && __jQuery('html')
			,current: null
			,delay: 100
			,getBreakPoint: function(_re){
				var _breakpoint;
				if(_re || !this.current){
					_breakpoint = this.determineBreakPoint();
					if(this.current !== _breakpoint){
						this.current = this.determineBreakPoint();
					}
				}
				return this.current;
			}
			,getResizeData: function(_re){
				var _current = this.current;
				return {
					breakPoint: this.getBreakPoint(_re)
					,lastBreakPoint: _current
				};
			}
			,handleResize: function(_event){
				var _this = this;
				clearTimeout(this.timeout);
				this.timeout = setTimeout(function(){
					var _resizeData = _this.getResizeData(true);
					if(_resizeData.breakPoint !== _resizeData.lastBreakPoint){
						_resizeData.event = _event;
						_this.pub('change', _resizeData);
					}
					_this.pub('resize');
				}, this.delay);
			}
			/*
			Method: isNVP
			Determine if passed breakpoint is considered narrow viewport.  Meant to be overridden if it is more complex than the default.
			*/
			,isNVP: function(_bp){
				return (_bp === 'nvp');
			}
			,method: 'lineHeight'
			,determineBreakPoint: function(){
				var _currentValue, _maxPoint, _point, _pointValue;
				switch(this.method){
					case 'lineHeight':
						_currentValue = this.container.css('line-height');
						if(_currentValue.indexOf('px') > -1){
							_currentValue = parseFloat(_currentValue, 10) / 10;
						}
					break;
					case 'width':
						_currentValue = this.container.width();
						if(_currentValue.indexOf('px') > -1){
							_currentValue = parseFloat(_currentValue, 10);
						}
					break;
				}
				for(_point in this.breakpoints){
					if(this.breakpoints.hasOwnProperty(_point)){
						_pointValue = this.breakpoints[_point];
						if(_currentValue <= _pointValue){
							_maxPoint = _point;
							break;
						}
					}
				}
				return _maxPoint;
			}
			,timeout: null
		}
	});
	return __ResponsiveHandler;
});
<|endoftext|>