• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { BaseElement, element } from '../BaseElement.js';
17
18@element('lit-slider')
19export class LitSlider extends BaseElement {
20  private litSliderStyle: LitSliderStyle | undefined | null;
21  private litSlider: HTMLInputElement | undefined | null;
22  private litSliderCon: HTMLDivElement | undefined | null;
23  private litResult: HTMLInputElement | undefined | null;
24  private slotEl: HTMLSlotElement | undefined | null;
25  private currentValue: number = 0;
26  private defaultTimeText: string | undefined | null;
27
28  static get observedAttributes() {
29    return ['percent', 'disabled-X', 'custom-slider', 'custom-line', 'custom-button'];
30  }
31
32  get sliderStyle(): LitSliderStyle {
33    if (this.litSliderStyle) {
34      return this.litSliderStyle;
35    } else {
36      return {
37        minRange: 0,
38        maxRange: 100,
39        defaultValue: '0',
40        resultUnit: '',
41        stepSize: 1,
42        lineColor: 'var(--dark-color3,#46B1E3)',
43        buttonColor: '#999999',
44      };
45    }
46  }
47
48  set sliderStyle(value: LitSliderStyle) {
49    this.litSliderStyle = value;
50    this.currentValue = Number(value.defaultValue);
51    this.litSliderStyle.defaultValue = value.defaultValue;
52    if (this.litSliderStyle.resultUnit === 'h:m:s') {
53      let timeData = this.litSliderStyle.defaultValue.split(':');
54      let timeSize = Number(timeData[0]) * 3600 + Number(timeData[1]) * 60 + Number(timeData[2]);
55      this.defaultTimeText = timeSize.toString();
56      let defaultSize =
57        ((timeSize - this.litSliderStyle.minRange) * 100) /
58        (this.litSliderStyle.maxRange - this.litSliderStyle.minRange);
59      this.litSlider!.style.backgroundSize = defaultSize + '%';
60    } else {
61      this.defaultTimeText = this.litSliderStyle.defaultValue;
62      this.litSlider!.style.backgroundSize = '0%';
63      if (Number(this.litSliderStyle.defaultValue)) {
64        let defaultSize =
65          ((Number(this.litSliderStyle.defaultValue) - this.litSliderStyle.minRange) /
66            (this.litSliderStyle.maxRange - this.litSliderStyle.minRange)) *
67          100;
68        this.litSlider!.style.backgroundSize = defaultSize + '%';
69      }
70    }
71    let htmlInputElement = this.shadowRoot?.querySelector('#slider') as HTMLInputElement;
72    let attribute = htmlInputElement.getAttribute('type');
73    if (attribute === 'range') {
74      htmlInputElement!.setAttribute('value', this.defaultTimeText!);
75      htmlInputElement!.setAttribute('min', this.litSliderStyle!.minRange.toString());
76      htmlInputElement!.setAttribute('max', this.litSliderStyle!.maxRange.toString());
77      htmlInputElement!.setAttribute('step', this.litSliderStyle!.stepSize.toString());
78    }
79  }
80
81  get disabledX() {
82    return this.getAttribute('disabled-X') || '';
83  }
84
85  set disabledX(value: string) {
86    if (value) {
87      this.setAttribute('disabled-X', '');
88    } else {
89      this.removeAttribute('disabled-X');
90    }
91  }
92
93  get customSlider() {
94    return this.getAttribute('custom-slider') || '';
95  }
96
97  set customSlider(value: string) {
98    if (value) {
99      this.setAttribute('custom-slider', '');
100    } else {
101      this.removeAttribute('custom-slider');
102    }
103  }
104
105  get customLine() {
106    return this.getAttribute('custom-line') || '';
107  }
108
109  set customLine(value: string) {
110    this.setAttribute('custom-line', value);
111  }
112
113  get customButton() {
114    return this.getAttribute('custom-button') || '';
115  }
116
117  set customButton(value: string) {
118    this.setAttribute('custom-button', value);
119  }
120
121  get percent() {
122    return this.getAttribute('percent') || '';
123  }
124
125  set percent(value: string) {
126    this.setAttribute('percent', value);
127    let resultNumber =
128      ((Number(value) - this.sliderStyle!.minRange) * 100) / (this.sliderStyle!.maxRange - this.sliderStyle!.minRange);
129    this.litSlider!.style.backgroundSize = resultNumber + '%';
130  }
131
132  get resultUnit() {
133    return this.getAttribute('resultUnit') || '';
134  }
135
136  set resultUnit(value: string) {
137    this.setAttribute('resultUnit', value);
138  }
139
140  initElements(): void {
141    this.litSlider = this.shadowRoot?.querySelector('#slider') as HTMLInputElement;
142  }
143
144  initHtml(): string {
145    return `
146        <style>
147        /*
148         * Outer box style
149         */
150        :host{
151            box-sizing:border-box;
152            display:flex;
153
154        }
155        /*
156         * The mouse is missing
157         */
158        :host([disabled]){
159            opacity:0.8;
160            cursor:not-allowed;
161        }
162        /*
163         * Disable sliding
164         */
165        :host([disabled]) input[type="range"]{
166            pointer-events:none;
167        }
168        /*
169         * Currently the entire sliding container is controlled
170         */
171        #slider-con{
172            cursor:pointer;
173            display:flex;
174            align-items:center;
175            width:95%;
176            grid-auto-flow: row dense;
177            position: relative;
178        }
179        /*
180         * Display prompt information
181         */
182        :host([showtips]){
183            pointer-events:all;
184        }
185
186        #slider{
187            background-color: var(--dark-background7,#D8D8D8);
188            z-index: 5;
189        }
190
191        /*
192         * Slider basic style
193         */
194        input[type="range"]{
195            pointer-events:all;
196            margin:0 -5px;
197            width: 100%;
198            -webkit-appearance: none;
199            outline : 0;
200            background: rgba(0,0,0,0.1);
201            height: 10px;
202            border-radius:2px;
203            background: -webkit-linear-gradient(right, ${
204              this.getAttribute('defaultColor') ? this.getAttribute('defaultColor') : '#46B1E3'
205            }, ${this.getAttribute('defaultColor') ? this.getAttribute('defaultColor') : '#46B1E3'}) no-repeat;
206        }
207
208        /*
209         * Slider-line slidedAble area component
210         */
211        input[type="range"]::-webkit-slider-runnable-track{
212            display: flex;
213            align-items: center;
214            position: relative;
215            height: 10px;
216            border-radius:5px;
217        }
218
219         /*
220         * Slider slider component
221         */
222        input[type="range"]::-webkit-slider-thumb{
223            -webkit-appearance: none;
224            position: relative;
225            width:20px;
226            height:20px;
227            margin-top: -4px;
228            border-radius: 5px;
229            background:#999999;
230            transition:0.2s cubic-bezier(.12, .4, .29, 1.46);
231        }
232
233        input[type="range"]:focus{
234            z-index:2;
235        }
236
237        :host(:focus-within) #slider-con,:host(:hover) #slider-con{
238            z-index:10
239        }
240
241        </style>
242        <slot id="slot"></slot>
243        <div id='slider-con' dir="right">
244            <input id="slider" type="range" max="10000000">
245        </div>
246        `;
247  }
248
249  // It is called when the custom element is first inserted into the document DOM.
250  connectedCallback() {
251    this.slotEl = this.shadowRoot?.querySelector('#slot');
252    this.litSliderCon = this.shadowRoot?.querySelector('#slider-con');
253    // Add a slider for input event listeners
254    this.litSlider?.addEventListener('input', this.inputChangeEvent);
255    this.litSlider?.addEventListener('change', this.inputChangeEvent);
256    this.litSliderStyle = this.sliderStyle;
257  }
258
259  inputChangeEvent = (event: any) => {
260    if (this.litSlider) {
261      this.currentValue = parseInt(this.litSlider?.value);
262      let resultNumber =
263        ((this.currentValue - this.litSliderStyle!.minRange) * 100) /
264        (this.litSliderStyle!.maxRange - this.litSliderStyle!.minRange);
265      this.percent = Number(resultNumber) + '%';
266      this.litSliderCon?.style.setProperty('percent', this.currentValue + '%');
267      let parentElement = this.parentNode as Element;
268      parentElement.setAttribute('percent', this.currentValue + '');
269      if (this.sliderStyle.resultUnit === 'h:m:s') {
270        this.litSlider!.style.backgroundSize = this.percent;
271      } else {
272        this.litSlider!.style.backgroundSize = this.percent;
273      }
274      this.parentElement!.setAttribute('percent', this.litSlider?.value);
275    }
276  };
277
278  disconnectedCallback() {
279    this.litSlider?.removeEventListener('input', this.inputChangeEvent);
280    this.litSlider?.removeEventListener('change', this.inputChangeEvent);
281  }
282
283  adoptedCallback() {}
284
285  attributeChangedCallback(name: string, oldValue: string, newValue: string) {
286    switch (name) {
287      case 'percent':
288        if (newValue === null || newValue === '0%') {
289          let parentElement = this.parentNode as Element;
290          parentElement?.removeAttribute('percent');
291        } else {
292          let parentElement = this.parentNode as Element;
293        }
294        break;
295      default:
296        break;
297    }
298  }
299
300  formatSeconds(value: string) {
301    let result = parseInt(value);
302    let hours = Math.floor(result / 3600) < 10 ? '0' + Math.floor(result / 3600) : Math.floor(result / 3600);
303    let minute =
304      Math.floor((result / 60) % 60) < 10 ? '0' + Math.floor((result / 60) % 60) : Math.floor((result / 60) % 60);
305    let second = Math.floor(result % 60) < 10 ? '0' + Math.floor(result % 60) : Math.floor(result % 60);
306    let resultTime = '';
307    if (hours === '00') {
308      resultTime += `00:`;
309    } else {
310      resultTime += `${hours}:`;
311    }
312    if (minute === '00') {
313      resultTime += `00:`;
314    } else {
315      resultTime += `${minute}:`;
316    }
317    resultTime += `${second}`;
318    return resultTime;
319  }
320}
321
322export interface LitSliderStyle {
323  minRange: number;
324  maxRange: number;
325  defaultValue: string;
326  resultUnit: string;
327  stepSize: number;
328  lineColor?: string;
329  buttonColor?: string;
330}
331
332export interface LitSliderLineStyle {
333  lineWith: number;
334  lineHeight: number;
335  border?: string;
336  borderRadiusValue?: number;
337  lineChangeColor?: string;
338}
339
340export interface LitSliderButtonStyle {
341  buttonWith: number;
342  buttonHeight: number;
343  border?: string;
344  borderRadiusValue?: number;
345  buttonChangeColor?: string;
346}
347