Example #1
0
var Property = require('./property'),
    View = require('./view'),
    statham = require('statham'),
    createSpec = require('spec-js');

function TemplaterProperty(){}
TemplaterProperty = createSpec(TemplaterProperty, Property);
TemplaterProperty.prototype.trackKeys = true;

function findValueIn(value, source){
    var isArray = Array.isArray(source);
    for(var key in source){
        if(isArray && isNaN(key)){
            continue;
        }
        if(source[key] === value){
            return key;
        }
    }
}

TemplaterProperty.prototype._immediate = true;
TemplaterProperty.prototype.watchChanges = 'structure value';
TemplaterProperty.prototype.hasChanged = function(){
    var lastKeys = this._lastValue._lastKeys || [],
        changes = this._lastValue.update(this.value),
        watched = this.watchChanges.split(' '),
        newKeys = [],
        keysChanged;

    if(this._sourcePathInfo && this._sourcePathInfo.subPaths){
Example #2
0
    }
    tokens.forEach(function(token){
        token.evaluate(scope);
    })
}

function createOpperatorTokeniser(Constructor, opperator) {
    return function(substring){
        if(substring.indexOf(opperator) === 0){
            return new Constructor(opperator, opperator.length);
        }
    };
}

function PipeToken(){}
PipeToken = createSpec(PipeToken, Token);
PipeToken.prototype.name = 'PipeToken';
PipeToken.tokenPrecedence = 1;
PipeToken.prototype.parsePrecedence = 5;
PipeToken.tokenise = createOpperatorTokeniser(PipeToken, '|');
PipeToken.prototype.evaluate = function(scope, args) {
    this.result = '|';
};

function ParenthesesCloseToken(){}
ParenthesesCloseToken = createSpec(ParenthesesCloseToken, Token);
ParenthesesCloseToken.tokenPrecedence = 1;
ParenthesesCloseToken.prototype.parsePrecedence = 10;
ParenthesesCloseToken.prototype.name = 'ParenthesesCloseToken'
ParenthesesCloseToken.tokenise = function(substring) {
    if(substring.charAt(0) === ')'){
Example #3
0
            viewItem[key] = description[key];
        }
    }
}

/**
    ## ViewItem

    The base constructor for all gaffa ViewItems.

    Views, Behaviours, and Actions inherrit from ViewItem.
*/
function ViewItem(viewItemDescription){
    inflateViewItem(this, viewItemDescription);
}
ViewItem = createSpec(ViewItem, Bindable);

    /**
        ## .path

        the base path for a viewItem.

        Any bindings on a ViewItem will recursivly resolve through the ViewItems parent's paths.

        Eg:

            // Some ViewItems
            var viewItem1 = new views.button(),
                viewItem2 = new actions.set();

            // Give viewItem1 a path.
Example #4
0
    action.bind(parent, scope);
}

function triggerActions(actions, parent, scope, event) {
    if(Array.isArray(actions)){
        for(var i = 0; i < actions.length; i++) {
            triggerAction(actions[i], parent, scope, event);
        }
    }else if(actions instanceof Action){
        triggerAction(actions, parent, scope, event);
    }
}

function Action(actionDescription){
}
Action = createSpec(Action, ViewItem);
Action.trigger = triggerActions;
Action.prototype.trigger = function(){
    throw 'Nothing is implemented for this action (' + this.constructor.name + ')';
};
Action.prototype.condition = new Property({
    value: true
});

// Because actions shouldn't neccisarily debind untill they are complete,
// They have an odd debind impementation.
Action.prototype.debind = function(){
    if(!this._complete && !this._destroyed){
        return;
    }
    this.complete();
Example #5
0
var createSpec = require('spec-js'),
    ViewItem = require('./viewItem');

function Behaviour(behaviourDescription){}
Behaviour = createSpec(Behaviour, ViewItem);
Behaviour.prototype.bind = function(parent){
    ViewItem.prototype.bind.apply(this, arguments);
}

module.exports = Behaviour;
Example #6
0
    return scope;
}

function bindViewEvent(view, eventName){
    return view.gaffa.events.on(eventName, view.renderedElement, function (event) {
        view.triggerActions(eventName, createEventedActionScope(view, event), event);
    });
}

function View(viewDescription){
    var view = this;

    view.behaviours = view.behaviours || [];
    this.consuela = new Consuela();
}
View = createSpec(View, ViewItem);

function watchElements(view){
    for(var key in view){
        if(!view.hasOwnProperty(key)){
            return;
        }
        if(crel.isElement(view[key])){
            view.consuela.watch(view[key]);
        }
    }
}

function bindViewEvents(view){
    for(var key in view.actions){
        var actions = view.actions[key],
Example #7
0
        }

        referenceItem = referenceItem.parent;
    }

    return gedi.paths.resolve.apply(this, paths.reverse());
}

var iuid = 0;

function Bindable(){
    this.setMaxListeners(1000);
    // instance unique ID
    this.__iuid = iuid++;
}
Bindable = createSpec(Bindable, EventEmitter);
Bindable.bindables = {};
Bindable.getByIuid = function(id){
    return this.bindables[id];
};
Bindable.prototype.getPath = function(){
    return getItemPath(this);
};
Bindable.prototype.getDataAtPath = function(){
    if(!this.gaffa){
        return;
    }
    return this.gaffa.model.get(getItemPath(this));
};
Bindable.prototype.toJSON = function(){
    var tempObject = jsonConverter(this, this.__serialiseExclude__, this.__serialiseInclude__);
Example #8
0
    if(identifier != null){
        return identifier;
    }
}

function createKeywordTokeniser(Constructor, keyword){
    return function(substring){
        substring = isIdentifier(substring);
        if (substring === keyword) {
            return new Constructor(substring, substring.length);
        }
    };
}

function StringToken(){}
StringToken = createSpec(StringToken, Token);
StringToken.tokenPrecedence = 2;
StringToken.prototype.parsePrecedence = 2;
StringToken.prototype.stringTerminal = '"';
StringToken.prototype.name = 'StringToken';
StringToken.prototype.static = true;
StringToken.tokenise = function (substring) {
    if (substring.charAt(0) === this.prototype.stringTerminal) {
        var index = 0,
        escapes = 0;

        while (substring.charAt(++index) !== this.prototype.stringTerminal)
        {
           if(index >= substring.length){
                   throw "Unclosed " + this.name;
           }
Example #9
0
    }else{
        for(var key in propertyDescription){
            if(
                !propertyDescription.hasOwnProperty(key) ||
                propertyDescription instanceof Property && (
                    ~propertyDescription.__serialiseExclude__.indexOf(key) || 
                    ~excludeProps.indexOf(key)
                )
            ){
                continue;
            }
            this[key] = propertyDescription[key];
        }
    }
}
Property = createSpec(Property, Bindable);
Property.prototype.watchChanges = 'value keys structure reference type';
Property.prototype.hasChanged = function(){
    var changes = this._lastValue.update(this.value),
        watched = this.watchChanges.split(' ');

    for(var i = 0; i < watched.length; i++){
        if(changes[watched[i]]){
            return true;
        }
    }
};
Property.prototype.set = function(value, isDirty, scope){
    if(!this._bound){
        this.value = value;
        return;
Example #10
0
},{}],2:[function(require,module,exports){
var Lang = require('lang-js'),
    Token = Lang.Token,
    global = require('./global'),
    createSpec = require('spec-js');

var createNestingParser = Lang.createNestingParser,
    Token = Lang.Token,
    Scope = Lang.Scope;

function combinedTokensResult(tokens){
    if(tokens.length === 1){
        return tokens[0].result;
    }
    return tokens.reduce(function(result, token){
        return result += token.result;
    },'');
}

function evaluateTokens(tokens, scope){
    if(!tokens){
        return;
    }
    tokens.forEach(function(token){
        token.evaluate(scope);
    })
}

function createOpperatorTokeniser(Constructor, opperator) {
    return function(substring){
        if(substring.indexOf(opperator) === 0){
            return new Constructor(opperator, opperator.length);
        }
    };
}

function PipeToken(){}
PipeToken = createSpec(PipeToken, Token);
PipeToken.prototype.name = 'PipeToken';
PipeToken.tokenPrecedence = 1;
PipeToken.prototype.parsePrecedence = 5;
PipeToken.tokenise = createOpperatorTokeniser(PipeToken, '|');
PipeToken.prototype.parse = function(tokens, position){
    this.leftTokens = tokens.splice(0, position);

    var rightIndex = 1;
    while(tokens[rightIndex] && !(tokens[rightIndex] instanceof PipeToken)){
        rightIndex++;
    }

    this.rightTokens = tokens.splice(1, rightIndex - 1);

    if(!this.leftTokens){
        throw "Invalid syntax, expected token before |";
    }
    if(!this.rightTokens){
        throw "Invalid syntax, expected token after |";
    }
};
PipeToken.prototype.evaluate = function(scope, args) {
    evaluateTokens(this.leftTokens, scope);
    evaluateTokens(this.rightTokens, scope);

    var leftTokens = this.leftTokens,
        rightTokens = this.rightTokens;

    if(leftTokens.length === 1 && leftTokens[0] instanceof PipeToken){
        // concat
        this.result = leftTokens[0].result.slice();
    }else{
        this.result = [];
        if(leftTokens.length){
            this.result.push(combinedTokensResult(leftTokens));
        }
    }

    this.result.push(combinedTokensResult(rightTokens));
};

function ParenthesesCloseToken(){}
ParenthesesCloseToken = createSpec(ParenthesesCloseToken, Token);
ParenthesesCloseToken.tokenPrecedence = 1;
ParenthesesCloseToken.prototype.parsePrecedence = 10;
ParenthesesCloseToken.prototype.name = 'ParenthesesCloseToken'
ParenthesesCloseToken.tokenise = function(substring) {
    if(substring.charAt(0) === ')'){
        return new ParenthesesCloseToken(substring.charAt(0), 1);
    }
}

function ParenthesesOpenToken(){}
ParenthesesOpenToken = createSpec(ParenthesesOpenToken, Token);
ParenthesesOpenToken.tokenPrecedence = 1;
ParenthesesOpenToken.prototype.parsePrecedence = 3;
ParenthesesOpenToken.prototype.name = 'ParenthesesOpenToken'
ParenthesesOpenToken.tokenise = function(substring) {
    if(substring.charAt(0) === '('){
        return new ParenthesesOpenToken(substring.charAt(0), 1);
    }
}
ParenthesesOpenToken.prototype.parse = createNestingParser(ParenthesesCloseToken);
ParenthesesOpenToken.prototype.evaluate = function(scope){
    for(var i = 0; i < this.childTokens.length; i++){
        this.childTokens[i].evaluate(scope);
    }

    if(this.childTokens.length === 1 && this.childTokens[0] instanceof PipeToken){
        this.result = this.childTokens[0].result;
    }else{
        this.result = [combinedTokensResult(this.childTokens)];
    }
}

function WordToken(){}
WordToken = createSpec(WordToken, Token);
WordToken.tokenPrecedence = 100; // very last thing always
WordToken.prototype.parsePrecedence = 1;
WordToken.prototype.name = 'WordToken';
WordToken.tokenise = function(substring) {
    var character = substring.slice(0,1),
        length = 1;

    if(character === '\\'){
        if(substring.charAt(1) !== '\\'){
            character = substring.charAt(1);
        }
        length++;
    }

    return new WordToken(character, length);
};
WordToken.prototype.parse = function(tokens, position){
    var index = 0;

    while(tokens[position + index + 1] && tokens[position + index + 1].name === 'WordToken'){
        index++
    }

    this.childTokens = tokens.splice(position + 1, index);
};
WordToken.prototype.evaluate = function(scope){
    this.result = this.original;

    for(var i = 0; i < this.childTokens.length; i++){
        this.result+= this.childTokens[i].original;
    }
};

function PlaceholderToken(){}
PlaceholderToken = createSpec(PlaceholderToken, Token);
PlaceholderToken.tokenPrecedence = 1;
PlaceholderToken.prototype.parsePrecedence = 2;
PlaceholderToken.prototype.name = 'PlaceholderToken';
PlaceholderToken.regex = /^(\{.+?\})/;
PlaceholderToken.tokenise = function(substring){
    var match = substring.match(PlaceholderToken.regex);

    if(match){
        if(!match[1].match(/^\{\w+\}$/)){
            throw "Invalid placeholder name. Placeholders may only contain word characters";
        }
        var token = new PlaceholderToken(match[1], match[1].length);
        token.key = token.original.slice(1,-1);
        return token;
    }
};
PlaceholderToken.prototype.evaluate = function(scope){
    var result = scope.get(this.original.slice(1,-1));
    if(result instanceof Term){
        result = '';
    }
    this.result = result;
};

function EvaluateToken(){}
EvaluateToken = createSpec(EvaluateToken, Token);
EvaluateToken.tokenPrecedence = 1;
EvaluateToken.prototype.parsePrecedence = 4;
EvaluateToken.prototype.name = 'EvaluateToken';
EvaluateToken.regex = /^~(\w+)?(?:\(|\||\)|\s|$)/;
EvaluateToken.tokenise = function(substring){
    var match = substring.match(EvaluateToken.regex);

    if(!match){
        return;
    }

    var term = match[1];

    var token = new EvaluateToken(match[1], match[1].length + 1);
    token.term = term;

    return token;
};
EvaluateToken.prototype.parse = function(tokens, position){
    if(tokens[position+1] instanceof ParenthesesOpenToken){
        this.argsToken = tokens.splice(position+1,1).pop();
    }
};
EvaluateToken.prototype.evaluate = function(scope){
    var term = scope.get(this.term),
        fn,
        args = [];

    if(this.argsToken){
        this.argsToken.evaluate(scope);
        args = this.argsToken.result;
    }

    if(term instanceof Term){
        this.result = scope.evaluateTerm(term, scope, args);
    }else{
        this.result = scope.callWith(term, args);
    }
};

function Term(key, expression){
    var parts = key.match(/(\w+)(?:\((.*?)\))?(?:\||\)|\s|$)/);

    if(!parts){
        throw "Invalid term definition: " + key;
    }

    this.term = parts[1];
    this.parameters = parts[2] ? parts[2].split('|') : [];
    this.expression = expression;
}

var tokenConverters = [
        ParenthesesCloseToken,
        ParenthesesOpenToken,
        WordToken,
        PlaceholderToken,
        EvaluateToken,
        PipeToken
    ];

function convertTerms(termDefinitions, terms){
    terms || (terms = {});
    for(var key in termDefinitions){
        var term = new Term(key, termDefinitions[key]);
        terms[term.term] = term;
    }
    return terms;
}

var SeeThreepio = function(termDefinitions){
    var seeThreepio = {},
        lang = new Lang(),
        terms = convertTerms(termDefinitions);

    function evaluateTerm(term, scope, args){
        for(var i = 0; i < term.parameters.length; i++){
            var paremeter = term.parameters[i];

            scope.set(paremeter, args[i]);
        }

        var tokens = lang.evaluate(term.expression, scope, tokenConverters, true);

        return '' + combinedTokensResult(tokens);
    }

    seeThreepio.lang = lang;
    seeThreepio.tokenConverters = tokenConverters;
    seeThreepio.global = global;
    seeThreepio.tokenise = function(expression){
        return seeThreepio.lang.tokenise(expression, seeThreepio.tokenConverters);
    }
    seeThreepio.get = function(termName, args){
        var scope = new Lang.Scope();

        scope.add(this.global).add(terms);
        scope.evaluateTerm = evaluateTerm;

        var term = scope.get(termName);

        if(!term){
            // ToDo, something nicer than throw
            throw "term not defined: " + termName;
        }

        return evaluateTerm(term, scope, args);
    };
    seeThreepio.addTerms = function(termDefinitions){
        convertTerms(termDefinitions, terms);
    };
    seeThreepio.replaceTerms = function(termDefinitions){
        terms = convertTerms(termDefinitions);
    };

    return seeThreepio;
};

module.exports = SeeThreepio;
},{"./global":1,"lang-js":3,"spec-js":5}],3:[function(require,module,exports){
Example #11
0
*/

var createSpec = require('spec-js'),
    View = require('./view'),
    ViewContainer = require('./viewContainer'),
    Property = require('./property');

function ContainerView(viewDescription){
    this.views = this.views || {};
    this.views.content = new ViewContainer(this.views.content);
    this.on('bind', function(){
        for(var key in this.views){
            var viewContainer = this.views[key];

            if(viewContainer instanceof ViewContainer){
                viewContainer.bind(this);
            }
        }
    });
}
ContainerView = createSpec(ContainerView, View);
ContainerView.prototype.renderChildren = new Property({
    update: function(view, value){
        for(var key in view.views){
            view.views[key][value ? 'render' : 'derender']();
        }
    },
    value: true
});

module.exports = ContainerView;