Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Items model #170

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ The attributes listed below are used in *components.json* to configure **Narrati
On mobile devices, the narrative text is collapsed above the image. It is accessed by clicking an icon (+) next the to strapline.

----------------------------
**Version number:** 2.0.8 <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>
**Version number:** 2.1.0 <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>
**Framework versions:** 2.0
**Author / maintainer:** Adapt Core Team with [contributors](https://github.com/adaptlearning/adapt-contrib-narrative/graphs/contributors)
**Accessibility support:** WAI AA
Expand Down
4 changes: 2 additions & 2 deletions bower.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "adapt-contrib-narrative",
"version": "2.0.8",
"framework": "^2.0.0",
"version": "2.1.0",
"framework": "^2.0.19",
"homepage": "https://github.com/adaptlearning/adapt-contrib-narrative",
"issues": "https://github.com/adaptlearning/adapt_framework/issues/new?title=contrib-narrative%3A%20please%20enter%20a%20brief%20summary%20of%20the%20issue%20here&body=please%20provide%20a%20full%20description%20of%20the%20problem,%20including%20steps%20on%20how%20to%20replicate,%20what%20browser(s)/device(s)%20the%20problem%20occurs%20on%20and,%20where%20helpful,%20screenshots.",
"displayName" : "Narrative",
Expand Down
362 changes: 9 additions & 353 deletions js/adapt-contrib-narrative.js
Original file line number Diff line number Diff line change
@@ -1,356 +1,12 @@
define(function(require) {

var ComponentView = require('coreViews/componentView');
var Adapt = require('coreJS/adapt');

var Narrative = ComponentView.extend({

events: {
'click .narrative-strapline-title': 'openPopup',
'click .narrative-controls': 'onNavigationClicked',
'click .narrative-indicators .narrative-progress': 'onProgressClicked'
},

preRender: function() {
this.listenTo(Adapt, 'device:changed', this.reRender, this);
this.listenTo(Adapt, 'device:resize', this.resizeControl, this);
this.listenTo(Adapt, 'notify:closed', this.closeNotify, this);
this.setDeviceSize();

// Checks to see if the narrative should be reset on revisit
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)
}
},

postRender: function() {
this.renderState();
this.$('.narrative-slider').imageready(_.bind(function() {
this.setReadyStatus();
}, this));
this.setupNarrative();
},

// Used to check if the narrative should reset on revisit
checkIfResetOnRevisit: function() {
var isResetOnRevisit = this.model.get('_isResetOnRevisit');

// If reset is enabled set defaults
if (isResetOnRevisit) {
this.model.reset(isResetOnRevisit);
this.model.set({_stage: 0});

_.each(this.model.get('_items'), function(item) {
item._isVisited = false;
});
}
},

setupNarrative: function() {
this.setDeviceSize();
if(!this.model.has('_items') || !this.model.get('_items').length) return;
this.model.set('_marginDir', 'left');
if (Adapt.config.get('_defaultDirection') == 'rtl') {
this.model.set('_marginDir', 'right');
}
this.model.set('_itemCount', this.model.get('_items').length);

this.model.set('_active', true);

if (this.model.get('_stage')) {
this.setStage(this.model.get('_stage'), true);
} else {
this.setStage(0, true);
}
this.calculateWidths();

if (Adapt.device.screenSize !== 'large' && !this.model.get('_wasHotgraphic')) {
this.replaceInstructions();
}
this.setupEventListeners();
},

calculateWidths: function() {
var slideWidth = this.$('.narrative-slide-container').width();
var slideCount = this.model.get('_itemCount');
var marginRight = this.$('.narrative-slider-graphic').css('margin-right');
var extraMargin = marginRight === '' ? 0 : parseInt(marginRight);
var fullSlideWidth = (slideWidth + extraMargin) * slideCount;

this.$('.narrative-slider-graphic').width(slideWidth);
this.$('.narrative-strapline-header').width(slideWidth);
this.$('.narrative-strapline-title').width(slideWidth);

this.$('.narrative-slider').width(fullSlideWidth);
this.$('.narrative-strapline-header-inner').width(fullSlideWidth);

var stage = this.model.get('_stage');
var margin = -(stage * slideWidth);

this.$('.narrative-slider').css(('margin-' + this.model.get('_marginDir')), margin);
this.$('.narrative-strapline-header-inner').css(('margin-' + this.model.get('_marginDir')), margin);

this.model.set('_finalItemLeft', fullSlideWidth - slideWidth);
},

resizeControl: function() {
var wasDesktop = this.model.get('_isDesktop');
this.setDeviceSize();
if (wasDesktop != this.model.get('_isDesktop')) this.replaceInstructions();
this.calculateWidths();
this.evaluateNavigation();
},

reRender: function() {
if (this.model.get('_wasHotgraphic') && Adapt.device.screenSize == 'large') {
this.replaceWithHotgraphic();
} else {
this.resizeControl();
}
},

closeNotify: function() {
this.evaluateCompletion()
},

replaceInstructions: function() {
if (Adapt.device.screenSize === 'large') {
this.$('.narrative-instruction-inner').html(this.model.get('instruction')).a11y_text();
} else if (this.model.get('mobileInstruction') && !this.model.get('_wasHotgraphic')) {
this.$('.narrative-instruction-inner').html(this.model.get('mobileInstruction')).a11y_text();
}
},

replaceWithHotgraphic: function() {
if (!Adapt.componentStore.hotgraphic) throw "Hotgraphic not included in build";
var Hotgraphic = Adapt.componentStore.hotgraphic;

var model = this.prepareHotgraphicModel();
var newHotgraphic = new Hotgraphic({ model: model });
var $container = $(".component-container", $("." + this.model.get("_parentId")));

$container.append(newHotgraphic.$el);
this.remove();
$.a11y_update();
_.defer(function() {
Adapt.trigger('device:resize');
});
},

prepareHotgraphicModel: function() {
var model = this.model;
model.set('_component', 'hotgraphic');
model.set('body', model.get('originalBody'));
model.set('instruction', model.get('originalInstruction'));
return model;
},

moveSliderToIndex: function(itemIndex, animate, callback) {
var extraMargin = parseInt(this.$('.narrative-slider-graphic').css('margin-right'));
var movementSize = this.$('.narrative-slide-container').width() + extraMargin;
var marginDir = {};
if (animate && !Adapt.config.get('_disableAnimation')) {
marginDir['margin-' + this.model.get('_marginDir')] = -(movementSize * itemIndex);
this.$('.narrative-slider').velocity("stop", true).velocity(marginDir);
this.$('.narrative-strapline-header-inner').velocity("stop", true).velocity(marginDir, {complete:callback});
} else {
marginDir['margin-' + this.model.get('_marginDir')] = -(movementSize * itemIndex);
this.$('.narrative-slider').css(marginDir);
this.$('.narrative-strapline-header-inner').css(marginDir);
callback();
}
},

setStage: function(stage, initial) {
this.model.set('_stage', stage);
if (this.model.get('_isDesktop')) {
// Set the visited attribute for large screen devices
var currentItem = this.getCurrentItem(stage);
currentItem._isVisited = true;
}

this.$('.narrative-progress:visible').removeClass('selected').eq(stage).addClass('selected');
this.$('.narrative-slider-graphic').children('.controls').a11y_cntrl_enabled(false);
this.$('.narrative-slider-graphic').eq(stage).children('.controls').a11y_cntrl_enabled(true);
this.$('.narrative-content-item').addClass('narrative-hidden').a11y_on(false).eq(stage).removeClass('narrative-hidden').a11y_on(true);
this.$('.narrative-strapline-title').a11y_cntrl_enabled(false).eq(stage).a11y_cntrl_enabled(true);

this.evaluateNavigation();
this.evaluateCompletion();

this.moveSliderToIndex(stage, !initial, _.bind(function() {
if (this.model.get('_isDesktop')) {
if (!initial) this.$('.narrative-content-item').eq(stage).a11y_focus();
} else {
if (!initial) this.$('.narrative-strapline-title').a11y_focus();
}
}, this));
},

constrainStage: function(stage) {
if (stage > this.model.get('_items').length - 1) {
stage = this.model.get('_items').length - 1;
} else if (stage < 0) {
stage = 0;
}
return stage;
},

constrainXPosition: function(previousLeft, newLeft, deltaX) {
if (newLeft > 0 && deltaX > 0) {
newLeft = previousLeft + (deltaX / (newLeft * 0.1));
}
var finalItemLeft = this.model.get('_finalItemLeft');
if (newLeft < -finalItemLeft && deltaX < 0) {
var distance = Math.abs(newLeft + finalItemLeft);
newLeft = previousLeft + (deltaX / (distance * 0.1));
}
return newLeft;
},

evaluateNavigation: function() {
var currentStage = this.model.get('_stage');
var itemCount = this.model.get('_itemCount');
if (currentStage == 0) {
this.$('.narrative-controls').addClass('narrative-hidden');

if (itemCount > 1) {
this.$('.narrative-control-right').removeClass('narrative-hidden');
}
} else {
this.$('.narrative-control-left').removeClass('narrative-hidden');

if (currentStage == itemCount - 1) {
this.$('.narrative-control-right').addClass('narrative-hidden');
} else {
this.$('.narrative-control-right').removeClass('narrative-hidden');
}
}

},

getNearestItemIndex: function() {
var currentPosition = parseInt(this.$('.narrative-slider').css('margin-left'));
var graphicWidth = this.$('.narrative-slider-graphic').width();
var absolutePosition = currentPosition / graphicWidth;
var stage = this.model.get('_stage');
var relativePosition = stage - Math.abs(absolutePosition);

if (relativePosition < -0.3) {
stage++;
} else if (relativePosition > 0.3) {
stage--;
}

return this.constrainStage(stage);
},

getCurrentItem: function(index) {
return this.model.get('_items')[index];
},

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.trigger('allItems');
}
},

moveElement: function($element, deltaX) {
var previousLeft = parseInt($element.css('margin-left'));
var newLeft = previousLeft + deltaX;

newLeft = this.constrainXPosition(previousLeft, newLeft, deltaX);
$element.css(('margin-' + this.model.get('_marginDir')), newLeft + 'px');
},

openPopup: function(event) {
event.preventDefault();
var currentItem = this.getCurrentItem(this.model.get('_stage'));
var popupObject = {
title: currentItem.title,
body: currentItem.body
};

// Set the visited attribute for small and medium screen devices
currentItem._isVisited = true;

Adapt.trigger('notify:popup', popupObject);
},

onNavigationClicked: function(event) {

if (!this.model.get('_active')) return;

var stage = this.model.get('_stage');
var numberOfItems = this.model.get('_itemCount');

if ($(event.currentTarget).hasClass('narrative-control-right')) {
stage++;
} else if ($(event.currentTarget).hasClass('narrative-control-left')) {
stage--;
}
stage = (stage + numberOfItems) % numberOfItems;
this.setStage(stage);
},

onProgressClicked: function(event) {
event.preventDefault();
var clickedIndex = $(event.target).index();
this.setStage(clickedIndex);
},

inview: function(event, visible, visiblePartX, visiblePartY) {
if (visible) {
if (visiblePartY === 'top') {
this._isVisibleTop = true;
} else if (visiblePartY === 'bottom') {
this._isVisibleBottom = true;
} else {
this._isVisibleTop = true;
this._isVisibleBottom = true;
}

if (this._isVisibleTop && this._isVisibleBottom) {
this.$('.component-inner').off('inview');
this.setCompletionStatus();
}
}
},

onCompletion: function() {
this.setCompletionStatus();
if (this.completionEvent && this.completionEvent != 'inview') {
this.off(this.completionEvent, this);
}
},

setupEventListeners: function() {
this.completionEvent = (!this.model.get('_setCompletionOn')) ? 'allItems' : this.model.get('_setCompletionOn');
if (this.completionEvent !== 'inview' && this.model.get('_items').length > 1) {
this.on(this.completionEvent, _.bind(this.onCompletion, this));
} else {
this.$('.component-widget').on('inview', _.bind(this.inview, this));
}
}

define([
'coreJS/adapt',
'./narrativeModel',
'./narrativeView'
], function(Adapt, NarrativeModel, NarrativeView) {

return Adapt.register('narrative', {
view: NarrativeView,
model: NarrativeModel
});

Adapt.register('narrative', Narrative);

return Narrative;

});
Loading