-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Items component model/accessibility update (#42)
* split code into model and view, as per hotgraphic * set correct framework dependency; update version number & cross platform coverage list in README * updates for compatibility with Adapt v4 style accessibility * schema, README & example.json improvements
- Loading branch information
Matt Leathes
authored
May 17, 2019
1 parent
11853b9
commit 407d08b
Showing
10 changed files
with
623 additions
and
299 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,126 +1,11 @@ | ||
|
||
define([ | ||
'core/js/adapt', | ||
'core/js/views/componentView' | ||
], function(Adapt, ComponentView) { | ||
|
||
var Hotgrid = ComponentView.extend({ | ||
|
||
events: { | ||
'click .hotgrid-item-image': 'onItemClicked' | ||
}, | ||
|
||
isPopupOpen: false, | ||
|
||
preRender: function () { | ||
_.each(this.model.get('_items'), function(item) { | ||
if (item._graphic.srcHover && item._graphic.srcVisited) { | ||
item._graphic.hasImageStates = true; | ||
} | ||
}); | ||
|
||
this.listenTo(Adapt, 'device:changed', this.resizeControl); | ||
|
||
this.setDeviceSize(); | ||
|
||
this.checkIfResetOnRevisit(); | ||
}, | ||
|
||
setDeviceSize: function() { | ||
if (Adapt.device.screenSize === 'large') { | ||
this.$el.addClass('desktop').removeClass('mobile'); | ||
this.model.set('_isDesktop', true); | ||
} else { | ||
this.$el.addClass('mobile').removeClass('desktop'); | ||
this.model.set('_isDesktop', false); | ||
} | ||
}, | ||
|
||
checkIfResetOnRevisit: function() { | ||
var isResetOnRevisit = this.model.get('_isResetOnRevisit'); | ||
|
||
// If reset is enabled set defaults | ||
if (isResetOnRevisit) { | ||
this.model.reset(isResetOnRevisit); | ||
|
||
_.each(this.model.get('_items'), function(item) { | ||
item._isVisited = false; | ||
}); | ||
} | ||
}, | ||
|
||
postRender: function() { | ||
this.setUpColumns(); | ||
this.$('.hotgrid-widget').imageready(this.setReadyStatus.bind(this)); | ||
}, | ||
|
||
resizeControl: function() { | ||
this.setDeviceSize(); | ||
this.render(); | ||
}, | ||
'core/js/models/itemsComponentModel', | ||
'./hotgridView' | ||
], function(Adapt, ItemsComponentModel, HotgridView) { | ||
|
||
setUpColumns: function() { | ||
var columns = this.model.get('_columns'); | ||
|
||
if (columns && Adapt.device.screenSize === 'large') { | ||
this.$('.hotgrid-grid-item').css('width', (100 / columns) + '%'); | ||
} | ||
}, | ||
|
||
onItemClicked: function(event) { | ||
if (event) event.preventDefault(); | ||
|
||
var $link = $(event.currentTarget); | ||
var $item = $link.parent(); | ||
var itemModel = this.model.get('_items')[$item.index()]; | ||
|
||
if(!itemModel._isVisited) { | ||
$link.addClass('visited'); | ||
itemModel._isVisited = true; | ||
// append the word 'visited.' to the link's aria-label | ||
var visitedLabel = this.model.get('_globals')._accessibility._ariaLabels.visited + "."; | ||
$link.attr('aria-label', function(index, val) { | ||
return val + " " + visitedLabel; | ||
}); | ||
} | ||
|
||
this.showItemContent(itemModel); | ||
}, | ||
|
||
showItemContent: function(itemModel) { | ||
if(this.isPopupOpen) return;// ensure multiple clicks don't open multiple notify popups | ||
|
||
Adapt.trigger('notify:popup', { | ||
title: itemModel.title, | ||
body: "<div class='hotgrid-notify-container'><div class='hotgrid-notify-body'>" + itemModel.body + "</div>" + | ||
"<img class='hotgrid-notify-graphic' src='" + | ||
itemModel._itemGraphic.src + "' alt='" + | ||
itemModel._itemGraphic.alt + "'/></div>" | ||
}); | ||
|
||
this.isPopupOpen = true; | ||
|
||
Adapt.once('notify:closed', function() { | ||
this.isPopupOpen = false; | ||
this.evaluateCompletion(); | ||
}.bind(this)); | ||
}, | ||
|
||
getVisitedItems: function() { | ||
return _.filter(this.model.get('_items'), function(item) { | ||
return item._isVisited; | ||
}); | ||
}, | ||
|
||
evaluateCompletion: function() { | ||
if (this.getVisitedItems().length === this.model.get('_items').length) { | ||
this.setCompletionStatus(); | ||
} | ||
} | ||
|
||
},{ | ||
template: "hotgrid" | ||
return Adapt.register('hotgrid', { | ||
model: ItemsComponentModel, | ||
view: HotgridView | ||
}); | ||
|
||
return Adapt.register("hotgrid", Hotgrid); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
define([ | ||
'core/js/adapt' | ||
], function(Adapt) { | ||
'use strict'; | ||
|
||
var HotgridPopupView = Backbone.View.extend({ | ||
|
||
className: 'hotgrid-popup', | ||
|
||
events: { | ||
'click .hotgrid-popup-done': 'closePopup', | ||
'click .hotgrid-popup-controls': 'onControlClick' | ||
}, | ||
|
||
initialize: function() { | ||
this.listenToOnce(Adapt, 'notify:opened', this.onOpened); | ||
this.listenTo(this.model.get('_children'), { | ||
'change:_isActive': this.onItemsActiveChange, | ||
'change:_isVisited': this.onItemsVisitedChange | ||
}); | ||
this.render(); | ||
}, | ||
|
||
onOpened: function() { | ||
this.applyNavigationClasses(this.model.getActiveItem().get('_index')); | ||
this.updatePageCount(); | ||
this.handleTabs(); | ||
}, | ||
|
||
applyNavigationClasses: function (index) { | ||
var itemCount = this.model.get('_items').length; | ||
var canCycleThroughPagination = this.model.get('_canCycleThroughPagination'); | ||
|
||
var shouldEnableBack = index > 0 || canCycleThroughPagination; | ||
var shouldEnableNext = index < itemCount - 1 || canCycleThroughPagination; | ||
var $controls = this.$('.hotgrid-popup-controls'); | ||
|
||
this.$('hotgrid-popup-nav') | ||
.toggleClass('first', !shouldEnableBack) | ||
.toggleClass('last', !shouldEnableNext); | ||
|
||
$controls.filter('.back').a11y_cntrl_enabled(shouldEnableBack); | ||
$controls.filter('.next').a11y_cntrl_enabled(shouldEnableNext); | ||
}, | ||
|
||
updatePageCount: function() { | ||
var template = Adapt.course.get('_globals')._components._hotgrid.popupPagination; | ||
var labelText = Handlebars.compile(template || '')({ | ||
itemNumber: this.model.getActiveItem().get('_index') + 1, | ||
totalItems: this.model.get('_items').length | ||
}); | ||
this.$('.hotgrid-popup-count').html(labelText); | ||
}, | ||
|
||
handleTabs: function() { | ||
this.$('.hotgrid-popup-inner').a11y_on(false); | ||
this.$('.hotgrid-popup-inner .active').a11y_on(true); | ||
}, | ||
|
||
onItemsActiveChange: function(item, _isActive) { | ||
if (!_isActive) return; | ||
|
||
var index = item.get('_index'); | ||
this.applyNavigationClasses(index); | ||
this.updatePageCount(); | ||
this.handleTabs(); | ||
this.applyItemClasses(index); | ||
this.handleFocus(); | ||
}, | ||
|
||
applyItemClasses: function(index) { | ||
this.$('.hotgrid-item.active').removeClass('active'); | ||
this.$('.hotgrid-item').filter('[data-index="' + index + '"]').addClass('active'); | ||
}, | ||
|
||
handleFocus: function() { | ||
this.$('.hotgrid-popup-inner .active').a11y_focus(); | ||
}, | ||
|
||
onItemsVisitedChange: function(item, _isVisited) { | ||
if (!_isVisited) return; | ||
|
||
this.$('.hotgrid-item') | ||
.filter('[data-index="' + item.get('_index') + '"]') | ||
.addClass('visited'); | ||
}, | ||
|
||
render: function() { | ||
var data = this.model.toJSON(); | ||
data.view = this; | ||
var template = Handlebars.templates['hotgridPopup']; | ||
this.$el.html(template(data)); | ||
}, | ||
|
||
closePopup: function(event) { | ||
Adapt.trigger('notify:close'); | ||
}, | ||
|
||
onControlClick: function(event) { | ||
event.preventDefault(); | ||
|
||
var direction = $(event.currentTarget).hasClass('back') ? 'back' : 'next'; | ||
var index = this.getNextIndex(direction); | ||
|
||
if (index === -1) return; | ||
|
||
this.setItemState(index); | ||
}, | ||
|
||
getNextIndex: function(direction) { | ||
var index = this.model.getActiveItem().get('_index'); | ||
var lastIndex = this.model.get('_items').length - 1; | ||
|
||
switch (direction) { | ||
case 'back': | ||
if (index > 0) return --index; | ||
if (this.model.get('_canCycleThroughPagination')) return lastIndex; | ||
break; | ||
case 'next': | ||
if (index < lastIndex) return ++index; | ||
if (this.model.get('_canCycleThroughPagination')) return 0; | ||
} | ||
return -1; | ||
}, | ||
|
||
setItemState: function(index) { | ||
this.model.getActiveItem().toggleActive(); | ||
|
||
var nextItem = this.model.getItem(index); | ||
nextItem.toggleActive(); | ||
nextItem.toggleVisited(true); | ||
} | ||
|
||
}); | ||
|
||
return HotgridPopupView; | ||
|
||
}); |
Oops, something went wrong.