src/backgrid_modules/editors/select_cell.js   A
last analyzed

Complexity

Total Complexity 18
Complexity/F 3

Size

Lines of Code 142
Function Count 6

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 0
c 2
b 0
f 0
nc 1
dl 0
loc 142
rs 10
wmc 18
mnd 3
bc 13
fnc 6
bpm 2.1666
cpm 3
noi 15

6 Functions

Rating   Name   Duplication   Size   Complexity  
A CellEditor.extend._renderOptions 0 11 2
A CellEditor.extend.setMultiple 0 4 1
A CellEditor.extend.save 0 5 1
A CellEditor.extend.setOptionValues 0 4 1
B CellEditor.extend.render 0 43 5
B CellEditor.extend.close 0 15 8
1
import _ from 'underscore';
0 ignored issues
show
introduced by
Definition for rule 'keyword-spacing' was not found
Loading history...
2
import $ from 'jquery';
3
import {
4
  CellEditor
5
} from './cell.js';
6
import {
7
  Command
8
} from '../command.js';
9
/**
10
   SelectCellEditor renders an HTML `<select>` fragment as the editor.
11
12
   @class Backgrid.SelectCellEditor
13
   @extends Backgrid.CellEditor
14
*/
15
var SelectCellEditor = CellEditor.extend({
16
17
  /** @property */
18
  tagName: "select",
19
20
  /** @property */
21
  events: {
22
    "change": "save",
23
    "blur": "close",
24
    "keydown": "close"
25
  },
26
27
  /** @property {function(Object, ?Object=): string} template */
28
  template: _.template(
29
    '<option value="<%- value %>" <%= selected ? \'selected="selected"\' : "" %>><%- text %></option>',
30
    null, {
31
      variable: null,
32
      evaluate: /<%([\s\S]+?)%>/g,
33
      interpolate: /<%=([\s\S]+?)%>/g,
34
      escape: /<%-([\s\S]+?)%>/g
35
    }),
36
37
  setOptionValues: function (optionValues) {
38
    this.optionValues = optionValues;
39
    this.optionValues = _.result(this, "optionValues");
40
  },
41
42
  setMultiple: function (multiple) {
43
    this.multiple = multiple;
44
    this.$el.prop("multiple", multiple);
45
  },
46
47
  _renderOptions: function (nvps, selectedValues) {
48
    var options = '';
49
    for (var i = 0; i < nvps.length; i++) {
50
      options = options + this.template({
51
        text: nvps[i][0],
52
        value: nvps[i][1],
53
        selected: _.indexOf(selectedValues, nvps[i][1]) > -1
54
      });
55
    }
56
    return options;
57
  },
58
59
  /**
60
     Renders the options if `optionValues` is a list of name-value pairs. The
61
     options are contained inside option groups if `optionValues` is a list of
62
     object hashes. The name is rendered at the option text and the value is the
63
     option value. If `optionValues` is a function, it is called without a
64
     parameter.
65
  */
66
  render: function () {
67
    this.$el.empty();
68
69
    var optionValues = _.result(this, "optionValues");
70
    var model = this.model;
71
    var selectedValues = this.formatter.fromRaw(model.get(this.column.get("name")), model);
72
73
    if (!_.isArray(optionValues)) throw new TypeError("optionValues must be an array");
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
introduced by
Expected { after 'if' condition.
Loading history...
74
75
    var optionValue = null;
0 ignored issues
show
Unused Code introduced by
The assignment to optionValue seems to be never used. If you intend to free memory here, this is not necessary since the variable leaves the scope anyway.
Loading history...
76
    var optionText = null;
0 ignored issues
show
Unused Code introduced by
The assignment to optionText seems to be never used. If you intend to free memory here, this is not necessary since the variable leaves the scope anyway.
Loading history...
77
    var optionValue = null;
0 ignored issues
show
Unused Code introduced by
The assignment to optionValue seems to be never used. If you intend to free memory here, this is not necessary since the variable leaves the scope anyway.
Loading history...
Comprehensibility Naming Best Practice introduced by
The variable optionValue already seems to be declared on line 75. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
introduced by
"optionValue" is already defined
Loading history...
78
    var optgroupName = null;
0 ignored issues
show
Unused Code introduced by
The assignment to optgroupName seems to be never used. If you intend to free memory here, this is not necessary since the variable leaves the scope anyway.
Loading history...
79
    var optgroup = null;
0 ignored issues
show
Unused Code introduced by
The assignment to optgroup seems to be never used. If you intend to free memory here, this is not necessary since the variable leaves the scope anyway.
Loading history...
80
81
    for (var i = 0; i < optionValues.length; i++) {
82
      var optionValue = optionValues[i];
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable optionValue already seems to be declared on line 75. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
introduced by
"optionValue" is already defined
Loading history...
83
84
      if (_.isArray(optionValue)) {
85
        optionText = optionValue[0];
86
        optionValue = optionValue[1];
87
88
        this.$el.append(this.template({
89
          text: optionText,
90
          value: optionValue,
91
          selected: _.indexOf(selectedValues, optionValue) > -1
92
        }));
93
      } else if (_.isObject(optionValue)) {
94
        optgroupName = optionValue.name;
95
        optgroup = $("<optgroup></optgroup>", {
96
          label: optgroupName
97
        });
98
        optgroup.append(this._renderOptions.call(this, optionValue.values, selectedValues));
99
        this.$el.append(optgroup);
100
      } else {
101
        throw new TypeError("optionValues elements must be a name-value pair or an object hash of { name: 'optgroup label', value: [option name-value pairs] }");
0 ignored issues
show
Coding Style introduced by
This line exceeds the maximum configured line length of 150.
Loading history...
102
      }
103
    }
104
105
    this.delegateEvents();
106
107
    return this;
108
  },
109
110
  /**
111
     Saves the value of the selected option to the model attribute.
112
  */
113
  save: function (e) {
0 ignored issues
show
Unused Code introduced by
The parameter e is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
114
    var model = this.model;
115
    var column = this.column;
116
    model.set(column.get("name"), this.formatter.toRaw(this.$el.val(), model));
117
  },
118
119
  /**
120
     Triggers a `backgrid:edited` event from the model so the body can close
121
     this editor.
122
  */
123
  close: function (e) {
124
    var model = this.model;
125
    var column = this.column;
126
    var command = new Command(e);
127
    if (command.cancel()) {
128
      e.stopPropagation();
129
      model.trigger("backgrid:edited", model, column, new Command(e));
130
    } else if (command.save() || command.moveLeft() || command.moveRight() ||
131
      command.moveUp() || command.moveDown() || e.type == "blur") {
0 ignored issues
show
Bug Best Practice introduced by
Apart from some edge-cases, it is generally advisable to use the strict comparison === instead of ==.

The loose comparison such as == or != might produce some weird results for some values, unless you explicitly want to have this behavior here, better use the strict alternative.

Learn more about loose comparison in Javascript.

Loading history...
132
      e.preventDefault();
133
      e.stopPropagation();
134
      this.save(e);
135
      model.trigger("backgrid:edited", model, column, new Command(e));
136
    }
137
  }
138
139
});
140
export {
141
  SelectCellEditor
142
};
143