devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
293 lines (237 loc) • 9.66 kB
JavaScript
"use strict";
var $ = require("../../core/renderer"),
eventsEngine = require("../../events/core/events_engine"),
registerComponent = require("../../core/component_registrator"),
extend = require("../../core/utils/extend").extend,
each = require("../../core/utils/iterator").each,
eventUtils = require("../../events/utils"),
clickEvent = require("../../events/click"),
Scrollable = require("../scroll_view/ui.scrollable"),
fx = require("../../animation/fx"),
translator = require("../../animation/translator");
var DATEVIEW_ROLLER_CLASS = "dx-dateviewroller",
DATEVIEW_ROLLER_ACTIVE_CLASS = "dx-state-active",
DATEVIEW_ROLLER_CURRENT_CLASS = "dx-dateviewroller-current",
DATEVIEW_ROLLER_ITEM_CLASS = "dx-dateview-item",
DATEVIEW_ROLLER_ITEM_SELECTED_CLASS = "dx-dateview-item-selected",
DATEVIEW_ROLLER_ITEM_SELECTED_FRAME_CLASS = "dx-dateview-item-selected-frame",
DATEVIEW_ROLLER_ITEM_SELECTED_BORDER_CLASS = "dx-dateview-item-selected-border";
var DateViewRoller = Scrollable.inherit({
_getDefaultOptions: function _getDefaultOptions() {
return extend(this.callBase(), {
showScrollbar: false,
useNative: false,
selectedIndex: 0,
bounceEnabled: false,
items: [],
showOnClick: false,
onClick: null,
onSelectedIndexChanged: null
});
},
_defaultOptionsRules: function _defaultOptionsRules() {
return this.callBase().concat([{
device: function device(_device) {
return _device.platform === "win" && _device.version && _device.version[0] === 8;
},
options: {
showOnClick: true
}
}, {
device: { platform: "generic" },
options: {
scrollByContent: true
}
}]);
},
_init: function _init() {
this.callBase();
this._renderSelectedItemFrame();
},
_render: function _render() {
this.callBase();
this.$element().addClass(DATEVIEW_ROLLER_CLASS);
this._renderContainerClick();
this._renderItems();
this._renderSelectedValue();
this._renderItemsClick();
this._wrapAction("_endAction", this._endActionHandler.bind(this));
this._renderSelectedIndexChanged();
},
_renderSelectedIndexChanged: function _renderSelectedIndexChanged() {
this._selectedIndexChanged = this._createActionByOption("onSelectedIndexChanged");
},
_renderContainerClick: function _renderContainerClick() {
if (!this.option("showOnClick")) {
return;
}
var eventName = eventUtils.addNamespace(clickEvent.name, this.NAME);
var clickAction = this._createActionByOption("onClick");
eventsEngine.off(this._$container, eventName);
eventsEngine.on(this._$container, eventName, function (e) {
clickAction({ event: e });
});
},
_wrapAction: function _wrapAction(actionName, callback) {
var strategy = this._strategy,
originalAction = strategy[actionName];
strategy[actionName] = function () {
callback.apply(this, arguments);
return originalAction.apply(this, arguments);
};
},
_renderItems: function _renderItems() {
var items = this.option("items") || [],
$items = $();
this._$content.empty();
// NOTE: rendering ~166+30+12+24+60 <div>s >> 50mc
items.forEach(function (item) {
$items = $items.add($("<div>").addClass(DATEVIEW_ROLLER_ITEM_CLASS).append(item));
});
this._$content.append($items);
this._$items = $items;
this.update();
},
_renderSelectedItemFrame: function _renderSelectedItemFrame() {
$("<div>").addClass(DATEVIEW_ROLLER_ITEM_SELECTED_FRAME_CLASS).append($("<div>").addClass(DATEVIEW_ROLLER_ITEM_SELECTED_BORDER_CLASS)).appendTo(this._$container);
},
_renderSelectedValue: function _renderSelectedValue(selectedIndex) {
var index = this._fitIndex(selectedIndex || this.option("selectedIndex"));
this._moveTo({ top: this._getItemPosition(index) });
this._renderActiveStateItem();
},
_fitIndex: function _fitIndex(index) {
var items = this.option("items") || [],
itemCount = items.length;
if (index >= itemCount) {
return itemCount - 1;
}
if (index < 0) {
return 0;
}
return index;
},
_getItemPosition: function _getItemPosition(index) {
return Math.round(this._itemHeight() * index);
},
_renderItemsClick: function _renderItemsClick() {
var itemSelector = this._getItemSelector(),
eventName = eventUtils.addNamespace(clickEvent.name, this.NAME);
eventsEngine.off(this.$element(), eventName, itemSelector);
eventsEngine.on(this.$element(), eventName, itemSelector, this._itemClickHandler.bind(this));
},
_getItemSelector: function _getItemSelector() {
return "." + DATEVIEW_ROLLER_ITEM_CLASS;
},
_itemClickHandler: function _itemClickHandler(e) {
this.option("selectedIndex", this._itemElementIndex(e.currentTarget));
},
_itemElementIndex: function _itemElementIndex(itemElement) {
return this._itemElements().index(itemElement);
},
_itemElements: function _itemElements() {
return this.$element().find(this._getItemSelector());
},
_renderActiveStateItem: function _renderActiveStateItem() {
var selectedIndex = this.option("selectedIndex");
each(this._$items, function (index) {
$(this).toggleClass(DATEVIEW_ROLLER_ITEM_SELECTED_CLASS, selectedIndex === index);
});
},
_moveTo: function _moveTo(targetLocation) {
targetLocation = this._normalizeLocation(targetLocation);
var location = this._location(),
delta = {
x: -(location.left - targetLocation.left),
y: -(location.top - targetLocation.top)
};
if (this._isVisible() && (delta.x || delta.y)) {
this._strategy._prepareDirections(true);
if (this._animation) {
var that = this;
fx.stop(this._$content);
fx.animate(this._$content, {
duration: 200,
type: "slide",
to: { top: Math.floor(delta.y) },
complete: function complete() {
translator.resetPosition(that._$content);
that._strategy.handleMove({ delta: delta });
}
});
delete this._animation;
} else {
this._strategy.handleMove({ delta: delta });
}
}
},
_validate: function _validate(e) {
return this._strategy.validate(e);
},
_endActionHandler: function _endActionHandler() {
var currentSelectedIndex = this.option("selectedIndex"),
ratio = -this._location().top / this._itemHeight(),
newSelectedIndex = Math.round(ratio);
this._animation = true;
if (newSelectedIndex === currentSelectedIndex) {
this._renderSelectedValue(newSelectedIndex);
} else {
this.option("selectedIndex", newSelectedIndex);
}
},
_itemHeight: function _itemHeight() {
var $item = this._$items.first();
return $item.get(0) && $item.get(0).getBoundingClientRect().height || 0;
},
_toggleActive: function _toggleActive(state) {
this.$element().toggleClass(DATEVIEW_ROLLER_ACTIVE_CLASS, state);
},
_isVisible: function _isVisible() {
return this._$container.is(":visible");
},
_fireSelectedIndexChanged: function _fireSelectedIndexChanged(value, previousValue) {
this._selectedIndexChanged({
value: value,
previousValue: previousValue,
event: undefined
});
},
_visibilityChanged: function _visibilityChanged(visible) {
this.callBase(visible);
if (visible) {
this._renderSelectedValue(this.option("selectedIndex"));
}
this.toggleActiveState(false);
},
toggleActiveState: function toggleActiveState(state) {
this.$element().toggleClass(DATEVIEW_ROLLER_CURRENT_CLASS, state);
},
_refreshSelectedIndex: function _refreshSelectedIndex() {
var selectedIndex = this.option("selectedIndex");
var fitIndex = this._fitIndex(selectedIndex);
fitIndex === selectedIndex ? this._renderActiveStateItem() : this.option("selectedIndex", fitIndex);
},
_optionChanged: function _optionChanged(args) {
switch (args.name) {
case "selectedIndex":
this._fireSelectedIndexChanged(args.value, args.previousValue);
this._renderSelectedValue(args.value);
break;
case "items":
this._renderItems();
this._refreshSelectedIndex();
break;
case "onClick":
case "showOnClick":
this._renderContainerClick();
break;
case "onSelectedIndexChanged":
this._renderSelectedIndexChanged();
break;
default:
this.callBase(args);
}
}
});
registerComponent("dxDateViewRoller", DateViewRoller);
module.exports = DateViewRoller;