CartoDB/cartodb20

View on GitHub
lib/assets/javascripts/cartodb/table/menu_modules/wizards/category_wizard.js

Summary

Maintainability
C
1 day
Test Coverage

  /**
   *  Category wizard, it extends from color map wizard
   *
   *  - It creates a collection (cartoProperties.categories) from the beginning.
   *  - This collection has the custom values of each column, if they
   *  were previously set.
   *  - When cartoProperties are set, collection is reset and view is re-rendered.
   *  - Collection view and subviews are at the end of this file.
   *
   *  var category_wizard = new cdb.admin.mod.CategoryWizard({
   *    table: table,
   *    model: model
   *  });
   *
   */
  cdb.admin.mod.CategoryWizard = cdb.admin.mod.SimpleWizard.extend({

    _TEXTS: {
      default_color:    _t('Others'),
      select_column:    _t('Select a column'),
      no_valid_columns: _t('There are no valid columns on your table to make a this visualization. \
                            Try to add a new one or change the existing ones to a valid type \
                            (string, number or boolean).')
    },

    initialize: function() {
      var self = this;
      this.type = this.type || 'category';
      cdb.admin.mod.SimpleWizard.prototype.initialize.call(this);
      this.table = this.options.table;
      this.categories = new Backbone.Collection(this.cartoProperties.get('categories'));

      this.cartoProperties.bind('change:metadata', this._getMetadata, this);
      this.categories.bind('change reset', function() {
        this.cartoProperties.set('categories', this.categories.toJSON());
      }, this);

      this.cartoProperties.bind('load', this._hideLoader, this);
      this.cartoProperties.bind('loading', this._showLoader, this);

      this.add_related_model(this.categories);

      this._addViews();
    },

    _showLoader: function() {
      this.loader.show();
    },

    _hideLoader: function() {
      this.loader.hide();
    },

    render: function() {
      var $wrapper = $("<div>").addClass("wrapper")
      , $content = $("<div>").addClass("content");

      if (this.isValid()) {
        $content.append(this.form.render().el);
        $content.append(this.custom_categories.render().el);
        $content.append(this.error.render().el);
        $content.append(this.loader.render().el);

        $wrapper.append($content);

        // Remove old custom scroll
        if (this.custom_scroll) {
          this.removeView(this.custom_scroll);
          this.custom_scroll.clean();
        }

        // Add new custom scroll
        this.custom_scroll = new cdb.admin.CustomScrolls({
          el:     $wrapper,
          parent: $wrapper.parent()
        });

        this.addView(this.custom_scroll);
        this.$el.html($wrapper);
      } else {
        this.renderError(this._TEXTS.no_valid_columns);
      }

      return this;
    },

    isValid: function() {
      return this._getColorColumns().length > 0;
    },

    _addViews: function() {
      // Properties form view
      this.form = new cdb.forms.Form({
        form_data: this.cartoProperties.formData(this.type),
        model: this.cartoProperties
      });
      this.addView(this.form);

      // Custom categories view
      this.custom_categories = new cdb.admin.mod.CategoryWizard.CategoriesView({
        collection:       this.categories,
        cartoProperties:  this.cartoProperties
      });
      this.addView(this.custom_categories);

      // Error view
      this.error = new cdb.admin.mod.CategoryWizard.Error();
      this.addView(this.error);

      // Loader view
      this.loader = new cdb.admin.mod.CategoryWizard.Loader();
      this.addView(this.loader);
    },

    _getMetadata: function() {
      // Set new categories
      var metadata = this.cartoProperties.get('metadata');
      
      // check if the metadata is an object array

      if (metadata && metadata.length && metadata[0].title !== undefined) {
        this.categories.reset(metadata);
      }
    },

    comeFromColor: function() {
      var colors = _.clone(this.model.get('properties').colors);
      var categories = _.clone(this.model.get('properties').categories);

      for (var i = 0, l = colors.length; i < l; i++) {
        if ((colors[i][0] != categories[i].title) || (colors[i][1] != categories[i].color) || (colors[i][2] != categories[i].title_type)) {
          return false;
        }
      }

      return true;
    }

  });


  /**
   *  Custom categories view within Categories Wizard
   *  - Manage thanks to a collection.
   *  - Each item needs a model with 'title', 'title_type', 'color' || 'file',
   *  'value_type' and 'default' if it is neccessary.
   *
   *  new cdb.admin.mod.CategoryWizard.CategoryView({
   *    collection: categories
   *  })
   */

  cdb.admin.mod.CategoryWizard.CategoriesView = cdb.core.View.extend({

    tagName: 'ul',

    className: 'custom_categories',

    initialize: function() {
      this.collection.bind('add remove reset', this.render, this);
      this.add_related_model(this.collection);
    },

    render: function() {
      var self = this;

      // clean old views
      this.clearSubViews();

      // render new items
      this.collection.each(function(category) {
        var item = new cdb.admin.mod.CategoryWizard.CategoriesViewItem({
          model:            category,
          cartoProperties:  self.options.cartoProperties
        });

        self.$el.append(item.render().el);
        self.addView(item);
      });

      return this;
    }
  });


  /**
   *  Custom category item view using the categories collection.
   *  - It needs a model with 'title', 'title_type', 'color' || 'file',
   *  'value_type' and 'default' if it is neccessary.
   *
   *  new cdb.admin.mod.CategoryWizard.CategoriesViewItem({
   *    model: category
   *  })
   */

  cdb.admin.mod.CategoryWizard.CategoriesViewItem = cdb.core.View.extend({

    tagName: 'li',

    className: 'custom_category_item',

    initialize: function() {
      this.template = cdb.templates.getTemplate('table/menu_modules/wizards/views/category_wizard_custom_categories');
    },

    render: function() {
      this.clearSubViews();

      this.$el.append(this.template(this.model.toJSON()));

      var view = new cdb.admin.mod.CategoryColor({
        model:            this.model,
        property:         'color',
        extra:            { image_property: 'file' },
        cartoProperties:  this.options.cartoProperties
      });

      this.model.bind("change", this._setModel, this);
      this.$('span.field').append(view.render().el);
      this.addView(view);

      return this;
    },

    _setModel: function(model, obj) {
      if (obj.changes && obj.changes.file && model.get('file')) {
        var file = model.get('file');
        model.set({ value_type: 'file' }, { silent: true })
      } else {
        model.set({ value_type: 'color' }, { silent: true })
      }

      this._triggerChange();
    },

    _triggerChange: function() {
      this.model.trigger('valueChanged')
    }
  });

  
  
  /**
   *  Custom color form to check extra colors each time
   *  is opened.
   *
   */

  cdb.admin.mod.CategoryColor = cdb.forms.Color.extend({
    
    _createPicker: function() {
      // Get wizard applied colors
      if (this.options.cartoProperties) {
        this.options.extra_colors = this._getExtraColors()
      }
      
      cdb.forms.Color.prototype._createPicker.call(this);
    },

    _getExtraColors: function() {
      if (!this.options.cartoProperties) return [];
      
      // Tile style
      var style = this.options.cartoProperties.layer.get("tile_style");
      var cartoParser = new cdb.admin.CartoParser(style);
      return cartoParser.colorsUsed( { mode: "hex" });
    }

  })


  /**
   *  Error message
   */

  cdb.admin.mod.CategoryWizard.Error = cdb.core.View.extend({

    tagName: 'div',

    className: 'colors_error',

    initialize: function() {
      this.template = cdb.templates.getTemplate('table/menu_modules/wizards/views/color_wizard_error');
    },

    render: function() {
      this.$el.html(this.template());
      return this;
    }
  });


  /**
   *  Simple loader to request column values
   */

  cdb.admin.mod.CategoryWizard.Loader = cdb.core.View.extend({

    tagName: 'div',

    className: 'colors_loader',

    initialize: function() {
      this.template = cdb.templates.getTemplate('table/menu_modules/wizards/views/color_wizard_loader');
    },

    render: function() {
      this.$el.html(this.template());
      return this;
    }
  });