Skip to content
Draft
Changes from 1 commit
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
26b5b66
Added Slider Form-control.
rickyosser Aug 27, 2024
523826d
Added demo to input2.php.
rickyosser Aug 27, 2024
f20ffd5
Fixed a bunch of things regarding adding data to the array as well a…
rickyosser Aug 28, 2024
1bd2d1f
Added Slider to demo.
rickyosser Aug 28, 2024
2c80ee3
Code-style fixes.
rickyosser Aug 28, 2024
9305eed
Code-style fixes.
rickyosser Aug 28, 2024
73ded47
Code-style fixes.
rickyosser Aug 28, 2024
a0d5fb0
Added embryo of behat-tests.
rickyosser Aug 28, 2024
1ce3092
Fixed embryo of behat-tests.
rickyosser Aug 28, 2024
02d3e00
Added custom label function. It's not finished.
rickyosser Sep 1, 2024
1320399
Merge branch 'slider_form_controller' of github.com:rickyosser/ui int…
rickyosser Sep 1, 2024
9c54381
Behat changes.
rickyosser Sep 1, 2024
2546f87
Trying to get custom labels to work.
rickyosser Sep 2, 2024
641c54b
Fixed customLabels for slider.
rickyosser Sep 4, 2024
62a001b
Simplification of the code.
rickyosser Sep 4, 2024
91eed9e
Coding style fixes in demo.
rickyosser Sep 4, 2024
27c5895
Coding style fixes in demo.
rickyosser Sep 4, 2024
07790e8
Coding style fixes in demo.
rickyosser Sep 4, 2024
313f118
Coding style fixes in demo.
rickyosser Sep 4, 2024
3718627
Returned to using the array directly with spaces between brackets.
rickyosser Sep 6, 2024
946f736
Merge branch 'atk4:develop' into slider_form_controller
rickyosser Apr 20, 2025
c51fe87
Fixed vertical slider for complex version.
rickyosser Apr 20, 2025
fe4ce8d
Merge branch 'atk4:develop' into slider_form_controller
rickyosser Apr 21, 2025
03dfb2a
Added new layout for Vertical sliders. Fixed demo. Behat still needed…
rickyosser Apr 21, 2025
0c0a7db
Merge branch 'slider_form_controller' of github.com:rickyosser/ui int…
rickyosser Apr 21, 2025
7f5ae5a
Fixed coding-style.
rickyosser Apr 22, 2025
817ddf2
Fixed coding-style.
rickyosser Apr 22, 2025
7f40ad0
Fixed error in demo, checking styles.
rickyosser Apr 22, 2025
99b314e
Fixed coding style, checking coding style.
rickyosser Apr 22, 2025
e853926
Fixed coding style, checking coding style.
rickyosser Apr 22, 2025
5b68c47
Test of define.
rickyosser Apr 22, 2025
48aa458
Test of define.
rickyosser Apr 22, 2025
faa508f
Fixes for StaticAnalysis.
rickyosser Apr 22, 2025
a3d8366
Fixes for StaticAnalysis.
rickyosser Apr 22, 2025
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
215 changes: 215 additions & 0 deletions demos/form-control/Slider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
<?php

declare(strict_types=1);

namespace Atk4\Ui\Form\Control;

use Atk4\Ui\View;
use Atk4\Ui\Js\JsExpression;
use Atk4\Ui\Js\JsFunction;
use Atk4\Ui\Js\JsReload;

class Slider extends Input
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enabled/disabled/readonly demo should be added into demos/form-control/input2.php

and there should be probably a separate demo for Slicer + Behat tests are needed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll get to this in time...

{
public string $inputType = 'hidden';

/** The lowest value the slider can be. */
public int $min = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we limited to integers by something?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I've changed this to float, but then the result is also returned in float.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can easily allow int|float to accept integers over 2^53, the deeper question is if the values are correctly typecasted for attributes (machine data) and UI (for user). To verify this, the easiest test is to use Slider together with field with this https://github.com/atk4/ui/blob/5.2.0/demos/init-db.php#L55 DBAL type - you can use any demo model which use this type for all IDs.


/** The max value the slider can be. */
public int $max = 10;

/** @var float|null The slider step. Set to 0 to disable step. */
public $step = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a question for now - how feasible is histogram below the slider and non-liner steps or even non-numeric values (XS-S-M-L...)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's possible!
According to Fomantic https://fomantic-ui.com/modules/slider.html#custom-interpreted-labels it can be done with:

var labels = ["α", "β", "γ", "δ", "ε", "ζ", "η", "θ", "ι", "κ", "λ", "μ", "ν", "ξ", "ο", "π", "ρ", "σ/ς", "τ", "υ", "φ", "χ", "ψ", "ω"];
$('#interpretedlabel')
  .slider({
    interpretLabel: function(value) {
      return labels[value];
    }
  })
;

As a matter of fact, all the options I've implemented, except this one is directly from Fomantic. I just broke out ticked, bottom align and labeled from the class and made those options. If some of them are funky, yes, I know, they can be removed if we deem the don't add anything. I just added it for completness for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mvorisek, I think I need your help on this one. It seems that the function (interpretLabel) need to be existing before semantic.js (Fomantic-UI) is loaded. I've hacked a version of semantic.js to try this and it indeed added the custom labels then. This is not acceptable though as I know very well, it was just done for test.
I do need help though to add the function first on the page before loading Fomantic-UI. Maybe there is another way but I've already spent to much time on this without any workable solution.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that the function (interpretLabel) need to be existing before semantic.js (Fomantic-UI) is loaded.

That seems weird to me. All user JS is evaluated "after page is fully loaded", so the elements are guaranteed to exists. And you can define a JS function before you setup the FUI slider by JS.

I do not understand the issue you are facing here.. If you need to define global JS code - to deduplicate long JS code - you can put the code in /js/*.js. If you need a small JS code per control, you should always use anonymous JS function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mvorisek I fixed it... Using JsFunction and JsExpression was the way to go but I had trouble with the array but using slice instead of addressing the item directly solved it.


/** The value the slider will start at. */
public int $start = 0;

/** @var int|null The second value to set in case of a range slider. */
public $end = null;

/** @var int|false Makes sure that the two thumbs of a range slider always need to have a difference of the given value. */
public $minRange = false;

/** @var int|false Makes sure that the two thumbs of a range slider don't exceed a difference of the given value. */
public $maxRange = false;

/** @var 'number'|'letter' The type of label to display for a labeled slider. Can be number or letter. */
public $labelType = 'number';

/** @var array|null An array of label values which restrict the displayed labels to only those which are defined. */
public $restrictedLabels = null;

/** Whether a tooltip should be shown to the thumb(s) on hover. Will contain the current slider value. */
public bool $showThumbTooltip = false;

/**
* Tooltip configuration used when showThumbTooltip is true
* Refer to Tooltip Variations for possible values.
*
* @var array|null
*/
public $tooltipConfig = null;

/**
* Show ticks on a labeled slider.
*'always'will always show the ticks for all labels (even if not shown)
* true will display the ticks only if the related label is also shown.
*
* @var 'always'|bool
*/
public $showLabelTicks = false;

/** Define smoothness when the slider is moving. */
public bool $smooth = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this?

Copy link
Contributor Author

@rickyosser rickyosser Aug 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's for the movement of the thumb, if it's in steps between ticks or smooth scrolling.


/** Whether labels should auto adjust on window resize. */
public bool $autoAdjustLabels = true;

/** The distance between labels. */
public int $labelDistance = 100;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When is this helpful? Does this affect CSS only?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but it also defines what labels will be shown, depending on space available.


/** Number of decimals to use with an unstepped slider. */
public int $decimalPlaces = 2;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this helpful vs. step?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

decimalPlaces 2 Number of decimals to use with an unstepped slider
That is from the Fomantic doc, I don't know, just always use step! :)
We can always remove the option in the future.


/** Page up/down multiplier. Define how many more times the steps to take on page up/down press. */
public int $pageMultiplier = 2;

/** Prevents the lower thumb to crossover the thumb handle. */
public bool $preventCrossover = true;

/** Settings for the slider-class */
/** Whether the slider should be ticked or not. */
public bool $ticked = false;

/** Whether the slider should be labeled or not. */
public bool $labeled = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this controlled by something in Input or Control already?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, you are thinking of caption, that's the info "before" the controller, labeled is if the slider should have text at the ticks or not.


/** Whether the ticks and labels should be at the bottom. */
public bool $bottom = false;

/** @var object */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/** @var object */
/** @var View */

at least if general View type is needed

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

must be View not object|View, not only because we do not want to support general object, but also PHPStan will simplify object|View into object only

private $slider;

/** @var object */
private $owner;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

owner is stored in the parent API already

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't find this, do you have an example? I just need to know how to find the parent object.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


/** @var object */
private $firstInput;

/** @var object */
private $secondInput;

#[\Override]
protected function init(): void
{
parent::init();

$this->owner = $this->getOwner();

$this->slider = View::addTo($this->owner)->addClass('ui slider');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


if ($this->end) {
$this->slider->addClass('range');
}

if ($this->ticked) {
$this->slider->addClass('ticked');
}

if ($this->labeled) {
$this->slider->addClass('labeled');
}

if ($this->bottom) {
$this->slider->addClass('bottom aligned');
}

$sliderSettings = [];
$sliderSettings = $sliderSettings + ['min' => $this->min];
$sliderSettings = $sliderSettings + ['max' => $this->max];
if ($this->start) {
$sliderSettings = $sliderSettings + ['start' => $this->start];
}
if ($this->step) {
$sliderSettings = $sliderSettings + ['step' => $this->step];
}
if ($this->end) {
$sliderSettings = $sliderSettings + ['end' => $this->end];
if ($this->minRange) {
$sliderSettings = $sliderSettings + ['minRange' => $this->minRange];
}
if ($this->maxRange) {
$sliderSettings = $sliderSettings + ['maxRange' => $this->maxRange];
}
}
$sliderSettings = $sliderSettings + ['labelType' => $this->labelType];
if ($this->restrictedLabels) {
$sliderSettings = $sliderSettings + ['restrictedLabels' => $this->restrictedLabels];
}
if ($this->showThumbTooltip) {
$sliderSettings = $sliderSettings + ['showThumbTooltip' => $this->showThumbTooltip];
if ($this->tooltipConfig) {
$sliderSettings = $sliderSettings + ['tooltipConfig' => $this->tooltipConfig];
}
}
$sliderSettings = $sliderSettings + ['showLabelTicks' => $this->showLabelTicks];
$sliderSettings = $sliderSettings + ['smooth' => $this->smooth];
$sliderSettings = $sliderSettings + ['autoAdjustLabels' => $this->autoAdjustLabels];
$sliderSettings = $sliderSettings + ['labelDistance' => $this->labelDistance];
$sliderSettings = $sliderSettings + ['decimalPlaces' => $this->decimalPlaces];
$sliderSettings = $sliderSettings + ['pageMultiplier' => $this->pageMultiplier];
$sliderSettings = $sliderSettings + ['decimalPlaces' => $this->decimalPlaces];
$sliderSettings = $sliderSettings + ['preventCrossover' => $this->preventCrossover];

/*
* First input value, always present
*/
$this->firstInput = $this->owner->addControl(
$this->shortName . '_first',
[
Hidden::class
]
)->set($this->start);

$onChange = [
'onChange' => new JsFunction(
['v'],
[
new JsExpression($this->firstInput->js()->find('input')->jsRender().".val($('div#" . $this->slider->getHtmlId() . "').slider('get thumbValue', 'first'))"),
])
];

/*
* Second input value, optional, depending on $this->end
*/
if ($this->end) {
$this->secondInput = $this->owner->addControl(
$this->shortName . '_second',
[
Hidden::class
]
)->set($this->end);

$onChange = [
'onChange' => new JsFunction(
['v'],
[
new JsExpression($this->firstInput->js()->find('input')->jsRender().".val($('div#" . $this->slider->getHtmlId() . "').slider('get thumbValue', 'first'))"),
new JsExpression($this->secondInput->js()->find('input')->jsRender().".val($('div#" . $this->slider->getHtmlId() . "').slider('get thumbValue', 'second'))")
])
];
}
$sliderSettings = $sliderSettings + $onChange;

$this->slider->js(true)->slider(
$sliderSettings,
);
}

#[\Override]
protected function recursiveRender(): void
{
parent::recursiveRender();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#[\Override]
protected function recursiveRender(): void
{
parent::recursiveRender();
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll remove it later, now I'm using it to check variables and classes after render.

}