PageRenderTime 46ms CodeModel.GetById 26ms app.highlight 17ms RepoModel.GetById 0ms app.codeStats 0ms

/agora_site/static/js/agora/views/generic.js

https://bitbucket.org/rafacouto/agora-ciudadana-fork
JavaScript | 466 lines | 360 code | 80 blank | 26 comment | 40 complexity | 81c6e452de34383732d8392e1cd6184b MD5 | raw file
  1(function() {
  2    var Agora = this.Agora,
  3        app = this.app;
  4
  5    /*
  6     * Agora calendar widget scope
  7    */
  8
  9    (function() {
 10        var ElectionModel = Backbone.Model.extend({});
 11        var ElectionsCollection = Backbone.Collection.extend({
 12            model: ElectionModel
 13        });
 14
 15        Agora.CalendarWidgetView = Backbone.View.extend({
 16            el: "#agora-calendar",
 17
 18            events: {
 19                "keyup .election-search-query": "onSearchChange"
 20            },
 21
 22            initialize: function() {
 23                _.bindAll(this);
 24                this.template = _.template($("#template-election").html());
 25                this.collection = new ElectionsCollection();
 26                this.collection.on('reset', this.resetCollection);
 27
 28                var ajax = new Ajax();
 29                ajax.on('success', this.initializeSuccess);
 30                ajax.get(this.$el.data('url'));
 31
 32                // Debouncing
 33                this.onSearchChange = _.debounce(this.onSearchChange, 400);
 34            },
 35
 36            initializeSuccess: function(xhr) {
 37                if (xhr.status === 200) {
 38                    var data = JSON.parse(xhr.responseText);
 39                    this.collection.reset(data.objects);
 40                }
 41            },
 42
 43            onSearchChange: function(event) {
 44                var target = $(event.currentTarget);
 45                var data = {"q": target.val()};
 46
 47                var ajax = new Ajax();
 48                ajax.on('success', this.initializeSuccess);
 49                ajax.get(this.$el.data('url'), data);
 50                console.log("onSearchChange: " + target.val());
 51            },
 52
 53            resetCollection: function(collection) {
 54                this.$(".list-container").empty();
 55
 56                var data = collection.groupBy(function(item) {
 57                    var date = item.get('voting_extended_until_date') ||
 58                        item.get('voting_ends_at_date') ||
 59                        item.get('voting_starts_at_date');
 60                    if (date) {
 61                        return date.split("T")[0];
 62                    } else {
 63                        return null;
 64                    }
 65                });
 66
 67                _.each(_.pairs(data), function(item) {
 68                    var key = item[0],
 69                        val = item[1];
 70
 71                    var date = moment(key);
 72                    var dom = this.template({"datetime":date.format("LL"), "items": val});
 73
 74                    this.$(".list-container").append(dom);
 75                }, this);
 76
 77                if (collection.length === 0) {
 78                    this.$(".list-container").append(this.$("#no-elections"));
 79                }
 80            }
 81        });
 82    }).call(this);
 83
 84    /*
 85     * Agoras list widget scope.
 86     */
 87
 88    (function() {
 89        var AgoraModel = Backbone.Model.extend({});
 90        var AgorasCollection = Backbone.Collection.extend({
 91            model: AgoraModel
 92        });
 93
 94        Agora.AgoraWidgetListView = Backbone.View.extend({
 95            el: "#agora-list",
 96
 97            initialize: function() {
 98                _.bindAll(this);
 99                this.agoraTemplate = _.template($("#template-agora").html());
100                this.agorasCollection = new AgorasCollection();
101                this.agorasCollection.on('reset', this.resetAgorasCollection);
102
103                var ajax = new Ajax();
104                ajax.on("success", this.initializeSuccess);
105                ajax.get(this.$el.data('url'));
106            },
107
108            initializeSuccess: function(xhr) {
109                if (xhr.status === 200) {
110                    var data = JSON.parse(xhr.responseText);
111                    this.agorasCollection.reset(data.objects);
112                }
113            },
114
115            resetAgorasCollection: function(collection) {
116                this.$(".last-agoras .list-container").empty();
117                if (collection.length === 0) {
118                    var emptyItem = this.make('ul', {'id':'no-agoras'}, gettext('No agoras found'));
119                    this.$(".last-agoras .list-container").append(emptyItem);
120                } else {
121                    collection.each(this.addAgoraItem);
122                }
123            },
124
125            addAgoraItem: function(model) {
126                var dom = this.agoraTemplate(model.toJSON());
127                this.$(".last-agoras .list-container").append(dom);
128            }
129        });
130    }).call(this);
131
132    /**
133     * Used for showing modal dialogs
134     */
135    (function() {
136        Agora.ModalDialogView = Backbone.View.extend({
137            el: "#modaldialogdiv",
138
139            initialize: function() {
140                _.bindAll(this);
141                this.template = _.template($("#template-modal_dialog").html());
142                this.delegateEvents();
143            },
144
145            populate: function(header, body, footer) {
146                this.$el.html(this.template({'header': header,
147                                             'body':  body,
148                                             'footer': footer}));
149                this.delegateEvents();
150            },
151
152            modal: function(data) {
153                this.$el.find("#modal_dialog").modal(data);
154            },
155
156            hide: function() {
157                this.modal('hide');
158            },
159
160            show: function() {
161                this.modal('show');
162            },
163
164
165        });
166    }).call(this);
167
168    /**
169     * used to delegate your vote
170     */
171    Agora.delegateVoteHandler = function(e, self) {
172        if (self.sendingData) {
173            return;
174        }
175        var agora = $(e.target).data('agora');
176        var delegate = $(e.target).data('delegate');
177
178        var ballot = {
179            'action':'delegate_vote',
180            'user_id': delegate.id
181        };
182
183        var data = {"agora": agora, "delegate": delegate};
184
185        app.confirmDelegateActionDialog = new Agora.ModalDialogView();
186        var title = interpolate(gettext("Confirm delegation to %s in agora %s"),
187                [delegate.full_name, agora.full_name]);
188        var body =  _.template($("#template-confirm_delegate_modal_dialog_body").html())(data);
189        var footer = _.template($("#template-confirm_delegate_modal_dialog_footer").html())();
190
191        app.confirmDelegateActionDialog.populate(title, body, footer);
192        app.confirmDelegateActionDialog.show();
193
194        self.sendingData = true;
195        $("#confirm-delegate-action").click(function(e, self) {
196            e.preventDefault();
197            if ($("#confirm-delegate-action").hasClass("disabled")) {
198               return false;
199            }
200
201             $("#confirm-delegate-action").addClass("disabled");
202
203             var jqxhr = $.ajax("/api/v1/agora/" + agora.id + "/action/", {
204                 data: JSON.stringifyCompat(ballot),
205                 contentType : 'application/json',
206                 type: 'POST',
207             })
208             .done(function(e, self) {
209                 self.sendingData = false;
210                 $("#modal_dialog").modal('hide');
211                 return false;
212             })
213             .fail(function(e, self) {
214                 $("#confirm-delegate-action").removeClass("disabled");
215                 alert("Error casting the ballot, try again or report this problem");
216                 $("#modal_dialog").modal('hide');
217                 return false;
218             });
219
220            return false;
221        });
222
223        $("#deny-delegate-action").click(function(e, self) {
224            $("#modal_dialog").modal('hide');
225            return false;
226        });
227        self.sendingData = false;
228    };
229
230    /*
231     * Generic view for all search pages.
232    */
233
234    (function() {
235        var ItemModel = Backbone.Model.extend({});
236
237        var ItemCollection = Backbone.Collection.extend({
238            model: ItemModel
239        });
240
241        Agora.GenericListView = Backbone.View.extend({
242            el: "#activity-list",
243
244            events: {
245                "click a.endless_more": "onMoreClicked"
246            },
247
248            setup: function() {
249                this.url = this.$el.data('url');
250                this.method = this.$el.data('method') || 'get';
251            },
252
253            setupTemplates: function() {
254                if (this.templateEl !== undefined) {
255                    this.template = _.template($(this.templateEl).html());
256                }
257            },
258
259            initialize: function() {
260                _.bindAll(this);
261                this.firstLoadSuccess = false;
262                this.finished = false;
263
264                this.collection = new ItemCollection();
265                this.collection.on('reset', this.collectionReset);
266                this.collection.on('add', this.addItem);
267                this.endlessDom = this.$(".endless-container");
268                this.endlessDom.find("div.endless_loading").hide();
269
270                this.offset = 0;
271                this.limit = 20;
272
273                this.setup();
274                this.setupTemplates();
275                this.delegateEvents();
276                this.requestObjects();
277
278                $(window).scroll(this.infiniteScroll);
279            },
280
281            requestObjects: function() {
282                if (!this.finished) {
283                    var ajax = new Ajax();
284                    ajax.on('success', this.requestSuccess);
285
286                    var params = _.extend({}, {limit:this.limit, offset: this.offset},
287                                                                this.params || {});
288                    this.offset += this.limit;
289
290                    if (this.method === 'get') {
291                        ajax.get(this.url, params);
292                    } else if (this.method === 'post') {
293                        ajax.post(this.url, params);
294                    }
295                }
296            },
297
298            setEndlessFinishDom: function() {
299                this.endlessDom.find("a.endless_more").replaceWith(gettext("<span>No more results</span>"));
300                this.endlessDom.find("div.endless_loading").hide();
301            },
302
303            requestSuccess: function(xhr) {
304                if (xhr.status === 200) {
305                    var data = JSON.parse(xhr.responseText);
306
307                    this.endlessDom.find("div.endless_loading").hide();
308                    if (data.objects.length === 0) {
309                        this.setEndlessFinishDom();
310                        this.finished = true;
311                    } else {
312                        var doc = $(document), win = $(window);
313
314                        if (!this.firstLoadSuccess) {
315                            this.firstLoadSuccess = true;
316                            this.collection.reset(data.objects);
317                        } else {
318                            this.$("a.endless_more").show();
319                            _.each(data.objects, function(item) {
320                                this.collection.add(item);
321                            }, this);
322                        }
323
324                        this.endlessDom.appendTo(this.$el);
325
326                        // if received less than the limit per page, it means
327                        // there are no more items
328                        if (data.objects.length < this.limit) {
329                            this.setEndlessFinishDom();
330                            this.finished = true;
331
332                        // if received the limit per page, but the doc is still
333                        // the same height as the window and scrollTop is 0,
334                        // it means the window admits more elements and more
335                        // elements can be fetch, so fetch those
336                        } else if (doc.height() == win.height() &&
337                            win.scrollTop() == 0) {
338                            this.onMoreClicked();
339                            this.$("a.endless_more").hide();
340                            this.endlessDom.find("div.endless_loading").show();
341                        }
342                    }
343                }
344            },
345
346            collectionReset: function(collection) {
347                this.$el.empty();
348                collection.each(this.addItem);
349            },
350
351            renderItem: function(model) {
352                if (this.template !== undefined) {
353                    return this.template(model.toJSON());
354                } else {
355                    return "<div>REIMPLEMENT THIS</div>";
356                }
357            },
358
359            addItem: function(model) {
360                var html = this.renderItem(model);
361                this.$el.append(html);
362            },
363
364            infiniteScroll: function() {
365                var doc = $(document), win = $(window);
366                var margin = this.$el.data('margin') || 300;
367
368                if (!this.finished &&
369                    (doc.height() - win.height() - win.scrollTop()) <= margin)
370                {
371                    this.onMoreClicked();
372                    this.$("a.endless_more").hide();
373                    this.endlessDom.find("div.endless_loading").show();
374                }
375            },
376
377            onMoreClicked: function(event) {
378                if (event) {
379                    event.preventDefault();
380                }
381                this.requestObjects();
382            }
383        });
384        Agora.ActivityListView = Agora.GenericListView.extend({
385            el: "#activity-list",
386
387            setup: function() {
388                this.url = this.$el.data('url');
389                this.method = this.$el.data('method') || 'get';
390                this.templates = {}
391            },
392
393            renderItem: function(model) {
394                var json = model.toJSON();
395                json.actor.initials = Agora.getUserInitials(json.actor);
396                if (!this.templates[json.type_name]) {
397                    this.templates[json.type_name] = _.template(
398                        $('#template-action_' + json.type_name).html()
399                            || '<#template-action_' + json.type_name
400                            + ' not found>'
401                    );
402                }
403                return this.templates[json.type_name](json);
404            }
405        });
406        Agora.getUserInitials = function(json) {
407            if (json.full_name && json.full_name != json.username) {
408                var initials = "";
409                var words = $.trim(json.full_name).split(" ");
410                _.each(words, function (word) {
411                    var trimmed = $.trim(word);
412                    if (trimmed.length > 0) {
413                        initials += word[0].toUpperCase();
414                    }
415                });
416                return initials;
417            } else {
418                return json.username[0].toUpperCase();
419            }
420        };
421
422        /**
423         * This view renders a dynamic action list view. Inherit it
424         * overriding the model in the setup() function.
425         */
426        Agora.ActionListView = Backbone.View.extend({
427            el: "#action_list",
428
429            events: {
430                'click a.main-action': 'doMainAction',
431                'click a.action-link': 'doAction'
432            },
433
434            initialize: function() {
435                _.bindAll(this);
436                this.template = _.template($("#template-action_list").html());
437                this.setup();
438                this.render();
439
440                return this.$el;
441            },
442
443            setup: function() {
444                this.model = {};
445            },
446
447            render: function() {
448                if (this.model) {
449                    this.$el.html(this.template(this.model));
450                    this.delegateEvents();
451                }
452                return this;
453            },
454
455            doAction: function(e) {
456                e.preventDefault();
457                console.log("doAction not implemented");
458            },
459
460            doMainAction: function(e) {
461                e.preventDefault();
462                console.log("doMainAction not implemented");
463            }
464        });
465    }).call(this);
466}).call(this);