Initial commit
This commit is contained in:
+51
@@ -0,0 +1,51 @@
|
||||
var _ = require('underscore');
|
||||
|
||||
var GenericOnboardingLauncher = function (launcherOpts, viewOpts) {
|
||||
var _view;
|
||||
var _onboardingNotification;
|
||||
var _notificationKey;
|
||||
var _onboardings;
|
||||
var _viewOpts;
|
||||
|
||||
if (!launcherOpts || !launcherOpts.view) {
|
||||
throw new Error('view is required');
|
||||
}
|
||||
|
||||
if (!launcherOpts.onboardingNotification) {
|
||||
throw new Error('onboardingNotification is required');
|
||||
}
|
||||
|
||||
if (!launcherOpts.notificationKey) {
|
||||
throw new Error('notificationKey is required');
|
||||
}
|
||||
|
||||
if (!launcherOpts.onboardings) {
|
||||
throw new Error('onboardings is required');
|
||||
}
|
||||
|
||||
if (!viewOpts) {
|
||||
throw new Error('viewOpts is required');
|
||||
}
|
||||
|
||||
_view = launcherOpts.view;
|
||||
_onboardingNotification = launcherOpts.onboardingNotification;
|
||||
_notificationKey = launcherOpts.notificationKey;
|
||||
_onboardings = launcherOpts.onboardings;
|
||||
_viewOpts = viewOpts;
|
||||
|
||||
return {
|
||||
launch: function (launchOpts) {
|
||||
if (!_onboardingNotification.getKey(_notificationKey)) {
|
||||
_onboardings.create(function () {
|
||||
var extendedViewOptions = _.extend(_viewOpts, {
|
||||
onboardingNotification: _onboardingNotification,
|
||||
notificationKey: _notificationKey
|
||||
});
|
||||
return new _view(_.extend(extendedViewOptions, launchOpts));
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = GenericOnboardingLauncher;
|
||||
+220
@@ -0,0 +1,220 @@
|
||||
var $ = require('jquery');
|
||||
var Backbone = require('backbone');
|
||||
var _ = require('underscore');
|
||||
var CoreView = require('backbone/core-view');
|
||||
var checkAndBuildOpts = require('builder/helpers/required-opts');
|
||||
|
||||
var REQUIRED_OPTS = [
|
||||
'onboardingNotification',
|
||||
'editorModel',
|
||||
'template',
|
||||
'numberOfSteps',
|
||||
'selector',
|
||||
'modifier',
|
||||
'notificationKey'
|
||||
];
|
||||
|
||||
var LEFT_KEY_CODE = 37;
|
||||
var RIGHT_KEY_CODE = 39;
|
||||
|
||||
module.exports = CoreView.extend({
|
||||
className: 'is-step0 is-opening',
|
||||
|
||||
events: {
|
||||
'click .js-start': '_onClickNext',
|
||||
'click .js-next': '_onClickNext',
|
||||
'click .js-close': '_close',
|
||||
'click .js-highlight': '_close'
|
||||
},
|
||||
|
||||
initialize: function (opts) {
|
||||
checkAndBuildOpts(opts, REQUIRED_OPTS, this);
|
||||
this.$el.addClass(this._selector);
|
||||
this.model = new Backbone.Model({
|
||||
step: -1
|
||||
});
|
||||
this._defaultBodyPos = {
|
||||
top: 32,
|
||||
left: 380
|
||||
};
|
||||
|
||||
this._keyDown = this._onKeyDown.bind(this);
|
||||
this._initBinds();
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.$el.addClass(this._selector + this._modifier);
|
||||
this.$el.html(this._template());
|
||||
if (this.model.get('step') === -1) {
|
||||
this._next();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
_initBinds: function () {
|
||||
this.listenTo(this.model, 'destroy', this._close);
|
||||
this.listenTo(this.model, 'change:step', this._onChangeStep);
|
||||
this.listenTo(this._editorModel, 'change:edition', this._changeEdition);
|
||||
$(document).on('keydown', this._keyDown);
|
||||
},
|
||||
|
||||
_changeEdition: function (mdl) {
|
||||
var isEditing = !!mdl.get('edition');
|
||||
this.$el.toggleClass('is-editing', isEditing);
|
||||
},
|
||||
|
||||
_prev: function () {
|
||||
if (this._currentStep() >= 1) {
|
||||
this.model.set('step', this._currentStep() - 1);
|
||||
}
|
||||
},
|
||||
|
||||
_next: function () {
|
||||
if (this._currentStep() < this._numberOfSteps) {
|
||||
this.model.set('step', this._currentStep() + 1);
|
||||
}
|
||||
},
|
||||
|
||||
_currentStep: function () {
|
||||
return this.model.get('step');
|
||||
},
|
||||
|
||||
_onClickNext: function (event) {
|
||||
if (event) event.stopPropagation();
|
||||
this._next();
|
||||
},
|
||||
|
||||
_onChangeStep: function () {
|
||||
var prev = this.model.previous('step');
|
||||
var step = this.model.get('step');
|
||||
|
||||
this.$el.removeClass('is-step' + prev, function () {
|
||||
this.$el.addClass('is-step' + step);
|
||||
}.bind(this));
|
||||
|
||||
this.$('.js-step').removeClass('is-step' + prev).addClass('is-step' + step);
|
||||
|
||||
this.$('.' + this._selector + '-body').fadeOut(0).delay(200).fadeIn(100);
|
||||
|
||||
this.$('.' + this._selector + '-step.is-step' + prev).css('display', 'none');
|
||||
this.$('.' + this._selector + '-footer.is-step' + prev).css('display', 'none');
|
||||
this.$('.' + this._selector + '-step.is-step' + step).css('display', 'block');
|
||||
this.$('.' + this._selector + '-footer.is-step' + step).css('display', 'block');
|
||||
|
||||
this.$('.' + this._selector + '-contentBody').css('display', step === 0 ? 'block' : 'none');
|
||||
},
|
||||
|
||||
_close: function () {
|
||||
this._forget();
|
||||
this.trigger('close', this);
|
||||
},
|
||||
|
||||
_onKeyDown: function (event) {
|
||||
event.stopPropagation();
|
||||
|
||||
if (event.which === LEFT_KEY_CODE) {
|
||||
this._prev();
|
||||
} else if (event.which === RIGHT_KEY_CODE) {
|
||||
this._next();
|
||||
}
|
||||
},
|
||||
|
||||
_forget: function () {
|
||||
this._onboardingNotification.setKey(this._notificationKey, true);
|
||||
this._onboardingNotification.save();
|
||||
},
|
||||
|
||||
clean: function () {
|
||||
$(document).off('keydown', this._keyDown);
|
||||
CoreView.prototype.clean.apply(this);
|
||||
},
|
||||
|
||||
_setMiddlePad: function (position, padding, body) {
|
||||
var $window = $(window);
|
||||
var $top = this.$('.' + this._selector + '-pads--left .' + this._selector + '-padTop');
|
||||
var $middle = this.$('.' + this._selector + '-pads--left .' + this._selector + '-padMiddle');
|
||||
var $bottom = this.$('.' + this._selector + '-pads--left .' + this._selector + '-padBottom');
|
||||
var vh = $window.height();
|
||||
var vw = $window.width();
|
||||
var isSelector = _.isString(position);
|
||||
var $el = $(position);
|
||||
var width = 0;
|
||||
var height = 0;
|
||||
var left = 0;
|
||||
var top = 0;
|
||||
if ($el.length === 0) return;
|
||||
|
||||
if (isSelector) {
|
||||
width = $el.outerWidth();
|
||||
height = $el.outerHeight();
|
||||
left = $el.offset().left;
|
||||
top = $el.offset().top;
|
||||
} else {
|
||||
width = position.width;
|
||||
height = position.height;
|
||||
left = position.left;
|
||||
top = position.top;
|
||||
}
|
||||
|
||||
// Apply padding
|
||||
var appliedPadding = this._buildPadding(padding);
|
||||
top -= appliedPadding.top;
|
||||
left -= appliedPadding.left;
|
||||
width += appliedPadding.left + appliedPadding.right;
|
||||
height += appliedPadding.top + appliedPadding.bottom;
|
||||
|
||||
// Is it place outside the viewport?
|
||||
if (vw - left > 0 && vw - left < width) {
|
||||
width = vw - left;
|
||||
} else if (vw - left <= 0) {
|
||||
width = 0;
|
||||
}
|
||||
|
||||
// Left offset
|
||||
this.$('.' + this._selector + '-toolbarOverlay').outerWidth(left);
|
||||
|
||||
// Right panel
|
||||
this.$('.' + this._selector + '-contentWrapper').outerWidth(vw - (left + width));
|
||||
|
||||
// Width
|
||||
this.$('.' + this._selector + '-pads--left').outerWidth(width);
|
||||
$top.outerWidth(width);
|
||||
$middle.outerWidth(width);
|
||||
$bottom.outerWidth(width);
|
||||
|
||||
// Height
|
||||
var topHeight = top;
|
||||
var middleHeight = height;
|
||||
var bottomHeight = vh - (topHeight + middleHeight);
|
||||
|
||||
$top.outerHeight(topHeight);
|
||||
$middle.outerHeight(middleHeight);
|
||||
$bottom.outerHeight(bottomHeight);
|
||||
|
||||
// Body text
|
||||
this.$('.' + this._selector + '-body').css('top', body && body.top ? body.top : this._defaultBodyPos.top);
|
||||
this.$('.' + this._selector + '-body').css('left', body && body.left ? body.left : this._defaultBodyPos.left);
|
||||
},
|
||||
|
||||
_buildPadding: function (padding) {
|
||||
var result = {
|
||||
top: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
left: 0
|
||||
};
|
||||
|
||||
if (padding) {
|
||||
result.top = this._calculatePadding(padding.top);
|
||||
result.right = this._calculatePadding(padding.right);
|
||||
result.bottom = this._calculatePadding(padding.bottom);
|
||||
result.left = this._calculatePadding(padding.left);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
_calculatePadding: function (padding) {
|
||||
return (padding && _.isFinite(padding)) ? padding : 0;
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user