Passed
Push — master ( 8f169b...36019d )
by Rafael
01:27
created

src/controls/multi-slider/device-selection/control.js   A

Size

Lines of Code 201

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
nc 1
dl 0
loc 201
rs 10
noi 1

1 Function

Rating   Name   Duplication   Size   Complexity  
B control.js ➔ ??? 0 44 1
1
const $ = jQuery;
2
3
import template from './template.html';
4
import './style.scss';
5
import unlinkIcon from '../img/unlink.svg';
6
import linkIcon from '../img/link.svg';
7
import titleCase from 'title-case';
8
import { EventEmitter } from 'eventemitter3';
9
10
export class Control {
11
12
	constructor( options ) {
13
		this.options = options || {};
14
15
		this.options.sizes = this.options.sizes || {
16
17
			// These are max widths.
18
			phone: 767, // 0 to 767 is phone.
19
			tablet: 991,  // 768 to 991 is tablet.
20
			desktop: 1199  // 992 to 1199 is desktop.
21
22
			// Large is 1200+
23
		};
24
25
		let maxRand = 1000000;
26
		this._id = _.random( 0, maxRand );
0 ignored issues
show
Bug introduced by
The variable _ seems to be never declared. If this is a global, consider adding a /** global: _ */ 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...
27
		this.template = _.template( template );
28
		this.$control = null;
29
		this.ranges = this._createDeviceRanges();
30
		this.events = new EventEmitter();
31
32
		this.devices = [
33
			{
34
				name: 'base',
35
				icon: require( '../../device-visibility/img/all-devices.svg' ),
36
				tooltip: 'All Devices'
37
			},
38
			{
39
				name: 'large',
40
				icon: require( '../../device-visibility/img/large.svg' )
41
			},
42
			{
43
				name: 'desktop',
44
				icon: require( '../../device-visibility/img/desktop.svg' )
45
			},
46
			{
47
				name: 'tablet',
48
				icon: require( '../../device-visibility/img/tablet.svg' )
49
			},
50
			{
51
				name: 'phone',
52
				icon: require( '../../device-visibility/img/phone.svg' )
53
			}
54
		];
55
	}
56
57
	/**
58
	 * Render the control.
59
	 *
60
	 * @since 1.0.0
61
	 *
62
	 * @return {jQuery} Control DOM element.
63
	 */
64
	render() {
65
		this.$control = $( this.template( {
66
			id: this._id,
67
			titleCase: titleCase,
68
			linkIcon: linkIcon,
69
			unlinkIcon: unlinkIcon
70
		} ) );
71
72
		this.$inputs = this.$control.find( 'input' );
73
		this.$selectionText = this.$control.find( '.selection-text' );
74
		this.$relationship = this.$control.find( '.relationship' );
75
76
		this._setupLinkedChange();
77
78
		return this.$control;
79
	}
80
81
	/**
82
	 * Update the current linked status.
83
	 *
84
	 * @since 1.0.0
85
	 *
86
	 * @param  {boolean} linked Is this device linked to the base?
87
	 */
88
	updateRelationship( linked ) {
89
		let title = 'Inherting from All Devices setting';
90
91
		if ( ! linked ) {
92
			title = 'Unlinked from All Devices setting';
93
		}
94
95
		this.$control.attr( 'data-relationship-linked', linked ? 1 : 0 );
96
		this.$relationship.attr( 'title', title );
97
	}
98
99
	/**
100
	 * Activate the requested device.
101
	 *
102
	 * @since 1.0.0
103
	 *
104
	 * @param  {string} device Device.
105
	 */
106
	activate( device ) {
107
		this.$inputs
108
			.filter( `#${this._id}-${device}` )
109
			.prop( 'checked', true )
110
			.change();
111
	}
112
113
	/**
114
	 * Add a media query to CSS given device selection.
115
	 *
116
	 * @since 1.0.0
117
	 *
118
	 * @param {string} css CSS to wrap.
119
	 */
120
	addMediaQuery( css ) {
121
		let prefix = this._getMediaPrefix();
122
		return prefix ? `${prefix}{${css}}` : css;
123
	}
124
125
	/**
126
	 * When the user clicks on the linked status, change to the opsite state.
127
	 *
128
	 * @since 1.0.0
129
	 */
130
	_setupLinkedChange() {
131
		this.$relationship.on( 'click', () => {
132
			let isLinked = ! parseInt( this.$control.attr( 'data-relationship-linked' ), 10 );
133
			this.updateRelationship( isLinked );
134
			this.events.emit( 'linkedToggle', isLinked );
135
		} );
136
	}
137
138
	/**
139
	 * Given a configuration of maximum screen sizes, create a list of ranges.
140
	 *
141
	 * @since 1.0.0
142
	 *
143
	 * @return {object} Devices ranges.
144
	 */
145
	_createDeviceRanges() {
146
		let ranges = {};
147
148
		ranges.phone = {};
149
		ranges.phone.max = this.options.sizes.phone;
150
151
		ranges.tablet = {};
152
		ranges.tablet.min = ranges.phone.max + 1;
153
		ranges.tablet.max = this.options.sizes.tablet;
154
155
		ranges.desktop = {};
156
		ranges.desktop.min = ranges.tablet.max + 1;
157
		ranges.desktop.max = this.options.sizes.desktop;
158
159
		ranges.large = {};
160
		ranges.large.min = ranges.desktop.max + 1;
161
162
		return ranges;
163
	}
164
165
	/**
166
	 * Based on the user selection, get the media query prefix that we'll use.
167
	 *
168
	 * @since 1.0.0
169
	 *
170
	 * @return {string} Media Query prefix.
171
	 */
172
	_getMediaPrefix() {
173
		let prefix = '',
174
			selectedValue = this.getSelectedValue(),
175
			range = this.ranges[ selectedValue ];
176
177
		if ( range ) {
178
			if ( range.min && range.max ) {
179
				prefix = `@media only screen and (max-width: ${range.max}px) and (min-width: ${range.min}px)`;
180
			} else if ( range.min && ! range.max ) {
181
				prefix = `@media only screen and ( min-width: ${range.min}px )`;
182
			} else if ( ! range.min && range.max ) {
183
				prefix = `@media only screen and ( max-width: ${range.max}px )`;
184
			}
185
		}
186
187
		return prefix;
188
	}
189
190
	/**
191
	 * Get the currently selected value.
192
	 *
193
	 * @since 1.0.0
194
	 *
195
	 * @return {string} Device selected.
196
	 */
197
	getSelectedValue() {
198
		return this.$inputs.filter( ':checked' ).val();
199
	}
200
201
}
202