diff --git a/README.md b/README.md index 7e3ad6b..4459577 100644 --- a/README.md +++ b/README.md @@ -80,8 +80,8 @@ Several elements of **Text Entry** have been assigned a label using the [aria-la No known limitations. ---------------------------- -**Version number:** 5.1.2 -**Framework versions supported:** 5+ +**Version number:** 5.2.0 +**Framework versions supported:** 5.8+ **Author / maintainer:** DeltaNet with [contributors](https://github.com/deltanet/adapt-textEntry-audio/graphs/contributors) **Accessibility support:** yes **RTL support:** yes diff --git a/bower.json b/bower.json index 58931c1..65dc4b7 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "adapt-textEntry-audio", - "version": "5.1.2", - "framework": ">=5", + "version": "5.2.0", + "framework": ">=5.8", "homepage": "https://github.com/deltanet/adapt-textEntry-audio", "issues": "https://github.com/deltanet/adapt-textEntry-audio/issues", "description": "A text entry component to capture user text", diff --git a/js/adapt-textEntry-audio.js b/js/adapt-textEntry-audio.js index 2cc8829..855e5d2 100644 --- a/js/adapt-textEntry-audio.js +++ b/js/adapt-textEntry-audio.js @@ -1,12 +1,8 @@ -define([ - 'core/js/adapt', - './textEntryAudioView', - 'core/js/models/componentModel' -], function(Adapt, TextEntryAudioView, ComponentModel) { - - return Adapt.register('textEntry-audio', { - view: TextEntryAudioView, - model: ComponentModel.extend({}) - }); +import Adapt from 'core/js/adapt'; +import TextEntryAudioModel from './textEntryAudioModel'; +import TextEntryAudioView from './textEntryAudioView'; +export default Adapt.register('textEntry-audio', { + model: TextEntryAudioModel, + view: TextEntryAudioView }); diff --git a/js/textEntryAudioModel.js b/js/textEntryAudioModel.js new file mode 100644 index 0000000..42eb752 --- /dev/null +++ b/js/textEntryAudioModel.js @@ -0,0 +1,3 @@ +import ComponentModel from 'core/js/models/componentModel'; + +export default class TextEntryAudioModel extends ComponentModel {} diff --git a/js/textEntryAudioPopupView.js b/js/textEntryAudioPopupView.js index 7308d41..85e748f 100644 --- a/js/textEntryAudioPopupView.js +++ b/js/textEntryAudioPopupView.js @@ -1,44 +1,47 @@ -define([ - 'core/js/adapt' -], function(Adapt) { - 'use strict'; +import Adapt from 'core/js/adapt'; - var TextEntryAudioPopupView = Backbone.View.extend({ +class TextEntryAudioPopupView extends Backbone.View { - className: 'textEntry-audio-popup-content', + className() { + return 'textEntry-audio-popup-content'; + } - events: { - 'click .textEntry-close-button': 'closePopup' - }, + events() { + return { + 'click .textEntry-close-button': 'closePopup' + }; + } - initialize: function() { - this.listenToOnce(Adapt, 'notify:opened', this.onOpened); - this.render(); - }, + initialize(...args) { + super.initialize(...args); - onOpened: function() { - this.playAudio(); - }, + this.listenToOnce(Adapt, 'notify:opened', this.onOpened); + this.render(); + } - render: function() { - var data = this.model.toJSON(); - var template = Handlebars.templates['textEntryAudioPopup']; - this.$el.html(template(data)); - }, + onOpened() { + this.playAudio(); + } - closePopup: function(event) { - Adapt.trigger('notify:close'); - }, + render() { + const data = this.model.toJSON(); + data.view = this; + const template = Handlebars.templates[this.constructor.template]; + this.$el.html(template(data)); + } - playAudio: function() { - if (Adapt.audio && this.model.has('_audio') && this.model.get('_audio')._isEnabled && Adapt.audio.audioClip[this.model.get('_audio')._channel].status==1) { - Adapt.audio.audioClip[this.model.get('_audio')._channel].onscreenID = ""; - Adapt.trigger('audio:playAudio', this.model.get("_feedback")._audio.src, this.model.get('_id'), this.model.get('_audio')._channel); - } - } + closePopup(event) { + Adapt.trigger('notify:close'); + } - }); + playAudio() { + if (Adapt.audio && this.model.has('_audio') && this.model.get('_audio')._isEnabled && Adapt.audio.audioClip[this.model.get('_audio')._channel].status==1) { + Adapt.audio.audioClip[this.model.get('_audio')._channel].onscreenID = ""; + Adapt.trigger('audio:playAudio', this.model.get("_feedback")._audio.src, this.model.get('_id'), this.model.get('_audio')._channel); + } + } +} - return TextEntryAudioPopupView; +TextEntryAudioPopupView.template = 'textEntryAudioPopup'; -}); +export default TextEntryAudioPopupView; diff --git a/js/textEntryAudioView.js b/js/textEntryAudioView.js index f888ae7..b6d63bf 100755 --- a/js/textEntryAudioView.js +++ b/js/textEntryAudioView.js @@ -1,193 +1,195 @@ -define([ - 'core/js/adapt', - 'core/js/views/componentView', - './textEntryAudioPopupView' -], function(Adapt, ComponentView, TextEntryAudioPopupView) { +import Adapt from 'core/js/adapt'; +import ComponentView from 'core/js/views/componentView'; +import TextEntryAudioPopupView from './textEntryAudioPopupView'; - var TextEntryAudioView = ComponentView.extend({ +class TextEntryAudioView extends ComponentView { - events: { - 'click .js-btn-action': 'onBtnClicked', - 'click .js-btn-feedback': 'openPopup', - 'keyup .textEntry-audio-item-textbox': 'onInputChanged' - }, + events() { + return { + 'click .js-btn-action': 'onBtnClicked', + 'click .js-btn-feedback': 'openPopup', + 'keyup .textEntry-audio-item-textbox': 'onInputChanged' + }; + } - initialize: function() { - ComponentView.prototype.initialize.call(this); - this.setUpViewData(); + initialize(...args) { + super.initialize(...args); - this.listenTo(Adapt.config, 'change:_activeLanguage', this.resetUserAnswers); - }, + this.setUpViewData(); + this.setUpEventListeners(); + } - setUpViewData: function() { - this.popupView = null; - this._isPopupOpen = false; - }, + setUpViewData() { + this.popupView = null; + this._isPopupOpen = false; + } - postRender: function() { - this.restoreUserAnswers(); - this.setReadyStatus(); + setUpEventListeners() { + this.listenTo(Adapt.config, 'change:_activeLanguage', this.resetUserAnswers); + } - if (this.model.get('_setCompletionOn') === 'inview') { - this.setupInviewCompletion(); - } + postRender() { + this.restoreUserAnswers(); + this.setReadyStatus(); - this.updateCounter(); - }, + if (this.model.get('_setCompletionOn') === 'inview') { + this.setupInviewCompletion(); + } - onBtnClicked: function(event) { - if (event) event.preventDefault(); + this.updateCounter(); + } - if (this.model.get('_isSubmitted')) return; + onBtnClicked(event) { + if (event) event.preventDefault(); - if (this.$('.textEntry-audio-item-textbox').val() == "") return; + if (this.model.get('_isSubmitted')) return; - this.userAnswer = this.$('.textEntry-audio-item-textbox').val(); - this.model.set("userAnswer", this.userAnswer); + if (this.$('.textEntry-audio-item-textbox').val() == "") return; - this.initFeedback(); + this.userAnswer = this.$('.textEntry-audio-item-textbox').val(); + this.model.set("userAnswer", this.userAnswer); - this.model.set('_isSubmitted', true); + this.initFeedback(); - this.$('.btn__action').addClass('is-disabled').attr('disabled', true); + this.model.set('_isSubmitted', true); - this.$('.textEntry-audio-item-textbox').attr('disabled', true); + this.$('.btn__action').addClass('is-disabled').attr('disabled', true); - Adapt.offlineStorage.set(this.model.get('_id'), this.model.get("userAnswer")); + this.$('.textEntry-audio-item-textbox').attr('disabled', true); - if (!this.model.get('_recordInteraction')) return; - Adapt.trigger('questionView:recordInteraction', this); - }, + Adapt.offlineStorage.set(this.model.get('_id'), this.model.get("userAnswer")); - initFeedback: function() { - if (this.model.get('_canShowFeedback')) { - this.$('.btn__feedback').removeClass('is-disabled').attr('disabled', false); - this.openPopup(); - } else { - this.setCompletionStatus(); - } - }, + if (!this.model.get('_recordInteraction')) return; + Adapt.trigger('questionView:recordInteraction', this); + } - openPopup: function() { - if (this._isPopupOpen) return; + initFeedback() { + if (this.model.get('_canShowFeedback')) { + this.$('.btn__feedback').removeClass('is-disabled').attr('disabled', false); + this.openPopup(); + } else { + this.setCompletionStatus(); + } + } - this._isPopupOpen = true; + openPopup() { + if (this._isPopupOpen) return; - Adapt.trigger('audio:stopAllChannels'); + this._isPopupOpen = true; - this.popupView = new TextEntryAudioPopupView({ - model: this.model - }); + Adapt.trigger('audio:stopAllChannels'); - Adapt.notify.popup({ - _view: this.popupView, - _isCancellable: true, - _showCloseButton: false, - _closeOnBackdrop: true, - _classes: 'textEntry-audio-popup' - }); - - this.listenToOnce(Adapt, { - 'popup:closed': this.onPopupClosed - }); - }, + this.popupView = new TextEntryAudioPopupView({ + model: this.model + }); - onPopupClosed: function() { - this._isPopupOpen = false; - this.setCompletionStatus(); - }, + Adapt.notify.popup({ + _view: this.popupView, + _isCancellable: true, + _showCloseButton: false, + _closeOnBackdrop: true, + _classes: 'textEntry-audio-popup' + }); - restoreUserAnswers: function() { - var storedAnswer = Adapt.offlineStorage.get(this.model.get('_id')); + this.listenToOnce(Adapt, { + 'popup:closed': this.onPopupClosed + }); + } - if (!storedAnswer) return; + onPopupClosed() { + this._isPopupOpen = false; + this.setCompletionStatus(); + } - this.setCompletionStatus(); + restoreUserAnswers() { + const storedAnswer = Adapt.offlineStorage.get(this.model.get('_id')); - this.model.set('userAnswer', storedAnswer); - this.model.set('_isSubmitted', true); + if (!storedAnswer) return; - this.$('.textEntry-audio-item-textbox').val(this.model.get('userAnswer')).attr('disabled', true); + this.setCompletionStatus(); - this.$('.btn__action').addClass('is-disabled').attr('disabled', true); + this.model.set('userAnswer', storedAnswer); + this.model.set('_isSubmitted', true); - if (this.model.get('_canShowFeedback')) { - this.$('.btn__feedback').attr('disabled', false).removeClass('is-disabled'); - } + this.$('.textEntry-audio-item-textbox').val(this.model.get('userAnswer')).attr('disabled', true); - this.updateCounter(); - }, + this.$('.btn__action').addClass('is-disabled').attr('disabled', true); - resetUserAnswers: function() { - this.model.set('userAnswer', ''); + if (this.model.get('_canShowFeedback')) { + this.$('.btn__feedback').attr('disabled', false).removeClass('is-disabled'); + } - this.$('.textEntry-audio-item-textbox').val(''); + this.updateCounter(); + } - this.model.set('_isSubmitted', false); + resetUserAnswers() { + this.model.set('userAnswer', ''); - this.$('.btn__action').addClass('is-disabled'); + this.$('.textEntry-audio-item-textbox').val(''); - this.$('.textEntry-audio-item-textbox').attr('disabled', false); + this.model.set('_isSubmitted', false); - if (this.model.get('_canShowFeedback')) { - this.$('.btn__feedback').attr('disabled', true).addClass('is-disabled'); - } + this.$('.btn__action').addClass('is-disabled'); - this.updateCounter(); + this.$('.textEntry-audio-item-textbox').attr('disabled', false); - this.model.reset(true); + if (this.model.get('_canShowFeedback')) { + this.$('.btn__feedback').attr('disabled', true).addClass('is-disabled'); + } - Adapt.offlineStorage.set(this.model.get('_id'), this.model.get("userAnswer")); - }, + this.updateCounter(); - onInputChanged: function(event) { - if (event) event.preventDefault(); + this.model.reset(true); - this.$('.btn__action').removeClass('is-disabled'); + Adapt.offlineStorage.set(this.model.get('_id'), this.model.get("userAnswer")); + } - this.updateCounter(); - }, + onInputChanged(event) { + if (event) event.preventDefault(); - updateCounter: function() { - if (!this.model.get('_characterLimit')) return; - if (!this.model.get('_characterLimit')._isEnabled) return; + this.$('.btn__action').removeClass('is-disabled'); - var length = this.$('.textEntry-audio-item-textbox').val().length; + this.updateCounter(); + } - var max = this.model.get('_characterLimit')._max; - var text = this.model.get('_characterLimit').text; + updateCounter() { + if (!this.model.get('_characterLimit')) return; + if (!this.model.get('_characterLimit')._isEnabled) return; - var output = text+" "+(max - length); + const length = this.$('.textEntry-audio-item-textbox').val().length; + const max = this.model.get('_characterLimit')._max; + const text = this.model.get('_characterLimit').text; + const output = text+" "+(max - length); - this.$('.textEntry-audio-counter').html(output); - }, + this.$('.textEntry-audio-counter').html(output); + } - isCorrect: function() { - return null; - }, + isCorrect() { + return null; + } - // Time elapsed between the time the interaction was made available to the learner for response and the time of the first response - getLatency:function() { - return null; - }, + // Time elapsed between the time the interaction was made available to the learner for response and the time of the first response + getLatency() { + return null; + } - /** - * used by adapt-contrib-spoor to get the user's answers in the format required by the cmi.interactions.n.student_response data field - * returns the user's answers as a string in the format 'answer1[,]answer2[,]answer3' - * the use of [,] as an answer delimiter is from the SCORM 2004 specification for the fill-in interaction type - */ - getResponse: function() { - return this.model.get('userAnswer'); - }, + /** + * used by adapt-contrib-spoor to get the user's answers in the format required by the cmi.interactions.n.student_response data field + * returns the user's answers as a string in the format 'answer1[,]answer2[,]answer3' + * the use of [,] as an answer delimiter is from the SCORM 2004 specification for the fill-in interaction type + */ + getResponse() { + return this.model.get('userAnswer'); + } - /** - * used by adapt-contrib-spoor to get the type of this question in the format required by the cmi.interactions.n.type data field - */ - getResponseType: function() { - return 'fill-in'; - } - }); + /** + * used by adapt-contrib-spoor to get the type of this question in the format required by the cmi.interactions.n.type data field + */ + getResponseType() { + return 'fill-in'; + } +} - return TextEntryAudioView; +TextEntryAudioView.template = 'textEntry-audio'; -}); +export default TextEntryAudioView;