/beancounter/static/js/tags.js
JavaScript | 231 lines | 175 code | 33 blank | 23 comment | 8 complexity | f83466d427fc566406a84bf935138210 MD5 | raw file
Possible License(s): 0BSD
- // vim: fdm=marker
- /*
- * Copyright (c) 2011-2012 Audrius KaĹžukauskas
- *
- * This file is part of BeanCounter and is released under
- * the ISC license, see LICENSE for more details.
- */
- /*jslint indent: 4, browser: true, nomen: true, sloppy: true */
- /*global $, _, Backbone, B, DATA */
- B.Tags = {};
- // Tag resource URL.
- B.Tags.URL = '/api/tags';
- B.Tags.Model = Backbone.Model.extend({ // {{{
- defaults: {
- checked: false
- },
- validate: function (attrs) {
- if (attrs.hasOwnProperty('name')) {
- var name = $.trim(attrs.name);
- if (!name) {
- return 'Tag name is required';
- }
- }
- },
- toggleChecked: function () {
- this.set({checked: !this.get('checked')});
- }
- }); // }}}
- B.Tags.Collection = B.Collection.extend({ // {{{
- model: B.Tags.Model,
- url: B.Tags.URL,
- parse: function (resp) {
- return resp.tags;
- }
- }); // }}}
- B.Tags.Views = {};
- B.Tags.Views.Row = B.Views.Row.extend({ // {{{
- // Cache template function.
- template: _.template($('#tag-row-template').html()),
- formFactory: function () {
- return B.Tags.Views.EditForm;
- }
- }); // }}}
- // Base view for tag forms.
- B.Tags.Views.Form = B.Views.Form.extend({ // {{{
- // Cache template function.
- template: _.template($('#tag-form-template').html()),
- render: function () {
- var tag;
- if (this.model) {
- tag = this.model.toJSON();
- } else {
- tag = {name: ''};
- }
- this.$el.html(this.template(tag));
- return this;
- }
- }); // }}}
- // Add tag form view.
- B.Tags.Views.AddForm = B.Tags.Views.Form.extend({ // {{{
- remove: function () {
- this.$el.remove();
- this.trigger('edit:end');
- },
- saveChanges: function () {
- this.collection.create(this.getValues(), {
- wait: true,
- success: _.bind(function (model, resp) {
- this.remove();
- $.sticky('Added new tag');
- }, this),
- error: function (model, resp) {
- if (typeof resp === 'object') {
- resp = JSON.parse(resp.responseText).error;
- }
- $.sticky(resp, {category: 'error'});
- }
- });
- }
- }); // }}}
- // Edit tag form view.
- B.Tags.Views.EditForm = B.Tags.Views.Form.extend({ // {{{
- initialize: function () {
- // Uncheck tag before editing.
- this.model.set({checked: false});
- },
- remove: function () {
- var row = new B.Tags.Views.Row({model: this.model});
- this.$el.after(row.render().el).remove();
- this.model.trigger('edit:end');
- },
- saveChanges: function () {
- var name = this.model.get('name');
- this.model.save(this.getValues(), {
- wait: true,
- success: _.bind(function (model, resp) {
- this.remove();
- model.trigger('sort');
- $.sticky('Changed a tag');
- }, this),
- error: function (model, resp) {
- if (typeof resp === 'object') {
- // Restore previous tag name.
- model.set({name: name});
- resp = JSON.parse(resp.responseText).error;
- }
- $.sticky(resp, {category: 'error'});
- }
- });
- }
- }); // }}}
- B.Tags.Views.Table = B.Views.Table.extend({ // {{{
- initialize: function () {
- B.Views.Table.prototype.initialize.call(this);
- this.setElement($('#tags table'));
- },
- rowFactory: function () {
- return B.Tags.Views.Row;
- }
- }); // }}}
- B.Tags.Views.Tab = Backbone.View.extend({ // {{{
- events: {
- 'click #show-add-tag': 'showAddForm',
- 'click #delete-tags': 'deleteTags'
- },
- initialize: function () {
- this.setElement($('#tags'));
- this.collection = new B.Tags.Collection();
- this.table = new B.Tags.Views.Table({
- collection: this.collection
- });
- // Populate collection with tags.
- this.collection.reset(DATA.tags);
- // Make functions for enabling/disabling input elements.
- this.enable = _.bind(this.setDisabled, this, false);
- this.disable = _.bind(this.setDisabled, this, true);
- this.collection.on('change:checked', this.toggleDeleteTags, this);
- this.collection.on('change:checked', this.toggleCheckAll, this);
- this.collection.on('edit:start', this.disable);
- this.collection.on('edit:end', this.enable);
- this.collection.on('reset', this.enable);
- },
- // Disable input elements while displaying add/edit form.
- setDisabled: function (disable) {
- this.$('#show-add-tag').disabled(disable);
- this.$('table input[type=checkbox]').prop('disabled', disable);
- this.$('tbody div.edit').prop('disabled', disable);
- if (!disable) {
- disable = _.isEmpty(this.collection.checked());
- }
- this.$('#delete-tags').disabled(disable);
- },
- showAddForm: function () {
- var form = new B.Tags.Views.AddForm({
- collection: this.collection
- });
- form.on('edit:end', function () {
- if (this.collection.isEmpty()) {
- this.$('tr.empty-msg').show();
- }
- this.enable();
- }, this);
- this.disable();
- this.$('tr.empty-msg').hide();
- this.$('tbody').prepend(form.render().el);
- form.focus();
- },
- toggleCheckAll: function () {
- this.$('input.check-all').prop('checked',
- this.collection.length === this.collection.checked().length);
- },
- toggleDeleteTags: function () {
- this.$('#delete-tags').disabled(_.isEmpty(this.collection.checked()));
- },
- deleteTags: function () {
- var checkedIds = this.collection.checkedIds();
- $.ajax({
- type: 'DELETE',
- contentType: 'application/json',
- dataType: 'json',
- data: JSON.stringify({ids: checkedIds}),
- url: B.Tags.URL,
- success: _.bind(function () {
- var count = checkedIds.length;
- this.$('#delete-tags').disabled(true);
- this.$('input.check-all').prop('checked', false);
- this.collection.remove(checkedIds);
- // Trigger 'remove:multiple' event to update tag lists for
- // entries at once.
- this.collection.trigger('remove:multiple');
- $.sticky('Removed ' + count + (count > 1 ? ' tags' : ' tag'));
- }, this),
- error: function (xhr, textStatus, errorThrown) {
- // TODO: notify about error.
- }
- });
- }
- }); // }}}