• 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 = (timeSize - this.litSliderStyle.minRange) * 100 / (this.litSliderStyle
57                .maxRange - this.litSliderStyle.minRange);
58            this.litSlider!.style.backgroundSize = defaultSize + '%'
59        } else {
60            this.defaultTimeText = this.litSliderStyle.defaultValue
61            this.litSlider!.style.backgroundSize = '0%'
62            if (Number(this.litSliderStyle.defaultValue)) {
63                let defaultSize = (Number(this.litSliderStyle.defaultValue) - this.litSliderStyle.minRange)
64                    / (this.litSliderStyle.maxRange - this.litSliderStyle.minRange) * 100;
65                this.litSlider!.style.backgroundSize = defaultSize + '%'
66            }
67        }
68        let htmlInputElement = this.shadowRoot?.querySelector('#slider') as HTMLInputElement;
69        let attribute = htmlInputElement.getAttribute('type');
70        if (attribute === 'range') {
71            htmlInputElement!.setAttribute('value', this.defaultTimeText!)
72            htmlInputElement!.setAttribute('min', this.litSliderStyle!.minRange.toString())
73            htmlInputElement!.setAttribute('max', this.litSliderStyle!.maxRange.toString())
74            htmlInputElement!.setAttribute('step', this.litSliderStyle!.stepSize.toString())
75        }
76    }
77
78    get disabledX() {
79        return this.getAttribute('disabled-X') || '';
80    }
81
82    set disabledX(value: string) {
83        if (value) {
84            this.setAttribute('disabled-X', '');
85        } else {
86            this.removeAttribute('disabled-X');
87        }
88    }
89
90    get customSlider() {
91        return this.getAttribute('custom-slider') || '';
92    }
93
94    set customSlider(value: string) {
95        if (value) {
96            this.setAttribute('custom-slider', '');
97        } else {
98            this.removeAttribute('custom-slider');
99        }
100    }
101
102    get customLine() {
103        return this.getAttribute('custom-line') || '';
104    }
105
106    set customLine(value: string) {
107        this.setAttribute('custom-line', value);
108    }
109
110    get customButton() {
111        return this.getAttribute('custom-button') || '';
112    }
113
114    set customButton(value: string) {
115        this.setAttribute('custom-button', value);
116    }
117
118    get percent() {
119        return this.getAttribute('percent') || '';
120    }
121
122    set percent(value: string) {
123        this.setAttribute('percent', value);
124        let resultNumber = (Number(value) - this.sliderStyle!.minRange) * 100 / (this.sliderStyle!.maxRange - this.sliderStyle!.minRange);
125        this.litSlider!.style.backgroundSize = resultNumber + '%';
126    }
127
128    get resultUnit() {
129        return this.getAttribute('resultUnit') || '';
130    }
131
132    set resultUnit(value: string) {
133        this.setAttribute('resultUnit', value);
134    }
135
136    initElements(): void {
137        this.litSlider = this.shadowRoot?.querySelector('#slider') as HTMLInputElement;
138    }
139
140    initHtml(): string {
141        return `
142        <style>
143        /*
144         * Outer box style
145         */
146        :host{
147            box-sizing:border-box;
148            display:flex;
149
150        }
151        /*
152         * The mouse is missing
153         */
154        :host([disabled]){
155            opacity:0.8;
156            cursor:not-allowed;
157        }
158        /*
159         * Disable sliding
160         */
161        :host([disabled]) input[type="range"]{
162            pointer-events:none;
163        }
164        /*
165         * Currently the entire sliding container is controlled
166         */
167        #slider-con{
168            cursor:pointer;
169            display:flex;
170            align-items:center;
171            width:95%;
172            grid-auto-flow: row dense;
173            position: relative;
174        }
175        /*
176         * Display prompt information
177         */
178        :host([showtips]){
179            pointer-events:all;
180        }
181
182        #slider{
183            background-color: var(--dark-background7,#D8D8D8);
184            z-index: 5;
185        }
186
187        /*
188         * Slider basic style
189         */
190        input[type="range"]{
191            pointer-events:all;
192            margin:0 -5px;
193            width: 100%;
194            -webkit-appearance: none;
195            outline : 0;
196            background: rgba(0,0,0,0.1);
197            height: 10px;
198            border-radius:2px;
199            background: -webkit-linear-gradient(right, ${this
200            .getAttribute('defaultColor') ? this
201            .getAttribute('defaultColor') : '#46B1E3'}, ${this
202            .getAttribute('defaultColor') ? this
203            .getAttribute('defaultColor') : '#46B1E3'}) no-repeat;
204        }
205
206        /*
207         * Slider-line slidedAble area component
208         */
209        input[type="range"]::-webkit-slider-runnable-track{
210            display: flex;
211            align-items: center;
212            position: relative;
213            height: 10px;
214            border-radius:5px;
215        }
216
217         /*
218         * Slider slider component
219         */
220        input[type="range"]::-webkit-slider-thumb{
221            -webkit-appearance: none;
222            position: relative;
223            width:20px;
224            height:20px;
225            margin-top: -4px;
226            border-radius: 5px;
227            background:#999999;
228            transition:0.2s cubic-bezier(.12, .4, .29, 1.46);
229        }
230
231        input[type="range"]:focus{
232            z-index:2;
233        }
234
235        :host(:focus-within) #slider-con,:host(:hover) #slider-con{
236            z-index:10
237        }
238
239        </style>
240        <slot id="slot"></slot>
241        <div id='slider-con' dir="right">
242            <input id="slider" type="range" max="10000000">
243        </div>
244        `
245    }
246
247    // It is called when the custom element is first inserted into the document DOM.
248    connectedCallback() {
249        this.slotEl = this.shadowRoot?.querySelector('#slot');
250        this.litSliderCon = this.shadowRoot?.querySelector('#slider-con');
251        // Add a slider for input event listeners
252        this.litSlider?.addEventListener('input', this.inputChangeEvent)
253        this.litSlider?.addEventListener('change', this.inputChangeEvent)
254        this.litSliderStyle = this.sliderStyle;
255
256    }
257
258    inputChangeEvent = (event: any) => {
259        if (this.litSlider) {
260            this.currentValue = parseInt(this.litSlider?.value)
261            let resultNumber = (this.currentValue - this.litSliderStyle!.minRange) * 100 / (this
262                .litSliderStyle!.maxRange - this.litSliderStyle!.minRange);
263            this.percent = Number(resultNumber) + "%";
264            this.litSliderCon?.style.setProperty('percent', this.currentValue + "%")
265            let parentElement = this.parentNode as Element;
266            parentElement.setAttribute('percent', this.currentValue + "");
267            if (this.sliderStyle.resultUnit === 'h:m:s') {
268                this.litSlider!.style.backgroundSize = this.percent;
269            } else {
270                this.litSlider!.style.backgroundSize = this.percent;
271            }
272            this.parentElement!.setAttribute('percent', this.litSlider?.value)
273        }
274    }
275
276    disconnectedCallback() {
277        this.litSlider?.removeEventListener('input', this.inputChangeEvent);
278        this.litSlider?.removeEventListener('change', this.inputChangeEvent)
279    }
280
281    adoptedCallback() {
282    }
283
284    attributeChangedCallback(name: string, oldValue: string, newValue: string) {
285        switch (name) {
286            case "percent":
287                if (newValue === null || newValue === "0%") {
288                    let parentElement = this.parentNode as Element;
289                    parentElement?.removeAttribute('percent');
290                } else {
291                    let parentElement = this.parentNode as Element;
292                }
293                break;
294            default:
295                break;
296        }
297    }
298
299    renderDefaultSlider() {
300        let htmlInputElement = this.shadowRoot?.querySelector('#slider') as HTMLInputElement;
301        let attribute = htmlInputElement.getAttribute('type');
302        if (attribute === 'range') {
303            htmlInputElement!.setAttribute('value', this.defaultTimeText!)
304            htmlInputElement!.setAttribute('min', this.litSliderStyle!.minRange.toString())
305            htmlInputElement!.setAttribute('max', this.litSliderStyle!.maxRange.toString())
306            htmlInputElement!.setAttribute('step', this.litSliderStyle!.stepSize.toString())
307        }
308    }
309
310    formatSeconds(value: string) {
311        let result = parseInt(value)
312        let hours = Math.floor(result / 3600) < 10 ? '0' + Math.floor(result / 3600) : Math
313            .floor(result / 3600);
314        let minute = Math.floor((result / 60 % 60)) < 10 ? '0' + Math
315            .floor((result / 60 % 60)) : Math.floor((result / 60 % 60));
316        let second = Math.floor((result % 60)) < 10 ? '0' + Math.floor((result % 60)) : Math.floor((result % 60));
317        let resultTime = '';
318        if (hours === '00') {
319            resultTime += `00:`;
320        } else {
321            resultTime += `${hours}:`;
322        }
323        if (minute === '00') {
324            resultTime += `00:`;
325        } else {
326            resultTime += `${minute}:`;
327        }
328        resultTime += `${second}`;
329        return resultTime;
330    }
331}
332
333export interface LitSliderStyle {
334    minRange: number
335    maxRange: number
336    defaultValue: string
337    resultUnit: string
338    stepSize: number
339    lineColor?: string
340    buttonColor?: string
341}
342
343export interface LitSliderLineStyle {
344    lineWith: number
345    lineHeight: number
346    border?: string
347    borderRadiusValue?: number
348    lineChangeColor?: string
349}
350
351export interface LitSliderButtonStyle {
352    buttonWith: number
353    buttonHeight: number
354    border?: string
355    borderRadiusValue?: number
356    buttonChangeColor?: string
357}
358