Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Branch master (5c2c02)
by Sebastian
03:02
created

plugins/pageview/tx_dlf_pageview_imagemanipulation_control.js   B

Complexity

Total Complexity 51
Complexity/F 2.43

Size

Lines of Code 424
Function Count 21

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 0
c 0
b 0
f 0
nc 24576
dl 0
loc 424
rs 8.3206
wmc 51
mnd 3
bc 35
fnc 21
bpm 1.6666
cpm 2.4285
noi 19

6 Functions

Rating   Name   Duplication   Size   Complexity  
A dlfViewerImageManipulationControl.createMap_ 0 62 1
B dlfViewerImageManipulationControl.createSlider_ 0 56 8
A dlfViewerImageManipulationControl.createFilters_ 0 63 1
B dlfViewerImageManipulationControl.activate 0 39 3
A dlfViewerImageManipulationControl.deactivate 0 22 3
A dlfViewerImageManipulationControl.isActive 0 3 1

How to fix   Complexity   

Complexity

Complex classes like plugins/pageview/tx_dlf_pageview_imagemanipulation_control.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
 * (c) Kitodo. Key to digital objects e.V. <[email protected]>
3
 *
4
 * This file is part of the Kitodo and TYPO3 projects.
5
 *
6
 * @license GNU General Public License version 3 or later.
7
 * For the full copyright and license information, please read the
8
 * LICENSE.txt file that was distributed with this source code.
9
 */
10
11
/**
12
 * Right know the image manipulation uses an own ol.Map object based on a webgl renderer. This is due to the fact
13
 * that other parts of the viewer application are using vector geometries and ol3 does only support full vector
14
 * renderering with the canvas and dom renderer yet. In contrast the image manipulation tool is only working
15
 * with a webgl renderer. Therefore it uses an own ol.Map object which is overlaid and synchronized with the
16
 * base ol.Map object.
17
 *
18
 * @constructor
19
 * @param {Object=} options Control options.
20
 * 		{Array.<ol.layer.Layer>} layers
21
 * 		{Element} target
22
 * 	  {ol.View} view
23
 * 	  {ol.Map} map
24
 */
25
dlfViewerImageManipulationControl = function(options) {
0 ignored issues
show
Bug introduced by
The variable dlfViewerImageManipulationControl seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.dlfViewerImageManipulationControl.
Loading history...
26
27
  /**
28
   * @type {Object}
29
   * @private
30
   */
31
  this.dic = $('#tx-dlf-tools-imagetools').length > 0 && $('#tx-dlf-tools-imagetools').attr('data-dic') ?
32
	    	dlfUtils.parseDataDic($('#tx-dlf-tools-imagetools')) :
0 ignored issues
show
Bug introduced by
The variable dlfUtils seems to be never declared. If this is a global, consider adding a /** global: dlfUtils */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
33
	    		{'imagemanipulation-on':'Activate image manipulation', 'imagemanipulation-off':'Dectivate image manipulation',
34
		  		'saturation':'Saturation', 'hue':'Hue', 'brightness': 'Brightness', 'contrast':'Contrast', 'reset': 'Reset',
35
					'invert': 'Color inverting'};
36
37
  /**
38
	* @type {Array.<ol.layer.Layer>}
39
	* @private
40
	*/
41
  this.layers = options.layers;
42
43
	/**
44
	 * @type {ol.Map}
45
	 * @private
46
	 */
47
	this.baseMap_ = options.map;
48
49
	/**
50
	 * @type {ol.Map|undefined}
51
	 * @private
52
	 */
53
	this.map_ = undefined;
54
55
	/**
56
	 * @type {ol.View}
57
	 * @private
58
	 */
59
	this.view_ = options.view;
60
61
  /**
62
   * @type {Element}
63
   * @private
64
   */
65
  this.anchor_ = $('<a/>', {
66
	  href: '#image-manipulation',
67
	  text: this.dic['imagemanipulation-on'],
68
	  title: this.dic['imagemanipulation-on']
69
  });
70
  $(options.controlTarget).append(this.anchor_);
71
72
  /**
73
   * @type {Element}
74
   * @private
75
   */
76
  this.toolContainerEl_ = dlfUtils.exists(options.toolContainer) ? options.toolContainer: $('.tx-dlf-toolbox')[0];
77
78
  //
79
  // Append open/close behavior to toolbox
80
  //
81
  var openToolbox = $.proxy(function(event) {
82
	  event.preventDefault();
83
84
	  if ($(event.target).hasClass('active')){
85
		  this.deactivate();
86
		  return;
87
	  }
88
89
	  this.activate();
90
  }, this);
91
  $(this.anchor_).on('click', openToolbox);
92
  $(this.anchor_).on('touchstart', openToolbox);
93
94
  //
95
  // Initialize the filter
96
  //
97
	var FILTERS_DEFAULT_ = {
98
		'brightness': 1,
99
		'contrast': 1,
100
		'hue': 0,
101
		'saturation': 0
102
	};
103
104
	/**
105
	 * @type {Object}
106
	 * @private
107
	 */
108
	this.filters_ = $.extend({}, FILTERS_DEFAULT_);
109
110
	/**
111
	 * Is filter updated
112
	 * @type {boolean}
113
	 * @private
114
	 */
115
	this.filterUpdated_ = false;
116
117
	/**
118
	 * @type {Object}
119
	 * @private
120
	 */
121
	this.handler_ = {
122
		'postcomposeImageFilter': $.proxy(function (event) {
123
			var webglContext = event['glContext'],
124
				canvas = $('#' + this.map_.getTargetElement().id + ' canvas.ol-unselectable')[0];
125
126
			if (webglContext !== undefined && webglContext !== null) {
127
				var gl = webglContext.getGL();
128
129
				if (this.filterUpdated_) {
130
131
					glif.reset();
0 ignored issues
show
Bug introduced by
The variable glif seems to be never declared. If this is a global, consider adding a /** global: glif */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
132
133
					for (var filter in this.filters_) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
134
						glif.addFilter(filter, this.filters_[filter]);
135
					};
136
137
					this.filterUpdated_ = false;
138
				}
139
140
				glif.apply(gl, canvas);
141
142
				// for showing openlayers that the program changed
143
				// if missing openlayers will produce errors because it
144
				// expected other shaders in the webgl program
145
				webglContext.useProgram(undefined);
146
			}
147
		}, this),
148
		'resetFilter': $.proxy(function(event) {
0 ignored issues
show
Unused Code introduced by
The parameter event 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...
149
150
			// reset the checked filters
151
			if (this.filters_.hasOwnProperty('invert')) {
152
				$('#invert-filter').click();
153
			}
154
155
			// reset the slider filters
156
			var sliderEls = $('.slider.slider-imagemanipulation');
157
			for (var i = 0; i < sliderEls.length; i++) {
158
				var sliderEl = sliderEls[i],
159
					type = sliderEl.getAttribute('data-type'),
160
					value = FILTERS_DEFAULT_[type];
161
162
				$(sliderEl).slider('value', value);
163
			};
164
		}, this)
165
	}
166
};
167
168
/**
169
 * Activates the image manipulation tool
170
 */
171
dlfViewerImageManipulationControl.prototype.activate = function(){
172
173
	//
174
	// Toggle maps
175
	//
176
	$.when($(this.baseMap_.getTargetElement())
177
		// fadeOut the base map container
178
		.hide())
179
		// fadeIn image map container
180
		.done($.proxy(function(){
181
			if (!dlfUtils.exists(this.map_)) {
0 ignored issues
show
Bug introduced by
The variable dlfUtils seems to be never declared. If this is a global, consider adding a /** global: dlfUtils */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
182
				// create map container and map object if not exists yet
183
				this.createMap_();
184
			}
185
186
			// Show map
187
			$(this.map_.getTargetElement()).show();
188
189
			// trigger open event
190
			$(this).trigger("activate-imagemanipulation", this.map_);
191
		}, this));
192
193
	//
194
	// Toggle toolbox controls
195
	//
196
	$(this.anchor_).addClass('active')
197
		.text(this.dic['imagemanipulation-off'])
198
		.attr('title', this.dic['imagemanipulation-off']);
199
200
	if (!dlfUtils.exists(this.sliderContainer_)) {
201
		// in case filter sliders are not initialize yet add them
202
		this.createFilters_();
203
	};
204
	$(this.sliderContainer_).show().addClass('open');
205
206
	// add postcompose listener to layers
207
	if (this.map_ !== undefined)
208
		this.map_.on('postcompose', this.handler_.postcomposeImageFilter);
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...
209
};
210
211
/**
212
 * Setup the image manipulation filters + reset functionality
213
 * @private
214
 */
215
dlfViewerImageManipulationControl.prototype.createFilters_ = function() {
216
217
	// create outer container
218
	var outerContainer = $('<div class="image-manipulation ol-unselectable"></div>');
219
	$(this.toolContainerEl_).append(outerContainer);
220
221
	/**
222
	 * Inner slider container
223
	 * @type {Element}
224
	 * @private
225
	 */
226
	this.sliderContainer_ = $('<div class="slider-container"></div>');
227
	$(outerContainer).append(this.sliderContainer_);
228
229
	//
230
	// Create sliders for filters and append them to the toolbox
231
	//
232
	var contrastSlider = this.createSlider_('slider-contrast', 'horizontal', 'contrast',
233
		[1, 0, 2, 0.01], this.dic['contrast'], function(v) {
234
			return parseInt(v * 100 - 100);
235
		}),
236
		saturationSlider = this.createSlider_('slider-saturation', 'horizontal', 'saturation',
237
			[0, -1, 1, 0.01], this.dic['saturation'], function(v) {
238
				return parseInt(v * 100);
239
			}),
240
		brightnessSlider = this.createSlider_('slider-brightness', 'horizontal', 'brightness',
241
			[1, 0, 2, 0.1], this.dic['brightness'],function(v) {
242
				return parseInt(v * 100 - 100);
243
			}),
244
		hueSlider = this.createSlider_('slider-hue', 'horizontal', 'hue',
245
			[0, -180, 180, 5], this.dic['hue'], function(v) {
246
				return parseInt(v);
247
			});
248
	$(this.sliderContainer_).append(contrastSlider);
249
	$(this.sliderContainer_).append(saturationSlider);
250
	$(this.sliderContainer_).append(brightnessSlider);
251
	$(this.sliderContainer_).append(hueSlider);
252
253
	// add invert filter
254
	var elFilterId = 'invert-filter';
255
	$(this.sliderContainer_).append($('<div class="checkbox"><label><input type="checkbox" id="' + elFilterId + '">' +
256
		 this.dic['invert'] + '</label></div>'));
257
	$('#' + elFilterId).on('click', $.proxy(function(event) {
258
		if (event.target.checked === true && !this.filters_.hasOwnProperty('invert')) {
259
			// if checked add the invert filter to the filters
260
			this.filters_['invert'] = true;
261
		} else {
262
			// remove invert filter
263
			if (this.filters_.hasOwnProperty('invert')) {
264
				delete this.filters_['invert'];
265
			}
266
		}
267
268
		// update filter chain
269
		this.filterUpdated_ = true;
270
		this.layers[0].changed();
271
	}, this));
272
273
	// button for reset to default state
274
	var resetBtn = $('<button class="reset-btn" title="' + this.dic['reset'] + '">' + this.dic['reset'] + '</button>');
275
	$(this.sliderContainer_).append(resetBtn);
276
	$(resetBtn).on('click', this.handler_.resetFilter);
277
};
278
279
/**
280
 * Setup the map object used from the image manipulation tool and bind it to the baseMap
281
 * @private
282
 */
283
dlfViewerImageManipulationControl.prototype.createMap_ = function() {
284
	var mapEl_ = $('<div id="tx-dfgviewer-map-manipulate" class="tx-dlf-map"></div>');
285
	$(this.baseMap_.getTargetElement().parentElement).append(mapEl_);
286
287
	this.map_ = new ol.Map({
0 ignored issues
show
Bug introduced by
The variable ol seems to be never declared. If this is a global, consider adding a /** global: ol */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
288
		layers: this.layers,
289
		target: mapEl_[0].id,
290
		controls: [],
291
		interactions: [
292
			new ol.interaction.DragRotate(),
293
			new ol.interaction.DragPan(),
294
			new ol.interaction.DragZoom(),
295
			new ol.interaction.PinchRotate(),
296
			new ol.interaction.PinchZoom(),
297
			new ol.interaction.MouseWheelZoom(),
298
			new ol.interaction.KeyboardPan(),
299
			new ol.interaction.KeyboardZoom,
300
			new ol.interaction.DragRotateAndZoom()
301
		],
302
		// necessary for proper working of the keyboard events
303
		keyboardEventTarget: document,
304
		view: this.view_,
305
		renderer: 'webgl'
306
	});
307
308
	// couple map behavior with baseMap
309
	var adjustViews = function(sourceView, destMap) {
310
			var rotateDiff = sourceView.getRotation() !== destMap.getView().getRotation();
311
			var resDiff = sourceView.getResolution() !== destMap.getView().getResolution();
312
			var centerDiff = sourceView.getCenter() !== destMap.getView().getCenter();
313
314
			if (rotateDiff || resDiff || centerDiff) {
315
				destMap.zoomTo(sourceView.getCenter(),
316
					sourceView.getZoom(), 50);
317
				destMap.getView().rotate(sourceView.getRotation());
318
			}
319
320
		},
321
		adjustViewHandler = function(event) {
322
			adjustViews(event.target, this);
323
		};
324
325
	// when deactivate / activate adjust both map centers / zoom
326
	$(this).on("activate-imagemanipulation", $.proxy(function(event, map) {
0 ignored issues
show
Unused Code introduced by
The parameter map 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...
Unused Code introduced by
The parameter event 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...
327
		// pass change events for resolution and rotation to image manipulation map
328
		// created through external view controls
329
		this.baseMap_.getView().on('change:resolution', adjustViewHandler, this.map_);
330
		this.baseMap_.getView().on('change:rotation', adjustViewHandler, this.map_);
331
332
		// adjust the view of both maps
333
		adjustViews(this.baseMap_.getView(), this.map_);
334
	}, this));
335
	$(this).on("deactivate-imagemanipulation", $.proxy(function(event, map) {
0 ignored issues
show
Unused Code introduced by
The parameter map 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...
Unused Code introduced by
The parameter event 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...
336
		// pass change events for resolution and rotation to image manipulation map
337
		// created through external view controls
338
		this.baseMap_.getView().un('change:resolution', adjustViewHandler, this.map_);
339
		this.baseMap_.getView().un('change:rotation', adjustViewHandler, this.map_);
340
341
		// adjust the view of both maps
342
		adjustViews(this.map_.getView(), this.baseMap_);
343
	}, this));
344
};
345
346
/**
347
 * Functions creates a slider + behavior.
348
 *
349
 * @param {string} className
350
 * @param {string} orientation
351
 * @param {string} key
352
 * @param {Array.<number>|undefined} opt_baseValue
0 ignored issues
show
Documentation Bug introduced by
The parameter opt_baseValue does not exist. Did you maybe mean opt_baseValues instead?
Loading history...
353
 * @param {string=} opt_title
354
 * @param {Function=} opt_labelFn
355
 * @return {Element}
356
 * @private
357
 */
358
dlfViewerImageManipulationControl.prototype.createSlider_ = function(className, orientation, key, opt_baseValues, opt_title, opt_labelFn){
359
	var title = dlfUtils.exists('opt_title') ? opt_title : '',
0 ignored issues
show
Bug introduced by
The variable dlfUtils seems to be never declared. If this is a global, consider adding a /** global: dlfUtils */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
360
		sliderEl = $('<div class="slider slider-imagemanipulation ' + className + '" title="' + title + '" data-type="' +
361
			key +'"></div>'),
362
		baseMin = dlfUtils.exists(opt_baseValues) ? opt_baseValues[1] : 0,
363
		baseMax = dlfUtils.exists(opt_baseValues) ? opt_baseValues[2] : 100,
364
		steps = dlfUtils.exists(opt_baseValues) ? opt_baseValues[3] : 1,
365
		minValueEl,
0 ignored issues
show
Unused Code introduced by
The variable minValueEl seems to be never used. Consider removing it.
Loading history...
366
		maxValueEl,
0 ignored issues
show
Unused Code introduced by
The variable maxValueEl seems to be never used. Consider removing it.
Loading history...
367
		startValue = dlfUtils.exists(opt_baseValues) ? opt_baseValues[0] : 100;
368
369
	/**
370
	 * @param {Object} event
371
	 * @param {Object} ui
372
	 */
373
	var update = $.proxy(function(event, ui){
374
		var value = ui['value'],
375
				layer = this.layers[0],
376
				element = valueEl[0],
377
				labelValue = dlfUtils.exists(opt_labelFn) ? opt_labelFn(value) : value + '%';
0 ignored issues
show
Bug introduced by
The variable dlfUtils seems to be never declared. If this is a global, consider adding a /** global: dlfUtils */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
378
379
		if (orientation == 'vertical') {
380
			var style_top = 100 - ((value - baseMin) / (baseMax - baseMin) * 100);
381
			element.style.top = style_top + '%';
382
			element.innerHTML = labelValue;
383
			return;
384
		}
385
386
		var style_left = (value - baseMin) / (baseMax - baseMin) * 100;
387
		element.style.left = style_left + '%';
388
		element.innerHTML = labelValue;
389
390
		// update filters.
391
		this.filters_[key] = value;
392
		this.filterUpdated_ = true;
393
		layer.changed();
394
	}, this);
395
396
	$(sliderEl).slider({
397
        'min': baseMin,
398
        'max': baseMax,
399
        'value': startValue,
400
        'animate': 'slow',
401
        'orientation': orientation,
402
        'step': steps,
403
        'slide': update,
404
        'change': update
405
    });
406
407
	// append tooltips
408
	var innerHtml = dlfUtils.exists(opt_labelFn) && dlfUtils.exists(opt_baseValues) ? opt_labelFn(opt_baseValues[0]) : '100%',
409
			valueEl = $('<div class="tooltip value ' + className + '">' + innerHtml + '</div>');
410
	$(sliderEl).append(valueEl);
411
412
	return sliderEl;
413
};
414
415
/**
416
 * Deactivates the image manipulation control
417
 */
418
dlfViewerImageManipulationControl.prototype.deactivate = function(){
419
420
	// toggle maps
421
	if (dlfUtils.exists(this.map_)) {
0 ignored issues
show
Bug introduced by
The variable dlfUtils seems to be never declared. If this is a global, consider adding a /** global: dlfUtils */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
422
		$(this.map_.getTargetElement()).hide();
423
	}
424
	$(this.baseMap_.getTargetElement()).show();
425
426
	// toggle view of image manipulation control element
427
	$(this.anchor_).removeClass('active')
428
		.text(this.dic['imagemanipulation-on'])
429
		.attr('title', this.dic['imagemanipulation-on']);
430
431
	$(this.sliderContainer_).hide().removeClass('open');
432
433
	// remove postcompose listener to map
434
	if (this.map_ !== undefined)
435
		this.map_.un('postcompose', this.handler_.postcomposeImageFilter);
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...
436
437
	// trigger close event for trigger map adjust behavior
438
	$(this).trigger("deactivate-imagemanipulation");
439
};
440
441
/**
442
 * Function checks if the image manipulation is in active state or not.
443
 *
444
 * @return {boolean}
445
 */
446
dlfViewerImageManipulationControl.prototype.isActive = function() {
447
	return $(this.anchor_).hasClass('active');
448
};
449