CartoDB/cartodb20

View on GitHub
lib/assets/javascripts/cartodb/old_common/forms/geometry_field.js

Summary

Maintainability
D
1 day
Test Coverage

  /**
   *  Geometry field -> Place to choose and edit geometry field
   *  - It accepts a model with {attribute: 'the_geom', value: '{{ "type": "Point", "coordinates": [100.0, 0.0] }}'}
   *  var geometry = new cdb.admin.GeometryField({ model: model, row: row, rowNumber: rowNumber })
   */

  cdb.admin.GeometryField = cdb.admin.StringField.extend({

    className: 'field geometry',

    default_options: {
      template_name: 'old_common/views/forms/geometry_field',
      label:          false,
      readOnly:       false
    },

    events: {
      'click .switch':    '_chooseEditor',
      'keyup input':      '_onKeyInputUp',
      'keydown textarea': '_onKeyTextareaDown',
      'change textarea':  '_onChange'
    },

    initialize: function() {
      _.defaults(this.options, this.default_options);

      _.bindAll(this, '_chooseEditor', '_onKeyInputUp', '_onKeyTextareaDown');

      this.template_base = this.options.template_base ? _.template(this.options.template_base) : cdb.templates.getTemplate(this.options.template_name);

      // Set important variables
      this.valid = true;
      this.row = this.options.row;

      // Get OS variable
      this._setOS();
    },

    render: function() {
      this.$el.html(this.template_base(_.extend(this.model.toJSON(), this.options)));

      // Apply views
      this._initViews();

      // Check readOnly and unbind all events
      if (this.options.readOnly) {
        this.undelegateEvents();
      }

      return this;
    },

    _initViews: function() {
      var geojson = this.model.get('value');

      if (!this.row.isGeomLoaded()) {
        // the_geom contents still haven't been loaded
        this._loadGeom();
      } else {
        this._chooseGeom();
      }
    },

    /**
     *  Load geom if it is not loaded
     */
    _loadGeom: function() {
      var self = this;
      this.row.bind('change', function() {
        self.model.set('value', self.row.get("the_geom"));
        self._chooseGeom();
      }, this);
      this.row.fetch({
        rowNumber: this.options.rowNumber
      });
    },


    /**
     *  Choose scenario for the editor
     */
    _chooseGeom: function() {
      var geom = null;

      try {
        geom = JSON.parse(this.model.get('value'));
      } catch(err) {
        // if the geom is not a valid json value
      }

      if (!this.options.readOnly) {
        if (!geom || geom.type.toLowerCase() == "point") {
          // Set status to point
          this.status = "point";
          // Remove loader
          this.$(".loader").remove();
          // Fill inputs
          this.$(".point").show();
          this.$(".selector").show();

          if (geom) {
            this.$("input.longitude").val(geom.coordinates[0]);
            this.$("input.latitude").val(geom.coordinates[1]);
            this.$("textarea").val(JSON.stringify(geom));
          }
        } else {
          // Set status to rest
          this.status = "rest";
          // Remove loader
          this.$(".loader").remove();
          // Fill textarea
          this.$(".rest").show();
          this.$("textarea").val(this.model.get('value'));
        }
      } else {
        this.$(".loader").remove();
        this.$(".selector").show();
        this.$("textarea").val(this.model.get('value'));
      }
    },

    _chooseEditor: function(ev) {
      this.killEvent(ev);

      var $el = $(ev.target).closest("a");

      // Change status value
      this.status = (this.status == "point") ? "rest" : "point";

      // Change switch
      $el
        .removeClass(this.status == "rest" ? "disabled" : "enabled")
        .addClass(this.status == "rest" ? "enabled" : "disabled");

      this.updateInputs();

      // Change between point to geom editor
      if (this.status == "rest") {
        this.$('.point').hide();
        this.$('.rest').show();
        this.valid = true;
      } else {
        this.$('.point').show();
        this.$('.rest').hide();
        this.valid = this._checkInputs();
      }
    },

    updateInputs: function() {
      if(this.model.get('value')) {
        try {
          var geom = JSON.parse(this.model.get('value'));
          this.$("input.longitude").val(geom.coordinates[0]);
          this.$("input.latitude").val(geom.coordinates[1]);
          this.$("textarea").val(JSON.stringify(geom));
        } catch(error) {
          return false;
        }
      }
    },

    /**
     *  Check if the number is well formed or not
     */
    _checkNumber: function(number, type) {
      var pattern = /^-?(?:[0-9]+|[0-9]*\.[0-9]+)$/;
      if (pattern.test(number)) {

        if (type === "lat") {
          if ( number >= -90 && number <= 90 ) {
            return true
          } else {
            return false
          }
        }

        if (type === "lon") {
          if ( number >= -180 && number <= 180 ) {
            return true
          } else {
            return false
          }
        }

        return true
      } else {
        return false
      }
    },


    /**
     *  Check latitude and longitude inputs
     */
    _checkInputs: function() {
      var enable = true
        , $lat = this.$("input.latitude")
        , $lon = this.$("input.longitude");

      if (this._checkNumber($lat.val(), 'lat')) {
        $lat.removeClass("error");
      } else {
        $lat.addClass("error");
        enable = false;
      }

      if (this._checkNumber($lon.val(), 'lon')) {
        $lon.removeClass("error");
      } else {
        $lon.addClass("error");
        enable = false;
      }

      return enable;
    },

    /**
     *  When user type any number we check it if it is correct
     */
    _onKeyInputUp: function(e) {

      if (this._checkInputs()) {

        if (e.keyCode === 13) {
          e.preventDefault();
          this._triggerEvent('ENTER');
          return false;
        }

        this.valid = true;

        // Save model
        var lat = parseFloat(this.$("input.latitude").val())
          , lon = parseFloat(this.$("input.longitude").val());

        this.model.set('value', JSON.stringify({"type": "Point", "coordinates": [lon,lat]}));

      } else {
        this.valid = false;
      }
    },

    /**
     *  Key press binding for textarea
     */
    _onKeyTextareaDown: function(e) {
      if (((this.so=="mac" && e.metaKey) || (this.so=="rest" && e.ctrlKey)) && e.keyCode == 13 ) {
        e.preventDefault();
        this._triggerEvent('ENTER');
        return false;
      }

      var value = $(e.target).val();

      this.model.set('value', value);
    },
  })