• 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 litSliderButton: HTMLDivElement | undefined | null;
25    private slotEl: HTMLSlotElement | undefined | null;
26    private currentValue: number = 0;
27    private sliderLineHeight: string | undefined;
28    private sliderButtonHeight: string | undefined;
29    private sliderButtonWidth: string | undefined;
30    private defaultTimeText: string | undefined | null;
31
32    static get observedAttributes() {
33        return ['percent', 'disabled-X', 'custom-slider', 'custom-line', 'custom-button']
34    }
35
36    get sliderStyle() {
37        if (this.hasAttribute('custom-slider')) {
38            this.defaultTimeText = "50";
39            return {
40                minRange: 0,
41                maxRange: 1024,
42                defaultValue: this.defaultTimeText,
43                resultUnit: "MB",
44                stepSize: 2,
45                lineColor: "var(--dark-color3,#46B1E3)",
46                buttonColor: "#999999"
47            }
48        } else {
49            let defaultTime = "00:00:50";
50            this.defaultTimeText = defaultTime.split(':')[2];
51            return {
52                minRange: 0,
53                maxRange: 480,
54                defaultValue: defaultTime,
55                resultUnit: "h:m:s",
56                stepSize: 1,
57                lineColor: "var(--dark-color4,#61CFBE)",
58                buttonColor: "#999999"
59            }
60        }
61
62    }
63
64    set sliderStyle(value) {
65        this.litSliderStyle = value;
66        this.litSliderStyle = this.sliderStyle;
67        this.litSliderStyle.defaultValue = value.defaultValue
68        if (this.hasAttribute('custom-slider')) {
69            this.renderCustomSlider();
70        } else {
71            this.renderDefaultSlider();
72        }
73    }
74
75    get disabledX() {
76        return this.getAttribute('disabled-X') || '';
77    }
78
79    set disabledX(value: string) {
80        if (value) {
81            this.setAttribute('disabled-X', '');
82        } else {
83            this.removeAttribute('disabled-X');
84        }
85    }
86
87    get customSlider() {
88        return this.getAttribute('custom-slider') || '';
89    }
90
91    set customSlider(value: string) {
92        if (value) {
93            this.setAttribute('custom-slider', '');
94        } else {
95            this.removeAttribute('custom-slider');
96        }
97    }
98
99    get customLine() {
100        return this.getAttribute('custom-line') || '';
101    }
102
103    set customLine(value: string) {
104        this.setAttribute('custom-line', value);
105    }
106
107    get customButton() {
108        return this.getAttribute('custom-button') || '';
109    }
110
111    set customButton(value: string) {
112        this.setAttribute('custom-button', value);
113    }
114
115    get percent() {
116        return this.getAttribute('percent') || '';
117    }
118
119    set percent(value: string) {
120        this.setAttribute('percent', value);
121    }
122
123    get resultUnit() {
124        return this.getAttribute('resultUnit') || '';
125    }
126
127    set resultUnit(value: string) {
128        this.setAttribute('resultUnit', value);
129    }
130
131    get sliderSize() {
132        return this.currentValue;
133    }
134
135    initElements(): void {
136    }
137
138    initHtml(): string {
139        this.litSliderStyle = this.sliderStyle;
140        this.currentValue = Number(this.sliderStyle.defaultValue);
141        let parentElement = this.parentNode as Element;
142        if (parentElement) {
143            parentElement.setAttribute('percent', this.defaultTimeText + "");
144        }
145        return `
146        <style>
147        :host{
148            box-sizing:border-box;
149            display:flex;
150
151        }
152        :host([disabled]){
153            opacity:0.8;
154            cursor:not-allowed;
155        }
156        :host([disabled]) input[type="range"]{
157            pointer-events:none;
158        }
159        #slider-con{
160            cursor:pointer;
161            display:flex;
162            align-items:center;
163            padding:5px 0;
164            width:80%;
165            margin: 20px;
166            grid-auto-flow: row dense;
167            position: relative;
168        }
169        :host([showtips]){
170            pointer-events:all;
171        }
172
173        #slider{
174            background-color: var(--dark-background7,#D8D8D8);
175            z-index: 5;
176        }
177
178        input[type="range"]{
179            pointer-events:all;
180            margin:0 -5px;
181            width: 100%;
182            -webkit-appearance: none;
183            outline : 0;
184            background: rgba(0,0,0,0.1);
185            height: 10px;
186            border-radius:2px;
187            background: -webkit-linear-gradient(right, ${this.litSliderStyle?.lineColor},${this.litSliderStyle?.lineColor} ) no-repeat;
188            background-size: ${((Number(this.defaultTimeText) - this.litSliderStyle?.minRange) * 100 / (this.litSliderStyle?.maxRange - this.litSliderStyle?.minRange))}%;
189        }
190
191        input[type="range"]::-webkit-slider-runnable-track{
192            display: flex;
193            align-items: center;
194            position: relative;
195            height: ${this.sliderLineHeight ? this.sliderLineHeight : "10px"};
196            border-radius:5px;
197        }
198
199        input[type="range"]::-webkit-slider-thumb{
200            -webkit-appearance: none;
201            /*border:2px solid #42b983;*/
202            position: relative;
203            width:${this.sliderButtonHeight ? this.sliderButtonHeight : "20px"};
204            height:${this.sliderButtonWidth ? this.sliderButtonWidth : "20px"};
205            margin-top: -4px;
206            border-radius: 5px;
207            background:${this.litSliderStyle?.buttonColor};
208            transition:0.2s cubic-bezier(.12, .4, .29, 1.46);
209        }
210
211        input[type="range"]:focus{
212            z-index:2;
213        }
214
215        input[type="range"]::-webkit-slider-thumb:active,
216        input[type="range"]:focus::-webkit-slider-thumb{
217            transform:scale(1.2);
218            border: 2px solid;
219            box-shadow: 0 0 10px rgba(0,0,0,0.1);
220            background: #fff;
221        }
222
223        :host(:focus-within) #slider-con,:host(:hover) #slider-con{
224            z-index:10
225        }
226
227        #result{
228            margin: 10px;
229            width: 196px;
230            height: 40px;
231            background-color: var(--dark-background5,#F2F2F2);
232            -webkit-appearance:none;
233            outline:0;
234            font-size:14px;
235            border-radius:20px;
236            border:1px solid var(--dark-border,#c8cccf);
237            color:var(--dark-color,#6a6f77);
238            text-align: left;
239        }
240
241        #unitSpan{
242            position: absolute;
243            /*width: min-content;*/
244            width: 50px;
245            /*top: -50px;*/
246            right: 0px;
247            color: #adadad;
248            display: table-cell;
249            white-space: nowrap;
250            padding: 7px 10px;
251            font-size:14px;
252        }
253
254        </style>
255        <slot id="slot"></slot>
256        <div id='slider-con' dir="right">
257            <input id="slider"
258                value=${this.defaultTimeText}
259                min=${this.litSliderStyle?.minRange}
260                max=${this.litSliderStyle?.maxRange}
261                step=${this.litSliderStyle?.stepSize}
262                type="range">
263            <input id="result" type="text" value='     ${this.litSliderStyle?.defaultValue}'><span id="unitSpan" >${this.litSliderStyle?.resultUnit}</span>
264        </div>
265        `
266    }
267
268    connectedCallback() {
269        this.slotEl = this.shadowRoot?.querySelector('#slot');
270        this.litSlider = this.shadowRoot?.querySelector('#slider');
271        this.litSliderCon = this.shadowRoot?.querySelector('#slider-con');
272        this.litResult = this.shadowRoot?.querySelector('#result');
273        this.litSlider?.addEventListener('input', this.inputChangeEvent)
274        this.litSlider?.addEventListener('change', this.inputChangeEvent)
275        this.slotEl?.addEventListener('slotchange', this.slotChangeEvent);
276        this.litSlider?.addEventListener('click', this.sliderClickEvent);
277        this.litSliderButton?.addEventListener('TouchEvent', this.sliderStartTouchEvent);
278        this.litSliderStyle = this.sliderStyle;
279    }
280
281    slotChangeEvent = (event: any) => {
282    }
283
284    sliderClickEvent = (event: any) => {
285    }
286
287    inputChangeEvent = (event: any) => {
288        if (this.litSlider) {
289            this.currentValue = parseInt(this.litSlider?.value)
290            let resultNumber = (this.currentValue - this.litSliderStyle!.minRange) * 100 / (this.litSliderStyle!.maxRange - this.litSliderStyle!.minRange);
291            this.percent = Math.floor(resultNumber) + "%";
292            this.litSliderCon?.style.setProperty('percent', this.currentValue + "%")
293            let parentElement = this.parentNode as Element;
294            parentElement.setAttribute('percent', this.currentValue + "");
295            if (this.sliderStyle.resultUnit === 'MB') {
296                this.litSlider!.style.backgroundSize = this.percent;
297                this.litResult!.value = "     " + this.currentValue;
298            } else if (this.sliderStyle.resultUnit === 'h:m:s') {
299                this.litSlider!.style.backgroundSize = this.percent;
300                let time = this.formatSeconds(this.litSlider?.value);
301                this.litResult!.value = "     " + time;
302            }
303        }
304    }
305
306    sliderStartTouchEvent = (event: any) => {
307    }
308
309    sliderMoveTouchEvent = (event: any) => {
310    }
311
312    sliderEndTouchEvent = (event: any) => {
313    }
314
315    disconnectedCallback() {
316        this.litSlider?.removeEventListener('input', this.inputChangeEvent);
317        this.litSlider?.removeEventListener('change', this.inputChangeEvent)
318        this.litSlider?.removeEventListener('click', this.sliderClickEvent);
319        this.litSliderButton?.removeEventListener('TouchEvent', this.sliderStartTouchEvent);
320    }
321
322    attributeChangedCallback(name: string, oldValue: string, newValue: string) {
323        switch (name) {
324            case "percent":
325                if (newValue === null || newValue === "0%") {
326                    let parentElement = this.parentNode as Element;
327                    parentElement?.removeAttribute('percent');
328                } else {
329                    let parentElement = this.parentNode as Element;
330                }
331                break;
332            default:
333                break;
334        }
335    }
336
337    renderCustomSlider() {
338    }
339
340    renderDefaultSlider() {
341        if (!this.litSliderStyle) return;
342    }
343
344    formatSeconds(value: string) {
345        let result = parseInt(value)
346        let hours = Math.floor(result / 3600) < 10 ? '0' + Math.floor(result / 3600) : Math.floor(result / 3600);
347        let minute = Math.floor((result / 60 % 60)) < 10 ? '0' + Math.floor((result / 60 % 60)) : Math.floor((result / 60 % 60));
348        let second = Math.floor((result % 60)) < 10 ? '0' + Math.floor((result % 60)) : Math.floor((result % 60));
349        let resultTime = '';
350        if (hours === '00') {
351            resultTime += `00:`;
352        } else {
353            resultTime += `${hours}:`;
354        }
355        if (minute === '00') {
356            resultTime += `00:`;
357        } else {
358            resultTime += `${minute}:`;
359        }
360        resultTime += `${second}`;
361        return resultTime;
362    }
363}
364
365export interface LitSliderStyle {
366    minRange: number
367    maxRange: number
368    defaultValue: string
369    resultUnit: string
370    stepSize?: number
371    lineColor?: string
372    buttonColor?: string
373}
374
375export interface LitSliderLineStyle {
376    lineWith: number
377    lineHeight: number
378    border?: string
379    borderRadiusValue?: number
380    lineChangeColor?: string
381}
382
383export interface LitSliderButtonStyle {
384    buttonWith: number
385    buttonHeight: number
386    border?: string
387    borderRadiusValue?: number
388    buttonChangeColor?: string
389}
390