diff --git a/core/modules/widgets/range.js b/core/modules/widgets/range.js index 46e12061a..4dd55dc3c 100644 --- a/core/modules/widgets/range.js +++ b/core/modules/widgets/range.js @@ -52,8 +52,10 @@ RangeWidget.prototype.render = function(parent,nextSibling) { this.inputDomNode.value = this.getValue(); // Add a click event handler $tw.utils.addEventListeners(this.inputDomNode,[ - {name: "input", handlerObject: this, handlerMethod: "handleInputEvent"}, - {name: "change", handlerObject: this, handlerMethod: "handleInputEvent"} + {name:"mousedown", handlerObject:this, handlerMethod:"handleMouseDownEvent"}, + {name:"mouseup", handlerObject:this, handlerMethod:"handleMouseUpEvent"}, + {name:"change", handlerObject:this, handlerMethod:"handleChangeEvent"}, + {name:"input", handlerObject:this, handlerMethod:"handleInputEvent"}, ]); // Insert the label into the DOM and render any children parent.insertBefore(this.inputDomNode,nextSibling); @@ -62,23 +64,77 @@ RangeWidget.prototype.render = function(parent,nextSibling) { RangeWidget.prototype.getValue = function() { var tiddler = this.wiki.getTiddler(this.tiddlerTitle), - fieldName = this.tiddlerField || "text", - value = this.defaultValue; + fieldName = this.tiddlerField, + value = this.defaultValue; if(tiddler) { if(this.tiddlerIndex) { - value = this.wiki.extractTiddlerDataItem(tiddler,this.tiddlerIndex,this.defaultValue || ""); + value = this.wiki.extractTiddlerDataItem(tiddler,this.tiddlerIndex,this.defaultValue); } else { if($tw.utils.hop(tiddler.fields,fieldName)) { value = tiddler.fields[fieldName] || ""; } else { - value = this.defaultValue || ""; + value = this.defaultValue; } } } return value; }; +RangeWidget.prototype.getActionVariables = function(options) { + options = options || {}; + var hasChanged = (this.startValue !== this.inputDomNode.value) ? "yes" : "no"; + // Trigger actions. Use variables = {key:value, key:value ...} + // the "value" is needed. + return $tw.utils.extend({"actionValue": this.inputDomNode.value, "actionValueHasChanged": hasChanged}, options); +} + +// actionsStart +RangeWidget.prototype.handleMouseDownEvent = function(event) { + this.mouseDown = true; // TODO remove once IE is gone. + this.startValue = this.inputDomNode.value; // TODO remove this line once IE is gone! + this.handleEvent(event); + // Trigger actions + if(this.actionsMouseDown) { + var variables = this.getActionVariables() // TODO this line will go into the function call below. + this.invokeActionString(this.actionsMouseDown,this,event,variables); + } +} + +// actionsStop +RangeWidget.prototype.handleMouseUpEvent = function(event) { + this.mouseDown = false; // TODO remove once IE is gone. + this.handleEvent(event); + // Trigger actions + if(this.actionsMouseUp) { + var variables = this.getActionVariables() + this.invokeActionString(this.actionsMouseUp,this,event,variables); + } + // TODO remove the following if() once IE is gone! + if ($tw.browser.isIE) { + if (this.startValue !== this.inputDomNode.value) { + this.handleChangeEvent(event); + this.startValue = this.inputDomNode.value; + } + } +} + +RangeWidget.prototype.handleChangeEvent = function(event) { + if (this.mouseDown) { // TODO refactor this function once IE is gone. + this.handleInputEvent(event); + } +}; + RangeWidget.prototype.handleInputEvent = function(event) { + this.handleEvent(event); + // Trigger actions + if(this.actionsInput) { + // "tiddler" parameter may be missing. See .execute() below + var variables = this.getActionVariables({"actionValueHasChanged": "yes"}) // TODO this line will go into the function call below. + this.invokeActionString(this.actionsInput,this,event,variables); + } +}; + +RangeWidget.prototype.handleEvent = function(event) { if(this.getValue() !== this.inputDomNode.value) { if(this.tiddlerIndex) { this.wiki.setText(this.tiddlerTitle,"",this.tiddlerIndex,this.inputDomNode.value); @@ -92,16 +148,24 @@ RangeWidget.prototype.handleInputEvent = function(event) { Compute the internal state of the widget */ RangeWidget.prototype.execute = function() { + // TODO remove the next 1 lines once IE is gone! + this.mouseUp = true; // Needed for IE10 // Get the parameters from the attributes this.tiddlerTitle = this.getAttribute("tiddler",this.getVariable("currentTiddler")); - this.tiddlerField = this.getAttribute("field"); + this.tiddlerField = this.getAttribute("field","text"); this.tiddlerIndex = this.getAttribute("index"); this.minValue = this.getAttribute("min"); this.maxValue = this.getAttribute("max"); this.increment = this.getAttribute("increment"); - this.defaultValue = this.getAttribute("default"); + this.defaultValue = this.getAttribute("default",""); this.elementClass = this.getAttribute("class",""); this.isDisabled = this.getAttribute("disabled","no"); + // Actions since 5.1.23 + // Next 2 only fire once! + this.actionsMouseDown = this.getAttribute("actionsStart",""); + this.actionsMouseUp = this.getAttribute("actionsStop",""); + // Input fires very often! + this.actionsInput = this.getAttribute("actions",""); // Make the child widgets this.makeChildWidgets(); }; @@ -111,7 +175,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of */ RangeWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); - if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes['min'] || changedAttributes['max'] || changedAttributes['increment'] || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.disabled) { + if($tw.utils.count(changedAttributes) > 0) { this.refreshSelf(); return true; } else { @@ -119,7 +183,7 @@ RangeWidget.prototype.refresh = function(changedTiddlers) { if(changedTiddlers[this.tiddlerTitle]) { var value = this.getValue(); if(this.inputDomNode.value !== value) { - this.inputDomNode.value = value; + this.inputDomNode.value = value; } refreshed = true; } diff --git a/editions/tw5.com/tiddlers/widgets/RangeWidget Example.tid b/editions/tw5.com/tiddlers/widgets/RangeWidget Example.tid new file mode 100644 index 000000000..822313374 --- /dev/null +++ b/editions/tw5.com/tiddlers/widgets/RangeWidget Example.tid @@ -0,0 +1,54 @@ +created: 20201130191618831 +modified: 20201130194441670 +tags: RangeWidget +title: RangeWidget Example +type: text/vnd.tiddlywiki + +\define getText() $(text)$ - value: $(value)$ - changed: $(actionValueHasChanged)$ + +\define range-log(text:"", value:"", tiddler:"$:/temp/range/log") +<$vars text="""$text$""" value="""$value$""" > +<$action-setfield $tiddler="""$tiddler$""" $index=<> $value=<>/> + +\end + +\define clear-range-log(tiddler:"$:/temp/range/log") +<$action-setfield $tiddler="""$tiddler$""" text="{}" show=show/> +\end + +\define logTiddler()$:/temp/range/log + +\define clearLogButton()<$button actions=<>>Clear Log + +\define actionsStop() +<$macrocall $name="range-log" text=" actionsStop" value=<> /> +\end + +\define actionsStart() +<$macrocall $name="range-log" text=" actionsStart" value=<> /> +\end + +\define actions() +<$macrocall $name="range-log" text="actions" value=<> /> +\end + +!! Using Actions + +<$range tiddler="$:/temp/range/1__" min="-1" max="10" default="1" increment="1" + actionsStart=<> actionsStop=<> actions=<>/> {{$:/temp/range/1__}} + +<$range tiddler="$:/temp/range/__2" min="0" max="1" default=".01" increment=".01" + actionsStart=<> actionsStop=<> actions=<> /> {{$:/temp/range/__2}} + +<$checkbox tiddler=<> field="show" checked="show" unchecked="hide"> Show log <> + +<$reveal stateTitle=<> stateField="show" type="match" text="show"> +<$transclude tiddler=<> /> + + +--- + +
+ Show the code [[RangeWidget Example]] +
<$view mode=text&>

+
diff --git a/editions/tw5.com/tiddlers/widgets/RangeWidget.tid b/editions/tw5.com/tiddlers/widgets/RangeWidget.tid index bcabe646c..195b32fec 100644 --- a/editions/tw5.com/tiddlers/widgets/RangeWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/RangeWidget.tid @@ -1,6 +1,6 @@ caption: range created: 20171102134825376 -modified: 20201109091723430 +modified: 20201130193635857 tags: Widgets title: RangeWidget type: text/vnd.tiddlywiki @@ -22,6 +22,9 @@ The content of the `<$range>` widget is ignored. |increment |The minimum amount by which a value may be changed. Defaults to 1 | |default |If the field is missing or empty this is the default position for the widget handle relative to the min and max values.| |class |CSS classes to be assigned to the label around the range slider | +|actions|<<.from-version "5.1.23">> Optional, A string containing ActionWidgets to be triggered when the value changes.
The variable: ''actionValue'' is available for ''all'' actions.
The variable: ''actionValueHasChanged'' is always `yes` here.| +|actionsStart|<<.from-version "5.1.23">> Optional, A string containing ~ActionWidgets to be triggered when the "handle" is ''clicked''.
The variable: ''actionValueHasChanged'' is always `no` here.| +|actionsStop|<<.from-version "5.1.23">> Optional, A string containing ~ActionWidgets to be triggered when the "handle" is ''released''.
The variable: ''actionValueHasChanged'' is `yes`, ''if'' the new-value is different to the start-value | |disabled|<<.from-version "5.1.23">> Optional, disables the range input if set to "yes". Defaults to "no"| ! Examples @@ -36,3 +39,5 @@ src="""<$range tiddler="$:/_RangeDemo/1" min="-1" max="10" default="1" increment <$macrocall $name='wikitext-example-without-html' src="""<$range tiddler="$:/_RangeDemo/2" min="0" max="1" default=".01" increment=".01"/> {{$:/_RangeDemo/2}}"""/> + +{{RangeWidget Example}} \ No newline at end of file