<commit_before>"use strict";
var ECSAction = Java.type("com.cardshifter.modapi.actions.ECSAction");
var Players = Java.type("com.cardshifter.modapi.players.Players");
var Cards = Java.type("com.cardshifter.modapi.cards.Cards");
var ComponentRetriever = Java.type("com.cardshifter.modapi.base.ComponentRetriever");
var keywords = {};
keywords.cards = {};
keywords.afterCards = [];
keywords.moreSystems = [];
keywords.effects = {};

function resolveFilter(entity, filter) {
    return function (source, target) {
        var result = true;
        if (filter.samePlayer) {
            result = result && Players.findOwnerFor(source) == Players.findOwnerFor(target);
        }
        if (filter.zone) {
            var card = ComponentRetriever.retreiverFor(com.cardshifter.modapi.cards.CardComponent.class);
            var targetCard = card.get(target);
            if (!targetCard) {
                return false;
            }
            result = result && targetCard.currentZone.name === filter.zone;
        }
        if (filter.creature) {
            result = result && target.hasComponent(com.cardshifter.modapi.base.CreatureTypeComponent.class);
        }
        return result;
    };
}

function resolveModifier(entity, data) {
    var priority = data.priority;
    var res = data.res;

    var change = data.change;
    var appliesTo = resolveFilter(entity, data.filter);
    var active = function (entity) {
        return !entity.removed;
    };
    var amount = function (source, target, resource, actualValue) {
        return actualValue + data.change;
    };

    print("EntityModifier " + entity + " prio " + priority + " applies " + appliesTo + " amount " + amount);
    var obj = new com.cardshifter.modapi.resources.EntityModifier(entity, priority, active, appliesTo, amount);
    return obj;

}

function resolveModifiers(entity, data) {
    var result = [];
    for (var i = 0; i < data.length; i++) {
        var modifierData = data[i];

        var modifier = resolveModifier(entity, modifierData);
        result.push({ res: modifierData.res, object: modifier });
    }
    return result;
}

function zoneLookup(entity, zoneName) {
    return entity.getSuperComponents(com.cardshifter.modapi.cards.ZoneComponent.class).stream()
        .filter(function(zone) { return zone.name.equals(zoneName); }).findAny()
        .orElseThrow(function() {
            return new java.lang.IllegalStateException("No zone found with name '" + zoneName + "' on " + entity);
        });
}

function valueDescription(value) {
    if (typeof value === 'number') {
        return value;
    } else if (typeof value === 'object') {
        if (value.func && value.description) {
            return "X (where X is " + value.description + ")";
        }
        return value.min + " to " + value.max;
    } else {
        throw new Error("Unknown type for value: " + value + " with type " + typeof value);
    }
}

function valueLookup(entity, value) {
    if (typeof value === 'number') {
        return value;
    } else if (typeof value === 'object') {
        if (value.func && value.description) {
            return value.func(entity);
        }
        return entity.game.randomRange(value.min, value.max);
    } else {
        throw new Error("Unknown type for value: " + value + " with type " + typeof value);
    }
}

function entityLookup(origin, who) {
    if (who === 'owner') {
        return Players.findOwnerFor(origin);
    }
    if (who === 'opponent') {
        return Players.getNextPlayer(Players.findOwnerFor(origin));
    }
    if (who === 'this') {
        return origin;
    }
    throw new Error("unexpected target for entity lookup: " + who);
}

function applyEffect(obj) {
    print("applyEffect " + obj);

    var result = null;

    for (var property in obj) {
        if (obj.hasOwnProperty(property)) {
            var value = obj[property];
            print("property found: " + property + " with value " + value + " keyword data is " + keywords.effects[property]);
            if (keywords.effects[property] === undefined) {
                print("keyword " + property + " is undefined");
                throw new Error("property " + property + " was found but is not a declared keyword");
            }
            if (result !== null) {
                throw new Error("currently only supporting one effect");
            }
            result = {};
            result.description = keywords.effects[property].description(value);
            result.action = keywords.effects[property].action(value);
        }
    }
    return result;
}

function requireActions(actions) {
    for (var i = 0; i < actions.length; i++) {
        var type = typeof actions[i];
        if (type !== 'string') {
            throw new Error("A required action constant was not found: index " + i + ", expected String but was " + type);
        }
    }
}

function createResource(name) {
    return new com.cardshifter.modapi.resources.ECSResourceDefault(name);
}

function applyEntity(game, card, entity, keyword) {
    print("applyEntity " + card + ": " + entity);

    for (var property in card) {
        if (card.hasOwnProperty(property)) {
            var value = card[property];
            print("property found: " + property + " with value " + value + " keyword data is " + keyword[property]);
            if (keyword[property] === undefined) {
                print("keyword " + property + " is undefined");
                throw new Error("property " + property + " was found but is not a declared keyword");
            }
            keyword[property].call(null, entity, card, value);
        }
    }

}

function applyCardKeywords(game, zone, data) {
    var cardEntities = [];
    for (var i = 0; i < data.cards.length; i++) {
        var card = data.cards[i];
        var entity = game.newEntity();
        applyEntity(game, card, entity, keywords.cards);
        zone.addOnBottom(entity);
        cardEntities.push(entity);
    }
    for (var i = 0; i < keywords.afterCards.length; i++) {
        keywords.afterCards[i](game, data, cardEntities);
    }
}

function applySystem(game, data, keyword) {
    print("applySystem " + data);

    for (var property in data) {
        if (data.hasOwnProperty(property)) {
            var value = data[property];
            print("property found: " + property + " with value " + value + " keyword data is " + keyword[property]);
            if (keyword[property] === undefined) {
                print("keyword " + property + " is undefined");
                throw new Error("property " + property + " was found but is not a declared keyword");
            }
            var system = keyword[property].call(null, game, data, value);
            game.addSystem(system);
        }
    }
}

function applySystems(game, data) {
    for (var i = 0; i < keywords.moreSystems.length; i++) {
        keywords.moreSystems[i](game, data);
    }

    for (var i = 0; i < data.length; i++) {
        var system = data[i];
        if (system instanceof com.cardshifter.modapi.base.ECSSystem) {
            game.addSystem(system);
        } else {
            applySystem(game, system, keywords.systems);
        }
    }
}
<commit_msg>refactored filter keywords<commit_after>"use strict";
var ECSAction = Java.type("com.cardshifter.modapi.actions.ECSAction");
var Players = Java.type("com.cardshifter.modapi.players.Players");
var Cards = Java.type("com.cardshifter.modapi.cards.Cards");
var ComponentRetriever = Java.type("com.cardshifter.modapi.base.ComponentRetriever");
var keywords = {};
keywords.cards = {};
keywords.afterCards = [];
keywords.moreSystems = [];
keywords.effects = {};
keywords.filters = {};

keywords.filters.owner = {
    description: function (value) {
        return "owned by " + value;
    },
    func: function (entity, filter) {
        if (filter === "owner") {
            return function (source, target) {
                return Players.findOwnerFor(source) === Players.findOwnerFor(target);
            }
        }
        if (filter === "opponent") {
            return function (source, target) {
                var src = Players.findOwnerFor(source);
                var dst = Players.findOwnerFor(target);
                return (src !== null) && (dst !== null) && (src !== dst);
            }
        }
        if (filter === "next") {
            return function (source, target) {
                return Players.getNextPlayer(Players.findOwnerFor(source)) === Players.findOwnerFor(target);
            }
        }
        if (filter === "none") {
            return function (source, target) {
                return Players.findOwnerFor(target) === null;
            }
        }
        if (filter === "active") {
            return function (source, target) {
                var phaseController = ComponentRetriever.singleton(source.game, com.cardshifter.modapi.phase.PhaseController.class);
                return Players.findOwnerFor(target) === phaseController.currentPhase.owner;
            }
        }
        if (filter === "inactive") {
            return function (source, target) {
                var phaseController = ComponentRetriever.singleton(source.game, com.cardshifter.modapi.phase.PhaseController.class);
                return Players.findOwnerFor(target) !== phaseController.currentPhase.owner;
            }
        }
    }
};

keywords.filters.zone = {
    description: function (value) {
        return "on " + value;
    },
    func: function (entity, filter) {
        return function (source, target) {
            if (!target.hasComponent(com.cardshifter.modapi.cards.CardComponent.class)) {
                return false;
            }
            var card = ComponentRetriever.retreiverFor(com.cardshifter.modapi.cards.CardComponent.class);
            var targetCard = card.get(target);
            return targetCard.currentZone !== null && targetCard.currentZone.name === filter;
        }
    }
};

keywords.filters.creature = {
    description: function (value) {
        return "creature";
    },
    func: function (entity, filter) {
        return function (source, target) {
            return target.hasComponent(com.cardshifter.modapi.base.CreatureTypeComponent.class);
        }
    }
};

keywords.filters.creatureType = {
    description: function (value) {
        return value + " creatures";
    },
    func: function (entity, filter) {
        return function (source, target) {
            return filter === target.getComponent(com.cardshifter.modapi.base.CreatureTypeComponent.class).creatureType;
        }
    }
};

function resolveFilter(entity, filter) {
    var description = "";
    var functions = [];

    for (var property in filter) {
        if (filter.hasOwnProperty(property)) {
            var value = filter[property];
            print("property found: " + property + " with value " + value + " keyword data is " + keywords.effects[property]);
            if (keywords.filters[property] === undefined) {
                print("keyword " + property + " is undefined");
                throw new Error("property " + property + " was found but is not a declared keyword");
            }
            description += keywords.filters[property].description(value);
            functions.push(keywords.filters[property].func(entity, value));
        }
    }
    return function (source, target) {
        for (var i = 0; i < functions.length; i++) {
            var fnc = functions[i](source, target);
            if (!fnc) {
                return false;
            }
        }
        return true;
    };
}

function resolveModifier(entity, data) {
    var priority = data.priority;
    var res = data.res;

    var change = data.change;
    var appliesTo = resolveFilter(entity, data.filter);
    var active = function (entity) {
        return !entity.removed;
    };
    var amount = function (source, target, resource, actualValue) {
        return actualValue + data.change;
    };

    print("EntityModifier " + entity + " prio " + priority + " applies " + appliesTo + " amount " + amount);
    var obj = new com.cardshifter.modapi.resources.EntityModifier(entity, priority, active, appliesTo, amount);
    return obj;

}

function resolveModifiers(entity, data) {
    var result = [];
    for (var i = 0; i < data.length; i++) {
        var modifierData = data[i];

        var modifier = resolveModifier(entity, modifierData);
        result.push({ res: modifierData.res, object: modifier });
    }
    return result;
}

function zoneLookup(entity, zoneName) {
    return entity.getSuperComponents(com.cardshifter.modapi.cards.ZoneComponent.class).stream()
        .filter(function(zone) { return zone.name.equals(zoneName); }).findAny()
        .orElseThrow(function() {
            return new java.lang.IllegalStateException("No zone found with name '" + zoneName + "' on " + entity);
        });
}

function valueDescription(value) {
    if (typeof value === 'number') {
        return value;
    } else if (typeof value === 'object') {
        if (value.func && value.description) {
            return "X (where X is " + value.description + ")";
        }
        return value.min + " to " + value.max;
    } else {
        throw new Error("Unknown type for value: " + value + " with type " + typeof value);
    }
}

function valueLookup(entity, value) {
    if (typeof value === 'number') {
        return value;
    } else if (typeof value === 'object') {
        if (value.func && value.description) {
            return value.func(entity);
        }
        return entity.game.randomRange(value.min, value.max);
    } else {
        throw new Error("Unknown type for value: " + value + " with type " + typeof value);
    }
}

function entityLookup(origin, who) {
    if (who === 'owner') {
        return Players.findOwnerFor(origin);
    }
    if (who === 'opponent') {
        return Players.getNextPlayer(Players.findOwnerFor(origin));
    }
    if (who === 'this') {
        return origin;
    }
    throw new Error("unexpected target for entity lookup: " + who);
}

function applyEffect(obj) {
    print("applyEffect " + obj);

    var result = null;

    for (var property in obj) {
        if (obj.hasOwnProperty(property)) {
            var value = obj[property];
            print("property found: " + property + " with value " + value + " keyword data is " + keywords.effects[property]);
            if (keywords.effects[property] === undefined) {
                print("keyword " + property + " is undefined");
                throw new Error("property " + property + " was found but is not a declared keyword");
            }
            if (result !== null) {
                throw new Error("currently only supporting one effect");
            }
            result = {};
            result.description = keywords.effects[property].description(value);
            result.action = keywords.effects[property].action(value);
        }
    }
    return result;
}

function requireActions(actions) {
    for (var i = 0; i < actions.length; i++) {
        var type = typeof actions[i];
        if (type !== 'string') {
            throw new Error("A required action constant was not found: index " + i + ", expected String but was " + type);
        }
    }
}

function createResource(name) {
    return new com.cardshifter.modapi.resources.ECSResourceDefault(name);
}

function applyEntity(game, card, entity, keyword) {
    print("applyEntity " + card + ": " + entity);

    for (var property in card) {
        if (card.hasOwnProperty(property)) {
            var value = card[property];
            print("property found: " + property + " with value " + value + " keyword data is " + keyword[property]);
            if (keyword[property] === undefined) {
                print("keyword " + property + " is undefined");
                throw new Error("property " + property + " was found but is not a declared keyword");
            }
            keyword[property].call(null, entity, card, value);
        }
    }

}

function applyCardKeywords(game, zone, data) {
    var cardEntities = [];
    for (var i = 0; i < data.cards.length; i++) {
        var card = data.cards[i];
        var entity = game.newEntity();
        applyEntity(game, card, entity, keywords.cards);
        zone.addOnBottom(entity);
        cardEntities.push(entity);
    }
    for (var i = 0; i < keywords.afterCards.length; i++) {
        keywords.afterCards[i](game, data, cardEntities);
    }
}

function applySystem(game, data, keyword) {
    print("applySystem " + data);

    for (var property in data) {
        if (data.hasOwnProperty(property)) {
            var value = data[property];
            print("property found: " + property + " with value " + value + " keyword data is " + keyword[property]);
            if (keyword[property] === undefined) {
                print("keyword " + property + " is undefined");
                throw new Error("property " + property + " was found but is not a declared keyword");
            }
            var system = keyword[property].call(null, game, data, value);
            game.addSystem(system);
        }
    }
}

function applySystems(game, data) {
    for (var i = 0; i < keywords.moreSystems.length; i++) {
        keywords.moreSystems[i](game, data);
    }

    for (var i = 0; i < data.length; i++) {
        var system = data[i];
        if (system instanceof com.cardshifter.modapi.base.ECSSystem) {
            game.addSystem(system);
        } else {
            applySystem(game, system, keywords.systems);
        }
    }
}
<|endoftext|>


<commit_before>"use strict";

function propertyEquals(pTo, pRule, pProperty) {
    return pRule.to.hasOwnProperty(pProperty)
        ? pTo[pProperty] === pRule.to[pProperty]
        : true;
}

function intersects(pToDependencyTypes, pRuleDependencyTypes) {
    return pToDependencyTypes.some(
        pDepType => pRuleDependencyTypes.some(
            pRDepType => pDepType === pRDepType
        )
    );
}

/* if there is at least one group expression in the given pRulePath
   return the first matched one.
   return null in all other cases

   This fills our current need. Later we can expand it to return all group
   matches.
*/

function extractGroups(pRule, pActualPath) {
    let lRetval = [];

    if (Boolean(pRule.path)) {
        let lMatchResult = pActualPath.match(pRule.path);

        if (Boolean(lMatchResult) && lMatchResult.length > 1) {
            lRetval = lMatchResult;
        }
    }
    return lRetval;
}

function replaceGroupPlaceholders(pString, pExtractedGroups) {
    return pExtractedGroups.reduce(
        (pAll, pThis, pIndex) => pAll.replace(`$${pIndex}`, pThis),
        pString
    );
}

function matchRule(pFrom, pTo) {
    return pRule => {
        const lGroups = extractGroups(pRule.from, pFrom);

        /*
         * the replace("$1", lGroup) things below are a bit simplistic (they
         * also match \$, which they probably shouldn't) - but good enough for
         * now.
         */
        return (!Boolean(pRule.from.path) ||
                pFrom.match(pRule.from.path)
        ) && (!Boolean(pRule.from.pathNot) ||
                !(pFrom.match(pRule.from.pathNot))
        ) && (!Boolean(pRule.to.path) ||
                (lGroups.length > 0
                    ? pTo.resolved.match(replaceGroupPlaceholders(pRule.to.path, lGroups))
                    : pTo.resolved.match(pRule.to.path))
        ) && (!Boolean(pRule.to.pathNot) ||
                !(
                    (lGroups.length > 0
                        ? pTo.resolved.match(replaceGroupPlaceholders(pRule.to.pathNot, lGroups))
                        : pTo.resolved.match(pRule.to.pathNot))
                )
        ) && (!pRule.to.hasOwnProperty("dependencyTypes") ||
                intersects(pTo.dependencyTypes, pRule.to.dependencyTypes)
        ) && (!pRule.to.hasOwnProperty("moreThanOneDependencyType") ||
                pTo.dependencyTypes.length > 1
        ) && (!pRule.to.hasOwnProperty("license") ||
                pTo.license && pTo.license.match(pRule.to.license)
        ) && (!pRule.to.hasOwnProperty("licenseNot") ||
                pTo.license && !pTo.license.match(pRule.to.licenseNot)
        ) && propertyEquals(pTo, pRule, "couldNotResolve") &&
                 propertyEquals(pTo, pRule, "circular");
    };
}

function validateAgainstRules(pRuleSet, pFrom, pTo) {
    let lMatchedRule = {};

    if (pRuleSet.hasOwnProperty("allowed")){
        lMatchedRule = pRuleSet.allowed.find(matchRule(pFrom, pTo));
        if (!Boolean(lMatchedRule)){
            return {
                valid: false,
                rule: {
                    severity: "warn",
                    name: "not-in-allowed"
                }
            };
        }
    }
    if (pRuleSet.hasOwnProperty("forbidden")){
        lMatchedRule = pRuleSet.forbidden.find(matchRule(pFrom, pTo));
        if (Boolean(lMatchedRule)){
            return {
                valid: false,
                rule: {
                    severity : lMatchedRule.severity,
                    name     : lMatchedRule.name
                }
            };
        }
    }
    return {valid:true};
}

/**
 * If pValidate equals true, validates the pFrom and pTo
 * dependency pair against the given ruleset pRuleSet
 *
 * @param  {Boolean} pValidate whether or not to validate at all
 * @param  {object} pRuleSet  a ruleset (adhering to
 *                            [the ruleset schema](jsonschema.json))
 * @param  {object} pFrom     The from part of the dependency
 * @param  {object} pTo       The 'to' part of the dependency
 * @return {object}           an object with as attributes:
 *                            - valid: (boolean) true if the relation
 *                              between pTo and pFalse is valid (as far as the
 *                              given ruleset is concerend). false in all other
 *                              cases.
 *                            - rule (only when the relation between pFrom and
 *                              pTo was false):
 *                              - name: the name (from the ruleset) of the
 *                                  violated rule
 *                              - severity: the severity of that rule - as per
 *                                  the ruleset
 */
module.exports = (pValidate, pRuleSet, pFrom, pTo) => {
    if (!pValidate) {
        return {valid:true};
    }
    return validateAgainstRules(pRuleSet, pFrom, pTo);
};

/* ignore security/detect-object-injection because:
   - we only use it from within the module with two fixed values
   - the propertyEquals function is not exposed externaly
 */
/* eslint security/detect-object-injection: 0, complexity: 0 */
<commit_msg>style(validate): do attribute existence detection more uniformly<commit_after>"use strict";

function propertyEquals(pTo, pRule, pProperty) {
    return pRule.to.hasOwnProperty(pProperty)
        ? pTo[pProperty] === pRule.to[pProperty]
        : true;
}

function intersects(pToDependencyTypes, pRuleDependencyTypes) {
    return pToDependencyTypes.some(
        pDepType => pRuleDependencyTypes.some(
            pRDepType => pDepType === pRDepType
        )
    );
}

/* if there is at least one group expression in the given pRulePath
   return the first matched one.
   return null in all other cases

   This fills our current need. Later we can expand it to return all group
   matches.
*/

function extractGroups(pRule, pActualPath) {
    let lRetval = [];

    if (Boolean(pRule.path)) {
        let lMatchResult = pActualPath.match(pRule.path);

        if (Boolean(lMatchResult) && lMatchResult.length > 1) {
            lRetval = lMatchResult;
        }
    }
    return lRetval;
}

function replaceGroupPlaceholders(pString, pExtractedGroups) {
    return pExtractedGroups.reduce(
        (pAll, pThis, pIndex) => pAll.replace(`$${pIndex}`, pThis),
        pString
    );
}

function matchRule(pFrom, pTo) {
    return pRule => {
        const lGroups = extractGroups(pRule.from, pFrom);

        /*
         * the replace("$1", lGroup) things below are a bit simplistic (they
         * also match \$, which they probably shouldn't) - but good enough for
         * now.
         */
        return (!pRule.from.path ||
                pFrom.match(pRule.from.path)
        ) && (!pRule.from.pathNot ||
                !(pFrom.match(pRule.from.pathNot))
        ) && (!pRule.to.path ||
                (lGroups.length > 0
                    ? pTo.resolved.match(replaceGroupPlaceholders(pRule.to.path, lGroups))
                    : pTo.resolved.match(pRule.to.path))
        ) && (!Boolean(pRule.to.pathNot) ||
                !(
                    (lGroups.length > 0
                        ? pTo.resolved.match(replaceGroupPlaceholders(pRule.to.pathNot, lGroups))
                        : pTo.resolved.match(pRule.to.pathNot))
                )
        ) && (!pRule.to.dependencyTypes ||
                intersects(pTo.dependencyTypes, pRule.to.dependencyTypes)
        ) && (!pRule.to.hasOwnProperty("moreThanOneDependencyType") ||
                pTo.dependencyTypes.length > 1
        ) && (!pRule.to.license ||
                pTo.license && pTo.license.match(pRule.to.license)
        ) && (!pRule.to.licenseNot ||
                pTo.license && !pTo.license.match(pRule.to.licenseNot)
        ) && propertyEquals(pTo, pRule, "couldNotResolve") &&
                 propertyEquals(pTo, pRule, "circular");
    };
}

function validateAgainstRules(pRuleSet, pFrom, pTo) {
    let lMatchedRule = {};

    if (pRuleSet.allowed){
        lMatchedRule = pRuleSet.allowed.find(matchRule(pFrom, pTo));
        if (!Boolean(lMatchedRule)){
            return {
                valid: false,
                rule: {
                    severity: "warn",
                    name: "not-in-allowed"
                }
            };
        }
    }
    if (pRuleSet.forbidden){
        lMatchedRule = pRuleSet.forbidden.find(matchRule(pFrom, pTo));
        if (Boolean(lMatchedRule)){
            return {
                valid: false,
                rule: {
                    severity : lMatchedRule.severity,
                    name     : lMatchedRule.name
                }
            };
        }
    }
    return {valid:true};
}

/**
 * If pValidate equals true, validates the pFrom and pTo
 * dependency pair against the given ruleset pRuleSet
 *
 * @param  {Boolean} pValidate whether or not to validate at all
 * @param  {object} pRuleSet  a ruleset (adhering to
 *                            [the ruleset schema](jsonschema.json))
 * @param  {object} pFrom     The from part of the dependency
 * @param  {object} pTo       The 'to' part of the dependency
 * @return {object}           an object with as attributes:
 *                            - valid: (boolean) true if the relation
 *                              between pTo and pFalse is valid (as far as the
 *                              given ruleset is concerend). false in all other
 *                              cases.
 *                            - rule (only when the relation between pFrom and
 *                              pTo was false):
 *                              - name: the name (from the ruleset) of the
 *                                  violated rule
 *                              - severity: the severity of that rule - as per
 *                                  the ruleset
 */
module.exports = (pValidate, pRuleSet, pFrom, pTo) => {
    if (!pValidate) {
        return {valid:true};
    }
    return validateAgainstRules(pRuleSet, pFrom, pTo);
};

/* ignore security/detect-object-injection because:
   - we only use it from within the module with two fixed values
   - the propertyEquals function is not exposed externaly
 */
/* eslint security/detect-object-injection: 0, complexity: 0 */
<|endoftext|>


<commit_before>var yo = require('yo-yo')

// -------------- styling ----------------------
var csjs = require('csjs-inject')
var remix = require('ethereum-remix')
var styleGuide = remix.ui.styleGuide
var styles = styleGuide()

var css = csjs`
  .debuggerTabView {
    padding: 2%;
  }
  .debugger {
    ${styles.displayBox}
    margin-bottom: 1%;
  }
`

module.exports = debuggerTab

function debuggerTab (container, appAPI, events, opts) {
  var el = yo`

`
  container.appendChild(el)
}
<commit_msg>remove display box in debugger<commit_after>var yo = require('yo-yo')

// -------------- styling ----------------------
var csjs = require('csjs-inject')

var css = csjs`
  .debuggerTabView {
    padding: 2%;
  }
  .debugger {
    margin-bottom: 1%;
  }
`

module.exports = debuggerTab

function debuggerTab (container, appAPI, events, opts) {
  var el = yo`

`
  container.appendChild(el)
}
<|endoftext|>


<commit_before>/*
	The MIT License (MIT)

	Copyright (c) 2013 Fernando Bevilacqua

	Permission is hereby granted, free of charge, to any person obtaining a copy of
	this software and associated documentation files (the "Software"), to deal in
	the Software without restriction, including without limitation the rights to
	use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
	the Software, and to permit persons to whom the Software is furnished to do so,
	subject to the following conditions:

	The above copyright notice and this permission notice shall be included in all
	copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
	FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
	COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
	IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
	CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

var CodebotTabs = function() {
    var mSelf           = null;
    var mTabController  = null;
    var mActiveTab      = null;
    var mCodebot        = null;
    var mIds            = 0;

    var onTabClose = function(theTab) {
        var aData = theTab.data('tabData').data;
        $('#' + aData.container).remove();
		aData.editor = null;

		console.debug('onTabClose', aData);
	};

	var onTabBlur = function(theTab) {
        var aData = theTab.data('tabData').data;
        $('#' + aData.container).hide();
        console.debug('onTabBlur', aData);
	};

	var onTabFocus = function(theTab) {
        var aData = theTab.data('tabData').data;
		$('#' + aData.container).show();
        mActiveTab = theTab;

        console.debug('onTabFocus', aData);
	};

    /**
     * Invoked by the tab manager to check if the tab can be closed or not.
     *
     * @return bool true if the tab can be closed, or false otherwise (tab will remain open).
     */
    var tabPreClose = function(theTab) {
        // TODO: check if file has changes
        var aHasChanges = true;
        var aData = theTab.data('tabData').data;

        if(aHasChanges) {
            mCodebot.ui.showDialog({
                keyboard: true,
                title: 'Important',
                content: 'This file has changes. Do you want to save them?',
                buttons: {
                    'Yes': {css: 'btn-primary', dismiss: true, callback: function() {
                        CODEBOT.writeTabToDisk(aData);
                        mTabController.closeTab(theTab);
                    }},
                    'No': {css: 'btn-default', dismiss: true, callback: function() {
                        mTabController.closeTab(theTab);
                    }},
                    'Cancel': {css: 'btn-default', dismiss: true}
                }
            });

            // Inform the tab to remain active until the user has decided what
            // to do with it (using the dialog above)
            return false;

        } else {
            // No changes, it's clear to go!
            return true;
        }
    };

    var onTabSorted = function(theTab, theNewZIndex) {
        var aTab = theTab.data('tabData');

        if(aTab) {
            aTab.data.index = theNewZIndex;
        }
	};

    var getTabDataById = function(theId) {
        return mTabController.getRawTabById(theId).data('tabData').data;
    };

    /**
     * Adds a new tab.
     *
     * @param {object} theConfig - configuration used to create the new tab. Structure:
     *
     * {
     *    favicon: String,      // FontAwesome class, e.g. file-text-o
     *    title: String,        // Tab title.
     *    editor: Object,       // Instance of an editor able to manipulate the content, e.g. CodeMirror.
     *    file: String,         // File name. E.g. codebot.js
     *    path: String,         // File path. E.g. /home/user/project/codebot.js
     *    data: Object,         // (Optional) Any special data you want connected to that tab (read it later at tab.data).
     * }
     *
     * @returns {object} an object describing the newly created tab.
     */
    this.add = function(theConfig) {
        var aTab = {
            favicon: 'file-text-o',
            title: 'Unknown',
            editor: null,
            file: 'unknown',
            path: '',
            id: mIds,
            index: 0,
            container: 'tab-content-' + mIds,
            dirty: false, // TODO: make it private

            // TODO: move this to a new class
            setDirty: function(theStatus) {
                this.dirty = theStatus;
                var aColor = this.dirty ? '#ff0000' : 'transparent';
                $('#codebot-tab-' + this.id + ' div.chrome-tab-favicon').html('');
            }
        };

        $.extend(aTab, theConfig);
        $('#working-area').append('

');

        mTabController.add({
            favicon: theConfig.favicon || 'file-text-o',
            title: theConfig.title,
            data: aTab
        });

        mIds++;

        return getTabDataById(mIds - 1);
	};

    this.remove = function(theTabId) {
        var aTabRaw = mTabController.getRawTabById(theTabId);

        if(aTabRaw && tabPreClose(aTabRaw)) {
            mTabController.closeTab(aTabRaw);
        }
    };

    /**
     * Opens any filespanel node in a new tab. The method will use Codebot
     * registered editors to pick the best one able to handle the file editing.
     *
     * @param {Object} theNode - filespanel node.
     */
    this.openNode = function(theNode) {
        var aTab = null;

        mCodebot.io.readFile(theNode.data, function(theData) {
            aTab = mCodebot.ui.tabs.add({
                favicon: 'file-text-o', // TODO: dynamic icon?
                title: theNode.data.name,
                file: theNode.data.name,
                path: theNode.data.path,
                editor: null
            });

            aTab.editor = mCodebot.editors.create(aTab, theData, theNode.data);
        });
    };

    this.init = function(theCodebot) {
        mSelf = this;
        mCodebot = theCodebot;

        // get tab context from codebot.ui.tabs.js
		mTabController = window.chromeTabs;

		mTabController.init({
			container: '.chrome-tabs-shell',
			minWidth: 20,
			maxWidth: 100,

			deactivated: onTabBlur,
			activated: onTabFocus,
			closed: onTabClose,
			shouldClose: tabPreClose,
			sorted: onTabSorted,
		});
    };

    // Getters and setters

    this.__defineGetter__("active", function(){
        return mActiveTab ? mActiveTab.data('tabData').data : null;
    });
};

/*
	The MIT License (MIT)
	Copyright (c) 2013 Adam Schwartz

	Permission is hereby granted, free of charge, to any person obtaining a copy of
	this software and associated documentation files (the "Software"), to deal in
	the Software without restriction, including without limitation the rights to
	use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
	the Software, and to permit persons to whom the Software is furnished to do so,
	subject to the following conditions:

	The above copyright notice and this permission notice shall be included in all
	copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
	FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
	COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
	IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
	CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

    NOTE: original code has been modified by Fernando Bevilacqua <dovyski@gmail.com>
*/

(function() {
  var $, chromeTabs, defaultNewTabData, tabTemplate, $shell, opts;
  $ = jQuery;
  if (document.body.style['-webkit-mask-repeat'] !== void 0) {
    $('html').addClass('cssmasks');
  } else {
    $('html').addClass('no-cssmasks');
  }
  tabTemplate = '
\n

\n

\n

\n
\n

\n

\n

\n

\n

\n

\n
\n
';
  defaultNewTabData = {
    title: 'New Tab',
    favicon: '',
    data: {}
  };
  chromeTabs = {
    init: function(options) {
      var render;

	  opts = options;
	  $shell = $(options.container);

      $.extend($shell.data(), options);
      $shell.find('.chrome-tab').each(function() {
        return $(this).data().tabData = {
          data: {}
        };
      });
      render = function() {
        return chromeTabs.render($shell);
      };
      $(window).resize(render);
      return render();
    },
    render: function() {
      chromeTabs.fixTabSizes($shell);
      chromeTabs.fixZIndexes($shell);
      chromeTabs.setupEvents($shell);
      chromeTabs.setupSortable($shell);
      return $shell.trigger('chromeTabRender');
    },
    setupSortable: function() {
      var $tabs;
      $tabs = $shell.find('.chrome-tabs');
      return $tabs.sortable({
        axis: 'x',
        tolerance: 'pointer',
        start: function(e, ui) {
          chromeTabs.fixZIndexes($shell);
          if (!$(ui.item).hasClass('chrome-tab-current')) {
            return $tabs.sortable('option', 'zIndex', $(ui.item).data().zIndex);
          } else {
            return $tabs.sortable('option', 'zIndex', $tabs.length + 40);
          }
        },
        stop: function(e, ui) {
          return chromeTabs.setCurrent($(ui.item));
        }
      });
    },
    fixTabSizes: function() {
      var $tabs, margin, width;
      $tabs = $shell.find('.chrome-tab');
      margin = (parseInt($tabs.first().css('marginLeft'), 10) + parseInt($tabs.first().css('marginRight'), 10)) || 0;
      width = $shell.width() - 50;
      width = (width / $tabs.length) - margin;
      width = Math.max($shell.data().minWidth, Math.min($shell.data().maxWidth, width));
      return $tabs.css({
        width: width
      });
    },
    fixZIndexes: function() {
      var $tabs;
      $tabs = $shell.find('.chrome-tab');
      return $tabs.each(function(i) {
        var $tab, zIndex;
        $tab = $(this);
        zIndex = $tabs.length - i;

        if(opts.sorted) { opts.sorted($tab, i); }

        if ($tab.hasClass('chrome-tab-current')) {
          zIndex = $tabs.length + 40;
        }
        $tab.css({
          zIndex: zIndex
        });
        return $tab.data({
          zIndex: zIndex
        });
      });
    },
    setupEvents: function() {
      $shell.unbind('dblclick').bind('dblclick', function() {
        return chromeTabs.add();
      });
      return $shell.find('.chrome-tab').each(function() {
        var $tab;
        $tab = $(this);
        $tab.unbind('click').click(function() {
          return chromeTabs.setCurrent($tab);
        });
        return $tab.find('.chrome-tab-close').unbind('click').click(function() {
          var shouldClose = true;
          if(opts.shouldClose) {
              shouldClose = opts.shouldClose($tab);
          }
          if(shouldClose) {
            return chromeTabs.closeTab($tab);
          }
        });
      });
    },
    add: function(newTabData) {
      var $newTab, tabData;
      $newTab = $(tabTemplate.replace('{id}', 'codebot-tab-' + newTabData.data.id));
      $shell.find('.chrome-tabs').append($newTab);
      tabData = $.extend(true, {}, defaultNewTabData, newTabData);
      chromeTabs.updateTab($shell, $newTab, tabData);
      chromeTabs.fixZIndexes($shell);
      return chromeTabs.setCurrent($newTab);
    },
    setCurrent: function($tab) {
	  var $old = $shell.find('.chrome-tab-current');
      chromeTabs.fixZIndexes($shell);

	  $old.removeClass('chrome-tab-current');
	  if($old.length && opts.deactivated) { opts.deactivated($old); }

      $tab.addClass('chrome-tab-current');
	  if(opts.activated) { opts.activated($tab); }

      return chromeTabs.render($shell);
    },
    closeTab: function($tab) {
      if ($tab.hasClass('chrome-tab-current') && $tab.prev().length) {
        chromeTabs.setCurrent($tab.prev());
      }
	  if(opts.closed) { opts.closed($tab); }
      $tab.remove();

      return chromeTabs.render($shell);
    },
    updateTab: function($shell, $tab, tabData) {
      $tab.find('.chrome-tab-title').html(tabData.title);
      $tab.find('.chrome-tab-favicon').html('');
      return $tab.data().tabData = tabData;
    },
    getRawTabById: function(theId) {
      var ret = null;
      $shell.find('.chrome-tab').each(function() {
        var $tab;
        $tab = $(this);
        if($tab.data('tabData').data.id == theId) {
          ret = $tab;
          return false;
        }
      });
      return ret;
    },
  };

  window.chromeTabs = chromeTabs;
}).call(this);
<commit_msg>Close tab immediately when not dirty<commit_after>/*
	The MIT License (MIT)

	Copyright (c) 2013 Fernando Bevilacqua

	Permission is hereby granted, free of charge, to any person obtaining a copy of
	this software and associated documentation files (the "Software"), to deal in
	the Software without restriction, including without limitation the rights to
	use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
	the Software, and to permit persons to whom the Software is furnished to do so,
	subject to the following conditions:

	The above copyright notice and this permission notice shall be included in all
	copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
	FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
	COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
	IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
	CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

var CodebotTabs = function() {
    var mSelf           = null;
    var mTabController  = null;
    var mActiveTab      = null;
    var mCodebot        = null;
    var mIds            = 0;

    var onTabClose = function(theTab) {
        var aData = theTab.data('tabData').data;
        $('#' + aData.container).remove();
		aData.editor = null;

		console.debug('onTabClose', aData);
	};

	var onTabBlur = function(theTab) {
        var aData = theTab.data('tabData').data;
        $('#' + aData.container).hide();
        console.debug('onTabBlur', aData);
	};

	var onTabFocus = function(theTab) {
        var aData = theTab.data('tabData').data;
		$('#' + aData.container).show();
        mActiveTab = theTab;

        console.debug('onTabFocus', aData);
	};

    /**
     * Invoked by the tab manager to check if the tab can be closed or not.
     *
     * @return bool true if the tab can be closed, or false otherwise (tab will remain open).
     */
    var tabPreClose = function(theRawTab) {
        // TODO: check if file has changes
        var aTab = theRawTab.data('tabData').data;

        if(aTab.isDirty()) {
            mCodebot.ui.showDialog({
                keyboard: true,
                title: 'Important',
                content: 'This file has changes. Do you want to save them?',
                buttons: {
                    'Yes': {css: 'btn-primary', dismiss: true, callback: function() {
                        CODEBOT.writeTabToDisk(aTab);
                        mTabController.closeTab(theRawTab);
                    }},
                    'No': {css: 'btn-default', dismiss: true, callback: function() {
                        mTabController.closeTab(theRawTab);
                    }},
                    'Cancel': {css: 'btn-default', dismiss: true}
                }
            });

            // Inform the tab to remain active until the user has decided what
            // to do with it (using the dialog above)
            return false;

        } else {
            // No changes, it's clear to go!
            return true;
        }
    };

    var onTabSorted = function(theTab, theNewZIndex) {
        var aTab = theTab.data('tabData');

        if(aTab) {
            aTab.data.index = theNewZIndex;
        }
	};

    var getTabDataById = function(theId) {
        return mTabController.getRawTabById(theId).data('tabData').data;
    };

    /**
     * Adds a new tab.
     *
     * @param {object} theConfig - configuration used to create the new tab. Structure:
     *
     * {
     *    favicon: String,      // FontAwesome class, e.g. file-text-o
     *    title: String,        // Tab title.
     *    editor: Object,       // Instance of an editor able to manipulate the content, e.g. CodeMirror.
     *    file: String,         // File name. E.g. codebot.js
     *    path: String,         // File path. E.g. /home/user/project/codebot.js
     *    data: Object,         // (Optional) Any special data you want connected to that tab (read it later at tab.data).
     * }
     *
     * @returns {object} an object describing the newly created tab.
     */
    this.add = function(theConfig) {
        var aTab = {
            favicon: 'file-text-o',
            title: 'Unknown',
            editor: null,
            file: 'unknown',
            path: '',
            id: mIds,
            index: 0,
            container: 'tab-content-' + mIds,
            dirty: false, // TODO: make it private

            // TODO: move this to a new class
            setDirty: function(theStatus) {
                this.dirty = theStatus;
                var aColor = this.dirty ? '#ff0000' : 'transparent';
                $('#codebot-tab-' + this.id + ' div.chrome-tab-favicon').html('');
            },

            isDirty: function() {
                return this.dirty;
            }
        };

        $.extend(aTab, theConfig);
        $('#working-area').append('

');

        mTabController.add({
            favicon: theConfig.favicon || 'file-text-o',
            title: theConfig.title,
            data: aTab
        });

        mIds++;

        return getTabDataById(mIds - 1);
	};

    this.remove = function(theTabId) {
        var aTabRaw = mTabController.getRawTabById(theTabId);

        if(aTabRaw && tabPreClose(aTabRaw)) {
            mTabController.closeTab(aTabRaw);
        }
    };

    /**
     * Opens any filespanel node in a new tab. The method will use Codebot
     * registered editors to pick the best one able to handle the file editing.
     *
     * @param {Object} theNode - filespanel node.
     */
    this.openNode = function(theNode) {
        var aTab = null;

        mCodebot.io.readFile(theNode.data, function(theData) {
            aTab = mCodebot.ui.tabs.add({
                favicon: 'file-text-o', // TODO: dynamic icon?
                title: theNode.data.name,
                file: theNode.data.name,
                path: theNode.data.path,
                editor: null
            });

            aTab.editor = mCodebot.editors.create(aTab, theData, theNode.data);
        });
    };

    this.init = function(theCodebot) {
        mSelf = this;
        mCodebot = theCodebot;

        // get tab context from codebot.ui.tabs.js
		mTabController = window.chromeTabs;

		mTabController.init({
			container: '.chrome-tabs-shell',
			minWidth: 20,
			maxWidth: 100,

			deactivated: onTabBlur,
			activated: onTabFocus,
			closed: onTabClose,
			shouldClose: tabPreClose,
			sorted: onTabSorted,
		});
    };

    // Getters and setters

    this.__defineGetter__("active", function(){
        return mActiveTab ? mActiveTab.data('tabData').data : null;
    });
};

/*
	The MIT License (MIT)
	Copyright (c) 2013 Adam Schwartz

	Permission is hereby granted, free of charge, to any person obtaining a copy of
	this software and associated documentation files (the "Software"), to deal in
	the Software without restriction, including without limitation the rights to
	use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
	the Software, and to permit persons to whom the Software is furnished to do so,
	subject to the following conditions:

	The above copyright notice and this permission notice shall be included in all
	copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
	FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
	COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
	IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
	CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

    NOTE: original code has been modified by Fernando Bevilacqua <dovyski@gmail.com>
*/

(function() {
  var $, chromeTabs, defaultNewTabData, tabTemplate, $shell, opts;
  $ = jQuery;
  if (document.body.style['-webkit-mask-repeat'] !== void 0) {
    $('html').addClass('cssmasks');
  } else {
    $('html').addClass('no-cssmasks');
  }
  tabTemplate = '
\n

\n

\n

\n
\n

\n

\n

\n

\n

\n

\n
\n
';
  defaultNewTabData = {
    title: 'New Tab',
    favicon: '',
    data: {}
  };
  chromeTabs = {
    init: function(options) {
      var render;

	  opts = options;
	  $shell = $(options.container);

      $.extend($shell.data(), options);
      $shell.find('.chrome-tab').each(function() {
        return $(this).data().tabData = {
          data: {}
        };
      });
      render = function() {
        return chromeTabs.render($shell);
      };
      $(window).resize(render);
      return render();
    },
    render: function() {
      chromeTabs.fixTabSizes($shell);
      chromeTabs.fixZIndexes($shell);
      chromeTabs.setupEvents($shell);
      chromeTabs.setupSortable($shell);
      return $shell.trigger('chromeTabRender');
    },
    setupSortable: function() {
      var $tabs;
      $tabs = $shell.find('.chrome-tabs');
      return $tabs.sortable({
        axis: 'x',
        tolerance: 'pointer',
        start: function(e, ui) {
          chromeTabs.fixZIndexes($shell);
          if (!$(ui.item).hasClass('chrome-tab-current')) {
            return $tabs.sortable('option', 'zIndex', $(ui.item).data().zIndex);
          } else {
            return $tabs.sortable('option', 'zIndex', $tabs.length + 40);
          }
        },
        stop: function(e, ui) {
          return chromeTabs.setCurrent($(ui.item));
        }
      });
    },
    fixTabSizes: function() {
      var $tabs, margin, width;
      $tabs = $shell.find('.chrome-tab');
      margin = (parseInt($tabs.first().css('marginLeft'), 10) + parseInt($tabs.first().css('marginRight'), 10)) || 0;
      width = $shell.width() - 50;
      width = (width / $tabs.length) - margin;
      width = Math.max($shell.data().minWidth, Math.min($shell.data().maxWidth, width));
      return $tabs.css({
        width: width
      });
    },
    fixZIndexes: function() {
      var $tabs;
      $tabs = $shell.find('.chrome-tab');
      return $tabs.each(function(i) {
        var $tab, zIndex;
        $tab = $(this);
        zIndex = $tabs.length - i;

        if(opts.sorted) { opts.sorted($tab, i); }

        if ($tab.hasClass('chrome-tab-current')) {
          zIndex = $tabs.length + 40;
        }
        $tab.css({
          zIndex: zIndex
        });
        return $tab.data({
          zIndex: zIndex
        });
      });
    },
    setupEvents: function() {
      $shell.unbind('dblclick').bind('dblclick', function() {
        return chromeTabs.add();
      });
      return $shell.find('.chrome-tab').each(function() {
        var $tab;
        $tab = $(this);
        $tab.unbind('click').click(function() {
          return chromeTabs.setCurrent($tab);
        });
        return $tab.find('.chrome-tab-close').unbind('click').click(function() {
          var shouldClose = true;
          if(opts.shouldClose) {
              shouldClose = opts.shouldClose($tab);
          }
          if(shouldClose) {
            return chromeTabs.closeTab($tab);
          }
        });
      });
    },
    add: function(newTabData) {
      var $newTab, tabData;
      $newTab = $(tabTemplate.replace('{id}', 'codebot-tab-' + newTabData.data.id));
      $shell.find('.chrome-tabs').append($newTab);
      tabData = $.extend(true, {}, defaultNewTabData, newTabData);
      chromeTabs.updateTab($shell, $newTab, tabData);
      chromeTabs.fixZIndexes($shell);
      return chromeTabs.setCurrent($newTab);
    },
    setCurrent: function($tab) {
	  var $old = $shell.find('.chrome-tab-current');
      chromeTabs.fixZIndexes($shell);

	  $old.removeClass('chrome-tab-current');
	  if($old.length && opts.deactivated) { opts.deactivated($old); }

      $tab.addClass('chrome-tab-current');
	  if(opts.activated) { opts.activated($tab); }

      return chromeTabs.render($shell);
    },
    closeTab: function($tab) {
      if ($tab.hasClass('chrome-tab-current') && $tab.prev().length) {
        chromeTabs.setCurrent($tab.prev());
      }
	  if(opts.closed) { opts.closed($tab); }
      $tab.remove();

      return chromeTabs.render($shell);
    },
    updateTab: function($shell, $tab, tabData) {
      $tab.find('.chrome-tab-title').html(tabData.title);
      $tab.find('.chrome-tab-favicon').html('');
      return $tab.data().tabData = tabData;
    },
    getRawTabById: function(theId) {
      var ret = null;
      $shell.find('.chrome-tab').each(function() {
        var $tab;
        $tab = $(this);
        if($tab.data('tabData').data.id == theId) {
          ret = $tab;
          return false;
        }
      });
      return ret;
    },
  };

  window.chromeTabs = chromeTabs;
}).call(this);
<|endoftext|>


<commit_before>// Dynamically set the css background images for all the sprites
import React from "react";
import { createPortal } from "react-dom";
import { connect } from "react-redux";

import { imageSelectors, cursorSelectors } from "../skinSelectors";

const mapRegionNamesToIds = {
  normal: "mainWindowClipPath",
  windowshade: "shadeMainWindowClipPath",
  equalizer: "equalizerWindowClipPath",
  equalizerws: "shadeEqualizerWindowClipPath"
};

const mapRegionNamesToMatcher = {
  normal: "#main-window",
  windowshade: "#main-window.shade",
  equalizer: "#equalizer-window",
  equalizerws: "#equalizer-window.shade"
};

const numExIsUsed = skinImages => !!skinImages.DIGIT_0_EX;

class Css extends React.Component {
  componentWillMount() {
    const style = document.createElement("style");
    style.type = "text/css";
    document.head.appendChild(style);
    this.style = style;
  }

  componentWillUnmount() {
    this.style.remove();
    this.style = null;
  }

  render() {
    return createPortal(this.props.children, this.style);
  }
}

class ClipPaths extends React.Component {
  componentWillMount() {
    const paths = document.createElement("div");
    document.body.appendChild(paths);
    this.paths = paths;
  }

  componentWillUnmount() {
    this.paths.remove();
    this.paths = null;
  }

  render() {
    // this.props.children should be an object containing arrays of strings. The
    // keys are ids, and the arrays are arrays of polygon point strings
    const { children } = this.props;

    return createPortal(
      <svg height={0} width={0}>
        <defs>
          {Object.keys(children).map(id => (
            <clipPath id={id} key={id}>
              {children[id].map((points, i) => (
                <polygon points={points} key={i} />
              ))}
            </clipPath>
          ))}
        </defs>
      </svg>,
      this.paths
    );
  }
}

const Skin = props => {
  const { skinImages, skinCursors } = props;
  if (!skinImages) {
    return null;
  }
  const cssRules = [];
  Object.keys(imageSelectors).map(imageName => {
    const imageUrl = skinImages[imageName];
    if (imageUrl) {
      imageSelectors[imageName].forEach(selector => {
        cssRules.push(
          `#winamp2-js ${selector} {background-image: url(${imageUrl})}`
        );
      });
    }
  });
  Object.keys(cursorSelectors).map(cursorName => {
    const cursorUrl = skinCursors[cursorName];
    if (cursorUrl) {
      cursorSelectors[cursorName].forEach(selector => {
        cssRules.push(
          `#winamp2-js ${selector} {cursor: url(${cursorUrl}), auto}`
        );
      });
    }
  });

  if (numExIsUsed(skinImages)) {
    // This alternate number file requires that the minus sign be
    // formatted differently.
    cssRules.push(
      "#winamp2-js .status #time #minus-sign { top: 0px; left: -1px; width: 9px; height: 13px; }"
    );
  }

  const clipPaths = {};
  for (const [regionName, polygons] of Object.entries(props.skinRegion)) {
    if (polygons) {
      const matcher = mapRegionNamesToMatcher[regionName];
      const id = mapRegionNamesToIds[regionName];
      clipPaths[id] = polygons;
      cssRules.push(`#winamp2-js ${matcher} { clip-path: url(#${id}); }`);
    }
  }
  return (

      <Css>{cssRules.join("\n")}</Css>
      <ClipPaths>{clipPaths}</ClipPaths>

  );
};

export default connect(state => ({
  skinImages: state.display.skinImages,
  skinCursors: state.display.skinCursors,
  skinRegion: state.display.skinRegion
}))(Skin);
<commit_msg>Improve region scoping<commit_after>// Dynamically set the css background images for all the sprites
import React from "react";
import { createPortal } from "react-dom";
import { connect } from "react-redux";

import { imageSelectors, cursorSelectors } from "../skinSelectors";

const mapRegionNamesToIds = {
  normal: "mainWindowClipPath",
  windowshade: "shadeMainWindowClipPath",
  equalizer: "equalizerWindowClipPath",
  equalizerws: "shadeEqualizerWindowClipPath"
};

const mapRegionNamesToMatcher = {
  normal: "#main-window:not(.shade)",
  windowshade: "#main-window.shade",
  equalizer: "#equalizer-window:not(.shade)",
  equalizerws: "#equalizer-window.shade"
};

const numExIsUsed = skinImages => !!skinImages.DIGIT_0_EX;

class Css extends React.Component {
  componentWillMount() {
    const style = document.createElement("style");
    style.type = "text/css";
    document.head.appendChild(style);
    this.style = style;
  }

  componentWillUnmount() {
    this.style.remove();
    this.style = null;
  }

  render() {
    return createPortal(this.props.children, this.style);
  }
}

class ClipPaths extends React.Component {
  componentWillMount() {
    const paths = document.createElement("div");
    document.body.appendChild(paths);
    this.paths = paths;
  }

  componentWillUnmount() {
    this.paths.remove();
    this.paths = null;
  }

  render() {
    // this.props.children should be an object containing arrays of strings. The
    // keys are ids, and the arrays are arrays of polygon point strings
    const { children } = this.props;

    return createPortal(
      <svg height={0} width={0}>
        <defs>
          {Object.keys(children).map(id => (
            <clipPath id={id} key={id}>
              {children[id].map((points, i) => (
                <polygon points={points} key={i} />
              ))}
            </clipPath>
          ))}
        </defs>
      </svg>,
      this.paths
    );
  }
}

const Skin = props => {
  const { skinImages, skinCursors } = props;
  if (!skinImages) {
    return null;
  }
  const cssRules = [];
  Object.keys(imageSelectors).map(imageName => {
    const imageUrl = skinImages[imageName];
    if (imageUrl) {
      imageSelectors[imageName].forEach(selector => {
        cssRules.push(
          `#winamp2-js ${selector} {background-image: url(${imageUrl})}`
        );
      });
    }
  });
  Object.keys(cursorSelectors).map(cursorName => {
    const cursorUrl = skinCursors[cursorName];
    if (cursorUrl) {
      cursorSelectors[cursorName].forEach(selector => {
        cssRules.push(
          `#winamp2-js ${selector} {cursor: url(${cursorUrl}), auto}`
        );
      });
    }
  });

  if (numExIsUsed(skinImages)) {
    // This alternate number file requires that the minus sign be
    // formatted differently.
    cssRules.push(
      "#winamp2-js .status #time #minus-sign { top: 0px; left: -1px; width: 9px; height: 13px; }"
    );
  }

  const clipPaths = {};
  for (const [regionName, polygons] of Object.entries(props.skinRegion)) {
    if (polygons) {
      const matcher = mapRegionNamesToMatcher[regionName];
      const id = mapRegionNamesToIds[regionName];
      clipPaths[id] = polygons;
      cssRules.push(`#winamp2-js ${matcher} { clip-path: url(#${id}); }`);
    }
  }
  return (

      <Css>{cssRules.join("\n")}</Css>
      <ClipPaths>{clipPaths}</ClipPaths>

  );
};

export default connect(state => ({
  skinImages: state.display.skinImages,
  skinCursors: state.display.skinCursors,
  skinRegion: state.display.skinRegion
}))(Skin);
<|endoftext|>


<commit_before>/**
 * Created by starov on 05.09.14.
 */

controllers.feed = function ($scope, cfpLoadingBar, $stateParams, $state, Types, smoothScroll, $timeout) {

    //View options

    $scope.mtd.showLetters=false;
    $scope.mtd.showRating=false;

    //Find free letters for registering new users

    $scope.mtd.getPersonalUsed = function () {
        var result=[];
        var letters;
        for (var phrase in $scope.mtd.personae) {
            if (angular.isObject($scope.mtd.personae[phrase]) && $scope.mtd.personae[phrase].letters) {
                letters=$scope.mtd.personae[phrase].letters;
                if (letters.indexOf('|') == -1) {
                    result.push($scope.mtd.personae[phrase].letters);
                }
            }
        }

        return result;

    };

    $scope.mtd.types=Types.types;  //types of phrases

    $scope.mtd.preset = preset;
    $scope.mtd.shuffle = shuffle;
    $scope.mtd.colorize = colorize;
    $scope.mtd.parent = parent;
    $scope.mtd.convertLetters = convertLetters;
    $scope.mtd.convertStory=convertStory;

    $scope.mtd.selector = function (letters,addOnly) {
        if (letters) {
            letters=convertLetters(letters);
            var found = false;
            for (var i = 0; i < $scope.mtd.selected.length; i++) {
                if ($scope.mtd.selected[i] == letters) {
                    found = true;
                    if (!addOnly) {
                        $scope.mtd.selected.splice(i, 1);
                    }
                }
            }
            if (!found) {
                $scope.mtd.selected.push(letters);
            }
            if (letters.indexOf('|') == -1) {
                if (found && !addOnly) {
                    $scope.mtd.fltr = ''
                }
                if (!found || addOnly) {
                    $scope.mtd.fltr = letters;
                }
            }
        }
    };

    $scope.mtd.parseParams = function (id) {
        id=convertLetters(id);
        if(id) {
            var parts=id.split('|');
            for (var j=parts.length;j>0;j--) {

                if(parts[j-1]) {
                    $scope.mtd.selector(parts.join('|'), true);
                }
                parts.pop();
            }
        }
        $timeout(function () {
            var element = document.getElementById(id);
            smoothScroll(element, {duration:80});
        },4000);

    };

    $scope.mtd.parseParams($stateParams.id);

    $scope.mtd.isSelected = function (letters) {
        for (var i=0;i<$scope.mtd.selected.length;i++) {
            if ($scope.mtd.selected[i]==letters) {
                return true
            }
        }
        return false;
    };

    $scope.mtd.addToFeed = function (saying) {
        var said;
        var found=false;
        if (saying && saying.title && saying.type && saying.letters) {

            said = angular.copy(saying);
            if (said.next) {delete said.next}
            saying.text='';
            saying.title='';
            saying.letters='';
            saying.image='';
            said.letters=convertLetters(said.letters);
            said.author=$scope.mtd.persona;
            said.time=Date.now();
            angular.forEach($scope.feed, function (val, key) {
                if (val.letters && val.letters==said.letters) {
                    found = key;
                }
            });
            if ($scope.mtd.firebase) {
                if (found) {
                    $scope.feed[found]=said;
                    $scope.feed.$save(found);
                } else $scope.feed.$add(said);

            } else {
                if (found) {
                    $scope.feed[found]=said;
                } else {
                    $scope.feed.push(said);
                }
            }

        } else {console.log('a phrase without title, type, or color/letters')}

        $scope.updateTree();
    };

    $scope.updateTree=function () {
        $scope.tree=convertStory($scope.feed);
        $scope.source=$scope.tree;
    };

    $scope.mtd.updateTree=$scope.updateTree;

    $scope.$watch('feed', function (feed) {
        if (feed) {$scope.updateTree();}

    });

    $scope.mtd.isRated = function (letters) {
        if($scope.rating[letters]) {return $scope.rating[letters].pluses+$scope.rating[letters].minuses+$scope.rating[letters].zeros}
        return 0;
    };

    $scope.rate={};
    $scope.rate.rating = $scope.rating;
    $scope.rate.reset = function () {
        $scope.rating={};
    };

    $scope.rate.cancel = function (letters) {
        if ($scope.mtd.ratingView=='global' && $scope.mtd.rates[$scope.mtd.persona]) {
            if ($scope.mtd.rates[$scope.mtd.persona][letters]=='+1' && $scope.rating[letters].pluses>0) {
                $scope.rating[letters].pluses--;
                delete $scope.mtd.rates[$scope.mtd.persona][letters];
            }
            if ($scope.mtd.rates[$scope.mtd.persona][letters]=='-1' && $scope.rating[letters].minuses>0) {
                $scope.rating[letters].minuses--;
                delete $scope.mtd.rates[$scope.mtd.persona][letters];
            }
            if ($scope.mtd.rates[$scope.mtd.persona][letters]=='-' && $scope.rating[letters].zeros>0) {
                $scope.rating[letters].zeros--;
                delete $scope.mtd.rates[$scope.mtd.persona][letters];
            }

        }

    };
    $scope.rate.plus=function (letters) {
        if ($scope.mtd.ratingView=='global' && !$scope.mtd.rates[$scope.mtd.persona]) {
            $scope.mtd.rates[$scope.mtd.persona]={};

        }
        if ($scope.mtd.ratingView=='global' && $scope.mtd.rates[$scope.mtd.persona] && !$scope.mtd.rates[$scope.mtd.persona][letters]) {
            $scope.rating[letters] = $scope.rating[letters] || {pluses:0,zeros:0,minuses:0};
            $scope.rating[letters].pluses++;
            $scope.mtd.rates[$scope.mtd.persona][letters]='+1';
        } else {
            $scope.rating[letters] = $scope.rating[letters] || {pluses:0,zeros:0,minuses:0};
            $scope.rating[letters].pluses++;
        }

    };
    $scope.rate.minus=function (letters) {
        if ($scope.mtd.ratingView=='global' && !$scope.mtd.rates[$scope.mtd.persona]) {
            $scope.mtd.rates[$scope.mtd.persona]={};

        }
        if ($scope.mtd.ratingView=='global' && $scope.mtd.rates[$scope.mtd.persona] && !$scope.mtd.rates[$scope.mtd.persona][letters]) {
            $scope.rating[letters] = $scope.rating[letters] || {pluses:0,zeros:0,minuses:0};
            $scope.rating[letters].minuses++;
            $scope.mtd.rates[$scope.mtd.persona][letters]='-1';
        } else {
            $scope.rating[letters] = $scope.rating[letters] || {pluses:0,zeros:0,minuses:0};
            $scope.rating[letters].minuses++;
        }

    };
    $scope.rate.zero=function (letters) {
        if ($scope.mtd.ratingView=='global' && !$scope.mtd.rates[$scope.mtd.persona]) {
            $scope.mtd.rates[$scope.mtd.persona]={};

        }
        if ($scope.mtd.ratingView=='global' && $scope.mtd.rates[$scope.mtd.persona] && !$scope.mtd.rates[$scope.mtd.persona][letters]) {
            $scope.rating[letters] = $scope.rating[letters] || {pluses:0,zeros:0,minuses:0};
            $scope.rating[letters].zeros++;
            $scope.mtd.rates[$scope.mtd.persona][letters]='-';
        } else {
            $scope.rating[letters] = $scope.rating[letters] || {pluses:0,zeros:0,minuses:0};
            $scope.rating[letters].zeros++;
        }
    };
    $scope.rate.getPluses=function (letters) {
        if ($scope.rating[letters] && $scope.rating[letters].pluses>$scope.rating[letters].minuses) {
            return $scope.rating[letters].pluses - $scope.rating[letters].minuses;
        } else return '';
    };
    $scope.rate.getMinuses=function (letters) {
        if ($scope.rating[letters] && $scope.rating[letters].pluses<$scope.rating[letters].minuses) {
            return $scope.rating[letters].minuses - $scope.rating[letters].pluses
        }
        else return '';
    };
    $scope.rate.getZeros=function (letters) {
        if ($scope.rating[letters]) {return $scope.rating[letters].zeros+$scope.rating[letters].pluses+$scope.rating[letters].minuses}
        else return '';
    };
    $scope.rate.getRating = function (letters) {
        if($scope.rating[letters]) {return $scope.rating[letters].pluses-$scope.rating[letters].minuses}
        return 0;
    };
    $scope.rate.ratingSort = function (phrase) {
        if($scope.rating[phrase.letters]) {
            return (-$scope.rating[phrase.letters].pluses+$scope.rating[phrase.letters].minuses);
        };
        return 0;
    };
    $scope.rate.seenSort = function (phrase) {
        if($scope.rating[phrase.letters]) {
            return ($scope.rating[phrase.letters].zeros + $scope.rating[phrase.letters].pluses + $scope.rating[phrase.letters].minuses);
        };
        return 0;
    };
    $scope.rate.timeSort = function (phrase) {
        if (phrase.time) {
            return -phrase.time;
        }
    };

    $scope.rate.totalRated = function (rate) {
        var total=0;
        for (var a in $scope.rating) {
            if (rate>0 && $scope.rating[a] && $scope.rating[a].pluses > $scope.rating[a].minuses) {total++}
            if (rate===0 && $scope.rating[a] && $scope.rating[a].pluses === $scope.rating[a].minuses && ($scope.rating[a].zeros>0 || $scope.rating[a].pluses>0)) {

                total++
            }
            if (rate<0 && $scope.rating[a] && $scope.rating[a].pluses < $scope.rating[a].minuses) {total++}
        }
        return total;
    };
    $scope.rate.countNew = function () {
        var total=0;
        for (var i in $scope.source) {
            if ($scope.rating && !$scope.rating[$scope.source[i].letters]) {total++}
        }
        return total;
    };
    $scope.rate.toggleRF = function (rate) {
        if (rate == 'news') {$scope.ratingMode.news=!$scope.ratingMode.news
        } else if (rate>0) {
            $scope.ratingMode.plus=!$scope.ratingMode.plus
        } else if (rate<0) {
            $scope.ratingMode.minus=!$scope.ratingMode.minus
        } else {
            $scope.ratingMode.zero=!$scope.ratingMode.zero
        }
    };
    $scope.rate.ratingFilter = function (phrase) {
        var result=true;
        result=result && phrase.letters;
        if (result && $scope.rating && !$scope.rating[phrase.letters] && $scope.ratingMode.news) {return true}
        return result && $scope.rating && $scope.rating[phrase.letters] &&
            (
                (($scope.rating[phrase.letters].pluses > $scope.rating[phrase.letters].minuses) && $scope.ratingMode.plus) ||
                (($scope.rating[phrase.letters].minuses > $scope.rating[phrase.letters].pluses) && $scope.ratingMode.minus) ||
                (($scope.rating[phrase.letters].pluses == $scope.rating[phrase.letters].minuses)
                    && $scope.ratingMode.zero)
                );
    };

};

<commit_msg>cleaning open cards without cleaning filter<commit_after>/**
 * Created by starov on 05.09.14.
 */

controllers.feed = function ($scope, cfpLoadingBar, $stateParams, $state, Types, smoothScroll, $timeout) {

    //View options

    $scope.mtd.showLetters=false;
    $scope.mtd.showRating=false;

    //Find free letters for registering new users

    $scope.mtd.getPersonalUsed = function () {
        var result=[];
        var letters;
        for (var phrase in $scope.mtd.personae) {
            if (angular.isObject($scope.mtd.personae[phrase]) && $scope.mtd.personae[phrase].letters) {
                letters=$scope.mtd.personae[phrase].letters;
                if (letters.indexOf('|') == -1) {
                    result.push($scope.mtd.personae[phrase].letters);
                }
            }
        }

        return result;

    };

    $scope.mtd.types=Types.types;  //types of phrases

    $scope.mtd.preset = preset;
    $scope.mtd.shuffle = shuffle;
    $scope.mtd.colorize = colorize;
    $scope.mtd.parent = parent;
    $scope.mtd.convertLetters = convertLetters;
    $scope.mtd.convertStory=convertStory;

    $scope.mtd.selector = function (letters,addOnly) {
        if (letters) {
            letters=convertLetters(letters);
            var found = false;
            for (var i = 0; i < $scope.mtd.selected.length; i++) {
                if ($scope.mtd.selected[i] == letters) {
                    found = true;
                    if (!addOnly) {
                        $scope.mtd.selected.splice(i, 1);
                    }
                }
            }
            if (!found) {
                $scope.mtd.selected.push(letters);
            }
            if (letters.indexOf('|') == -1) {
                if (found && letters==$scope.mtd.fltr && !addOnly) {
                    $scope.mtd.fltr = ''
                }
                if (!found || addOnly) {
                    $scope.mtd.fltr = letters;
                }
            }
        }
    };

    $scope.mtd.parseParams = function (id) {
        id=convertLetters(id);
        if(id) {
            var parts=id.split('|');
            for (var j=parts.length;j>0;j--) {

                if(parts[j-1]) {
                    $scope.mtd.selector(parts.join('|'), true);
                }
                parts.pop();
            }
        }
        $timeout(function () {
            var element = document.getElementById(id);
            smoothScroll(element, {duration:80});
        },4000);

    };

    $scope.mtd.parseParams($stateParams.id);

    $scope.mtd.isSelected = function (letters) {
        for (var i=0;i<$scope.mtd.selected.length;i++) {
            if ($scope.mtd.selected[i]==letters) {
                return true
            }
        }
        return false;
    };

    $scope.mtd.addToFeed = function (saying) {
        var said;
        var found=false;
        if (saying && saying.title && saying.type && saying.letters) {

            said = angular.copy(saying);
            if (said.next) {delete said.next}
            saying.text='';
            saying.title='';
            saying.letters='';
            saying.image='';
            said.letters=convertLetters(said.letters);
            said.author=$scope.mtd.persona;
            said.time=Date.now();
            angular.forEach($scope.feed, function (val, key) {
                if (val.letters && val.letters==said.letters) {
                    found = key;
                }
            });
            if ($scope.mtd.firebase) {
                if (found) {
                    $scope.feed[found]=said;
                    $scope.feed.$save(found);
                } else $scope.feed.$add(said);

            } else {
                if (found) {
                    $scope.feed[found]=said;
                } else {
                    $scope.feed.push(said);
                }
            }

        } else {console.log('a phrase without title, type, or color/letters')}

        $scope.updateTree();
    };

    $scope.updateTree=function () {
        $scope.tree=convertStory($scope.feed);
        $scope.source=$scope.tree;
    };

    $scope.mtd.updateTree=$scope.updateTree;

    $scope.$watch('feed', function (feed) {
        if (feed) {$scope.updateTree();}

    });

    $scope.mtd.isRated = function (letters) {
        if($scope.rating[letters]) {return $scope.rating[letters].pluses+$scope.rating[letters].minuses+$scope.rating[letters].zeros}
        return 0;
    };

    $scope.rate={};
    $scope.rate.rating = $scope.rating;
    $scope.rate.reset = function () {
        $scope.rating={};
    };

    $scope.rate.cancel = function (letters) {
        if ($scope.mtd.ratingView=='global' && $scope.mtd.rates[$scope.mtd.persona]) {
            if ($scope.mtd.rates[$scope.mtd.persona][letters]=='+1' && $scope.rating[letters].pluses>0) {
                $scope.rating[letters].pluses--;
                delete $scope.mtd.rates[$scope.mtd.persona][letters];
            }
            if ($scope.mtd.rates[$scope.mtd.persona][letters]=='-1' && $scope.rating[letters].minuses>0) {
                $scope.rating[letters].minuses--;
                delete $scope.mtd.rates[$scope.mtd.persona][letters];
            }
            if ($scope.mtd.rates[$scope.mtd.persona][letters]=='-' && $scope.rating[letters].zeros>0) {
                $scope.rating[letters].zeros--;
                delete $scope.mtd.rates[$scope.mtd.persona][letters];
            }

        }

    };
    $scope.rate.plus=function (letters) {
        if ($scope.mtd.ratingView=='global' && !$scope.mtd.rates[$scope.mtd.persona]) {
            $scope.mtd.rates[$scope.mtd.persona]={};

        }
        if ($scope.mtd.ratingView=='global' && $scope.mtd.rates[$scope.mtd.persona] && !$scope.mtd.rates[$scope.mtd.persona][letters]) {
            $scope.rating[letters] = $scope.rating[letters] || {pluses:0,zeros:0,minuses:0};
            $scope.rating[letters].pluses++;
            $scope.mtd.rates[$scope.mtd.persona][letters]='+1';
        } else {
            $scope.rating[letters] = $scope.rating[letters] || {pluses:0,zeros:0,minuses:0};
            $scope.rating[letters].pluses++;
        }

    };
    $scope.rate.minus=function (letters) {
        if ($scope.mtd.ratingView=='global' && !$scope.mtd.rates[$scope.mtd.persona]) {
            $scope.mtd.rates[$scope.mtd.persona]={};

        }
        if ($scope.mtd.ratingView=='global' && $scope.mtd.rates[$scope.mtd.persona] && !$scope.mtd.rates[$scope.mtd.persona][letters]) {
            $scope.rating[letters] = $scope.rating[letters] || {pluses:0,zeros:0,minuses:0};
            $scope.rating[letters].minuses++;
            $scope.mtd.rates[$scope.mtd.persona][letters]='-1';
        } else {
            $scope.rating[letters] = $scope.rating[letters] || {pluses:0,zeros:0,minuses:0};
            $scope.rating[letters].minuses++;
        }

    };
    $scope.rate.zero=function (letters) {
        if ($scope.mtd.ratingView=='global' && !$scope.mtd.rates[$scope.mtd.persona]) {
            $scope.mtd.rates[$scope.mtd.persona]={};

        }
        if ($scope.mtd.ratingView=='global' && $scope.mtd.rates[$scope.mtd.persona] && !$scope.mtd.rates[$scope.mtd.persona][letters]) {
            $scope.rating[letters] = $scope.rating[letters] || {pluses:0,zeros:0,minuses:0};
            $scope.rating[letters].zeros++;
            $scope.mtd.rates[$scope.mtd.persona][letters]='-';
        } else {
            $scope.rating[letters] = $scope.rating[letters] || {pluses:0,zeros:0,minuses:0};
            $scope.rating[letters].zeros++;
        }
    };
    $scope.rate.getPluses=function (letters) {
        if ($scope.rating[letters] && $scope.rating[letters].pluses>$scope.rating[letters].minuses) {
            return $scope.rating[letters].pluses - $scope.rating[letters].minuses;
        } else return '';
    };
    $scope.rate.getMinuses=function (letters) {
        if ($scope.rating[letters] && $scope.rating[letters].pluses<$scope.rating[letters].minuses) {
            return $scope.rating[letters].minuses - $scope.rating[letters].pluses
        }
        else return '';
    };
    $scope.rate.getZeros=function (letters) {
        if ($scope.rating[letters]) {return $scope.rating[letters].zeros+$scope.rating[letters].pluses+$scope.rating[letters].minuses}
        else return '';
    };
    $scope.rate.getRating = function (letters) {
        if($scope.rating[letters]) {return $scope.rating[letters].pluses-$scope.rating[letters].minuses}
        return 0;
    };
    $scope.rate.ratingSort = function (phrase) {
        if($scope.rating[phrase.letters]) {
            return (-$scope.rating[phrase.letters].pluses+$scope.rating[phrase.letters].minuses);
        };
        return 0;
    };
    $scope.rate.seenSort = function (phrase) {
        if($scope.rating[phrase.letters]) {
            return ($scope.rating[phrase.letters].zeros + $scope.rating[phrase.letters].pluses + $scope.rating[phrase.letters].minuses);
        };
        return 0;
    };
    $scope.rate.timeSort = function (phrase) {
        if (phrase.time) {
            return -phrase.time;
        }
    };

    $scope.rate.totalRated = function (rate) {
        var total=0;
        for (var a in $scope.rating) {
            if (rate>0 && $scope.rating[a] && $scope.rating[a].pluses > $scope.rating[a].minuses) {total++}
            if (rate===0 && $scope.rating[a] && $scope.rating[a].pluses === $scope.rating[a].minuses && ($scope.rating[a].zeros>0 || $scope.rating[a].pluses>0)) {

                total++
            }
            if (rate<0 && $scope.rating[a] && $scope.rating[a].pluses < $scope.rating[a].minuses) {total++}
        }
        return total;
    };
    $scope.rate.countNew = function () {
        var total=0;
        for (var i in $scope.source) {
            if ($scope.rating && !$scope.rating[$scope.source[i].letters]) {total++}
        }
        return total;
    };
    $scope.rate.toggleRF = function (rate) {
        if (rate == 'news') {$scope.ratingMode.news=!$scope.ratingMode.news
        } else if (rate>0) {
            $scope.ratingMode.plus=!$scope.ratingMode.plus
        } else if (rate<0) {
            $scope.ratingMode.minus=!$scope.ratingMode.minus
        } else {
            $scope.ratingMode.zero=!$scope.ratingMode.zero
        }
    };
    $scope.rate.ratingFilter = function (phrase) {
        var result=true;
        result=result && phrase.letters;
        if (result && $scope.rating && !$scope.rating[phrase.letters] && $scope.ratingMode.news) {return true}
        return result && $scope.rating && $scope.rating[phrase.letters] &&
            (
                (($scope.rating[phrase.letters].pluses > $scope.rating[phrase.letters].minuses) && $scope.ratingMode.plus) ||
                (($scope.rating[phrase.letters].minuses > $scope.rating[phrase.letters].pluses) && $scope.ratingMode.minus) ||
                (($scope.rating[phrase.letters].pluses == $scope.rating[phrase.letters].minuses)
                    && $scope.ratingMode.zero)
                );
    };

};

<|endoftext|>


<commit_before>var Marks = me.Renderable.extend({
    /**
     * constructor
     */
    init: function () {
        this.markCount = 0;
        // call the parent constructor
        // (size does not matter here)
        this._super(me.Renderable, 'init', [0, 0, 10, 10]);

        // create a font
        this.font = new me.Font("Arial", 18, "#ffffff");

    },

    /**
     * update function
     */
    update: function (dt) {
        return true;
    },

    /**
     * draw the score
     */
    draw: function (renderer) {
        this.font.draw(renderer, this.markCount, 26, 8);
    }
});

game.PlayerEntity = me.Entity.extend({

    init: function (x, y, id, playerIdx) {

        this.direction = "right";
        this.animation = 'stand';
        this.dirX = 0;
        this.dirY = 0;
        this.playerId = id;

        this.marks = [];

        var settings = {};
        var imageName = "spritesheet" + playerIdx;
        settings.image = me.loader.getImage(imageName);
        settings.width = 64;
        settings.height = 64;
        // call the constructor
        this._super(me.Entity, 'init', [x, y, settings]);

        this.renderable = new me.Container(0, 0, 64, 64);

        var animSheet = new me.AnimationSheet(0, 0, settings);
        this.renderable.addChild(animSheet);

        this.mark = new Marks();
        this.renderable.addChild(this.mark);

        this.sheet = animSheet;

        // ensure the player is updated even when outside of the viewport
        this.alwaysUpdate = true;

        // define a basic walking animation (using all frames)
        animSheet.addAnimation("stand_side", [0,3,8,13]);
        animSheet.addAnimation("stand_up", [7,12,15,16]);
        animSheet.addAnimation("stand_down", [0,3,8,13]);

        animSheet.addAnimation("dead_side", [14]);
        animSheet.addAnimation("dead_up", [14]);
        animSheet.addAnimation("dead_down", [14]);

        animSheet.addAnimation("walk_side", [0,3,8,13]);
        animSheet.addAnimation("walk_up", [7,12,15,16]);
        animSheet.addAnimation("walk_down", [0,3,8,13]);

        animSheet.addAnimation("dance1_side", [6, 1, 10], 100);
        animSheet.addAnimation("dance1_up", [17, 5], 275);
        animSheet.addAnimation("dance1_down", [2, 11], 60);

        animSheet.addAnimation("carry", [0]);
        // set the standing animation as default
        animSheet.setCurrentAnimation("stand_side");
    },

    refreshCollision: function () {
        me.collision.check(this);
    },

    onCollision: function (response) {
        if (response.b.body.collisionType === me.collision.types.ENEMY_OBJECT) {
            console.log("Collision");
            if (response.b.marks.indexOf(response.a.playerId) === -1) {
                global.network.socket.emit("marked", response.b.playerId);
            }
        }
        return false;
    },

    update: function (dt) {
        this._super(me.Entity, 'update', [dt]);
        //this.body.update(dt);
        this.pos.x  = this.pos.x + this.dirX * dt * 0.001;
        this.pos.y  = this.pos.y + this.dirY * dt * 0.001;

    },

    refresh: function (playerInfo) {
        this.pos.x = playerInfo.x;
        this.pos.y = playerInfo.y;
        this.dirX = playerInfo.dx;
        this.dirY = playerInfo.dy;

        this.mark.markCount = playerInfo.marks.length;

        var dir = playerInfo.direction;

        this.sheet.flipX(dir == "right");

        if (dir == "left" || dir == "right") {
            dir = "side";
        }

        var animName = playerInfo.animation + "_" + dir;
        this.trySetAnim(animName);
    },

    trySetAnim: function (animName) {

        if (!this.sheet.isCurrentAnimation(animName)) {
            this.sheet.setCurrentAnimation(animName);
        }
    }

});
<commit_msg>fix: flip anim<commit_after>var Marks = me.Renderable.extend({
    /**
     * constructor
     */
    init: function () {
        this.markCount = 0;
        // call the parent constructor
        // (size does not matter here)
        this._super(me.Renderable, 'init', [0, 0, 10, 10]);

        // create a font
        this.font = new me.Font("Arial", 18, "#ffffff");

    },

    /**
     * update function
     */
    update: function (dt) {
        return true;
    },

    /**
     * draw the score
     */
    draw: function (renderer) {
        this.font.draw(renderer, this.markCount, 26, 8);
    }
});

game.PlayerEntity = me.Entity.extend({

    init: function (x, y, id, playerIdx) {

        this.direction = "right";
        this.animation = 'stand';
        this.dirX = 0;
        this.dirY = 0;
        this.playerId = id;

        this.marks = [];

        var settings = {};
        var imageName = "spritesheet" + playerIdx;
        settings.image = me.loader.getImage(imageName);
        settings.width = 64;
        settings.height = 64;
        // call the constructor
        this._super(me.Entity, 'init', [x, y, settings]);

        this.renderable = new me.Container(0, 0, 64, 64);

        var animSheet = new me.AnimationSheet(0, 0, settings);
        this.renderable.addChild(animSheet);

        this.mark = new Marks();
        this.renderable.addChild(this.mark);

        this.sheet = animSheet;

        // ensure the player is updated even when outside of the viewport
        this.alwaysUpdate = true;

        // define a basic walking animation (using all frames)
        animSheet.addAnimation("stand_side", [0,3,8,13]);
        animSheet.addAnimation("stand_up", [7,12,15,16]);
        animSheet.addAnimation("stand_down", [0,3,8,13]);

        animSheet.addAnimation("dead_side", [14]);
        animSheet.addAnimation("dead_up", [14]);
        animSheet.addAnimation("dead_down", [14]);

        animSheet.addAnimation("walk_side", [0,3,8,13]);
        animSheet.addAnimation("walk_up", [7,12,15,16]);
        animSheet.addAnimation("walk_down", [0,3,8,13]);

        animSheet.addAnimation("dance1_side", [6, 1, 10], 100);
        animSheet.addAnimation("dance1_up", [17, 5], 275);
        animSheet.addAnimation("dance1_down", [2, 11], 60);

        animSheet.addAnimation("carry", [0]);
        // set the standing animation as default
        animSheet.setCurrentAnimation("stand_side");
    },

    refreshCollision: function () {
        me.collision.check(this);
    },

    onCollision: function (response) {
        if (response.b.body.collisionType === me.collision.types.ENEMY_OBJECT) {
            console.log("Collision");
            if (response.b.marks.indexOf(response.a.playerId) === -1) {
                global.network.socket.emit("marked", response.b.playerId);
            }
        }
        return false;
    },

    update: function (dt) {
        this._super(me.Entity, 'update', [dt]);
        //this.body.update(dt);
        this.pos.x  = this.pos.x + this.dirX * dt * 0.001;
        this.pos.y  = this.pos.y + this.dirY * dt * 0.001;

    },

    refresh: function (playerInfo) {
        this.pos.x = playerInfo.x;
        this.pos.y = playerInfo.y;
        this.dirX = playerInfo.dx;
        this.dirY = playerInfo.dy;

        this.mark.markCount = playerInfo.marks.length;

        var dir = playerInfo.direction;

        this.sheet.flipX(dir == "left");

        if (dir == "left" || dir == "right") {
            dir = "side";
        }

        var animName = playerInfo.animation + "_" + dir;
        this.trySetAnim(animName);
    },

    trySetAnim: function (animName) {

        if (!this.sheet.isCurrentAnimation(animName)) {
            this.sheet.setCurrentAnimation(animName);
        }
    }

});
<|endoftext|>


<commit_before>/**
 * Created by Urthur on 2017/7/14.
 */
BI.DateTimeSelect = BI.inherit(BI.Widget, {
    _defaultConfig: function () {
        return BI.extend(BI.DateTimeSelect.superclass._defaultConfig.apply(this, arguments), {
            baseCls: "bi-date-time-select bi-border",
            max: 23,
            min: 0
        })
    },

    _init: function () {
        BI.DateTimeSelect.superclass._init.apply(this, arguments);
        var self = this, o = this.options;
        this.editor = BI.createWidget({
            type: "bi.sign_editor",
            value: this._alertInEditorValue(o.min),
            errorText: BI.i18nText("BI-Please_Input_Natural_Number"),
            validationChecker: function(v){
                return BI.isNaturalNumber(v);
            }
        });
        this.editor.on(BI.TextEditor.EVENT_CONFIRM, function(){
            self._finetuning(0);
            self.fireEvent(BI.DateTimeSelect.EVENT_CONFIRM);
        });
        this.topBtn = BI.createWidget({
            type: "bi.icon_button",
            cls: "column-pre-page-h-font top-button bi-border-left bi-border-bottom"
        });
        this.topBtn.on(BI.IconButton.EVENT_CHANGE, function(){
            self._finetuning(1);
            self.fireEvent(BI.DateTimeSelect.EVENT_CONFIRM);
        });
        this.bottomBtn = BI.createWidget({
            type: "bi.icon_button",
            cls: "column-next-page-h-font bottom-button bi-border-left"
        });
        this.bottomBtn.on(BI.IconButton.EVENT_CHANGE, function(){
            self._finetuning(-1);
            self.fireEvent(BI.DateTimeSelect.EVENT_CONFIRM);
        });
        this._finetuning(0);
        BI.createWidget({
            type: "bi.htape",
            element: this,
            items: [this.editor, {
                el: {
                    type: "bi.grid",
                    columns: 1,
                    rows: 2,
                    items: [{
                        column: 0,
                        row: 0,
                        el: this.topBtn
                    }, {
                        column: 0,
                        row: 1,
                        el: this.bottomBtn
                    }]
                },
                width: 30
            }]
        });
    },

    _alertOutEditorValue: function(v){
        if (v > this.options.max){
            v = this.options.min;
        }
        if (v < this.options.min){
            v = this.options.max
        }
        return BI.parseInt(v);
    },

    _alertInEditorValue: function(v){
        if (v > this.options.max){
            v = this.options.min;
        }
        if (v < this.options.min){
            v = this.options.max;
        }
        v = v < 10 ? "0" + v : v;
        return v;
    },

    _finetuning: function(add){
        var v = BI.parseInt(this._alertOutEditorValue(this.editor.getValue()));
        this.editor.setValue(this._alertInEditorValue(v + add));
    },

    getValue: function () {
        var v = this.editor.getValue();
        return this._alertOutEditorValue(v);
    },

    setValue: function (v) {
        this.editor.setValue(this._alertInEditorValue(v));
        this._finetuning(0);
    }

});
BI.DateTimeSelect.EVENT_CONFIRM = "EVENT_CONFIRM";
BI.shortcut("bi.date_time_select", BI.DateTimeSelect);<commit_msg>时分秒输入不可为空<commit_after>/**
 * Created by Urthur on 2017/7/14.
 */
BI.DateTimeSelect = BI.inherit(BI.Widget, {
    _defaultConfig: function () {
        return BI.extend(BI.DateTimeSelect.superclass._defaultConfig.apply(this, arguments), {
            baseCls: "bi-date-time-select bi-border",
            max: 23,
            min: 0
        })
    },

    _init: function () {
        BI.DateTimeSelect.superclass._init.apply(this, arguments);
        var self = this, o = this.options;
        this.editor = BI.createWidget({
            type: "bi.sign_editor",
            value: this._alertInEditorValue(o.min),
            allowBlank: false,
            errorText: BI.i18nText("BI-Please_Input_Natural_Number"),
            validationChecker: function(v){
                return BI.isNaturalNumber(v);
            }
        });
        this.editor.on(BI.TextEditor.EVENT_CONFIRM, function(){
            self._finetuning(0);
            self.fireEvent(BI.DateTimeSelect.EVENT_CONFIRM);
        });
        this.topBtn = BI.createWidget({
            type: "bi.icon_button",
            cls: "column-pre-page-h-font top-button bi-border-left bi-border-bottom"
        });
        this.topBtn.on(BI.IconButton.EVENT_CHANGE, function(){
            self._finetuning(1);
            self.fireEvent(BI.DateTimeSelect.EVENT_CONFIRM);
        });
        this.bottomBtn = BI.createWidget({
            type: "bi.icon_button",
            cls: "column-next-page-h-font bottom-button bi-border-left"
        });
        this.bottomBtn.on(BI.IconButton.EVENT_CHANGE, function(){
            self._finetuning(-1);
            self.fireEvent(BI.DateTimeSelect.EVENT_CONFIRM);
        });
        this._finetuning(0);
        BI.createWidget({
            type: "bi.htape",
            element: this,
            items: [this.editor, {
                el: {
                    type: "bi.grid",
                    columns: 1,
                    rows: 2,
                    items: [{
                        column: 0,
                        row: 0,
                        el: this.topBtn
                    }, {
                        column: 0,
                        row: 1,
                        el: this.bottomBtn
                    }]
                },
                width: 30
            }]
        });
    },

    _alertOutEditorValue: function(v){
        if (v > this.options.max){
            v = this.options.min;
        }
        if (v < this.options.min){
            v = this.options.max
        }
        return BI.parseInt(v);
    },

    _alertInEditorValue: function(v){
        if (v > this.options.max){
            v = this.options.min;
        }
        if (v < this.options.min){
            v = this.options.max;
        }
        v = v < 10 ? "0" + v : v;
        return v;
    },

    _finetuning: function(add){
        var v = BI.parseInt(this._alertOutEditorValue(this.editor.getValue()));
        this.editor.setValue(this._alertInEditorValue(v + add));
    },

    getValue: function () {
        var v = this.editor.getValue();
        return this._alertOutEditorValue(v);
    },

    setValue: function (v) {
        this.editor.setValue(this._alertInEditorValue(v));
        this._finetuning(0);
    }

});
BI.DateTimeSelect.EVENT_CONFIRM = "EVENT_CONFIRM";
BI.shortcut("bi.date_time_select", BI.DateTimeSelect);<|endoftext|>