Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slider styling #146

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions assets/slider.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
Slider styling css after Márk Munkácsi.
This was public on codepen, so it is MIT: https://blog.codepen.io/documentation/licensing/
See https://dev.to/munkacsimark/styled-range-input-a-way-out-of-range-input-nightmare-jeo ,
also for explanations.
*/

/*
These variables configures the appearance of the slider.

Two modifications wrt. to the orginal (citation above):

- colors modifid in order to work better with white background.
- added variable `--width`
*/
input[type="range"] {
--thumbSize: 15px;
--trackSize: 8px;
--thumbBg: #ddd;
--trackBg: #ccc;
--progressBg: #888;
--width: 13%;
/* webkit progress workaround */
--webkitProgressPercent: 0%;
}

input[type="range"] {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
height: var(--thumbSize);
width: var(--width);
margin: 0;
padding: 0;
}

input[type="range"]:focus {
outline: none;
}

/* Thumb */
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: var(--thumbSize);
height: var(--thumbSize);
background-color: var(--thumbBg);
border-radius: calc(var(--thumbSize) / 2);
border: none;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
margin-top: calc(((var(--thumbSize) - var(--trackSize)) / 2) * -1);
cursor: pointer;
}
input[type="range"]::-moz-range-thumb {
-moz-appearance: none;
appearance: none;
width: var(--thumbSize);
height: var(--thumbSize);
background-color: var(--thumbBg);
border-radius: calc(var(--thumbSize) / 2);
border: none;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
margin-top: calc(((var(--thumbSize) - var(--trackSize)) / 2) * -1);
cursor: pointer;
}
input[type="range"]::-ms-thumb {
-ms-appearance: none;
appearance: none;
width: var(--thumbSize);
height: var(--thumbSize);
background-color: var(--thumbBg);
border-radius: calc(var(--thumbSize) / 2);
border: none;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
margin-top: calc(((var(--thumbSize) - var(--trackSize)) / 2) * -1);
cursor: pointer;
}

/* Track */
input[type="range"]::-webkit-slider-runnable-track {
height: var(--trackSize);
background-image: linear-gradient(
90deg,
var(--progressBg) var(--webkitProgressPercent),
var(--trackBg) var(--webkitProgressPercent)
);
border-radius: calc(var(--trackSize) / 2);
}
input[type="range"]::-moz-range-track {
height: var(--trackSize);
background-color: var(--trackBg);
border-radius: calc(var(--trackSize) / 2);
}
input[type="range"]::-ms-track {
height: var(--trackSize);
background-color: var(--trackBg);
border-radius: calc(var(--trackSize) / 2);
}

/* Progress */
input[type="range"]::-moz-range-progress {
height: var(--trackSize);
background-color: var(--progressBg);
border-radius: calc(var(--trackSize) / 2) 0 0 calc(var(--trackSize) / 2);
}
input[type="range"]::-ms-fill-lower {
height: var(--trackSize);
background-color: var(--progressBg);
border-radius: calc(var(--trackSize) / 2) 0 0 calc(var(--trackSize) / 2);
}
53 changes: 53 additions & 0 deletions assets/slider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
Slider styling javascript after Márk Munkácsi.
This was public on codepen, so it is MIT: https://blog.codepen.io/documentation/licensing/
See https://dev.to/munkacsimark/styled-range-input-a-way-out-of-range-input-nightmare-jeo ,
also for explanations.


The javascript is used to set the progress bar.
*/

// Unmodified from the original (see above)
const handleInput = (inputElement) => {
let isChanging = false;

const setCSSProperty = () => {
const percent =
((inputElement.value - inputElement.min) /
(inputElement.max - inputElement.min)) *
100;
// Here comes the magic 🦄🌈
inputElement.style.setProperty("--webkitProgressPercent", `${percent}%`);
}

// Set event listeners
const handleMove = () => {
if (!isChanging) return;
setCSSProperty();
};
const handleUpAndLeave = () => isChanging = false;
const handleDown = () => isChanging = true;

inputElement.addEventListener("mousemove", handleMove);
inputElement.addEventListener("mousedown", handleDown);
inputElement.addEventListener("mouseup", handleUpAndLeave);
inputElement.addEventListener("mouseleave", handleUpAndLeave);
inputElement.addEventListener("click", setCSSProperty);

// Init input
setCSSProperty();
}


// This was the original code which would affect all sliders at once:

// const inputElements = document.querySelectorAll('[type="range"]');
// inputElements.forEach(handleInput)


// Modification for handle only the currenly created slider in pluto.
// need to go two elements back because of the <output> follwing
// directly the <input>
const slider = (currentScript ?? this.currentScript).previousElementSibling.previousElementSibling
handleInput(slider)
11 changes: 9 additions & 2 deletions src/Builtins.jl
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ begin
"""
Slider(range::AbstractRange; default=missing, show_value=false) = Slider(range, (default === missing) ? first(range) : default, show_value)

const slider_js = HypertextLiteral.JavaScript(read(joinpath(@__DIR__, "..", "assets", "slider.js"), String))
const slider_css = read(joinpath(@__DIR__, "..", "assets", "slider.css"), String)

function Base.show(io::IO, m::MIME"text/html", slider::Slider)
show(io, m, @htl("""
<input
Expand All @@ -86,11 +89,15 @@ begin
value=$(slider.default)
oninput=$(slider.show_value ? "this.nextElementSibling.value=this.value" : "")
>

$(
slider.show_value ? @htl("<output>$(slider.default)</output>") : nothing
)

<script>
$slider_js
</script>
<style>
$(slider_css)
</style>
"""))
end

Expand Down