Skip to content

Commit

Permalink
New: use native slider instead of rangeslider (fixes adaptlearning#161)
Browse files Browse the repository at this point in the history
  • Loading branch information
chris-steele authored Feb 22, 2023
1 parent 0a6ba0f commit 2c524f5
Show file tree
Hide file tree
Showing 9 changed files with 278 additions and 1,023 deletions.
12 changes: 5 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

To respond to the question, the learner positions a slider along a scale. Upon submission, feedback is provided via the [**Tutor** extension](https://github.com/adaptlearning/adapt-contrib-tutor), if installed. Feedback can be provided for correct, incorrect and partially correct answers. The number of attempts allowed may be configured.

The component uses [rangeslider.js (v2.3.1)](http://rangeslider.js.org/), a library that provides a polyfill for browsers that do not have support for the 'range' input type. rangeslider.js carries the MIT license compatible with Adapt.

[Visit the **Slider** wiki](https://github.com/adaptlearning/adapt-contrib-slider/wiki) for more information about its functionality and for explanations of key properties.

## Installation
Expand Down Expand Up @@ -80,7 +78,7 @@ guide the learner’s interaction with the component.
**\_showNumber** (boolean): When set to `true`, a numeric value appears on the marker described in **\_showScaleIndicator**. The value indicates the slider's position on the scale. The default is `true`. Note that **\_showScaleIndicator** must be set to `true` in order for this to work.

**\_showScaleIndicator** (boolean): Set to `true`, a marker for the position of the slider along the scale is shown. If **\_showNumber** is `true` this marker will contain a numeric value. If **\_showNumber** is `false` a blank marker is shown.
**\_showScaleIndicator** (boolean): Set to `true`, a marker for the position of the slider along the scale is shown. If **\_showNumber** is `true` this marker will contain a numeric value. If **\_showNumber** is `false` a blank marker is shown. The default is `true`.

**\_showScale** (boolean): When set to `false`, visual indications of the scale—range of numbers and short rules—are not displayed. The default is `true`.

Expand Down Expand Up @@ -113,7 +111,7 @@ No known limitations.

----------------------------
<a href="https://community.adaptlearning.org/" target="_blank"><img src="https://github.com/adaptlearning/documentation/blob/master/04_wiki_assets/plug-ins/images/adapt-logo-mrgn-lft.jpg" alt="adapt learning logo" align="right"></a>
**Author / maintainer:** Adapt Core Team with [contributors](https://github.com/adaptlearning/adapt-contrib-slider/graphs/contributors)
**Accessibility support:** WAI AA
**RTL support:** Yes
**Cross-platform coverage:** Chrome, Chrome for Android, Firefox (ESR + latest version), Edge, IE11, Safari 14 for macOS/iOS/iPadOS, Opera
**Author / maintainer:** Adapt Core Team with [contributors](https://github.com/adaptlearning/adapt-contrib-slider/graphs/contributors)<br>
**Accessibility support:** WAI AA<br>
**RTL support:** Yes<br>
**Cross-platform coverage:** Chrome, Chrome for Android, Firefox (ESR + latest version), Edge, IE11, Safari 14 for macOS/iOS/iPadOS, Opera<br>
9 changes: 9 additions & 0 deletions js/sliderModel.js → js/SliderModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ import QuestionModel from 'core/js/models/questionModel';

export default class SliderModel extends QuestionModel {

defaults() {
return QuestionModel.resultExtend('defaults', {
_showScale: true,
_showScaleNumbers: true,
_showScaleIndicator: true,
_showNumber: true
});
}

init() {
QuestionModel.prototype.init.call(this);

Expand Down
89 changes: 89 additions & 0 deletions js/SliderView.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import QuestionView from 'core/js/views/questionView';

class SliderView extends QuestionView {

initialize(...args) {
this.onInput = this.onInput.bind(this);
this.mapValue = this.mapValue.bind(this);
this.getIndexFromValue = this.getIndexFromValue.bind(this);
this.normalise = this.normalise.bind(this);
this.onNumberSelected = this.onNumberSelected.bind(this);
this.getCorrectAnswers = this.model.getCorrectAnswers.bind(this.model);
super.initialize(...args);
}

// Used by question to setup itself just before rendering
setupQuestion() {
if (this.model.get('_isSubmitted')) return;

this.selectItem(this.getIndexFromValue(this.model.get('_selectedItem').value));
}

onQuestionRendered() {
this.setReadyStatus();
}

// this shoud give the index of item using given slider value
getIndexFromValue(itemValue) {
const scaleStart = this.model.get('_scaleStart');
const scaleEnd = this.model.get('_scaleEnd');
return Math.round(this.mapValue(itemValue, scaleStart, scaleEnd, 0, this.model.get('_items').length - 1));
}

mapIndexToPixels(value, $widthObject) {
const numberOfItems = this.model.get('_items').length;
const width = $widthObject ? $widthObject.width() : this.$('.js-slider-scale').width();

return Math.round(this.mapValue(value, 0, numberOfItems - 1, 0, width));
}

normalise(value, low, high) {
const range = high - low;
return (value - low) / range;
}

mapValue(value, inputLow, inputHigh, outputLow, outputHigh) {
const normal = this.normalise(value, inputLow, inputHigh);
return normal * (outputHigh - outputLow) + outputLow;
}

onNumberSelected(event) {
event.preventDefault();

if (this.model.get('_isInteractionComplete')) {
return;
}

const itemValue = parseFloat($(event.currentTarget).attr('data-id'));
const index = this.getIndexFromValue(itemValue);
this.selectItem(index);
}

onCannotSubmit() { }

// according to given item index this should make the item as selected
selectItem(itemIndex) {
// deselect all items before selecting the chosen item
this.model.deselectAllItems();
const item = this.model.get('_items')[itemIndex];
if (!item) return;
item.selected = true;
this.model.set('_selectedItem', item);
}

onInput(e) {
const value = e.target.value;

if (this.oldValue === value) {
return;
}
const itemIndex = this.getIndexFromValue(value);
this.selectItem(itemIndex);
this.oldValue = value;
}

}

SliderView.template = 'slider.jsx';

export default SliderView;
4 changes: 2 additions & 2 deletions js/adapt-contrib-slider.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import components from 'core/js/components';
import SliderView from './sliderView';
import SliderModel from './sliderModel';
import SliderView from './SliderView';
import SliderModel from './SliderModel';

export default components.register('slider', {
view: SliderView,
Expand Down
Loading

0 comments on commit 2c524f5

Please sign in to comment.