editor: actions implementation
[fnpeditor.git] / src / editor / modules / documentToolbar / actionView.js
1 define(function(require) {
2     
3 'use strict';
4
5 var $ = require('libs/jquery'),
6     Backbone = require('libs/backbone'),
7     _ = require('libs/underscore'),
8     viewTemplate = require('libs/text!modules/documentToolbar/templates/actionView.html'),
9     buttonTemplate = require('libs/text!modules/documentToolbar/templates/actionViewButton.html'),
10     selectionTemplate = require('libs/text!modules/documentToolbar/templates/actionViewSelection.html');
11
12
13 viewTemplate = _.template(viewTemplate);
14 buttonTemplate = _.template(buttonTemplate);
15 selectionTemplate = _.template(selectionTemplate);
16
17 var iconExists = function(iconName) {
18     /* globals window */
19     var el = $('<i>').addClass('icon-' + iconName);
20     $('body').append(el);
21     var style = window.getComputedStyle(el[0]);
22     var toret = /glyphicons/.test(style.backgroundImage) && !/14px 14px/.test(style.backgroundPosition);
23     el.remove();
24     return toret;
25 };
26
27 var ActionView = Backbone.View.extend({
28     events: {
29         'mousedown .btn': 'onMouseDown',
30         'click .btn': 'onExecute',
31         'change select': 'onSelectionChange',
32         'mouseenter': 'onMouseEnter',
33         'mouseleave': 'onMouseLeave'
34     },
35     initialize: function() {
36         this.action = this.options.action;
37         this.action.on('paramsChanged', function() {
38             this.render();
39         }, this);
40         this.setElement(viewTemplate());
41     },
42     render: function() {
43         /* globals document */
44
45         var actionState = this.action.getState();
46
47         var templateContext = {
48             label: actionState.label || '?',
49             iconName: (iconExists(actionState.icon)) ? actionState.icon : null,
50             iconStyle: actionState.iconStyle
51         },
52             hovered = document.querySelectorAll(':hover'),
53             hovers = false,
54             button = this._button();
55            
56         if(hovered.length && _.last(hovered) === button[0]) {
57             hovers = true;
58         }
59
60         this.$el.empty();
61         _.pairs(this.action.definition.params).forEach(function(pair) {
62             var paramName = pair[0],
63                 paramDesc = pair[1],
64                 widget;
65             if(paramDesc.type === 'select') {
66                 widget = $(selectionTemplate({
67                     paramName: paramName,
68                     options: paramDesc.options
69                 }));
70                 if(this.action.params[paramName]) {
71                     widget.find('option[value=' + this.action.params[paramName].id + ']').attr('selected', true);
72                 }
73                 this.$el.append(widget);
74             }
75         }.bind(this));
76
77         this.$el.append(buttonTemplate(templateContext));
78         button = this._button();
79         
80         if(!actionState.allowed) {
81             button.attr('disabled', true);
82             button.wrap('<div style="position: relative;">');
83             button.after('<div style="position: absolute; top:0; bottom:0; left:0; right: 0"></div>');
84         }
85         
86         if(actionState.toggled !== undefined) {
87             button.toggleClass('active', actionState.toggled);
88         }
89
90         if(hovers) {
91             this.trigger('hover');
92         }
93     },
94     onMouseEnter: function() {
95         this.trigger('hover');
96     },
97     onMouseLeave: function() {
98         this.trigger('leave');
99     },
100     onMouseDown: function() {
101         this.trigger('mousedown');
102     },
103     onExecute: function() {
104         var ret = this.action.execute();
105         this.trigger('actionExecuted', this.action, ret);
106     },
107     onSelectionChange: function(e) {
108         var select = $(e.target),
109             paramName = select.attr('param');
110
111         this.action.definition.params[paramName].options.some(function(option) {
112             if(option.id.toString() === select.val()) {
113                 this.action.updateWidgetParam(paramName, option);
114                 return true; // break
115             }
116         }.bind(this));
117     },
118     _button: function() {
119         return this.$el.find('button');
120     }
121 });
122
123 var create = function(action) {
124     var view = new ActionView({action:action});
125     view.render();
126
127     return {
128         on: function() {
129             view.on.apply(view, Array.prototype.slice.call(arguments, 0));
130         },
131         dom: view.$el,
132     };
133 };
134
135 return {
136     create: create
137 };
138
139 });