@syncfusion/ej2-inputs 30.2.4 → 31.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ej2-inputs.min.js +2 -2
- package/dist/ej2-inputs.umd.min.js +2 -2
- package/dist/ej2-inputs.umd.min.js.map +1 -1
- package/dist/es6/ej2-inputs.es2015.js +1 -1
- package/dist/es6/ej2-inputs.es2015.js.map +1 -1
- package/dist/es6/ej2-inputs.es5.js +1 -1
- package/dist/es6/ej2-inputs.es5.js.map +1 -1
- package/dist/global/ej2-inputs.min.js +2 -2
- package/dist/global/ej2-inputs.min.js.map +1 -1
- package/dist/global/index.d.ts +1 -1
- package/dist/ts/color-picker/color-picker-model.d.ts +186 -0
- package/dist/ts/color-picker/color-picker.d.ts +398 -0
- package/dist/ts/color-picker/color-picker.ts +2209 -0
- package/dist/ts/color-picker/index.d.ts +5 -0
- package/dist/ts/color-picker/index.ts +5 -0
- package/dist/ts/common/index.d.ts +4 -0
- package/dist/ts/common/index.ts +4 -0
- package/dist/ts/common/signature-base.d.ts +340 -0
- package/dist/ts/common/signature-base.ts +1170 -0
- package/dist/ts/form-validator/form-validator-model.d.ts +121 -0
- package/dist/ts/form-validator/form-validator.d.ts +312 -0
- package/dist/ts/form-validator/form-validator.ts +1068 -0
- package/dist/ts/form-validator/index.d.ts +5 -0
- package/dist/ts/form-validator/index.ts +5 -0
- package/dist/ts/index.d.ts +18 -0
- package/dist/ts/index.ts +18 -0
- package/dist/ts/input/index.d.ts +4 -0
- package/dist/ts/input/index.ts +4 -0
- package/dist/ts/input/input.d.ts +345 -0
- package/dist/ts/input/input.ts +1277 -0
- package/dist/ts/maskedtextbox/base/index.d.ts +4 -0
- package/dist/ts/maskedtextbox/base/index.ts +4 -0
- package/dist/ts/maskedtextbox/base/mask-base.d.ts +134 -0
- package/dist/ts/maskedtextbox/base/mask-base.ts +1207 -0
- package/dist/ts/maskedtextbox/index.d.ts +5 -0
- package/dist/ts/maskedtextbox/index.ts +5 -0
- package/dist/ts/maskedtextbox/maskedtextbox/index.d.ts +5 -0
- package/dist/ts/maskedtextbox/maskedtextbox/index.ts +5 -0
- package/dist/ts/maskedtextbox/maskedtextbox/maskedtextbox-model.d.ts +167 -0
- package/dist/ts/maskedtextbox/maskedtextbox/maskedtextbox.d.ts +307 -0
- package/dist/ts/maskedtextbox/maskedtextbox/maskedtextbox.ts +709 -0
- package/dist/ts/numerictextbox/index.d.ts +5 -0
- package/dist/ts/numerictextbox/index.ts +5 -0
- package/dist/ts/numerictextbox/numerictextbox-model.d.ts +228 -0
- package/dist/ts/numerictextbox/numerictextbox.d.ts +431 -0
- package/dist/ts/numerictextbox/numerictextbox.ts +1672 -0
- package/dist/ts/otp-input/index.d.ts +5 -0
- package/dist/ts/otp-input/index.ts +5 -0
- package/dist/ts/otp-input/otp-input-model.d.ts +165 -0
- package/dist/ts/otp-input/otp-input.d.ts +365 -0
- package/dist/ts/otp-input/otp-input.ts +924 -0
- package/dist/ts/rating/index.d.ts +5 -0
- package/dist/ts/rating/index.ts +5 -0
- package/dist/ts/rating/rating-model.d.ts +239 -0
- package/dist/ts/rating/rating.d.ts +416 -0
- package/dist/ts/rating/rating.ts +1101 -0
- package/dist/ts/signature/index.d.ts +5 -0
- package/dist/ts/signature/index.ts +5 -0
- package/dist/ts/signature/signature-model.d.ts +131 -0
- package/dist/ts/signature/signature.d.ts +167 -0
- package/dist/ts/signature/signature.ts +266 -0
- package/dist/ts/slider/index.d.ts +5 -0
- package/dist/ts/slider/index.ts +5 -0
- package/dist/ts/slider/slider-model.d.ts +401 -0
- package/dist/ts/slider/slider.d.ts +721 -0
- package/dist/ts/slider/slider.ts +3497 -0
- package/dist/ts/smart-textarea/caret-helper.d.ts +17 -0
- package/dist/ts/smart-textarea/caret-helper.ts +95 -0
- package/dist/ts/smart-textarea/index.d.ts +5 -0
- package/dist/ts/smart-textarea/index.ts +5 -0
- package/dist/ts/smart-textarea/smart-textarea-model.d.ts +44 -0
- package/dist/ts/smart-textarea/smart-textarea.d.ts +80 -0
- package/dist/ts/smart-textarea/smart-textarea.ts +518 -0
- package/dist/ts/speech-to-text/index.d.ts +5 -0
- package/dist/ts/speech-to-text/index.ts +5 -0
- package/dist/ts/speech-to-text/speech-to-text-model.d.ts +270 -0
- package/dist/ts/speech-to-text/speech-to-text.d.ts +487 -0
- package/dist/ts/speech-to-text/speech-to-text.ts +1008 -0
- package/dist/ts/textarea/index.d.ts +5 -0
- package/dist/ts/textarea/index.ts +5 -0
- package/dist/ts/textarea/textarea-model.d.ts +161 -0
- package/dist/ts/textarea/textarea.d.ts +237 -0
- package/dist/ts/textarea/textarea.ts +812 -0
- package/dist/ts/textbox/index.d.ts +5 -0
- package/dist/ts/textbox/index.ts +5 -0
- package/dist/ts/textbox/textbox-model.d.ts +155 -0
- package/dist/ts/textbox/textbox.d.ts +288 -0
- package/dist/ts/textbox/textbox.ts +872 -0
- package/dist/ts/uploader/index.d.ts +5 -0
- package/dist/ts/uploader/index.ts +5 -0
- package/dist/ts/uploader/uploader-model.d.ts +555 -0
- package/dist/ts/uploader/uploader.d.ts +1216 -0
- package/dist/ts/uploader/uploader.ts +4391 -0
- package/package.json +62 -12
- package/src/input/input.js +1 -1
- package/styles/bootstrap5.3-lite.css +3 -3
- package/styles/bootstrap5.3.css +5 -5
- package/styles/input/_layout.scss +0 -1
- package/styles/input/tailwind3.css +0 -1
- package/styles/tailwind-dark-lite.css +3 -3
- package/styles/tailwind-dark.css +5 -5
- package/styles/tailwind-lite.css +3 -3
- package/styles/tailwind.css +5 -5
- package/styles/tailwind3-lite.css +0 -1
- package/styles/tailwind3.css +0 -1
- package/styles/uploader/_bootstrap5.3-definition.scss +1 -1
- package/styles/uploader/_tailwind-definition.scss +1 -1
- package/styles/uploader/bootstrap5.3.css +5 -5
- package/styles/uploader/tailwind-dark.css +5 -5
- package/styles/uploader/tailwind.css +5 -5
|
@@ -0,0 +1,1101 @@
|
|
|
1
|
+
import { addClass, Event, attributes, BaseEventArgs, compile, Component, EmitType, EventHandler, getUniqueID, INotifyPropertyChanged, select, Browser, append } from '@syncfusion/ej2-base';
|
|
2
|
+
import { isNullOrUndefined, KeyboardEventArgs, KeyboardEvents, MouseEventArgs, NotifyPropertyChanges, Property, remove, removeClass, initializeCSPTemplate, closest } from '@syncfusion/ej2-base';
|
|
3
|
+
import { Tooltip } from '@syncfusion/ej2-popups';
|
|
4
|
+
import { RatingModel } from './rating-model';
|
|
5
|
+
|
|
6
|
+
const ICONCSS: string = 'e-rating-icon e-icons e-star-filled';
|
|
7
|
+
const ITEMLIST: string = 'e-rating-item-list';
|
|
8
|
+
const ITEMCONTAINER: string = 'e-rating-item-container';
|
|
9
|
+
const SELECTED: string = 'e-rating-selected';
|
|
10
|
+
const INTERMEDIATE: string = 'e-rating-intermediate';
|
|
11
|
+
const LABEL: string = 'e-rating-label';
|
|
12
|
+
const RESET: string = 'e-icons e-reset';
|
|
13
|
+
const HIDDEN: string = 'e-rating-hidden';
|
|
14
|
+
const DISABLED: string = 'e-disabled';
|
|
15
|
+
const READONLY: string = 'e-rating-readonly';
|
|
16
|
+
const RTL: string = 'e-rtl';
|
|
17
|
+
const ANIMATION: string = 'e-rating-animation';
|
|
18
|
+
const FULLTEMPLATE: string = 'e-rating-full';
|
|
19
|
+
const EMPTYTEMPLATE: string = 'e-rating-empty';
|
|
20
|
+
const SELECTEDVALUE: string = 'e-selected-value';
|
|
21
|
+
|
|
22
|
+
const RATINGVALUE: string = '--rating-value';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Defines where to position the label in rating
|
|
26
|
+
*/
|
|
27
|
+
export enum LabelPosition {
|
|
28
|
+
/**
|
|
29
|
+
* The label is positioned at the top center of the rating component.
|
|
30
|
+
*/
|
|
31
|
+
Top = 'Top',
|
|
32
|
+
/**
|
|
33
|
+
* The label is positioned at the bottom center of the rating component.
|
|
34
|
+
*/
|
|
35
|
+
Bottom = 'Bottom',
|
|
36
|
+
/**
|
|
37
|
+
* The label is positioned at the left side of the rating component.
|
|
38
|
+
*/
|
|
39
|
+
Left = 'Left',
|
|
40
|
+
/**
|
|
41
|
+
* The label is positioned at the right side of the rating component.
|
|
42
|
+
*/
|
|
43
|
+
Right = 'Right'
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Defines the precision type of the rating.
|
|
48
|
+
* It is used to component the granularity of the rating, allowing users to provide ratings with varying levels of precision.
|
|
49
|
+
*/
|
|
50
|
+
export enum PrecisionType {
|
|
51
|
+
/**
|
|
52
|
+
* The rating is increased in whole number increments.
|
|
53
|
+
*/
|
|
54
|
+
Full = 'Full',
|
|
55
|
+
/**
|
|
56
|
+
* The rating is increased in increments of 0.5 (half).
|
|
57
|
+
*/
|
|
58
|
+
Half = 'Half',
|
|
59
|
+
/**
|
|
60
|
+
* The rating is increased in increments of 0.25 (quarter).
|
|
61
|
+
*/
|
|
62
|
+
Quarter = 'Quarter',
|
|
63
|
+
/**
|
|
64
|
+
* The rating is increased in increments of 0.1.
|
|
65
|
+
*/
|
|
66
|
+
Exact = 'Exact'
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Provides information about valueChanged event callback
|
|
71
|
+
*/
|
|
72
|
+
export interface RatingChangedEventArgs extends BaseEventArgs {
|
|
73
|
+
/**
|
|
74
|
+
* Provides the original event
|
|
75
|
+
*/
|
|
76
|
+
event: Event;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Provides whether the change is triggered by user interaction.
|
|
80
|
+
*/
|
|
81
|
+
isInteracted: boolean;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Provides the previous value.
|
|
85
|
+
*/
|
|
86
|
+
previousValue: number;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Provides the current value.
|
|
90
|
+
*/
|
|
91
|
+
value: number;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Provides information about onItemHover event callback.
|
|
96
|
+
*/
|
|
97
|
+
export interface RatingHoverEventArgs extends BaseEventArgs {
|
|
98
|
+
/**
|
|
99
|
+
* Provides the rating item element reference.
|
|
100
|
+
*/
|
|
101
|
+
element: HTMLElement;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Provides the original event.
|
|
105
|
+
*/
|
|
106
|
+
event: Event;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Provides the hover value at hovered point of rating.
|
|
110
|
+
*/
|
|
111
|
+
value: number;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Provides information about beforeItemRender event callback.
|
|
116
|
+
*/
|
|
117
|
+
export interface RatingItemEventArgs extends BaseEventArgs {
|
|
118
|
+
/**
|
|
119
|
+
* Provides the rating item element reference.
|
|
120
|
+
*/
|
|
121
|
+
element: HTMLElement;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Provides the place value of the item.
|
|
125
|
+
*/
|
|
126
|
+
value: number;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* The Rating component allows the user to rate something by clicking on a set of symbols on a numeric scale.
|
|
131
|
+
* This allows users to provide feedback or ratings for products, services, or content.
|
|
132
|
+
*
|
|
133
|
+
* ```html
|
|
134
|
+
* <input id="rating">
|
|
135
|
+
* ```
|
|
136
|
+
* ```typescript
|
|
137
|
+
* <script>
|
|
138
|
+
* let ratingObj: Rating = new Rating();
|
|
139
|
+
* ratingObj.appendTo('#rating');
|
|
140
|
+
* </script>
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
@NotifyPropertyChanges
|
|
144
|
+
export class Rating extends Component<HTMLElement> implements INotifyPropertyChanged {
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Defines whether to show or hide the reset button in a rating component.
|
|
148
|
+
* When set to "true", the reset button will be visible to the user, and they will be able to click it to reset the rating value to its default value.
|
|
149
|
+
*
|
|
150
|
+
* {% codeBlock src='rating/allowReset/index.md' %}{% endcodeBlock %}
|
|
151
|
+
*
|
|
152
|
+
* @default false
|
|
153
|
+
*/
|
|
154
|
+
@Property(false)
|
|
155
|
+
public allowReset: boolean;
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Defines one or more CSS classes that can be used to customize the appearance of a rating component.
|
|
159
|
+
* One or more CSS classes to customize the appearance of the rating component, such as by changing its colors, fonts, sizes, or other visual aspects.
|
|
160
|
+
*
|
|
161
|
+
* @default ''
|
|
162
|
+
*/
|
|
163
|
+
@Property('')
|
|
164
|
+
public cssClass: string;
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Defines whether a rating component is enabled or disabled.
|
|
168
|
+
* A disabled rating component may have a different visual appearance than an enabled one.
|
|
169
|
+
* When set to "true", the rating component will be disabled, and the user will not be able to interact with it.
|
|
170
|
+
*
|
|
171
|
+
* @default false
|
|
172
|
+
*/
|
|
173
|
+
@Property(false)
|
|
174
|
+
public disabled: boolean;
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Defines the template that defines the appearance of each un-rated item in a rating component.
|
|
178
|
+
*
|
|
179
|
+
* @default ''
|
|
180
|
+
* @angularType string | object
|
|
181
|
+
* @reactType string | function | JSX.Element
|
|
182
|
+
* @vueType string | function
|
|
183
|
+
* @aspType string
|
|
184
|
+
*/
|
|
185
|
+
@Property('')
|
|
186
|
+
public emptyTemplate: string | Function;
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Defines whether to add animation (to provide visual feedback to the user) when an item in a rating component is hovered.
|
|
190
|
+
* When set to "true", an animation will be added when the user hovers their cursor over an item in the rating component.
|
|
191
|
+
*
|
|
192
|
+
* @default true
|
|
193
|
+
*/
|
|
194
|
+
@Property(true)
|
|
195
|
+
public enableAnimation: boolean;
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Defines whether to select all the items before the selected item should be in selected state in a rating component.
|
|
199
|
+
* When set to "true", only the selected item will be in the selected state, and all other items will be un-selected.
|
|
200
|
+
* When set to "false", all items before the selected one will be in the selected state.
|
|
201
|
+
*
|
|
202
|
+
* @default false
|
|
203
|
+
*/
|
|
204
|
+
@Property(false)
|
|
205
|
+
public enableSingleSelection: boolean;
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Defines the template that defines the appearance of each rated item in a rating component.
|
|
209
|
+
*
|
|
210
|
+
* {% codeBlock src='rating/fullTemplate/index.md' %}{% endcodeBlock %}
|
|
211
|
+
*
|
|
212
|
+
* @default ''
|
|
213
|
+
* @angularType string | object
|
|
214
|
+
* @reactType string | function | JSX.Element
|
|
215
|
+
* @vueType string | function
|
|
216
|
+
* @aspType string
|
|
217
|
+
*/
|
|
218
|
+
@Property('')
|
|
219
|
+
public fullTemplate: string | Function;
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Defines the specific number of items (symbols) in rating component.
|
|
223
|
+
* The rating component typically consists of a number of items, such as stars or other symbols, that represent the rating value.
|
|
224
|
+
*
|
|
225
|
+
* @default 5
|
|
226
|
+
* @aspType int
|
|
227
|
+
*/
|
|
228
|
+
@Property(5)
|
|
229
|
+
public itemsCount: number;
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Defines the position of the label in rating component.
|
|
233
|
+
*
|
|
234
|
+
* The possible values are:
|
|
235
|
+
* * Top
|
|
236
|
+
* * Bottom
|
|
237
|
+
* * Left
|
|
238
|
+
* * Right
|
|
239
|
+
*
|
|
240
|
+
* {% codeBlock src='rating/labelPosition/index.md' %}{% endcodeBlock %}
|
|
241
|
+
*
|
|
242
|
+
* @isenumeration true
|
|
243
|
+
* @default LabelPosition.Right
|
|
244
|
+
* @asptype LabelPosition
|
|
245
|
+
*/
|
|
246
|
+
@Property(LabelPosition.Right)
|
|
247
|
+
public labelPosition: string | LabelPosition;
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Defines the template that used as label over default label of the rating. The current value of rating passed as context to build the content.
|
|
251
|
+
*
|
|
252
|
+
* {% codeBlock src='rating/labelTemplate/index.md' %}{% endcodeBlock %}
|
|
253
|
+
*
|
|
254
|
+
* @default ''
|
|
255
|
+
* @angularType string | object
|
|
256
|
+
* @reactType string | function | JSX.Element
|
|
257
|
+
* @vueType string | function
|
|
258
|
+
* @aspType string
|
|
259
|
+
*/
|
|
260
|
+
@Property('')
|
|
261
|
+
public labelTemplate: string | Function;
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Defines the value that specifies minimum rating that a user can select.
|
|
265
|
+
* The value is set to 0, which means that the minimum possible rating is 0.
|
|
266
|
+
*
|
|
267
|
+
* @default 0.0
|
|
268
|
+
* @aspType double
|
|
269
|
+
*/
|
|
270
|
+
@Property(0.0)
|
|
271
|
+
public min: number;
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Defines the precision type of the rating which used to component the granularity of the rating,
|
|
275
|
+
* allowing users to provide ratings with varying levels of precision.
|
|
276
|
+
*
|
|
277
|
+
* The possible values are:
|
|
278
|
+
* * Full
|
|
279
|
+
* * Half
|
|
280
|
+
* * Quarter
|
|
281
|
+
* * Exact
|
|
282
|
+
*
|
|
283
|
+
* {% codeBlock src='rating/precision/index.md' %}{% endcodeBlock %}
|
|
284
|
+
*
|
|
285
|
+
* @isenumeration true
|
|
286
|
+
* @default PrecisionType.Full
|
|
287
|
+
* @asptype PrecisionType
|
|
288
|
+
*/
|
|
289
|
+
@Property(PrecisionType.Full)
|
|
290
|
+
public precision: string | PrecisionType;
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Defines a boolean value that specifies whether the read-only mode is enabled for a rating component,
|
|
294
|
+
* which prevents the user from modifying or interacting with the rating value but allows them to read it.
|
|
295
|
+
*
|
|
296
|
+
* @default false
|
|
297
|
+
*/
|
|
298
|
+
@Property(false)
|
|
299
|
+
public readOnly: boolean;
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Defines a value that specifies whether to display a label that shows the current value of a rating.
|
|
303
|
+
* When set to "true", a label will be displayed that shows the current value of the rating; otherwise false.
|
|
304
|
+
*
|
|
305
|
+
* {% codeBlock src='rating/showLabel/index.md' %}{% endcodeBlock %}
|
|
306
|
+
*
|
|
307
|
+
* @default false
|
|
308
|
+
*/
|
|
309
|
+
@Property(false)
|
|
310
|
+
public showLabel: boolean;
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Defines a value that defines whether to show tooltip for the items.
|
|
314
|
+
* When set to "true", show tooltip for the items.
|
|
315
|
+
*
|
|
316
|
+
* @default true
|
|
317
|
+
*/
|
|
318
|
+
@Property(true)
|
|
319
|
+
public showTooltip: boolean;
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Defines the template that used as tooltip content over default tooltip content of the rating.
|
|
323
|
+
* The current value of rating passed as context to build the content.
|
|
324
|
+
*
|
|
325
|
+
* {% codeBlock src='rating/tooltipTemplate/index.md' %}{% endcodeBlock %}
|
|
326
|
+
*
|
|
327
|
+
* @default ''
|
|
328
|
+
* @angularType string | object
|
|
329
|
+
* @reactType string | function | JSX.Element
|
|
330
|
+
* @vueType string | function
|
|
331
|
+
* @aspType string
|
|
332
|
+
*/
|
|
333
|
+
@Property('')
|
|
334
|
+
public tooltipTemplate: string | Function;
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Defines the current rating value which used to display and update the rating selected by the user.
|
|
338
|
+
* Based on "PrecisionType", users can select ratings with varying levels of precision.
|
|
339
|
+
* The "value" is a decimal value that ranges from the minimum value to the items count,
|
|
340
|
+
* as specified by the "min" and "itemsCount" properties of the rating.
|
|
341
|
+
*
|
|
342
|
+
* {% codeBlock src='rating/value/index.md' %}{% endcodeBlock %}
|
|
343
|
+
*
|
|
344
|
+
* @default 0.0
|
|
345
|
+
* @aspType double
|
|
346
|
+
*/
|
|
347
|
+
@Property(0.0)
|
|
348
|
+
public value: number;
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Defines a value that indicates whether the rating component is visible or hidden.
|
|
352
|
+
* When set to "true", if the rating component is visible.
|
|
353
|
+
*
|
|
354
|
+
* @default true
|
|
355
|
+
*/
|
|
356
|
+
@Property(true)
|
|
357
|
+
public visible: boolean;
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Event callback that is raised before rendering each item.
|
|
361
|
+
*
|
|
362
|
+
* {% codeBlock src='rating/beforeItemRenderEvent/index.md' %}{% endcodeBlock %}
|
|
363
|
+
*
|
|
364
|
+
* @event beforeItemRender
|
|
365
|
+
*/
|
|
366
|
+
@Event()
|
|
367
|
+
public beforeItemRender: EmitType<RatingItemEventArgs>;
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Event callback that is raised after rendering the rating.
|
|
371
|
+
*
|
|
372
|
+
* @event created
|
|
373
|
+
*/
|
|
374
|
+
@Event()
|
|
375
|
+
public created: EmitType<Event>;
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Event callback that is raised when a user hovers over an item.
|
|
379
|
+
*
|
|
380
|
+
* {% codeBlock src='rating/onItemHoverEvent/index.md' %}{% endcodeBlock %}
|
|
381
|
+
*
|
|
382
|
+
* @event onItemHover
|
|
383
|
+
*/
|
|
384
|
+
@Event()
|
|
385
|
+
public onItemHover: EmitType<RatingHoverEventArgs>;
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Event callback that is raised when the value is changed.
|
|
389
|
+
*
|
|
390
|
+
* {% codeBlock src='rating/valueChangedEvent/index.md' %}{% endcodeBlock %}
|
|
391
|
+
*
|
|
392
|
+
* @event valueChanged
|
|
393
|
+
*/
|
|
394
|
+
@Event()
|
|
395
|
+
public valueChanged: EmitType<RatingChangedEventArgs>;
|
|
396
|
+
|
|
397
|
+
/* Private variables */
|
|
398
|
+
private wrapper: HTMLElement;
|
|
399
|
+
private ratingItemList: HTMLElement;
|
|
400
|
+
private spanLabel: HTMLElement;
|
|
401
|
+
private itemElements: HTMLElement[] = [];
|
|
402
|
+
private resetElement: HTMLSpanElement;
|
|
403
|
+
private keyboardModuleRating: KeyboardEvents;
|
|
404
|
+
private keyConfigs: { [key: string]: string };
|
|
405
|
+
private tooltipObj: Tooltip;
|
|
406
|
+
private currentValue: number;
|
|
407
|
+
private emptyTemplateFunction: Function;
|
|
408
|
+
private fullTemplateFunction: Function;
|
|
409
|
+
private tooltipOpen: boolean;
|
|
410
|
+
private isTouchSelected: boolean;
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Constructor for creating the widget
|
|
414
|
+
*
|
|
415
|
+
* @param {RatingModel} options - Specifies the rating model
|
|
416
|
+
* @param {string|HTMLButtonElement} element - Specifies the target element
|
|
417
|
+
*/
|
|
418
|
+
constructor(options?: RatingModel, element?: string | HTMLInputElement) {
|
|
419
|
+
super(options, <string | HTMLInputElement>element);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
protected preRender(): void {
|
|
423
|
+
if (!this.element.id) {
|
|
424
|
+
this.element.id = getUniqueID('e-' + this.getModuleName());
|
|
425
|
+
}
|
|
426
|
+
this.keyConfigs = {
|
|
427
|
+
downarrow: 'downarrow',
|
|
428
|
+
leftarrow: 'leftarrow',
|
|
429
|
+
rightarrow: 'rightarrow',
|
|
430
|
+
uparrow: 'uparrow',
|
|
431
|
+
space: 'space'
|
|
432
|
+
};
|
|
433
|
+
this.tooltipOpen = false;
|
|
434
|
+
this.isTouchSelected = false;
|
|
435
|
+
if (closest(this.element, 'form') && this.element.getAttribute('value')) {
|
|
436
|
+
this.setProperties({ value: this.element.getAttribute('value') }, true);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
public render(): void {
|
|
441
|
+
this.initialize();
|
|
442
|
+
this.updateMinValue();
|
|
443
|
+
this.updateTemplateFunction();
|
|
444
|
+
this.triggerChange(null, this.value, false, true);
|
|
445
|
+
this.renderItems();
|
|
446
|
+
this.displayLabel();
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
private initialize(): void {
|
|
450
|
+
this.wrapper = this.createElement('div', { className: 'e-' + this.getModuleName() + '-container ' });
|
|
451
|
+
this.element.parentNode.insertBefore(this.wrapper, this.element);
|
|
452
|
+
this.wrapper.appendChild(this.element);
|
|
453
|
+
if ((this.element.getAttribute('name') == null)) {
|
|
454
|
+
this.element.setAttribute('name', this.element.id);
|
|
455
|
+
}
|
|
456
|
+
attributes(this.element, { 'aria-label': 'rating' });
|
|
457
|
+
this.renderItemList();
|
|
458
|
+
this.updateReset();
|
|
459
|
+
if (this.readOnly) {
|
|
460
|
+
this.wrapper.classList.add(READONLY);
|
|
461
|
+
}
|
|
462
|
+
if (!this.visible) {
|
|
463
|
+
this.wrapper.classList.add(HIDDEN);
|
|
464
|
+
}
|
|
465
|
+
if (this.enableRtl) {
|
|
466
|
+
this.wrapper.classList.add(RTL);
|
|
467
|
+
}
|
|
468
|
+
if (this.enableAnimation) {
|
|
469
|
+
this.wrapper.classList.add(ANIMATION);
|
|
470
|
+
}
|
|
471
|
+
if (this.cssClass) {
|
|
472
|
+
addClass([this.wrapper], this.cssClass.split(' '));
|
|
473
|
+
}
|
|
474
|
+
this.updateTooltip();
|
|
475
|
+
this.wireKeyboardEvent();
|
|
476
|
+
this.updateDisabled();
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
private updateDisabled(): void {
|
|
480
|
+
this.wrapper.classList[this.disabled ? 'add' : 'remove'](DISABLED);
|
|
481
|
+
attributes(this.ratingItemList, { 'tabindex': (this.disabled) ? '-1' : '0' });
|
|
482
|
+
this.updateResetButton();
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
private updateResetButton(): void {
|
|
486
|
+
if (this.allowReset) {
|
|
487
|
+
if (this.resetElement) {
|
|
488
|
+
this.resetElement.blur();
|
|
489
|
+
}
|
|
490
|
+
const isDisabled: boolean = (this.value <= this.min) || this.disabled;
|
|
491
|
+
this.resetElement.classList[isDisabled ? 'add' : 'remove'](DISABLED);
|
|
492
|
+
attributes(this.resetElement, { 'tabindex': (isDisabled ? '-1' : '0'), 'aria-hidden': isDisabled.toString() });
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
private renderItemList(): void {
|
|
497
|
+
this.ratingItemList = this.createElement('div', {
|
|
498
|
+
className: ITEMLIST,
|
|
499
|
+
id: this.element.id + '_item-list'
|
|
500
|
+
});
|
|
501
|
+
attributes(this.ratingItemList, { 'aria-label': 'rating', 'role': 'slider' });
|
|
502
|
+
this.wrapper.appendChild(this.ratingItemList);
|
|
503
|
+
EventHandler.add(this.ratingItemList, 'touchmove', (e: Event) => this.touchMoveHandler(e), this);
|
|
504
|
+
EventHandler.add(this.ratingItemList, Browser.touchEndEvent, this.touchEndHandler, this);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
private touchMoveHandler(e: Event): void {
|
|
508
|
+
if (!this.isTouchSelected) {
|
|
509
|
+
this.wrapper.classList.add('e-rating-touch');
|
|
510
|
+
this.isTouchSelected = true;
|
|
511
|
+
}
|
|
512
|
+
this.wrapper.classList.add('e-touch-select');
|
|
513
|
+
const rect: DOMRect = this.ratingItemList.getBoundingClientRect() as DOMRect;
|
|
514
|
+
const x: number = (e as TouchEvent).touches[0].clientX - rect.x;
|
|
515
|
+
let currValue: number = (x / rect.width) * this.itemsCount;
|
|
516
|
+
currValue = (this.enableRtl) ? (this.itemsCount - currValue) : currValue;
|
|
517
|
+
currValue = currValue < this.min ? this.min : currValue > this.itemsCount ? this.itemsCount : currValue;
|
|
518
|
+
currValue = this.validateValue(currValue);
|
|
519
|
+
const element: HTMLElement = currValue === 0 ? null : this.itemElements[parseInt((Math.ceil(currValue) - 1).toString(), 10)];
|
|
520
|
+
if (currValue === this.currentValue) {
|
|
521
|
+
if (this.showTooltip && element) {
|
|
522
|
+
this.openRatingTooltip(element, false);
|
|
523
|
+
}
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
526
|
+
const previousValue: number = this.currentValue;
|
|
527
|
+
this.triggerChange(e, currValue);
|
|
528
|
+
this.updateCurrentValue(currValue);
|
|
529
|
+
if (this.showTooltip) {
|
|
530
|
+
if (element) {
|
|
531
|
+
if (Math.ceil(currValue) !== Math.ceil(previousValue)) { this.closeRatingTooltip(); }
|
|
532
|
+
this.openRatingTooltip(element, true);
|
|
533
|
+
} else {
|
|
534
|
+
this.closeRatingTooltip();
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
private touchEndHandler(): void {
|
|
540
|
+
this.closeRatingTooltip();
|
|
541
|
+
this.wrapper.classList.remove('e-touch-select');
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
private updateTemplateFunction(): void {
|
|
545
|
+
this.emptyTemplateFunction = this.emptyTemplate ? this.getTemplateString(this.emptyTemplate) : null;
|
|
546
|
+
this.fullTemplateFunction = this.fullTemplate ? this.getTemplateString(this.fullTemplate) : null;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
private renderItems(): void {
|
|
550
|
+
for (let i: number = 0; i < this.itemsCount; i++) {
|
|
551
|
+
const ratingItemContainer: HTMLElement = this.createElement('span', { className: ITEMCONTAINER });
|
|
552
|
+
const spanItem: HTMLElement = this.createElement('span', { className: 'e-rating-item' });
|
|
553
|
+
const ratingValue: number = this.getRatingValue(this.value, i);
|
|
554
|
+
this.renderItemContent(spanItem, ratingValue, i , false);
|
|
555
|
+
ratingItemContainer.appendChild(spanItem);
|
|
556
|
+
this.wireItemsEvents(ratingItemContainer, i + 1);
|
|
557
|
+
this.itemElements.push(ratingItemContainer);
|
|
558
|
+
const eventArgs: RatingItemEventArgs = { element: ratingItemContainer, value: i + 1 };
|
|
559
|
+
this.trigger('beforeItemRender', eventArgs, (args: RatingItemEventArgs) => {
|
|
560
|
+
this.ratingItemList.appendChild(args.element);
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
attributes(this.ratingItemList, { 'aria-valuemax': this.itemsCount.toString() });
|
|
564
|
+
this.updateItemValue(false);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
private renderItemContent(spanEle: HTMLElement, val: number, index: number, isrerender: boolean): void {
|
|
568
|
+
if (isrerender) {
|
|
569
|
+
this.removeItemContent(spanEle);
|
|
570
|
+
}
|
|
571
|
+
if (this.fullTemplate && val === 1) {
|
|
572
|
+
spanEle.classList.add(FULLTEMPLATE);
|
|
573
|
+
append(this.fullTemplateFunction({ index: index, ratingValue: val }, this, 'ratingFullTemplate', (this.element.id + 'fullTemplate'), this.isStringTemplate), spanEle);
|
|
574
|
+
}
|
|
575
|
+
else if (this.emptyTemplate) {
|
|
576
|
+
spanEle.classList.add(EMPTYTEMPLATE);
|
|
577
|
+
append(this.emptyTemplateFunction({ index: index, ratingValue: val }, this, 'ratingEmptyTemplate', (this.element.id + 'emptyTemplate'), this.isStringTemplate), spanEle);
|
|
578
|
+
}
|
|
579
|
+
else {
|
|
580
|
+
addClass([spanEle], ICONCSS.split(' '));
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
private removeItemContent(spanEle: HTMLElement): void {
|
|
585
|
+
spanEle.classList.remove(FULLTEMPLATE, EMPTYTEMPLATE);
|
|
586
|
+
removeClass([spanEle], ICONCSS.split(' '));
|
|
587
|
+
if (spanEle.firstChild) {
|
|
588
|
+
spanEle.innerHTML = '';
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
private updateTooltip(): void {
|
|
593
|
+
if (this.showTooltip) {
|
|
594
|
+
this.tooltipObj = new Tooltip({
|
|
595
|
+
target: '.e-rating-item-container', windowCollision: true,
|
|
596
|
+
opensOn: 'Custom', cssClass: this.cssClass ? ('e-rating-tooltip ' + this.cssClass) : 'e-rating-tooltip'
|
|
597
|
+
});
|
|
598
|
+
this.tooltipObj.appendTo(this.ratingItemList);
|
|
599
|
+
}
|
|
600
|
+
else {
|
|
601
|
+
if (!isNullOrUndefined(this.tooltipObj)) {
|
|
602
|
+
this.tooltipObj.destroy();
|
|
603
|
+
this.tooltipObj = null;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
private updateMinValue(): void {
|
|
609
|
+
this.setProperties({min: this.validateValue(this.min)}, true);
|
|
610
|
+
if (this.min > 0 && this.value < this.min) {
|
|
611
|
+
this.triggerChange(null, this.min, false);
|
|
612
|
+
}
|
|
613
|
+
attributes(this.ratingItemList, { 'aria-valuemin': this.min.toString() });
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
private validateValue(currentValue: number): number {
|
|
617
|
+
if (currentValue > this.itemsCount) {
|
|
618
|
+
currentValue = this.itemsCount;
|
|
619
|
+
}
|
|
620
|
+
else if (currentValue < 0) {
|
|
621
|
+
currentValue = 0;
|
|
622
|
+
}
|
|
623
|
+
else {
|
|
624
|
+
currentValue = ((this.precision === PrecisionType.Full) || this.enableSingleSelection) ? Math.round(currentValue) :
|
|
625
|
+
(this.precision === PrecisionType.Half) ? (Math.round(currentValue * 2) / 2) :
|
|
626
|
+
(this.precision === PrecisionType.Quarter) ? (Math.round(currentValue * 4) / 4) : (Math.round(currentValue * 10) / 10);
|
|
627
|
+
}
|
|
628
|
+
return currentValue;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
private getRatingValue(value: number, i: number): number {
|
|
632
|
+
return (this.enableSingleSelection) ? (((value > i) && (value <= i + 1)) ? 1 : 0) :
|
|
633
|
+
(value >= i + 1) ? 1 : ((value < i) ? 0 : (value - i));
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
private updateItemValue(isUpdate: boolean = true): void {
|
|
637
|
+
for (let i: number = 0; i < this.itemsCount; i++) {
|
|
638
|
+
const itemElement: HTMLElement = this.itemElements[parseInt(i.toString(), 10)];
|
|
639
|
+
itemElement.classList.remove(SELECTED, INTERMEDIATE, SELECTEDVALUE);
|
|
640
|
+
const ratingValue: number = this.getRatingValue(this.currentValue, i);
|
|
641
|
+
if (ratingValue === 1) { itemElement.classList.add(SELECTED); }
|
|
642
|
+
else if (ratingValue > 0) { itemElement.classList.add(INTERMEDIATE); }
|
|
643
|
+
else if ((this.precision === PrecisionType.Full) && (i + 1 <= this.value) && (!this.enableSingleSelection)) {
|
|
644
|
+
itemElement.classList.add(SELECTEDVALUE);
|
|
645
|
+
}
|
|
646
|
+
if (isUpdate) { this.updateItemContent(ratingValue, i); }
|
|
647
|
+
itemElement.style.setProperty(RATINGVALUE, (ratingValue * 100) + '%');
|
|
648
|
+
itemElement.classList[((this.value === 0) && (i === 0)) || (this.value === i + 1) || ((ratingValue > 0) && (ratingValue < 1)) ? 'add' : 'remove']('e-rating-focus');
|
|
649
|
+
}
|
|
650
|
+
if (isUpdate) { this.renderReactTemplates(); }
|
|
651
|
+
this.updateResetButton();
|
|
652
|
+
attributes(this.ratingItemList, { 'aria-valuenow': this.currentValue.toString() });
|
|
653
|
+
attributes(this.element, { 'value': this.value.toString() });
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
private updateItemContent(ratingValue: number, index: number): void {
|
|
657
|
+
if (!this.fullTemplate && !this.emptyTemplate) { return; }
|
|
658
|
+
const spanEle: HTMLElement = this.itemElements[parseInt(index.toString(), 10)].querySelector('.e-rating-item');
|
|
659
|
+
if (this.fullTemplate && ratingValue === 1) {
|
|
660
|
+
if (spanEle.classList.contains(FULLTEMPLATE)) { return; }
|
|
661
|
+
this.removeItemContent(spanEle as HTMLElement);
|
|
662
|
+
spanEle.classList.add(FULLTEMPLATE);
|
|
663
|
+
append(this.fullTemplateFunction({ ratingValue: ratingValue, index: index }, this, 'ratingFullTemplate', (this.element.id + 'fullTemplate' + index), this.isStringTemplate), spanEle);
|
|
664
|
+
}
|
|
665
|
+
else if (this.emptyTemplate) {
|
|
666
|
+
if (spanEle.classList.contains(EMPTYTEMPLATE)) { return; }
|
|
667
|
+
this.removeItemContent(spanEle as HTMLElement);
|
|
668
|
+
spanEle.classList.add(EMPTYTEMPLATE);
|
|
669
|
+
append(this.emptyTemplateFunction({ ratingValue: ratingValue, index: index }, this, 'ratingEmptyTemplate', (this.element.id + 'emptyTemplate' + index), this.isStringTemplate), spanEle);
|
|
670
|
+
}
|
|
671
|
+
else {
|
|
672
|
+
this.removeItemContent(spanEle as HTMLElement);
|
|
673
|
+
addClass([spanEle], ICONCSS.split(' '));
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
private updateTooltipContent(isChange: boolean): void {
|
|
678
|
+
if (this.showTooltip) {
|
|
679
|
+
if (this.isReact) { this.clearTemplate(['ratingTooltipTemplate']); }
|
|
680
|
+
let content: string | HTMLElement;
|
|
681
|
+
if (this.tooltipTemplate) {
|
|
682
|
+
content = this.createElement('span', { className: 'e-rating-tooltip-content' });
|
|
683
|
+
const templateFunction: Function = this.getTemplateString(this.tooltipTemplate);
|
|
684
|
+
append(templateFunction({ value: this.currentValue }, this, 'ratingTooltipTemplate', (this.element.id + 'tooltipTemplate'), this.isStringTemplate), (content as HTMLElement));
|
|
685
|
+
this.tooltipObj.setProperties({ content: content }, isChange);
|
|
686
|
+
if (this.isAngular) {
|
|
687
|
+
setTimeout(() => {
|
|
688
|
+
const ratingSpan: NodeListOf<HTMLElement> = this.ratingItemList.querySelectorAll('.' + ITEMCONTAINER + '.' + SELECTED);
|
|
689
|
+
this.tooltipObj.refresh(ratingSpan[ratingSpan.length - 1]);
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
else {
|
|
694
|
+
content = this.currentValue.toString();
|
|
695
|
+
this.tooltipObj.setProperties({ content: initializeCSPTemplate( () => { return content; }) }, isChange);
|
|
696
|
+
}
|
|
697
|
+
this.renderReactTemplates();
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
private getTemplateString(template: string | Function): Function {
|
|
702
|
+
let stringContent: string | Function = '';
|
|
703
|
+
try {
|
|
704
|
+
if (typeof template !== 'function') {
|
|
705
|
+
const tempEle: HTMLElement = select(template);
|
|
706
|
+
if (tempEle) {
|
|
707
|
+
//Return innerHTML incase of jsrenderer script else outerHTML
|
|
708
|
+
stringContent = tempEle.tagName === 'SCRIPT' ? tempEle.innerHTML : tempEle.outerHTML;
|
|
709
|
+
} else {
|
|
710
|
+
stringContent = template;
|
|
711
|
+
}
|
|
712
|
+
} else {
|
|
713
|
+
stringContent = template;
|
|
714
|
+
}
|
|
715
|
+
} catch (e) {
|
|
716
|
+
stringContent = template;
|
|
717
|
+
}
|
|
718
|
+
return compile(stringContent);
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
private displayLabel(): void {
|
|
722
|
+
if (this.showLabel) {
|
|
723
|
+
this.spanLabel = this.createElement('span', { className: LABEL });
|
|
724
|
+
this.updateLabel();
|
|
725
|
+
this.updateLabelPosition();
|
|
726
|
+
}
|
|
727
|
+
else {
|
|
728
|
+
if (this.wrapper.contains(this.spanLabel)) {
|
|
729
|
+
remove(this.spanLabel);
|
|
730
|
+
this.spanLabel = null;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
private updateLabel(): void {
|
|
736
|
+
if (this.showLabel) {
|
|
737
|
+
if (this.labelTemplate) {
|
|
738
|
+
if (this.isReact) { this.clearTemplate(['ratingLabelTemplate']); }
|
|
739
|
+
if (this.spanLabel.firstChild) {
|
|
740
|
+
this.spanLabel.innerHTML = '';
|
|
741
|
+
}
|
|
742
|
+
const templateFunction: Function = this.getTemplateString(this.labelTemplate);
|
|
743
|
+
append(templateFunction({ value: this.currentValue }, this, 'ratingLabelTemplate', (this.element.id + 'labelTemplate'), this.isStringTemplate), this.spanLabel);
|
|
744
|
+
this.renderReactTemplates();
|
|
745
|
+
}
|
|
746
|
+
else {
|
|
747
|
+
this.spanLabel.textContent = this.currentValue + ' / ' + this.itemsCount;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
private updateReset(): void {
|
|
753
|
+
if (this.allowReset) {
|
|
754
|
+
this.resetElement = this.createElement('span', {
|
|
755
|
+
className: RESET,
|
|
756
|
+
attrs: {'aria-label': 'resetbutton', 'role': 'button'}
|
|
757
|
+
});
|
|
758
|
+
this.updateResetButton();
|
|
759
|
+
EventHandler.add(this.resetElement, 'click', this.resetClicked, this);
|
|
760
|
+
this.wrapper.insertBefore(this.resetElement, this.ratingItemList);
|
|
761
|
+
}
|
|
762
|
+
else {
|
|
763
|
+
if (this.wrapper.contains(this.resetElement)) {
|
|
764
|
+
remove(this.resetElement);
|
|
765
|
+
this.resetElement = null;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
private updateLabelPosition(): void {
|
|
771
|
+
this.clearLabelPosition();
|
|
772
|
+
this.spanLabel.classList.add('e-label-' + this.labelPosition.toLowerCase());
|
|
773
|
+
if (this.labelPosition === 'Left' || this.labelPosition === 'Top') {
|
|
774
|
+
this.wrapper.firstChild.after(this.spanLabel);
|
|
775
|
+
}
|
|
776
|
+
else {
|
|
777
|
+
this.wrapper.appendChild(this.spanLabel);
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
private clearLabelPosition(): void {
|
|
782
|
+
const removeCss: string[] = this.spanLabel.classList.value.match(/(e-label-[top|bottom|right|left]+)/g);
|
|
783
|
+
if (removeCss) {
|
|
784
|
+
removeClass([this.spanLabel], removeCss);
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
private wireItemsEvents(itemElement: HTMLElement, index: number): void {
|
|
789
|
+
EventHandler.add(itemElement, 'click', (e: Event) => this.clickHandler(e), this);
|
|
790
|
+
EventHandler.add(itemElement, 'mousemove', (e: Event) => this.mouseMoveHandler(index, e), this);
|
|
791
|
+
EventHandler.add(itemElement, 'mouseleave', this.mouseLeaveHandler, this);
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
private clickHandler(e: Event): void {
|
|
795
|
+
this.currentValue = (this.min > 0 && this.currentValue < this.min) ? this.min : this.currentValue;
|
|
796
|
+
this.triggerChange(e, this.currentValue);
|
|
797
|
+
this.updateItemValue();
|
|
798
|
+
this.updateLabel();
|
|
799
|
+
this.updateResetButton();
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
private updateValueChange(e: Event, val: number, isInteracted: boolean = true): void{
|
|
803
|
+
this.triggerChange(e, val, isInteracted);
|
|
804
|
+
this.updateItemValue();
|
|
805
|
+
this.updateLabel();
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
private triggerChange(e: Event, val: number, isInteracted: boolean = true, isInitial: boolean = false): void {
|
|
809
|
+
const ratingObj: any = null || this;
|
|
810
|
+
val = this.validateValue(val);
|
|
811
|
+
this.currentValue = val;
|
|
812
|
+
if (this.currentValue === this.value) { return; }
|
|
813
|
+
const eventArgs: RatingChangedEventArgs = { event: e, isInteracted: isInteracted, value: val, previousValue: this.value };
|
|
814
|
+
this.setProperties({ value: val }, true);
|
|
815
|
+
if (this.isAngular && !isInitial) {
|
|
816
|
+
ratingObj.localChange({ value: val });
|
|
817
|
+
}
|
|
818
|
+
if (!isInitial) {
|
|
819
|
+
this.trigger('valueChanged', eventArgs);
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
private mouseMoveHandler(index: number, e: Event): void {
|
|
824
|
+
if (this.isTouchSelected) {
|
|
825
|
+
this.wrapper.classList.remove('e-rating-touch');
|
|
826
|
+
this.isTouchSelected = false;
|
|
827
|
+
}
|
|
828
|
+
let currValue: number = this.calculateCurrentValue(index, e as MouseEventArgs);
|
|
829
|
+
currValue = this.validateValue(currValue);
|
|
830
|
+
const element: HTMLElement = this.itemElements[parseInt((index - 1).toString(), 10)];
|
|
831
|
+
if (currValue === this.currentValue) {
|
|
832
|
+
this.openRatingTooltip(element, false);
|
|
833
|
+
return;
|
|
834
|
+
}
|
|
835
|
+
this.updateCurrentValue(currValue);
|
|
836
|
+
this.openRatingTooltip(element, true);
|
|
837
|
+
const eventArgs: RatingHoverEventArgs = { element: element, event: e, value: currValue };
|
|
838
|
+
this.trigger('onItemHover', eventArgs);
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
private openRatingTooltip(element: HTMLElement, isChange: boolean): void {
|
|
842
|
+
if (this.showTooltip) {
|
|
843
|
+
if (!this.tooltipOpen) {
|
|
844
|
+
this.updateTooltipContent(false);
|
|
845
|
+
this.tooltipObj.open(element);
|
|
846
|
+
this.tooltipOpen = true;
|
|
847
|
+
} else if (isChange) {
|
|
848
|
+
this.updateTooltipContent(true);
|
|
849
|
+
this.tooltipObj.refresh(element);
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
private closeRatingTooltip(): void {
|
|
855
|
+
if (this.tooltipOpen) {
|
|
856
|
+
this.tooltipObj.close();
|
|
857
|
+
this.tooltipOpen = false;
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
private updateCurrentValue(currValue: number): void {
|
|
862
|
+
this.currentValue = currValue;
|
|
863
|
+
this.updateItemValue();
|
|
864
|
+
this.updateLabel();
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
private mouseLeaveHandler(): void {
|
|
868
|
+
this.closeRatingTooltip();
|
|
869
|
+
this.updateCurrentValue(this.value);
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
private calculateCurrentValue(index: number, args: MouseEventArgs): number {
|
|
873
|
+
let currentValue: number = index;
|
|
874
|
+
if (!(this.enableSingleSelection || (this.precision === PrecisionType.Full))) {
|
|
875
|
+
currentValue = args.offsetX / this.itemElements[index - 1].clientWidth;
|
|
876
|
+
currentValue = (this.enableRtl) ? (1 - currentValue) : currentValue;
|
|
877
|
+
if (this.precision === PrecisionType.Quarter) {
|
|
878
|
+
currentValue = currentValue <= 0.25 ? 0.25 : currentValue <= 0.5 ? 0.5 : currentValue < 0.75 ? 0.75 : 1.0;
|
|
879
|
+
}
|
|
880
|
+
else if (this.precision === PrecisionType.Half) {
|
|
881
|
+
currentValue = currentValue <= 0.5 ? 0.5 : 1;
|
|
882
|
+
}
|
|
883
|
+
currentValue = currentValue + index - 1;
|
|
884
|
+
}
|
|
885
|
+
return currentValue;
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
/**
|
|
889
|
+
* Reset’s the value to minimum.
|
|
890
|
+
*
|
|
891
|
+
* {% codeBlock src='rating/reset/index.md' %}{% endcodeBlock %}
|
|
892
|
+
*
|
|
893
|
+
* @returns {void}
|
|
894
|
+
*/
|
|
895
|
+
public reset(): void {
|
|
896
|
+
this.resetClicked(null, false);
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
private resetClicked(e: Event, isInteracted: boolean = true): void {
|
|
900
|
+
this.updateValueChange(e, this.min, isInteracted);
|
|
901
|
+
this.updateResetButton();
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
private wireKeyboardEvent(): void {
|
|
905
|
+
this.keyboardModuleRating = new KeyboardEvents(this.wrapper, {
|
|
906
|
+
keyAction: this.keyActionHandler.bind(this),
|
|
907
|
+
keyConfigs: this.keyConfigs,
|
|
908
|
+
eventName: 'keydown'
|
|
909
|
+
});
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
private keyActionHandler(e: KeyboardEventArgs): void {
|
|
913
|
+
e.preventDefault();
|
|
914
|
+
if (this.disabled || this.readOnly) { return; }
|
|
915
|
+
if ((e.target as HTMLElement).classList.contains(ITEMLIST)) {
|
|
916
|
+
switch (e.action) {
|
|
917
|
+
case 'uparrow':
|
|
918
|
+
this.handleNavigation(e, true);
|
|
919
|
+
break;
|
|
920
|
+
case 'downarrow':
|
|
921
|
+
this.handleNavigation(e, false);
|
|
922
|
+
break;
|
|
923
|
+
case 'leftarrow':
|
|
924
|
+
this.handleNavigation(e, this.enableRtl);
|
|
925
|
+
break;
|
|
926
|
+
case 'rightarrow':
|
|
927
|
+
this.handleNavigation(e, !this.enableRtl);
|
|
928
|
+
break;
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
if (this.allowReset && (e.target as HTMLElement).classList.contains('e-reset')) {
|
|
932
|
+
switch (e.action) {
|
|
933
|
+
case 'space':
|
|
934
|
+
this.resetClicked(e);
|
|
935
|
+
break;
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
private handleNavigation(e: Event, isIncrease: boolean): void {
|
|
941
|
+
if ((!isIncrease && (this.value > this.min)) || (isIncrease && (this.value < this.itemsCount))) {
|
|
942
|
+
let currentValue: number = (this.precision === PrecisionType.Full || this.enableSingleSelection) ? 1 :
|
|
943
|
+
(this.precision === PrecisionType.Half) ? 0.5 : (this.precision === PrecisionType.Quarter) ? 0.25 :
|
|
944
|
+
Math.round(0.1 * 10) / 10;
|
|
945
|
+
currentValue = isIncrease ? this.value + currentValue : this.value - currentValue;
|
|
946
|
+
this.updateValueChange(e, (currentValue));
|
|
947
|
+
this.updateResetButton();
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
private updateContent(): void {
|
|
952
|
+
for (let i: number = 0; i < this.itemsCount; i++) {
|
|
953
|
+
const itemElement: HTMLElement = this.itemElements[parseInt(i.toString(), 10)].firstElementChild as HTMLElement;
|
|
954
|
+
this.renderItemContent(itemElement, this.getRatingValue(this.value, i), i, true);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
/**
|
|
959
|
+
* To get component name.
|
|
960
|
+
*
|
|
961
|
+
* @returns {string} - Module Name
|
|
962
|
+
* @private
|
|
963
|
+
*/
|
|
964
|
+
public getModuleName(): string {
|
|
965
|
+
return 'rating';
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
/**
|
|
969
|
+
* To get the properties to be maintained in the persisted state.
|
|
970
|
+
*
|
|
971
|
+
* @returns {string} - Persist data
|
|
972
|
+
*/
|
|
973
|
+
protected getPersistData(): string {
|
|
974
|
+
return this.addOnPersist([]);
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
private removeItemElements(): void {
|
|
978
|
+
for (let i: number = 0; i < this.itemElements.length; i++) {
|
|
979
|
+
remove(this.itemElements[parseInt(i.toString(), 10)]);
|
|
980
|
+
}
|
|
981
|
+
this.itemElements = [];
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
/**
|
|
985
|
+
* Destroys the Rating instance.
|
|
986
|
+
*
|
|
987
|
+
* @returns {void}
|
|
988
|
+
*/
|
|
989
|
+
public destroy(): void {
|
|
990
|
+
super.destroy();
|
|
991
|
+
// unwires the events and detach the li elements
|
|
992
|
+
this.removeItemElements();
|
|
993
|
+
this.clearTemplate();
|
|
994
|
+
if (this.spanLabel) {
|
|
995
|
+
remove(this.spanLabel);
|
|
996
|
+
this.spanLabel = null;
|
|
997
|
+
}
|
|
998
|
+
if (this.resetElement) {
|
|
999
|
+
remove(this.resetElement);
|
|
1000
|
+
this.resetElement = null;
|
|
1001
|
+
}
|
|
1002
|
+
if (this.showTooltip) {
|
|
1003
|
+
this.tooltipObj.destroy();
|
|
1004
|
+
this.tooltipObj = null;
|
|
1005
|
+
}
|
|
1006
|
+
remove(this.ratingItemList);
|
|
1007
|
+
this.ratingItemList = null;
|
|
1008
|
+
this.wrapper.parentNode.insertBefore(this.element, this.wrapper);
|
|
1009
|
+
remove(this.wrapper);
|
|
1010
|
+
this.wrapper = null;
|
|
1011
|
+
this.keyboardModuleRating.destroy();
|
|
1012
|
+
this.keyboardModuleRating = null;
|
|
1013
|
+
['value', 'aria-label', 'name'].forEach((attr: string) => {
|
|
1014
|
+
this.element.removeAttribute(attr);
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
/**
|
|
1019
|
+
* Called internally if any of the property value changed.
|
|
1020
|
+
*
|
|
1021
|
+
* @param {RatingModel} newProp - Specifies new properties
|
|
1022
|
+
* @param {RatingModel} oldProp - Specifies old properties
|
|
1023
|
+
* @returns {void}
|
|
1024
|
+
* @private
|
|
1025
|
+
*/
|
|
1026
|
+
public onPropertyChanged(newProp: RatingModel, oldProp?: RatingModel): void {
|
|
1027
|
+
for (const prop of Object.keys(newProp)) {
|
|
1028
|
+
switch (prop) {
|
|
1029
|
+
case 'value':
|
|
1030
|
+
this.updateValueChange(null, (this.value > this.min) ? this.value : this.min, false);
|
|
1031
|
+
break;
|
|
1032
|
+
case 'min':
|
|
1033
|
+
this.updateMinValue();
|
|
1034
|
+
this.updateItemValue();
|
|
1035
|
+
this.updateLabel();
|
|
1036
|
+
break;
|
|
1037
|
+
case 'showLabel':
|
|
1038
|
+
this.displayLabel();
|
|
1039
|
+
break;
|
|
1040
|
+
case 'visible':
|
|
1041
|
+
this.wrapper.classList[!this.visible ? 'add' : 'remove'](HIDDEN);
|
|
1042
|
+
break;
|
|
1043
|
+
case 'disabled':
|
|
1044
|
+
this.updateDisabled();
|
|
1045
|
+
break;
|
|
1046
|
+
case 'readOnly':
|
|
1047
|
+
this.wrapper.classList[this.readOnly ? 'add' : 'remove'](READONLY);
|
|
1048
|
+
break;
|
|
1049
|
+
case 'allowReset':
|
|
1050
|
+
this.updateReset();
|
|
1051
|
+
break;
|
|
1052
|
+
case 'enableRtl':
|
|
1053
|
+
this.wrapper.classList[this.enableRtl ? 'add' : 'remove'](RTL);
|
|
1054
|
+
break;
|
|
1055
|
+
case 'cssClass':
|
|
1056
|
+
if (oldProp.cssClass) {
|
|
1057
|
+
removeClass([this.wrapper], oldProp.cssClass.split(' '));
|
|
1058
|
+
}
|
|
1059
|
+
if (newProp.cssClass) {
|
|
1060
|
+
addClass([this.wrapper], newProp.cssClass.split(' '));
|
|
1061
|
+
}
|
|
1062
|
+
if (this.tooltipObj) {
|
|
1063
|
+
this.tooltipObj.setProperties({ cssClass: this.cssClass ? ('e-rating-tooltip ' + this.cssClass) : 'e-rating-tooltip'});
|
|
1064
|
+
}
|
|
1065
|
+
break;
|
|
1066
|
+
case 'labelPosition':
|
|
1067
|
+
this.updateLabelPosition();
|
|
1068
|
+
break;
|
|
1069
|
+
case 'showTooltip':
|
|
1070
|
+
this.updateTooltip();
|
|
1071
|
+
break;
|
|
1072
|
+
case 'precision':
|
|
1073
|
+
this.updateMinValue();
|
|
1074
|
+
this.triggerChange(null, this.value, false);
|
|
1075
|
+
this.updateItemValue();
|
|
1076
|
+
this.updateLabel();
|
|
1077
|
+
break;
|
|
1078
|
+
case 'enableSingleSelection':
|
|
1079
|
+
//To validate the value against single selection and update the items, label + trigger change event if value changed
|
|
1080
|
+
this.updateValueChange(null, this.currentValue, false);
|
|
1081
|
+
break;
|
|
1082
|
+
case 'enableAnimation':
|
|
1083
|
+
this.wrapper.classList[this.enableAnimation ? 'add' : 'remove'](ANIMATION);
|
|
1084
|
+
break;
|
|
1085
|
+
case 'emptyTemplate':
|
|
1086
|
+
case 'fullTemplate':
|
|
1087
|
+
this.updateTemplateFunction();
|
|
1088
|
+
this.updateContent();
|
|
1089
|
+
break;
|
|
1090
|
+
case 'labelTemplate':
|
|
1091
|
+
this.updateLabel();
|
|
1092
|
+
break;
|
|
1093
|
+
case 'itemsCount':
|
|
1094
|
+
this.removeItemElements();
|
|
1095
|
+
this.renderItems();
|
|
1096
|
+
this.updateLabel();
|
|
1097
|
+
break;
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
}
|