Passed
Push — master ( 89d1f0...c413c6 )
by Guangyu
10:50 queued 12s
created

admin/js/angular/angular-qrcode.js   B

Complexity

Total Complexity 44
Complexity/F 2.59

Size

Lines of Code 227
Function Count 17

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 44
eloc 155
mnd 27
bc 27
fnc 17
dl 0
loc 227
rs 8.8798
bpm 1.5882
cpm 2.5882
noi 0
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like admin/js/angular/angular-qrcode.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/*
2
 * angular-qrcode
3
 * (c) 2017 Monospaced http://monospaced.com
4
 * License: MIT
5
 */
6
7
if (typeof module !== 'undefined' &&
8
    typeof exports !== 'undefined' &&
9
    module.exports === exports){
10
  module.exports = 'monospaced.qrcode';
11
}
12
13
angular.module('monospaced.qrcode', [])
14
  .directive('qrcode', ['$window', function($window) {
15
16
    var canvas2D = !!$window.CanvasRenderingContext2D,
17
        levels = {
18
          'L': 'Low',
19
          'M': 'Medium',
20
          'Q': 'Quartile',
21
          'H': 'High'
22
        },
23
        draw = function(context, qr, modules, tile, color) {
24
          for (var row = 0; row < modules; row++) {
25
            for (var col = 0; col < modules; col++) {
26
              var w = (Math.ceil((col + 1) * tile) - Math.floor(col * tile)),
27
                  h = (Math.ceil((row + 1) * tile) - Math.floor(row * tile));
28
29
              context.fillStyle = qr.isDark(row, col) ? color.foreground : color.background;
30
              context.fillRect(Math.round(col * tile),
31
                               Math.round(row * tile), w, h);
32
            }
33
          }
34
        };
35
36
    return {
37
      restrict: 'E',
38
      template: '<canvas class="qrcode"></canvas>',
39
      link: function(scope, element, attrs) {
40
        var domElement = element[0],
41
            $canvas = element.find('canvas'),
42
            canvas = $canvas[0],
43
            context = canvas2D ? canvas.getContext('2d') : null,
44
            download = 'download' in attrs,
45
            href = attrs.href,
46
            link = download || href ? document.createElement('a') : '',
47
            trim = /^\s+|\s+$/g,
48
            error,
49
            version,
50
            errorCorrectionLevel,
51
            data,
52
            size,
53
            modules,
54
            tile,
55
            qr,
56
            $img,
57
            color = {
58
              foreground: '#000',
59
              background: '#fff'
60
            },
61
            setColor = function(value) {
62
              color.foreground = value || color.foreground;
63
            },
64
            setBackground = function(value) {
65
              color.background = value || color.background;
66
            },
67
            setVersion = function(value) {
68
              version = Math.max(1, Math.min(parseInt(value, 10), 40)) || 5;
69
            },
70
            setErrorCorrectionLevel = function(value) {
71
              errorCorrectionLevel = value in levels ? value : 'M';
72
            },
73
            setData = function(value) {
74
              if (!value) {
75
                return;
76
              }
77
78
              data = value.replace(trim, '');
79
              qr = qrcode(version, errorCorrectionLevel);
80
              qr.addData(data);
81
82
              try {
83
                qr.make();
84
              } catch (e) {
85
                var newVersion;
86
                if (version >= 40) {
87
                  throw new Error('Data is too long', e);
88
                }
89
                newVersion = version + 1;
90
                setVersion(newVersion);
91
                console.warn('qrcode version is too low and has been incremented to', newVersion)
92
                setData(value);
93
                return;
94
              }
95
96
              error = false;
97
              modules = qr.getModuleCount();
98
            },
99
            setSize = function(value) {
100
              size = parseInt(value, 10) || modules * 2;
101
              tile = size / modules;
102
              canvas.width = canvas.height = size;
103
            },
104
            render = function() {
105
              if (!qr) {
106
                return;
107
              }
108
109
              if (error) {
110
                if (link) {
111
                  link.removeAttribute('download');
112
                  link.title = '';
113
                  link.href = '#_';
114
                }
115
                if (!canvas2D) {
116
                  domElement.innerHTML = '<img src width="' + size + '"' +
117
                                         'height="' + size + '"' +
118
                                         'class="qrcode">';
119
                }
120
                scope.$emit('qrcode:error', error);
121
                return;
122
              }
123
124
              if (download) {
125
                domElement.download = 'qrcode.png';
126
                domElement.title = 'Download QR code';
127
              }
128
129
              if (canvas2D) {
130
                draw(context, qr, modules, tile, color);
131
132
                if (download) {
133
                  domElement.href = canvas.toDataURL('image/png');
134
                  return;
135
                }
136
              } else {
137
                domElement.innerHTML = qr.createImgTag(tile, 0);
138
                $img = element.find('img');
139
                $img.addClass('qrcode');
140
141
                if (download) {
142
                  domElement.href = $img[0].src;
143
                  return;
144
                }
145
              }
146
147
              if (href) {
148
                domElement.href = href;
149
              }
150
            };
151
152
        if (link) {
153
          link.className = 'qrcode-link';
154
          $canvas.wrap(link);
155
          domElement = domElement.firstChild;
156
        }
157
158
        setColor(attrs.color);
159
        setBackground(attrs.background);
160
        setVersion(attrs.version);
161
        setErrorCorrectionLevel(attrs.errorCorrectionLevel);
162
        setSize(attrs.size);
163
164
        attrs.$observe('version', function(value) {
165
          if (!value) {
166
            return;
167
          }
168
169
          setVersion(value);
170
          setData(data);
171
          setSize(size);
172
          render();
173
        });
174
175
        attrs.$observe('errorCorrectionLevel', function(value) {
176
          if (!value) {
177
            return;
178
          }
179
180
          setErrorCorrectionLevel(value);
181
          setData(data);
182
          setSize(size);
183
          render();
184
        });
185
186
        attrs.$observe('data', function(value) {
187
          if (!value) {
188
            return;
189
          }
190
191
          setData(value);
192
          setSize(size);
193
          render();
194
        });
195
196
        attrs.$observe('size', function(value) {
197
          if (!value) {
198
            return;
199
          }
200
201
          setSize(value);
202
          render();
203
        });
204
205
        attrs.$observe('color', function(value) {
206
          if (!value) {
207
            return;
208
          }
209
210
          setColor(value);
211
          render();
212
        });
213
214
        attrs.$observe('background', function(value) {
215
          if (!value) {
216
            return;
217
          }
218
219
          setBackground(value);
220
          render();
221
        });
222
223
        attrs.$observe('href', function(value) {
224
          if (!value) {
225
            return;
226
          }
227
228
          href = value;
229
          render();
230
        });
231
      }
232
    };
233
  }]);
234