| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| import {DomUtils} from "./tobago-utils"; |
| |
| class Stars extends HTMLElement { |
| |
| constructor() { |
| super(); |
| } |
| |
| connectedCallback(): void { |
| const hiddenInput = this.querySelector("input[type=hidden]") as HTMLInputElement; |
| const container = this.querySelector(".tobago-stars-container") as HTMLElement; |
| const tooltip = container.querySelector(".tobago-stars-tooltip") as HTMLElement; |
| const selected = container.querySelector(".tobago-stars-selected") as HTMLElement; |
| const unselected = container.querySelector(".tobago-stars-unselected") as HTMLElement; |
| const preselected = container.querySelector(".tobago-stars-preselected") as HTMLElement; |
| const slider = container.querySelector(".tobago-stars-slider") as HTMLInputElement; |
| |
| const readonly = slider.readOnly; |
| const disabled = slider.disabled; |
| const required = slider.required; |
| |
| const max = parseInt(slider.max); |
| const placeholder = parseInt(slider.placeholder); |
| |
| if (parseInt(slider.min) === 0) { |
| slider.style["left"] = "-" + (100 / max) + "%"; |
| slider.style["width"] = 100 + (100 / max) + "%"; |
| } |
| |
| const currentValue = parseInt(hiddenInput.value); |
| if (currentValue > 0) { |
| const percentValue = 100 * currentValue / max; |
| selected.style["width"] = percentValue + "%"; |
| unselected.style["left"] = percentValue + "%"; |
| unselected.style["width"] = 100 - percentValue + "%"; |
| } else if (placeholder) { |
| selected.classList.add("tobago-placeholder"); |
| const placeholderValue = 100 * placeholder / max; |
| selected.style["width"] = placeholderValue + "%"; |
| unselected.style["left"] = placeholderValue + "%"; |
| unselected.style["width"] = 100 - placeholderValue + "%"; |
| } |
| |
| if (!readonly && !disabled) { |
| /* preselectMode is a Workaround for IE11: fires change event instead of input event */ |
| let preselectMode = false; |
| slider.addEventListener("mousedown", function (event: Event): void { |
| preselectMode = true; |
| }); |
| slider.addEventListener("mouseup", function (event: Event): void { |
| preselectMode = false; |
| selectStars(); |
| }); |
| |
| slider.addEventListener("input", function (event: Event): void { |
| preselectStars(); |
| }); |
| slider.addEventListener("touchend", function (event: Event): void { |
| /* Workaround for mobile devices. TODO: fire AJAX request for 'touchend' */ |
| // slider.trigger("change"); |
| slider.dispatchEvent(new Event("change")); |
| }); |
| slider.addEventListener("change", function (event: Event): void { |
| if (preselectMode) { |
| preselectStars(); |
| } else { |
| selectStars(); |
| } |
| }); |
| |
| slider.addEventListener("touchstart", touchstart); |
| slider.addEventListener("touchmove", touchstart); |
| } |
| |
| // XXX current issue: on ios-Safari select 5 stars and than click on 1 star doesn't work on labeled component. |
| function touchstart(event: TouchEvent): void { |
| /* Workaround for Safari browser on iPhone */ |
| const target = event.currentTarget as HTMLInputElement; |
| const sliderValue = (parseInt(target.max) / target.offsetWidth) |
| * (event.touches[0].pageX - DomUtils.offset(slider).left); |
| if (sliderValue > parseInt(target.max)) { |
| slider.value = target.max; |
| } else if (sliderValue < parseInt(target.min)) { |
| slider.value = target.min; |
| } else { |
| slider.value = String(sliderValue); |
| } |
| preselectStars(); |
| } |
| |
| function preselectStars(): void { |
| tooltip.classList.add("show"); |
| |
| if (parseInt(slider.value) > 0) { |
| tooltip.classList.remove("trash"); |
| tooltip.textContent = (5 * (parseInt(slider.value)) / max).toFixed(2); |
| |
| preselected.classList.add("show"); |
| preselected.style["width"] = (100 * parseInt(slider.value) / max) + "%"; |
| } else { |
| tooltip.textContent = ""; |
| tooltip.classList.add("trash"); |
| |
| if (placeholder) { |
| preselected.classList.add("show"); |
| preselected.style["width"] = (100 * placeholder / max) + "%"; |
| } else { |
| preselected.classList.remove("show"); |
| } |
| } |
| } |
| |
| function selectStars(): void { |
| tooltip.classList.remove("show"); |
| preselected.classList.remove("show"); |
| |
| if (parseInt(slider.value) > 0) { |
| selected.classList.remove("tobago-placeholder"); |
| |
| const percentValue = 100 * parseInt(slider.value) / max; |
| selected.style["width"] = percentValue + "%"; |
| unselected.style["left"] = percentValue + "%"; |
| unselected.style["width"] = 100 - percentValue + "%"; |
| |
| hiddenInput.value = slider.value; |
| } else { |
| if (placeholder) { |
| selected.classList.add("tobago-placeholder"); |
| const placeholderValue = 100 * placeholder / max; |
| selected.style["width"] = placeholderValue + "%"; |
| unselected.style["left"] = placeholderValue + "%"; |
| unselected.style["width"] = 100 - placeholderValue + "%"; |
| } else { |
| selected.classList.remove("tobago-placeholder"); |
| selected.style["width"] = ""; |
| unselected.style["left"] = ""; |
| unselected.style["width"] = ""; |
| } |
| |
| hiddenInput.value = required ? "" : slider.value; |
| } |
| } |
| } |
| } |
| |
| document.addEventListener("DOMContentLoaded", function (event:Event): void { |
| window.customElements.define("tobago-stars", Stars); |
| }); |