Statistics
| Branch: | Tag: | Revision:

root / ui / static / snf / js / views.js @ e673a761

History | View | Annotate | Download (9.6 kB)

1
;(function(root){
2
    
3
    // root
4
    var root = root;
5
    
6
    // setup namepsaces
7
    var snf = root.synnefo = root.synnefo || {};
8
    var models = snf.models = snf.models || {}
9
    var storage = snf.storage = snf.storage || {};
10
    var views = snf.views = snf.views || {}
11
    var util = snf.util = snf.util || {}
12

    
13
    // shortcuts
14
    var bb = root.Backbone;
15
    
16
    // logging
17
    var logger = new snf.logging.logger("SNF-VIEWS");
18
    var debug = _.bind(logger.debug, logger);
19
    
20
    // Base view object
21
    views.View = bb.View.extend({
22
        // the main element of the view
23
        // view delegates show, visible, hide etc to this element
24
        view_id: false,
25

    
26
        el: '#app',
27
        data_from: false,
28
        selectors: {},
29
        
30
        initialize: function() {
31
            this.log = new snf.logging.logger("SNF-VIEWS:" + this.view_id);
32
        },
33
    
34
        // is the view visible ?
35
        visible: function(){
36
            return $(this.el).is(":visible");
37
        },
38
        
39
        // hide view
40
        hide: function(force) {
41
            if (!this.visible() && !force) { return this };
42
            return $(this.el).hide();
43
        },
44
        
45
        // show view
46
        show: function() {
47
            if (this.visible()) { return this };
48
            $(this.el).show();
49
            if (this.show_view) { this.show_view.apply(this, arguments)};
50
        },
51

    
52
        sel: function(id) {
53
            return this.$(this.selectors[id]);
54
        },
55

    
56
        // animations
57
        fadeIn: function(time, callback) {
58
            $(this.el).fadeIn(time, callback);
59
            return this.show();
60
        },
61

    
62
        fadeOut: function(time, callback) {
63
            $(this.el).fadeOut(time, callback);
64
            return this.hide();
65
        }
66
    });
67
    
68
    
69
    // overlays registry
70
    views._overlay_index = [];
71

    
72
    // overlay view helper
73
    views.Overlay = views.View.extend({
74
        view_id: 'overlay',
75
        tpl_selector: '#generic-overlay-tpl',
76
        css_class: 'overlay',
77
        oneInstance: true,
78
        fixed: false,
79

    
80
        
81
        initialize: function(options, selector) {
82
            this.defaults = {
83
                load: false,
84
                closeOnClick: false,
85
                closeOnEsc: false,
86
                mask: {
87
                    color: "#444",
88
                    loadSpeed: snf.config.overlay_speed || 0,
89
                    opacity: 0.7
90
                },
91
                speed: snf.config.overlay_speed || 200
92
            }
93
            
94
            this.tpl_selector = selector || this.tpl_selector;
95
            views.Overlay.__super__.initialize.apply(this);
96
            views._overlay_index.push(this);
97

    
98
            this.options = _.extend(this.defaults, options);
99
            this.options.clone = this.options.clone == undefined ? true : this.options.clonde;
100
            this.options.fixed = this.fixed;
101

    
102
            this.options.onOpen = this.options.onOpen || function() {};
103
            this.options.onClose = this.options.onClose || function() {};
104
            this.options.beforeOpen = this.options.beforeOpen || function() {};
105
            this.options.beforeClose = this.options.beforeClose || function() {};
106
            this.el = this.create_element();
107
            this.el.hide();
108
        
109
            var ajax_params = _.clone(this.options);
110

    
111
            ajax_params.onBeforeLoad = _.bind(this._beforeOpen, this);
112
            ajax_params.onLoad = _.bind(this._onOpen, this);
113
            ajax_params.onBeforeClose = _.bind(this._beforeClose, this);
114
            ajax_params.onClose = _.bind(this._onClose, this);
115
            ajax_params.oneInstance = this.oneInstance;
116
            // create overlay
117
            // TODO: does this return overlay object ?? (to avoid the next code line)
118
            $(this.el).overlay(ajax_params);
119

    
120
            this.overlay = $(this.el).overlay();
121
            this.append_css = this.options ? this.options.css_class ? this.options.css_class : "" : "";
122

    
123
            this.is_visible = false;
124
            return this;
125
        },
126

    
127
        create_element: function() {
128
            var el = undefined;
129
            if (this.options.clone) {
130
                el = $(this.tpl_selector).clone();
131
            } else {
132
                el = $(this.tpl_selector);
133
            }
134
            
135
            // append content
136
            if (this.content_selector) {
137
                var content = $(this.content_selector).clone();
138
                content.addClass("content");
139
                
140
                if ($(el).find(".content").length) {
141
                    $(el).find(".content").replaceWith(content);
142
                }
143
                content.removeClass("hidden");
144
            }
145

    
146
            if (this.overlay_id) {
147
            }
148

    
149
            $(el).addClass("overlay");
150
            if (this.css_class) {
151
                $(el).addClass(this.css_class);
152
            }
153
            
154
            if (this.options.clone) {
155
                $("body").append(el);
156
            }
157

    
158
            return el;
159
        },
160

    
161
        set_title: function(title) {
162
            if (title || this.title) {
163
                $(this.el).find(".header .title").html(title || this.title)
164
            }
165
        },
166

    
167
        set_subtitle: function(subtitle) {
168
            if (subtitle || this.subtitle) {
169
                $(this.el).find(".header .subtitle").html(subtitle || this.subtitle)
170
            }
171
        },
172

    
173
        _beforeOpen: function() {
174
            this.is_visible = true;
175
            if (this.append_css) {
176
                $(this.el).addClass(this.append_css);
177
            }
178

    
179
            this.set_title();
180
            this.set_subtitle();
181
            
182
            this.beforeOpen.apply(this, arguments);
183
            this.options.beforeOpen.apply(this, arguments);
184
        },
185

    
186
        _onOpen: function() {
187
            // clear previously bound click events
188
            $(this.el).find(".closeme").unbind("click");
189

    
190
            if ($(this.el).find(".closeme").length) {
191
                $(this.el).find(".closeme").click(_.bind(function(){
192
                    this.hide();
193
                }, this))
194
            }
195
            this.onOpen.apply(this, arguments);
196
            this.options.onOpen.apply(this, arguments);
197
        },
198

    
199
        _beforeClose: function() {
200
            this.is_visible = false;
201
            this.beforeClose.apply(this, arguments);
202
            this.options.beforeClose.apply(this, arguments);
203
        },
204

    
205
        _onClose: function() {
206
            if (this.append_css) {
207
                $(this.el).removeClass(this.append_css);
208
            }
209
            this.onClose.apply(this, arguments);
210
            this.options.onClose.apply(this, arguments);
211
        },
212

    
213
        beforeOpen: function () {},
214
        onOpen: function () {},
215
        beforeClose: function () {},
216
        onClose: function () {},
217

    
218
        show: function() {
219
            // close opened overlays
220
            var hidden = false;
221
            _.each(views._overlay_index, function(ovr){
222
                if (ovr == this) { return };
223
                if (ovr.visible()) {
224
                    hidden = true;
225
                    ovr.hide();
226
                }
227
            })
228

    
229
            // do we need to wait for other overlays to close ???
230
            if (hidden) { delay = 300; } else { delay = 0; }
231

    
232
            this.is_visible = true;
233
            window.setTimeout(_.bind(function(){ this.overlay.load() }, this), delay)
234
            return this;
235
        },
236

    
237
        hide: function() {
238
            if (!this.overlay.isOpened()) {
239
                // if its not opened events wont trigger
240
                this._onClose()
241
            } else {
242
                this.overlay.close();
243
            }
244
            return this;
245
        }
246
    });
247

    
248
    
249
    // overlay view helper
250
    views.VMOverlay = views.Overlay.extend({
251

    
252
        initialize: function() {
253
            views.VMOverlay.__super__.initialize.apply(this);
254
            this.vm = undefined;
255
            this.view_id_tpl = this.view_id;
256

    
257
            _.bindAll(this, "_handle_vm_change", "_handle_vm_remove");
258
        },
259

    
260
        set_vm: function(vm) {
261
            if (this.vm) { this.unbind_vm_handlers };
262
            this.vm = vm;
263
            this.view_id = this.view_id + "_" + vm.id;
264
            this.bind_vm_handlers();
265
        },
266

    
267
        bind_vm_handlers: function() {
268
            this.log.debug("binding handlers");
269
            this.vm.bind("change", this._handle_vm_change);
270
            storage.vms.bind("remove", this._handle_vm_remove);
271
        },
272
        
273
        unbind_vm_handlers: function() {
274
            this.log.debug("unbinding handlers", this.vm);
275
            if (!this.vm) { return };
276
            this.vm.unbind("change", this._handle_vm_change);
277
            storage.vms.unbind("remove", this._handle_vm_remove);
278
        },
279
        
280
        _update_vm_details: function() { 
281
            if (!this.vm) { console.error("invalid view state"); return }
282
            this.set_subtitle(this.vm.get("name") + snf.ui.helpers.vm_icon_tag(this.vm, "small"));
283
            this.update_vm_details() 
284
        },
285

    
286
        update_vm_details: function() {},
287
        handle_vm_remove: function() {},
288
        handle_vm_change: function () {},
289
        
290
        _handle_vm_remove: function(vm, collection) {
291
            if (this.vm && vm.id == this.vm.id) {
292
                this.hide();
293
            }
294
            this.handle_vm_remove();
295
        },
296
        
297
        _handle_vm_change: function(vm) {
298
            this._update_vm_details();
299
            this.handle_vm_change(vm);
300
        },
301
        
302
        beforeClose: function() {
303
            this.unbind_vm_handlers();
304
            this.vm = undefined;
305
        },
306

    
307
        show: function(vm) {
308
            this.set_vm(vm);
309
            views.VMOverlay.__super__.show.apply(this, arguments);
310
            this._update_vm_details();
311
        }
312

    
313
    });
314

    
315
    snf.config.update_hidden_views = true;
316

    
317
})(this);