View

constructor
 View() 

Option name Type Description
options object

owl.View

function View(options){
    var that = this;

    options = options || {};

    this.el = options.el || window.document.createElement('div');
    this.elements = {};
    this.className = options.className || '';
    this.events = options.events || {};
    this.template = options.template || null;
    this.model = options.model;
    this.collection = options.collection;
    this.controller = options.controller;
    this.specialEvents = ['submit', 'focus', 'blur'];

    if (this.className) {
        this.el.className = this.className;
    }

    Object.keys(this.events).forEach(function(event) {
        var index = event.indexOf(' '),
            eventName = event.substr(0, index),
            eventSelector = event.substr(index + 1),
            method = that.events[event],
            isElementSelector = eventSelector[0] === '$';

        if (isElementSelector) {
            eventSelector = eventSelector.substr(1);
        }
        if (that.specialEvents.indexOf(eventName) !== -1) {
            return;
        }
        that.el.addEventListener(eventName, function(event) {
            var matchingElement = isElementSelector ?
            that.getMatchingElement(event.target, '[data-element=' + eventSelector + ']') ||
            that.getMatchingElement(event.target, '[data-elements=' + eventSelector + ']'):
                that.getMatchingElement(event.target, eventSelector);

            if (event.target && matchingElement) {
                that.callEventListener(method, matchingElement, event);
            }
        });
    });
}

View.prototype = {

getMatchingElement

method
 getMatchingElement() 

Option name Type Description
element Element
selector string
return object

Gets element matching selector

getMatchingElement: function(element, selector) {
    while (element && element !== this.el) {
        if (element.matches(selector)) {
            return element;
        }
        element = element.parentNode;
    }
    return null;
},

update

method
 update() 

Option name Type Description
el Element

Update events and element

update: function(el) {
    if (!el) {
        el = this.el;
    }
    this.updateEvents(el);
    this.updateElements(el);
},

updateEvents

method
 updateEvents() 

Option name Type Description
el Element

Update events

updateEvents: function(el) {
    var that = this;
    Object.keys(this.events).forEach(function(event) {
        var index = event.indexOf(' '),
            eventName = event.substr(0, index),
            eventSelector = event.substr(index + 1),
            method = that.events[event],
            isElementSelector = eventSelector[0] === '$';
        if (that.specialEvents.indexOf(eventName) === -1) {
            return;
        }
        if (isElementSelector) {
            eventSelector = eventSelector.substr(1);
            eventSelector = '[data-element=' + eventSelector + '],[data-elements=' + eventSelector + ']';
        }
        Array.prototype.forEach.call(el.querySelectorAll(eventSelector), function(element) {
            element.addEventListener(eventName, function(event) {
                that.callEventListener(method, element, event);
            });
        });
    });
},

updateElements

method
 updateElements() 

Option name Type Description
el Element

Update element

updateElements: function(el) {
    var that = this;
    Array.prototype.forEach.call(el.querySelectorAll('[data-element]'), function(element) {
        var name = element.getAttribute('data-element');
        that.elements[name] = element;
    });
    Array.prototype.forEach.call(el.querySelectorAll('[data-elements]'), function(element) {
        var name = element.getAttribute('data-elements');
        if(!that.elements[name]) {
            that.elements[name] = [];
        }
        that.elements[name].push(element);
    });
},

callEventListener

method
 callEventListener() 

Option name Type Description
method string
element Element
event Event

Calls event listener

callEventListener: function(method, element, event) {
    if(this[method]) {
        this[method](element, event);
    } else {
        console.error('Method ' + method + ' is not defined' +
            (this.className ? 'in ' + this.className : ''));
    }
},

render

method
 render() 

Option name Type Description
data

Calls template function and adds result to element

render: function(data) {
    this.el.innerHTML = this.template ? this.template(data) : '';
    this.update();
},

remove

method
 remove() 

Removes element content

remove: function() {
    this.el.innerHTML = '';
    this.elements = {};
},

find

method
 find() 

Option name Type Description
selector string
return Element

Finds element in current component by selector

find: function(selector) {
    return this.el.querySelector(selector);
},

findAll

method
 findAll() 

Option name Type Description
selector string
return NodeList

Finds all elements in current component by selector

findAll: function(selector) {
    return this.el.querySelectorAll(selector);
},

getEl

method
 getEl() 

Gets DOM element related to the view

getEl: function() {
    return this.el;
}
    };

    owl.View = View;
})(window, owl);