delete files
This commit is contained in:
parent
00916345ab
commit
e337493a96
|
@ -266,8 +266,6 @@
|
||||||
<script type="text/javascript" src="../../../vendor/jquery/jquery.min.js"></script>
|
<script type="text/javascript" src="../../../vendor/jquery/jquery.min.js"></script>
|
||||||
<script type="text/javascript" src="../../../vendor/jquery.browser/dist/jquery.browser.min.js"></script>
|
<script type="text/javascript" src="../../../vendor/jquery.browser/dist/jquery.browser.min.js"></script>
|
||||||
<script type="text/javascript" src="../../../vendor/bootstrap/dist/js/bootstrap.js"></script>
|
<script type="text/javascript" src="../../../vendor/bootstrap/dist/js/bootstrap.js"></script>
|
||||||
<script type="text/javascript" src="../../../vendor/underscore/underscore.js"></script>
|
|
||||||
|
|
||||||
|
|
||||||
<script type="text/javascript" src="../../../vendor/sockjs/sockjs.min.js"></script>
|
<script type="text/javascript" src="../../../vendor/sockjs/sockjs.min.js"></script>
|
||||||
<script type="text/javascript" src="../../../vendor/underscore/underscore-min.js"></script>
|
<script type="text/javascript" src="../../../vendor/underscore/underscore-min.js"></script>
|
||||||
|
@ -275,8 +273,6 @@
|
||||||
<script type="text/javascript" src="../../../vendor/jszip/jszip.min.js"></script>
|
<script type="text/javascript" src="../../../vendor/jszip/jszip.min.js"></script>
|
||||||
<script type="text/javascript" src="../../../vendor/jszip-utils/jszip-utils.min.js"></script>
|
<script type="text/javascript" src="../../../vendor/jszip-utils/jszip-utils.min.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="../../../vendor/backbone/backbone.js"></script>
|
|
||||||
|
|
||||||
<script src="../../../vendor/requirejs/require.js"></script>
|
<script src="../../../vendor/requirejs/require.js"></script>
|
||||||
<script>
|
<script>
|
||||||
require.config({
|
require.config({
|
||||||
|
@ -299,14 +295,6 @@
|
||||||
<script type="text/javascript" src="../../unit-tests/common/main/lib/util/utils.js"></script>
|
<script type="text/javascript" src="../../unit-tests/common/main/lib/util/utils.js"></script>
|
||||||
<script type="text/javascript" src="../../unit-tests/common/main/lib/view/LoadMask.js"></script>
|
<script type="text/javascript" src="../../unit-tests/common/main/lib/view/LoadMask.js"></script>
|
||||||
|
|
||||||
<!--<script type="text/javascript" src="../../unit-tests/common/main/lib/component/BaseView.js"></script>
|
|
||||||
<script type="text/javascript" src="../../unit-tests/common/main/lib/core/application.js"></script>-->
|
|
||||||
<!--<script type="text/javascript" src="../../unit-tests/common/main/lib/view/modals.js"></script>
|
|
||||||
<script type="text/javascript" src="../../unit-tests/common/main/lib/controller/modals.js"></script>
|
|
||||||
<script type="text/javascript" src="js/CellEditorView.js"></script>
|
|
||||||
<script type="text/javascript" src="js/CellEditorController.js"></script>-->
|
|
||||||
|
|
||||||
|
|
||||||
<script type="text/javascript" src="../../unit-tests/common/main/lib/view/CellEditor.js"></script>
|
<script type="text/javascript" src="../../unit-tests/common/main/lib/view/CellEditor.js"></script>
|
||||||
<script type="text/javascript" src="../../unit-tests/common/main/lib/controller/CellEditor.js"></script>
|
<script type="text/javascript" src="../../unit-tests/common/main/lib/controller/CellEditor.js"></script>
|
||||||
<script type="text/javascript" src="js/ApplicationView.js"></script>
|
<script type="text/javascript" src="js/ApplicationView.js"></script>
|
||||||
|
|
|
@ -1,338 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* (c) Copyright Ascensio System SIA 2010-2019
|
|
||||||
*
|
|
||||||
* This program is a free software product. You can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
|
||||||
* version 3 as published by the Free Software Foundation. In accordance with
|
|
||||||
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
|
||||||
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
|
||||||
* of any third-party rights.
|
|
||||||
*
|
|
||||||
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
|
||||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
|
||||||
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
|
||||||
*
|
|
||||||
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
|
|
||||||
* street, Riga, Latvia, EU, LV-1050.
|
|
||||||
*
|
|
||||||
* The interactive user interfaces in modified source and object code versions
|
|
||||||
* of the Program must display Appropriate Legal Notices, as required under
|
|
||||||
* Section 5 of the GNU AGPL version 3.
|
|
||||||
*
|
|
||||||
* Pursuant to Section 7(b) of the License you must retain the original Product
|
|
||||||
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
|
||||||
* grant you any rights under trademark law for use of our trademarks.
|
|
||||||
*
|
|
||||||
* All the Product's GUI elements, including illustrations and icon sets, as
|
|
||||||
* well as technical writing content are licensed under the terms of the
|
|
||||||
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
|
||||||
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* CellEditor.js
|
|
||||||
*
|
|
||||||
* CellEditor Controller
|
|
||||||
*
|
|
||||||
* Created by Maxim Kadushkin on 08 April 2014
|
|
||||||
* Copyright (c) 2018 Ascensio System SIA. All rights reserved.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
define([
|
|
||||||
'test/unit-tests/common/main/lib/core/application'
|
|
||||||
|
|
||||||
], function (Viewport) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
SSE.Controllers.CellEditor = Backbone.Controller.extend({
|
|
||||||
views: [
|
|
||||||
'CellEditorView'
|
|
||||||
],
|
|
||||||
|
|
||||||
events: function() {
|
|
||||||
return {
|
|
||||||
'keyup input#ce-cell-name': _.bind(this.onCellName,this),
|
|
||||||
'keyup textarea#ce-cell-content': _.bind(this.onKeyupCellEditor,this),
|
|
||||||
'blur textarea#ce-cell-content': _.bind(this.onBlurCellEditor,this),
|
|
||||||
'click button#ce-btn-expand': _.bind(this.expandEditorField,this),
|
|
||||||
'click button#ce-func-label': _.bind(this.onInsertFunction, this)
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
initialize: function() {
|
|
||||||
this.addListeners({
|
|
||||||
'CellEditor': {},
|
|
||||||
'Viewport': {
|
|
||||||
'layout:resizedrag': _.bind(this.onLayoutResize, this)
|
|
||||||
},
|
|
||||||
'Common.Views.Header': {
|
|
||||||
'formulabar:hide': function (state) {
|
|
||||||
this.editor.setVisible(!state);
|
|
||||||
common.localStorage.setBool('sse-hidden-formula', state);
|
|
||||||
Common.NotificationCenter.trigger('layout:changed', 'celleditor', state?'hidden':'showed');
|
|
||||||
}.bind(this)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
setApi: function(api) {
|
|
||||||
this.api = api;
|
|
||||||
|
|
||||||
this.api.isCEditorFocused = false;
|
|
||||||
this.api.asc_registerCallback('asc_onSelectionNameChanged', _.bind(this.onApiCellSelection, this));
|
|
||||||
this.api.asc_registerCallback('asc_onEditCell', _.bind(this.onApiEditCell, this));
|
|
||||||
this.api.asc_registerCallback('asc_onCoAuthoringDisconnect', _.bind(this.onApiDisconnect,this));
|
|
||||||
Common.NotificationCenter.on('api:disconnect', _.bind(this.onApiDisconnect, this));
|
|
||||||
Common.NotificationCenter.on('cells:range', _.bind(this.onCellsRange, this));
|
|
||||||
this.api.asc_registerCallback('asc_onLockDefNameManager', _.bind(this.onLockDefNameManager, this));
|
|
||||||
this.api.asc_registerCallback('asc_onInputKeyDown', _.bind(this.onInputKeyDown, this));
|
|
||||||
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
setMode: function(mode) {
|
|
||||||
this.mode = mode;
|
|
||||||
|
|
||||||
this.editor.$btnfunc[this.mode.isEdit?'removeClass':'addClass']('disabled');
|
|
||||||
this.editor.btnNamedRanges.setVisible(this.mode.isEdit && !this.mode.isEditDiagram && !this.mode.isEditMailMerge);
|
|
||||||
|
|
||||||
if ( this.mode.isEdit ) {
|
|
||||||
this.api.asc_registerCallback('asc_onSelectionChanged', _.bind(this.onApiSelectionChanged, this));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onInputKeyDown: function(e) {
|
|
||||||
if (Common.UI.Keys.UP === e.keyCode || Common.UI.Keys.DOWN === e.keyCode ||
|
|
||||||
Common.UI.Keys.TAB === e.keyCode || Common.UI.Keys.RETURN === e.keyCode || Common.UI.Keys.ESC === e.keyCode ||
|
|
||||||
Common.UI.Keys.LEFT === e.keyCode || Common.UI.Keys.RIGHT === e.keyCode) {
|
|
||||||
var menu = $('#menu-formula-selection'); // for formula menu
|
|
||||||
if (menu.hasClass('open'))
|
|
||||||
menu.find('.dropdown-menu').trigger('keydown', e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onLaunch: function() {
|
|
||||||
this.editor = this.getView('CellEditor');
|
|
||||||
this.bindViewEvents(this.editor, this.events);
|
|
||||||
|
|
||||||
this.editor.$el.parent().find('.after').css({zIndex: '4'}); // for spreadsheets - bug 23127
|
|
||||||
|
|
||||||
var val = common.localStorage.getItem('sse-celleditor-height');
|
|
||||||
this.editor.keep_height = (val!==null && parseInt(val)>0) ? parseInt(val) : 74;
|
|
||||||
if (common.localStorage.getBool('sse-celleditor-expand')) {
|
|
||||||
this.editor.$el.height(this.editor.keep_height);
|
|
||||||
this.onLayoutResize(undefined, 'cell:edit');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.editor.btnNamedRanges.menu.on('item:click', _.bind(this.onNamedRangesMenu, this))
|
|
||||||
.on('show:before', _.bind(this.onNameBeforeShow, this));
|
|
||||||
this.namedrange_locked = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
onApiEditCell: function(state) {
|
|
||||||
if (this.viewmode) return; // signed file
|
|
||||||
|
|
||||||
if (state == Asc.c_oAscCellEditorState.editStart){
|
|
||||||
this.api.isCellEdited = true;
|
|
||||||
this.editor.cellNameDisabled(true);
|
|
||||||
} else if (state == Asc.c_oAscCellEditorState.editInCell) {
|
|
||||||
this.api.isCEditorFocused = 'clear';
|
|
||||||
} else if (state == Asc.c_oAscCellEditorState.editEnd) {
|
|
||||||
this.api.isCellEdited = false;
|
|
||||||
this.api.isCEditorFocused = false;
|
|
||||||
this.editor.cellNameDisabled(false);
|
|
||||||
}
|
|
||||||
this.editor.$btnfunc.toggleClass('disabled', state == Asc.c_oAscCellEditorState.editText);
|
|
||||||
},
|
|
||||||
|
|
||||||
onApiCellSelection: function(info) {
|
|
||||||
this.editor.updateCellInfo(info);
|
|
||||||
},
|
|
||||||
|
|
||||||
onApiSelectionChanged: function(info) {
|
|
||||||
if (this.viewmode) return; // signed file
|
|
||||||
|
|
||||||
var seltype = info.asc_getSelectionType(),
|
|
||||||
coauth_disable = (!this.mode.isEditMailMerge && !this.mode.isEditDiagram) ? (info.asc_getLocked() === true || info.asc_getLockedTable() === true || info.asc_getLockedPivotTable()===true) : false;
|
|
||||||
|
|
||||||
var is_chart_text = seltype == Asc.c_oAscSelectionType.RangeChartText,
|
|
||||||
is_chart = seltype == Asc.c_oAscSelectionType.RangeChart,
|
|
||||||
is_shape_text = seltype == Asc.c_oAscSelectionType.RangeShapeText,
|
|
||||||
is_shape = seltype == Asc.c_oAscSelectionType.RangeShape,
|
|
||||||
is_image = seltype == Asc.c_oAscSelectionType.RangeImage || seltype == Asc.c_oAscSelectionType.RangeSlicer,
|
|
||||||
is_mode_2 = is_shape_text || is_shape || is_chart_text || is_chart;
|
|
||||||
|
|
||||||
this.editor.$btnfunc.toggleClass('disabled', is_image || is_mode_2 || coauth_disable);
|
|
||||||
},
|
|
||||||
|
|
||||||
onApiDisconnect: function() {
|
|
||||||
this.mode.isEdit = false;
|
|
||||||
|
|
||||||
var controller = this.getApplication().getController('FormulaDialog');
|
|
||||||
if (controller) {
|
|
||||||
controller.hideDialog();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.mode.isEdit) {
|
|
||||||
$('#ce-func-label', this.editor.el).addClass('disabled');
|
|
||||||
this.editor.btnNamedRanges.setVisible(false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onCellsRange: function(status) {
|
|
||||||
this.editor.cellNameDisabled(status != Asc.c_oAscSelectionDialogType.None);
|
|
||||||
this.editor.$btnfunc.toggleClass('disabled', status != Asc.c_oAscSelectionDialogType.None);
|
|
||||||
},
|
|
||||||
|
|
||||||
onLayoutResize: function(o, r) {
|
|
||||||
if (r == 'cell:edit') {
|
|
||||||
if (Math.floor(this.editor.$el.height()) > 19) {
|
|
||||||
if (!this.editor.$btnexpand.hasClass('btn-collapse')) {
|
|
||||||
this.editor.$el.addClass('expanded');
|
|
||||||
this.editor.$btnexpand['addClass']('btn-collapse');
|
|
||||||
}
|
|
||||||
|
|
||||||
o && common.localStorage.setItem('sse-celleditor-height', this.editor.$el.height());
|
|
||||||
o && common.localStorage.setBool('sse-celleditor-expand', true);
|
|
||||||
} else {
|
|
||||||
this.editor.$el.removeClass('expanded');
|
|
||||||
this.editor.$btnexpand['removeClass']('btn-collapse');
|
|
||||||
o && common.localStorage.setBool('sse-celleditor-expand', false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onCellName: function(e) {
|
|
||||||
if (e.keyCode == Common.UI.Keys.RETURN){
|
|
||||||
var name = this.editor.$cellname.val();
|
|
||||||
if (name && name.length) {
|
|
||||||
this.api.asc_findCell(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
Common.NotificationCenter.trigger('edit:complete', this.editor);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onBlurCellEditor: function() {
|
|
||||||
if (this.api.isCEditorFocused == 'clear')
|
|
||||||
this.api.isCEditorFocused = undefined;
|
|
||||||
else if (this.api.isCellEdited)
|
|
||||||
this.api.isCEditorFocused = true;
|
|
||||||
// if (Common.Utils.isIE && !$('#menu-formula-selection').hasClass('open')) {// for formula menu
|
|
||||||
// this.getApplication().getController('DocumentHolder').documentHolder.focus();
|
|
||||||
// }
|
|
||||||
},
|
|
||||||
|
|
||||||
onKeyupCellEditor: function(e) {
|
|
||||||
if(e.keyCode == Common.UI.Keys.RETURN && !e.altKey){
|
|
||||||
this.api.isCEditorFocused = 'clear';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
expandEditorField: function() {
|
|
||||||
if ( Math.floor(this.editor.$el.height()) > 19) {
|
|
||||||
this.editor.keep_height = this.editor.$el.height();
|
|
||||||
this.editor.$el.height(19);
|
|
||||||
this.editor.$el.removeClass('expanded');
|
|
||||||
this.editor.$btnexpand['removeClass']('btn-collapse');
|
|
||||||
common.localStorage.setBool('sse-celleditor-expand', false);
|
|
||||||
} else {
|
|
||||||
this.editor.$el.height(this.editor.keep_height);
|
|
||||||
this.editor.$el.addClass('expanded');
|
|
||||||
this.editor.$btnexpand['addClass']('btn-collapse');
|
|
||||||
common.localStorage.setBool('sse-celleditor-expand', true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Common.NotificationCenter.trigger('layout:changed', 'celleditor');
|
|
||||||
Common.NotificationCenter.trigger('edit:complete', this.editor, {restorefocus:true});
|
|
||||||
},
|
|
||||||
|
|
||||||
onInsertFunction: function() {
|
|
||||||
if (this.viewmode) return; // signed file
|
|
||||||
|
|
||||||
if ( this.mode.isEdit && !this.editor.$btnfunc['hasClass']('disabled')) {
|
|
||||||
var controller = this.getApplication().getController('FormulaDialog');
|
|
||||||
if (controller) {
|
|
||||||
$('#ce-func-label', this.editor.el).blur();
|
|
||||||
controller.showDialog();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onNamedRangesMenu: function(menu, item) {
|
|
||||||
var me = this;
|
|
||||||
if (item.options.value=='manager') {
|
|
||||||
var wc = this.api.asc_getWorksheetsCount(),
|
|
||||||
i = -1,
|
|
||||||
items = [], sheetNames = [];
|
|
||||||
while (++i < wc) {
|
|
||||||
if (!this.api.asc_isWorksheetHidden(i)) {
|
|
||||||
sheetNames[i] = this.api.asc_getWorksheetName(i);
|
|
||||||
items.push({displayValue: sheetNames[i], value: i});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(new SSE.Views.NameManagerDlg({
|
|
||||||
api: this.api,
|
|
||||||
handler: function(result) {
|
|
||||||
Common.NotificationCenter.trigger('edit:complete', me.editor);
|
|
||||||
},
|
|
||||||
locked: this.namedrange_locked,
|
|
||||||
sheets: items,
|
|
||||||
sheetNames: sheetNames,
|
|
||||||
ranges: this.api.asc_getDefinedNames(Asc.c_oAscGetDefinedNamesList.All),
|
|
||||||
props : this.api.asc_getDefaultDefinedName(),
|
|
||||||
sort : this.rangeListSort
|
|
||||||
})).on('close', function(win){
|
|
||||||
me.rangeListSort = win.getSettings();
|
|
||||||
}).show();
|
|
||||||
} else {
|
|
||||||
this.api.asc_findCell(item.caption);
|
|
||||||
Common.NotificationCenter.trigger('edit:complete', this.editor);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onNameBeforeShow: function() {
|
|
||||||
var names = this.api.asc_getDefinedNames(Asc.c_oAscGetDefinedNamesList.WorksheetWorkbook, true),
|
|
||||||
rangesMenu = this.editor.btnNamedRanges.menu,
|
|
||||||
prev_name='';
|
|
||||||
|
|
||||||
rangesMenu.removeItems(2, rangesMenu.items.length-1);
|
|
||||||
names.sort(function(item1, item2) {
|
|
||||||
var n1 = item1.asc_getName(true).toLowerCase(),
|
|
||||||
n2 = item2.asc_getName(true).toLowerCase();
|
|
||||||
if (n1==n2) return 0;
|
|
||||||
return (n1<n2) ? -1 : 1;
|
|
||||||
});
|
|
||||||
_.each(names, function(field, index) {
|
|
||||||
var name = field.asc_getName(true);
|
|
||||||
if (prev_name !== name) {
|
|
||||||
rangesMenu.addItem(new Common.UI.MenuItem({
|
|
||||||
caption : name
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
prev_name = name;
|
|
||||||
});
|
|
||||||
this.editor.btnNamedRanges.menu.items[0].setDisabled(!!this.api.asc_isProtectedSheet());
|
|
||||||
this.editor.btnNamedRanges.menu.items[1].setVisible(rangesMenu.items.length>2);
|
|
||||||
},
|
|
||||||
|
|
||||||
onLockDefNameManager: function(state) {
|
|
||||||
this.namedrange_locked = (state == Asc.c_oAscDefinedNameReason.LockDefNameManager);
|
|
||||||
},
|
|
||||||
|
|
||||||
SetDisabled: function(disabled) {
|
|
||||||
this.editor.$btnfunc[!disabled && this.mode.isEdit ?'removeClass':'addClass']('disabled');
|
|
||||||
this.editor.btnNamedRanges.setVisible(!disabled && this.mode.isEdit && !this.mode.isEditDiagram && !this.mode.isEditMailMerge);
|
|
||||||
},
|
|
||||||
|
|
||||||
setPreviewMode: function(mode) {
|
|
||||||
if (this.viewmode === mode) return;
|
|
||||||
this.viewmode = mode;
|
|
||||||
this.editor.$btnfunc[!mode && this.mode.isEdit?'removeClass':'addClass']('disabled');
|
|
||||||
this.editor.cellNameDisabled(mode && !(this.mode.isEdit && !this.mode.isEditDiagram && !this.mode.isEditMailMerge));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,106 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* (c) Copyright Ascensio System SIA 2010-2019
|
|
||||||
*
|
|
||||||
* This program is a free software product. You can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
|
||||||
* version 3 as published by the Free Software Foundation. In accordance with
|
|
||||||
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
|
||||||
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
|
||||||
* of any third-party rights.
|
|
||||||
*
|
|
||||||
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
|
||||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
|
||||||
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
|
||||||
*
|
|
||||||
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
|
|
||||||
* street, Riga, Latvia, EU, LV-1050.
|
|
||||||
*
|
|
||||||
* The interactive user interfaces in modified source and object code versions
|
|
||||||
* of the Program must display Appropriate Legal Notices, as required under
|
|
||||||
* Section 5 of the GNU AGPL version 3.
|
|
||||||
*
|
|
||||||
* Pursuant to Section 7(b) of the License you must retain the original Product
|
|
||||||
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
|
||||||
* grant you any rights under trademark law for use of our trademarks.
|
|
||||||
*
|
|
||||||
* All the Product's GUI elements, including illustrations and icon sets, as
|
|
||||||
* well as technical writing content are licensed under the terms of the
|
|
||||||
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
|
||||||
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* CellEdit.js
|
|
||||||
*
|
|
||||||
* Created by Maxim Kadushkin on 04 April 2014
|
|
||||||
* Copyright (c) 2018 Ascensio System SIA. All rights reserved.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
define([
|
|
||||||
'text!spreadsheeteditor/main/template/CellEditor.template',
|
|
||||||
'test/unit-tests/common/main/lib/component/BaseView'
|
|
||||||
], function (template) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
SSE.Views.CellEditor = Common.UI.BaseView.extend(_.extend({
|
|
||||||
template: _.template(template),
|
|
||||||
|
|
||||||
initialize: function (options) {
|
|
||||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function () {
|
|
||||||
$(this.el).html(this.template());
|
|
||||||
|
|
||||||
this.btnNamedRanges = new Common.UI.Button({
|
|
||||||
parentEl: $('#ce-cell-name-menu'),
|
|
||||||
menu : new Common.UI.Menu({
|
|
||||||
style : 'min-width: 70px;max-width:400px;',
|
|
||||||
maxHeight: 250,
|
|
||||||
items: [
|
|
||||||
{ caption: this.textManager, value: 'manager' },
|
|
||||||
{ caption: '--' }
|
|
||||||
]
|
|
||||||
})
|
|
||||||
});
|
|
||||||
this.btnNamedRanges.setVisible(false);
|
|
||||||
this.btnNamedRanges.menu.setOffset(-81);
|
|
||||||
|
|
||||||
this.$cellname = $('#ce-cell-name', this.el);
|
|
||||||
this.$btnexpand = $('#ce-btn-expand', this.el);
|
|
||||||
this.$btnfunc = $('#ce-func-label', this.el);
|
|
||||||
|
|
||||||
var me = this;
|
|
||||||
this.$cellname.on('focus', function(e){
|
|
||||||
var txt = me.$cellname[0];
|
|
||||||
txt.selectionStart = 0;
|
|
||||||
txt.selectionEnd = txt.value.length;
|
|
||||||
txt.scrollLeft = txt.scrollWidth;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.$btnfunc.addClass('disabled');
|
|
||||||
this.$btnfunc.tooltip({
|
|
||||||
title : this.tipFormula,
|
|
||||||
placement : 'cursor'
|
|
||||||
});
|
|
||||||
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
updateCellInfo: function(info) {
|
|
||||||
if (info) {
|
|
||||||
this.$cellname.val(typeof(info)=='string' ? info : info.asc_getName());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
cellNameDisabled: function(disabled){
|
|
||||||
(disabled) ? this.$cellname.attr('disabled', 'disabled') : this.$cellname.removeAttr('disabled');
|
|
||||||
this.btnNamedRanges.setDisabled(disabled);
|
|
||||||
},
|
|
||||||
|
|
||||||
tipFormula: 'Insert Function',
|
|
||||||
textManager: 'Manager'
|
|
||||||
}, SSE.Views.CellEditor || {}));
|
|
||||||
});
|
|
|
@ -1,117 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* (c) Copyright Ascensio System SIA 2010-2019
|
|
||||||
*
|
|
||||||
* This program is a free software product. You can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
|
||||||
* version 3 as published by the Free Software Foundation. In accordance with
|
|
||||||
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
|
||||||
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
|
||||||
* of any third-party rights.
|
|
||||||
*
|
|
||||||
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
|
||||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
|
||||||
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
|
||||||
*
|
|
||||||
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
|
|
||||||
* street, Riga, Latvia, EU, LV-1050.
|
|
||||||
*
|
|
||||||
* The interactive user interfaces in modified source and object code versions
|
|
||||||
* of the Program must display Appropriate Legal Notices, as required under
|
|
||||||
* Section 5 of the GNU AGPL version 3.
|
|
||||||
*
|
|
||||||
* Pursuant to Section 7(b) of the License you must retain the original Product
|
|
||||||
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
|
||||||
* grant you any rights under trademark law for use of our trademarks.
|
|
||||||
*
|
|
||||||
* All the Product's GUI elements, including illustrations and icon sets, as
|
|
||||||
* well as technical writing content are licensed under the terms of the
|
|
||||||
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
|
||||||
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* BaseView.js
|
|
||||||
*
|
|
||||||
* Created by Alexander Yuzhin on 1/17/14
|
|
||||||
* Copyright (c) 2018 Ascensio System SIA. All rights reserved.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (Common === undefined)
|
|
||||||
var Common = {};
|
|
||||||
|
|
||||||
define([
|
|
||||||
'backbone'
|
|
||||||
], function (Backbone) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
Common.UI = _.extend(Common.UI || {}, {
|
|
||||||
Keys : {
|
|
||||||
BACKSPACE: 8,
|
|
||||||
TAB: 9,
|
|
||||||
RETURN: 13,
|
|
||||||
SHIFT: 16,
|
|
||||||
CTRL: 17,
|
|
||||||
ALT: 18,
|
|
||||||
ESC: 27,
|
|
||||||
LEFT: 37,
|
|
||||||
UP: 38,
|
|
||||||
RIGHT: 39,
|
|
||||||
DOWN: 40,
|
|
||||||
DELETE: 46,
|
|
||||||
HOME: 36,
|
|
||||||
END: 35,
|
|
||||||
SPACE: 32,
|
|
||||||
PAGEUP: 33,
|
|
||||||
PAGEDOWN: 34,
|
|
||||||
INSERT: 45,
|
|
||||||
EQUALITY_FF:61,
|
|
||||||
NUM_PLUS: 107,
|
|
||||||
NUM_MINUS: 109,
|
|
||||||
F1: 112,
|
|
||||||
F2: 113,
|
|
||||||
F3: 114,
|
|
||||||
F4: 115,
|
|
||||||
F5: 116,
|
|
||||||
F6: 117,
|
|
||||||
F7: 118,
|
|
||||||
F8: 119,
|
|
||||||
F9: 120,
|
|
||||||
F10: 121,
|
|
||||||
F11: 122,
|
|
||||||
F12: 123,
|
|
||||||
MINUS_FF: 173,
|
|
||||||
EQUALITY: 187,
|
|
||||||
MINUS: 189
|
|
||||||
},
|
|
||||||
|
|
||||||
BaseView: Backbone.View.extend({
|
|
||||||
isSuspendEvents: false,
|
|
||||||
|
|
||||||
initialize : function(options) {
|
|
||||||
this.options = this.options ? _({}).extend(this.options, options) : options;
|
|
||||||
},
|
|
||||||
|
|
||||||
setVisible: function(visible) {
|
|
||||||
return this[visible ? 'show': 'hide']();
|
|
||||||
},
|
|
||||||
|
|
||||||
isVisible: function() {
|
|
||||||
return $(this.el).is(":visible");
|
|
||||||
},
|
|
||||||
|
|
||||||
suspendEvents: function() {
|
|
||||||
this.isSuspendEvents = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
resumeEvents: function() {
|
|
||||||
this.isSuspendEvents = false;
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
|
|
||||||
getId: function(prefix) {
|
|
||||||
return _.uniqueId(prefix || "asc-gen");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,774 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* (c) Copyright Ascensio System SIA 2010-2019
|
|
||||||
*
|
|
||||||
* This program is a free software product. You can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
|
||||||
* version 3 as published by the Free Software Foundation. In accordance with
|
|
||||||
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
|
||||||
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
|
||||||
* of any third-party rights.
|
|
||||||
*
|
|
||||||
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
|
||||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
|
||||||
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
|
||||||
*
|
|
||||||
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
|
|
||||||
* street, Riga, Latvia, EU, LV-1050.
|
|
||||||
*
|
|
||||||
* The interactive user interfaces in modified source and object code versions
|
|
||||||
* of the Program must display Appropriate Legal Notices, as required under
|
|
||||||
* Section 5 of the GNU AGPL version 3.
|
|
||||||
*
|
|
||||||
* Pursuant to Section 7(b) of the License you must retain the original Product
|
|
||||||
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
|
||||||
* grant you any rights under trademark law for use of our trademarks.
|
|
||||||
*
|
|
||||||
* All the Product's GUI elements, including illustrations and icon sets, as
|
|
||||||
* well as technical writing content are licensed under the terms of the
|
|
||||||
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
|
||||||
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Button.js
|
|
||||||
*
|
|
||||||
* Created by Alexander Yuzhin on 1/20/14
|
|
||||||
* Copyright (c) 2018 Ascensio System SIA. All rights reserved.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Using template
|
|
||||||
*
|
|
||||||
* A simple button with text:
|
|
||||||
* <button type="button" class="btn" id="id-button">Caption</button>
|
|
||||||
*
|
|
||||||
* A simple button with icon:
|
|
||||||
* <button type="button" class="btn" id="id-button"><span class="icon"> </span></button>
|
|
||||||
*
|
|
||||||
* A button with menu:
|
|
||||||
* <div class="btn-group" id="id-button">
|
|
||||||
* <button type="button" class="btn dropdown-toggle" data-toggle="dropdown">
|
|
||||||
* <span class="icon"> </span>
|
|
||||||
* <span class="caret"></span>
|
|
||||||
* </button>
|
|
||||||
* <ul class="dropdown-menu" role="menu">
|
|
||||||
* </ul>
|
|
||||||
* </div>
|
|
||||||
*
|
|
||||||
* A split button:
|
|
||||||
* <div class="btn-group split" id="id-button">
|
|
||||||
* <button type="button" class="btn"><span class="icon"> </span></button>
|
|
||||||
* <button type="button" class="btn dropdown-toggle" data-toggle="dropdown">
|
|
||||||
* <span class="caret"></span>
|
|
||||||
* <span class="sr-only"></span>
|
|
||||||
* </button>
|
|
||||||
* <ul class="dropdown-menu" role="menu">
|
|
||||||
* </ul>
|
|
||||||
* </div>
|
|
||||||
*
|
|
||||||
* A useful classes of button size
|
|
||||||
*
|
|
||||||
* - `'small'`
|
|
||||||
* - `'normal'`
|
|
||||||
* - `'large'`
|
|
||||||
* - `'huge'`
|
|
||||||
*
|
|
||||||
* A useful classes of button type
|
|
||||||
*
|
|
||||||
* - `'default'`
|
|
||||||
* - `'active'`
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Buttons can also be toggled. To enable this, you simple set the {@link #enableToggle} property to `true`.
|
|
||||||
*
|
|
||||||
* Example usage:
|
|
||||||
* new Common.UI.Button({
|
|
||||||
* el: $('#id'),
|
|
||||||
* enableToggle: true
|
|
||||||
* });
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @property {Boolean} disabled
|
|
||||||
* True if this button is disabled. Read-only.
|
|
||||||
*
|
|
||||||
* disabled: false,
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @property {Boolean} pressed
|
|
||||||
* True if this button is pressed (only if enableToggle = true). Read-only.
|
|
||||||
*
|
|
||||||
* pressed: false,
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @cfg {Boolean} [allowDepress=true]
|
|
||||||
* False to not allow a pressed Button to be depressed. Only valid when {@link #enableToggle} is true.
|
|
||||||
*
|
|
||||||
* @cfg {String/Object} hint
|
|
||||||
* The tooltip for the button - can be a string to be used as bootstrap tooltip
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (Common === undefined)
|
|
||||||
var Common = {};
|
|
||||||
|
|
||||||
define([
|
|
||||||
'unit-tests/common/main/lib/component/BaseView',
|
|
||||||
'unit-tests/common/main/lib/component/ToggleManager'
|
|
||||||
], function () {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
window.createButtonSet = function() {
|
|
||||||
function ButtonsArray(args) {};
|
|
||||||
ButtonsArray.prototype = new Array;
|
|
||||||
ButtonsArray.prototype.constructor = ButtonsArray;
|
|
||||||
|
|
||||||
var _disabled = false;
|
|
||||||
|
|
||||||
ButtonsArray.prototype.add = function(button) {
|
|
||||||
button.setDisabled(_disabled);
|
|
||||||
this.push(button);
|
|
||||||
};
|
|
||||||
|
|
||||||
ButtonsArray.prototype.setDisabled = function(disable) {
|
|
||||||
// if ( _disabled != disable ) //bug when disable buttons outside the group
|
|
||||||
{
|
|
||||||
_disabled = disable;
|
|
||||||
|
|
||||||
this.forEach( function(button) {
|
|
||||||
button.setDisabled(disable);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ButtonsArray.prototype.toggle = function(state, suppress) {
|
|
||||||
this.forEach(function(button) {
|
|
||||||
button.toggle(state, suppress);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
ButtonsArray.prototype.pressed = function() {
|
|
||||||
return this.some(function(button) {
|
|
||||||
return button.pressed;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
ButtonsArray.prototype.contains = function(id) {
|
|
||||||
return this.some(function(button) {
|
|
||||||
return button.id == id;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
ButtonsArray.prototype.concat = function () {
|
|
||||||
var args = Array.prototype.slice.call(arguments);
|
|
||||||
var result = Array.prototype.slice.call(this);
|
|
||||||
|
|
||||||
args.forEach(function(sub){
|
|
||||||
if (sub instanceof Array )
|
|
||||||
Array.prototype.push.apply(result, sub);
|
|
||||||
else if (sub)
|
|
||||||
result.push(sub);
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
var _out_array = Object.create(ButtonsArray.prototype);
|
|
||||||
for ( var i in arguments ) {
|
|
||||||
_out_array.add(arguments[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return _out_array;
|
|
||||||
};
|
|
||||||
|
|
||||||
var templateBtnIcon =
|
|
||||||
'<% if ( iconImg ) { %>' +
|
|
||||||
'<img src="<%= iconImg %>">' +
|
|
||||||
'<% } else { %>' +
|
|
||||||
'<% if (/svgicon/.test(iconCls)) {' +
|
|
||||||
'print(\'<svg class=\"icon\"><use class=\"zoom-int\" xlink:href=\"#\' + /svgicon\\s(\\S+)/.exec(iconCls)[1] + \'\"></use>' +
|
|
||||||
'<use class=\"zoom-grit\" xlink:href=\"#\' + /svgicon\\s(\\S+)/.exec(iconCls)[1] + \'-150\"></use></svg>\');' +
|
|
||||||
'} else ' +
|
|
||||||
'print(\'<i class=\"icon \' + iconCls + \'\"> </i>\'); %>' +
|
|
||||||
'<% } %>';
|
|
||||||
|
|
||||||
var templateHugeCaption =
|
|
||||||
'<button type="button" class="btn <%= cls %>" id="<%= id %>" data-hint="<%= dataHint %>" data-hint-direction="<%= dataHintDirection %>" data-hint-offset="<%= dataHintOffset %>" <% if (dataHintTitle) { %> data-hint-title="<%= dataHintTitle %>" <% } %>> ' +
|
|
||||||
'<div class="inner-box-icon">' +
|
|
||||||
templateBtnIcon +
|
|
||||||
'</div>' +
|
|
||||||
'<div class="inner-box-caption">' +
|
|
||||||
'<span class="caption"><%= caption %></span>' +
|
|
||||||
'</div>' +
|
|
||||||
'</button>';
|
|
||||||
|
|
||||||
var templateHugeMenuCaption =
|
|
||||||
'<div class="btn-group icon-top" id="<%= id %>" style="<%= style %>">' +
|
|
||||||
'<button type="button" class="btn dropdown-toggle <%= cls %>" data-toggle="dropdown" data-hint="<%= dataHint %>" data-hint-direction="<%= dataHintDirection %>" data-hint-offset="<%= dataHintOffset %>" <% if (dataHintTitle) { %> data-hint-title="<%= dataHintTitle %>" <% } %>>' +
|
|
||||||
'<div class="inner-box-icon">' +
|
|
||||||
templateBtnIcon +
|
|
||||||
'</div>' +
|
|
||||||
'<div class="inner-box-caption">' +
|
|
||||||
'<span class="caption"><%= caption %></span>' +
|
|
||||||
'<i class="caret"></i>' +
|
|
||||||
'</div>' +
|
|
||||||
'</button>' +
|
|
||||||
'</div>';
|
|
||||||
|
|
||||||
var templateHugeSplitCaption =
|
|
||||||
'<div class="btn-group x-huge split icon-top" id="<%= id %>" style="<%= style %>">' +
|
|
||||||
'<button type="button" class="btn <%= cls %> inner-box-icon">' +
|
|
||||||
'<span class="btn-fixflex-hcenter">' +
|
|
||||||
templateBtnIcon +
|
|
||||||
'</span>' +
|
|
||||||
'</button>' +
|
|
||||||
'<button type="button" class="btn <%= cls %> inner-box-caption dropdown-toggle" data-toggle="dropdown" data-hint="<%= dataHint %>" data-hint-direction="<%= dataHintDirection %>" data-hint-offset="<%= dataHintOffset %>" <% if (dataHintTitle) { %> data-hint-title="<%= dataHintTitle %>" <% } %>>' +
|
|
||||||
'<span class="btn-fixflex-vcenter">' +
|
|
||||||
'<span class="caption"><%= caption %></span>' +
|
|
||||||
'<i class="caret"></i>' +
|
|
||||||
'</span>' +
|
|
||||||
'</button>' +
|
|
||||||
'</div>';
|
|
||||||
|
|
||||||
Common.UI.Button = Common.UI.BaseView.extend({
|
|
||||||
options : {
|
|
||||||
id : null,
|
|
||||||
hint : false,
|
|
||||||
enableToggle : false,
|
|
||||||
allowDepress : true,
|
|
||||||
toggleGroup : null,
|
|
||||||
cls : '',
|
|
||||||
iconCls : '',
|
|
||||||
caption : '',
|
|
||||||
menu : null,
|
|
||||||
disabled : false,
|
|
||||||
pressed : false,
|
|
||||||
split : false,
|
|
||||||
visible : true,
|
|
||||||
dataHint : '',
|
|
||||||
dataHintDirection: '',
|
|
||||||
dataHintOffset: '0, 0'
|
|
||||||
},
|
|
||||||
|
|
||||||
template: _.template([
|
|
||||||
'<% var applyicon = function() { %>',
|
|
||||||
'<% if (iconImg) { print(\'<img src=\"\' + iconImg + \'\">\'); } else { %>',
|
|
||||||
// '<% if (iconCls != "") { print(\'<i class=\"icon \' + iconCls + \'\"> </i>\'); }} %>',
|
|
||||||
'<% if (iconCls != "") { ' +
|
|
||||||
' if (/svgicon/.test(iconCls)) {' +
|
|
||||||
'print(\'<svg class=\"icon\"><use class=\"zoom-int\" xlink:href=\"#\' + /svgicon\\s(\\S+)/.exec(iconCls)[1] + \'\"></use>' +
|
|
||||||
'<use class=\"zoom-grit\" xlink:href=\"#\' + /svgicon\\s(\\S+)/.exec(iconCls)[1] + \'-150\"></use></svg>\');' +
|
|
||||||
'} else ' +
|
|
||||||
'print(\'<i class=\"icon \' + iconCls + \'\"> </i>\'); ' +
|
|
||||||
'}} %>',
|
|
||||||
'<% } %>',
|
|
||||||
'<% if ( !menu ) { %>',
|
|
||||||
'<button type="button" class="btn <%= cls %>" id="<%= id %>" style="<%= style %>" data-hint="<%= dataHint %>" data-hint-direction="<%= dataHintDirection %>" data-hint-offset="<%= dataHintOffset %>" <% if (dataHintTitle) { %> data-hint-title="<%= dataHintTitle %>" <% } %>>',
|
|
||||||
'<% applyicon() %>',
|
|
||||||
'<span class="caption"><%= caption %></span>',
|
|
||||||
'</button>',
|
|
||||||
'<% } else if (split == false) {%>',
|
|
||||||
'<div class="btn-group" id="<%= id %>" style="<%= style %>">',
|
|
||||||
'<button type="button" class="btn dropdown-toggle <%= cls %>" data-toggle="dropdown" data-hint="<%= dataHint %>" data-hint-direction="<%= dataHintDirection %>" data-hint-offset="<%= dataHintOffset %>" <% if (dataHintTitle) { %> data-hint-title="<%= dataHintTitle %>" <% } %>>',
|
|
||||||
'<% applyicon() %>',
|
|
||||||
'<span class="caption"><%= caption %></span>',
|
|
||||||
'<span class="inner-box-caret">' +
|
|
||||||
'<i class="caret"></i>' +
|
|
||||||
'</span>',
|
|
||||||
'</button>',
|
|
||||||
'</div>',
|
|
||||||
'<% } else { %>',
|
|
||||||
'<div class="btn-group split" id="<%= id %>" style="<%= style %>">',
|
|
||||||
'<button type="button" class="btn <%= cls %>">',
|
|
||||||
'<% applyicon() %>',
|
|
||||||
'<span class="caption"><%= caption %></span>',
|
|
||||||
'</button>',
|
|
||||||
'<button type="button" class="btn <%= cls %> dropdown-toggle" data-toggle="dropdown" data-hint="<%= dataHint %>" data-hint-direction="<%= dataHintDirection %>" data-hint-offset="<%= dataHintOffset %>" <% if (dataHintTitle) { %> data-hint-title="<%= dataHintTitle %>" <% } %>>',
|
|
||||||
'<i class="caret"></i>',
|
|
||||||
'<span class="sr-only"></span>',
|
|
||||||
'</button>',
|
|
||||||
'</div>',
|
|
||||||
'<% } %>'
|
|
||||||
].join('')),
|
|
||||||
|
|
||||||
initialize : function(options) {
|
|
||||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
|
||||||
|
|
||||||
var me = this;
|
|
||||||
|
|
||||||
me.id = me.options.id || Common.UI.getId();
|
|
||||||
me.hint = me.options.hint;
|
|
||||||
me.enableToggle = me.options.enableToggle;
|
|
||||||
me.allowDepress = me.options.allowDepress;
|
|
||||||
me.cls = me.options.cls;
|
|
||||||
me.iconCls = me.options.iconCls;
|
|
||||||
me.menu = me.options.menu;
|
|
||||||
me.split = me.options.split;
|
|
||||||
me.toggleGroup = me.options.toggleGroup;
|
|
||||||
me.disabled = me.options.disabled;
|
|
||||||
me.visible = me.options.visible;
|
|
||||||
me.pressed = me.options.pressed;
|
|
||||||
me.caption = me.options.caption;
|
|
||||||
me.template = me.options.template || me.template;
|
|
||||||
me.style = me.options.style;
|
|
||||||
me.rendered = false;
|
|
||||||
|
|
||||||
if (me.options.el) {
|
|
||||||
me.render();
|
|
||||||
} else if (me.options.parentEl)
|
|
||||||
me.render(me.options.parentEl);
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function(parentEl) {
|
|
||||||
var me = this;
|
|
||||||
|
|
||||||
me.trigger('render:before', me);
|
|
||||||
|
|
||||||
me.cmpEl = me.$el || $(me.el);
|
|
||||||
|
|
||||||
if (parentEl) {
|
|
||||||
me.setElement(parentEl, false);
|
|
||||||
|
|
||||||
if (!me.rendered) {
|
|
||||||
if ( /icon-top/.test(me.cls) && !!me.caption && /huge/.test(me.cls) ) {
|
|
||||||
if ( me.split === true ) {
|
|
||||||
!!me.cls && (me.cls = me.cls.replace(/\s?(?:x-huge|icon-top)/g, ''));
|
|
||||||
this.template = _.template(templateHugeSplitCaption);
|
|
||||||
} else
|
|
||||||
if ( !!me.menu ) {
|
|
||||||
this.template = _.template(templateHugeMenuCaption);
|
|
||||||
} else {
|
|
||||||
this.template = _.template(templateHugeCaption);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
me.cmpEl = $(this.template({
|
|
||||||
id : me.id,
|
|
||||||
cls : me.cls,
|
|
||||||
iconCls : me.iconCls,
|
|
||||||
iconImg : me.options.iconImg,
|
|
||||||
menu : me.menu,
|
|
||||||
split : me.split,
|
|
||||||
disabled : me.disabled,
|
|
||||||
pressed : me.pressed,
|
|
||||||
caption : me.caption,
|
|
||||||
style : me.style,
|
|
||||||
dataHint : me.options.dataHint,
|
|
||||||
dataHintDirection: me.options.dataHintDirection,
|
|
||||||
dataHintOffset: me.options.dataHintOffset,
|
|
||||||
dataHintTitle: me.options.dataHintTitle
|
|
||||||
}));
|
|
||||||
|
|
||||||
if (me.menu && _.isObject(me.menu) && _.isFunction(me.menu.render))
|
|
||||||
me.menu.render(me.cmpEl);
|
|
||||||
|
|
||||||
parentEl.html(me.cmpEl);
|
|
||||||
me.$icon = me.$el.find('.icon');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!me.rendered) {
|
|
||||||
var el = me.cmpEl,
|
|
||||||
isGroup = el.hasClass('btn-group'),
|
|
||||||
isSplit = el.hasClass('split');
|
|
||||||
|
|
||||||
if (me.options.hint) {
|
|
||||||
var modalParents = me.cmpEl.closest('.asc-window');
|
|
||||||
|
|
||||||
if (typeof me.options.hint == 'object' && me.options.hint.length>1 && $('button', el).length>0) {
|
|
||||||
var btnEl = $('button', el);
|
|
||||||
me.btnEl = $(btnEl[0]);
|
|
||||||
me.btnMenuEl = $(btnEl[1]);
|
|
||||||
} else {
|
|
||||||
me.btnEl = me.cmpEl;
|
|
||||||
me.btnEl.attr('data-toggle', 'tooltip');
|
|
||||||
}
|
|
||||||
me.btnEl.tooltip({
|
|
||||||
title : (typeof me.options.hint == 'string') ? me.options.hint : me.options.hint[0],
|
|
||||||
placement : me.options.hintAnchor||'cursor'
|
|
||||||
});
|
|
||||||
me.btnMenuEl && me.btnMenuEl.tooltip({
|
|
||||||
title : me.options.hint[1],
|
|
||||||
placement : me.options.hintAnchor||'cursor'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (modalParents.length > 0) {
|
|
||||||
me.btnEl.data('bs.tooltip').tip().css('z-index', parseInt(modalParents.css('z-index')) + 10);
|
|
||||||
me.btnMenuEl && me.btnMenuEl.data('bs.tooltip').tip().css('z-index', parseInt(modalParents.css('z-index')) + 10);
|
|
||||||
var onModalClose = function(dlg) {
|
|
||||||
if (modalParents[0] !== dlg.$window[0]) return;
|
|
||||||
var tip = me.btnEl.data('bs.tooltip');
|
|
||||||
if (tip) {
|
|
||||||
if (tip.dontShow===undefined)
|
|
||||||
tip.dontShow = true;
|
|
||||||
|
|
||||||
tip.hide();
|
|
||||||
}
|
|
||||||
Common.NotificationCenter.off({'modal:close': onModalClose});
|
|
||||||
};
|
|
||||||
Common.NotificationCenter.on({'modal:close': onModalClose});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_.isString(me.toggleGroup)) {
|
|
||||||
me.enableToggle = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var buttonHandler = function(e) {
|
|
||||||
if (!me.disabled && e.which == 1) {
|
|
||||||
me.doToggle();
|
|
||||||
if (me.options.hint) {
|
|
||||||
var tip = me.btnEl.data('bs.tooltip');
|
|
||||||
if (tip) {
|
|
||||||
if (tip.dontShow===undefined)
|
|
||||||
tip.dontShow = true;
|
|
||||||
|
|
||||||
tip.hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
me.trigger('click', me, e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var doSplitSelect = function(select, element, e) {
|
|
||||||
if (!select) {
|
|
||||||
// Is mouse under button
|
|
||||||
var isUnderMouse = false;
|
|
||||||
|
|
||||||
$('button', el).each(function(index, button){
|
|
||||||
if ($(button).is(':hover')) {
|
|
||||||
isUnderMouse = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!isUnderMouse) {
|
|
||||||
el.removeClass('over');
|
|
||||||
$('button', el).removeClass('over');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( element == 'button') {
|
|
||||||
if (!select && (me.enableToggle && me.allowDepress && me.pressed))
|
|
||||||
return;
|
|
||||||
if (select && !isSplit && (me.enableToggle && me.allowDepress && !me.pressed)) { // to depress button with menu
|
|
||||||
e.preventDefault();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$('button:first', el).toggleClass('active', select);
|
|
||||||
} else
|
|
||||||
$('[data-toggle^=dropdown]', el).toggleClass('active', select);
|
|
||||||
|
|
||||||
el.toggleClass('active', select);
|
|
||||||
};
|
|
||||||
|
|
||||||
var menuHandler = function(e) {
|
|
||||||
if (!me.disabled && e.which == 1) {
|
|
||||||
if (isSplit) {
|
|
||||||
if (me.options.hint) {
|
|
||||||
var tip = (me.btnMenuEl ? me.btnMenuEl : me.btnEl).data('bs.tooltip');
|
|
||||||
if (tip) {
|
|
||||||
if (tip.dontShow===undefined)
|
|
||||||
tip.dontShow = true;
|
|
||||||
|
|
||||||
tip.hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var isOpen = el.hasClass('open');
|
|
||||||
doSplitSelect(!isOpen, 'arrow', e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var doSetActiveState = function(e, state) {
|
|
||||||
if (isSplit) {
|
|
||||||
doSplitSelect(state, 'button', e);
|
|
||||||
} else {
|
|
||||||
el.toggleClass('active', state);
|
|
||||||
$('button', el).toggleClass('active', state);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var splitElement;
|
|
||||||
var onMouseDown = function (e) {
|
|
||||||
splitElement = e.currentTarget.className.match(/dropdown/) ? 'arrow' : 'button';
|
|
||||||
doSplitSelect(true, splitElement, e);
|
|
||||||
$(document).on('mouseup', onMouseUp);
|
|
||||||
};
|
|
||||||
|
|
||||||
var onMouseUp = function (e) {
|
|
||||||
doSplitSelect(false, splitElement, e);
|
|
||||||
$(document).off('mouseup', onMouseUp);
|
|
||||||
};
|
|
||||||
|
|
||||||
var onAfterHideMenu = function(e, isFromInputControl) {
|
|
||||||
me.cmpEl.find('.dropdown-toggle').blur();
|
|
||||||
if (me.cmpEl.hasClass('active') !== me.pressed)
|
|
||||||
me.cmpEl.trigger('button.internal.active', [me.pressed]);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (isGroup) {
|
|
||||||
if (isSplit) {
|
|
||||||
$('[data-toggle^=dropdown]', el).on('mousedown', _.bind(menuHandler, this));
|
|
||||||
$('button', el).on('mousedown', _.bind(onMouseDown, this));
|
|
||||||
(me.options.width>0) && $('button:first', el).css('width', me.options.width - $('[data-toggle^=dropdown]', el).outerWidth());
|
|
||||||
}
|
|
||||||
|
|
||||||
el.on('hide.bs.dropdown', _.bind(doSplitSelect, me, false, 'arrow'));
|
|
||||||
el.on('show.bs.dropdown', _.bind(doSplitSelect, me, true, 'arrow'));
|
|
||||||
el.on('hidden.bs.dropdown', _.bind(onAfterHideMenu, me));
|
|
||||||
|
|
||||||
$('button:first', el).on('click', buttonHandler);
|
|
||||||
} else {
|
|
||||||
el.on('click', buttonHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
el.on('button.internal.active', _.bind(doSetActiveState, me));
|
|
||||||
|
|
||||||
el.on('mouseover', function(e) {
|
|
||||||
if (!me.disabled) {
|
|
||||||
me.cmpEl.addClass('over');
|
|
||||||
me.trigger('mouseover', me, e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
el.on('mouseout', function(e) {
|
|
||||||
me.cmpEl.removeClass('over');
|
|
||||||
if (!me.disabled) {
|
|
||||||
me.trigger('mouseout', me, e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Register the button in the toggle manager
|
|
||||||
Common.UI.ToggleManager.register(me);
|
|
||||||
}
|
|
||||||
|
|
||||||
me.rendered = true;
|
|
||||||
|
|
||||||
if (me.pressed) {
|
|
||||||
me.toggle(me.pressed, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (me.disabled) {
|
|
||||||
me.setDisabled(!(me.disabled=false));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!me.visible) {
|
|
||||||
me.setVisible(me.visible);
|
|
||||||
}
|
|
||||||
|
|
||||||
me.trigger('render:after', me);
|
|
||||||
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
doToggle: function(){
|
|
||||||
var me = this;
|
|
||||||
if (me.enableToggle && (me.allowDepress !== false || !me.pressed)) {
|
|
||||||
me.toggle();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
toggle: function(toggle, suppressEvent) {
|
|
||||||
var state = toggle === undefined ? !this.pressed : !!toggle;
|
|
||||||
|
|
||||||
this.pressed = state;
|
|
||||||
|
|
||||||
if (this.cmpEl)
|
|
||||||
this.cmpEl.trigger('button.internal.active', [state]);
|
|
||||||
|
|
||||||
if (!suppressEvent)
|
|
||||||
this.trigger('toggle', this, state);
|
|
||||||
},
|
|
||||||
|
|
||||||
click: function(opts) {
|
|
||||||
if ( !this.disabled ) {
|
|
||||||
this.doToggle();
|
|
||||||
this.trigger('click', this, opts);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
isActive: function() {
|
|
||||||
if (this.enableToggle)
|
|
||||||
return this.pressed;
|
|
||||||
|
|
||||||
return this.cmpEl.hasClass('active')
|
|
||||||
},
|
|
||||||
|
|
||||||
setDisabled: function(disabled) {
|
|
||||||
if (this.rendered && this.disabled != disabled) {
|
|
||||||
var el = this.cmpEl,
|
|
||||||
isGroup = el.hasClass('btn-group'),
|
|
||||||
me = this;
|
|
||||||
|
|
||||||
disabled = (disabled===true);
|
|
||||||
|
|
||||||
if (disabled !== el.hasClass('disabled')) {
|
|
||||||
var decorateBtn = function(button) {
|
|
||||||
button.toggleClass('disabled', disabled);
|
|
||||||
if (!me.options.allowMouseEventsOnDisabled)
|
|
||||||
(disabled) ? button.attr({disabled: disabled}) : button.removeAttr('disabled');
|
|
||||||
};
|
|
||||||
|
|
||||||
decorateBtn(el);
|
|
||||||
isGroup && decorateBtn(el.children('button'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((disabled || !Common.Utils.isGecko) && this.options.hint) {
|
|
||||||
var tip = this.btnEl.data('bs.tooltip');
|
|
||||||
if (tip) {
|
|
||||||
disabled && tip.hide();
|
|
||||||
!Common.Utils.isGecko && (tip.enabled = !disabled);
|
|
||||||
}
|
|
||||||
if (this.btnMenuEl) {
|
|
||||||
tip = this.btnMenuEl.data('bs.tooltip');
|
|
||||||
if (tip) {
|
|
||||||
disabled && tip.hide();
|
|
||||||
!Common.Utils.isGecko && (tip.enabled = !disabled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (disabled && this.menu && _.isObject(this.menu) && this.menu.rendered && this.menu.isVisible())
|
|
||||||
setTimeout(function(){ me.menu.hide()}, 1);
|
|
||||||
|
|
||||||
if ( !!me.options.signals ) {
|
|
||||||
var opts = me.options.signals;
|
|
||||||
if ( !(opts.indexOf('disabled') < 0) ) {
|
|
||||||
me.trigger('disabled', me, disabled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.disabled = disabled;
|
|
||||||
},
|
|
||||||
|
|
||||||
isDisabled: function() {
|
|
||||||
return this.disabled;
|
|
||||||
},
|
|
||||||
|
|
||||||
setIconCls: function(cls) {
|
|
||||||
var btnIconEl = $(this.el).find('.icon'),
|
|
||||||
oldCls = this.iconCls;
|
|
||||||
|
|
||||||
this.iconCls = cls;
|
|
||||||
if (/svgicon/.test(this.iconCls)) {
|
|
||||||
var icon = /svgicon\s(\S+)/.exec(this.iconCls);
|
|
||||||
btnIconEl.find('use.zoom-int').attr('xlink:href', icon && icon.length>1 ? '#' + icon[1]: '');
|
|
||||||
btnIconEl.find('use.zoom-grit').attr('xlink:href', icon && icon.length>1 ? '#' + icon[1] + '-150' : '');
|
|
||||||
} else {
|
|
||||||
btnIconEl.removeClass(oldCls);
|
|
||||||
btnIconEl.addClass(cls || '');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
changeIcon: function(opts) {
|
|
||||||
var me = this;
|
|
||||||
if ( opts && (opts.curr || opts.next) && me.$icon) {
|
|
||||||
!!opts.curr && (me.$icon.removeClass(opts.curr));
|
|
||||||
!!opts.next && !me.$icon.hasClass(opts.next) && (me.$icon.addClass(opts.next));
|
|
||||||
|
|
||||||
if ( !!me.options.signals ) {
|
|
||||||
if ( !(me.options.signals.indexOf('icon:changed') < 0) ) {
|
|
||||||
me.trigger('icon:changed', me, opts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
hasIcon: function(iconcls) {
|
|
||||||
return this.$icon.hasClass(iconcls);
|
|
||||||
},
|
|
||||||
|
|
||||||
setVisible: function(visible) {
|
|
||||||
if (this.cmpEl) this.cmpEl.toggleClass('hidden', !visible);
|
|
||||||
this.visible = visible;
|
|
||||||
},
|
|
||||||
|
|
||||||
isVisible: function() {
|
|
||||||
return (this.cmpEl) ? this.cmpEl.is(":visible") : $(this.el).is(":visible");
|
|
||||||
},
|
|
||||||
|
|
||||||
updateHint: function(hint) {
|
|
||||||
this.options.hint = hint;
|
|
||||||
|
|
||||||
if (!this.rendered) return;
|
|
||||||
|
|
||||||
var cmpEl = this.cmpEl,
|
|
||||||
modalParents = cmpEl.closest('.asc-window');
|
|
||||||
|
|
||||||
|
|
||||||
if (!this.btnEl) {
|
|
||||||
if (typeof this.options.hint == 'object' && this.options.hint.length>1 && $('button', cmpEl).length>0) {
|
|
||||||
var btnEl = $('button', cmpEl);
|
|
||||||
this.btnEl = $(btnEl[0]);
|
|
||||||
this.btnMenuEl = $(btnEl[1]);
|
|
||||||
} else {
|
|
||||||
this.btnEl = cmpEl;
|
|
||||||
this.btnEl.attr('data-toggle', 'tooltip');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.btnEl.data('bs.tooltip'))
|
|
||||||
this.btnEl.removeData('bs.tooltip');
|
|
||||||
if (this.btnMenuEl && this.btnMenuEl.data('bs.tooltip'))
|
|
||||||
this.btnMenuEl.removeData('bs.tooltip');
|
|
||||||
|
|
||||||
this.btnEl.tooltip({
|
|
||||||
title : (typeof hint == 'string') ? hint : hint[0],
|
|
||||||
placement : this.options.hintAnchor||'cursor'
|
|
||||||
});
|
|
||||||
this.btnMenuEl && this.btnMenuEl.tooltip({
|
|
||||||
title : hint[1],
|
|
||||||
placement : this.options.hintAnchor||'cursor'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (modalParents.length > 0) {
|
|
||||||
this.btnEl.data('bs.tooltip').tip().css('z-index', parseInt(modalParents.css('z-index')) + 10);
|
|
||||||
this.btnMenuEl && this.btnMenuEl.data('bs.tooltip').tip().css('z-index', parseInt(modalParents.css('z-index')) + 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.disabled || !Common.Utils.isGecko) {
|
|
||||||
var tip = this.btnEl.data('bs.tooltip');
|
|
||||||
if (tip) {
|
|
||||||
this.disabled && tip.hide();
|
|
||||||
!Common.Utils.isGecko && (tip.enabled = !this.disabled);
|
|
||||||
}
|
|
||||||
if (this.btnMenuEl) {
|
|
||||||
tip = this.btnMenuEl.data('bs.tooltip');
|
|
||||||
if (tip) {
|
|
||||||
this.disabled && tip.hide();
|
|
||||||
!Common.Utils.isGecko && (tip.enabled = !this.disabled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
setCaption: function(caption) {
|
|
||||||
if (this.caption != caption) {
|
|
||||||
this.caption = caption;
|
|
||||||
|
|
||||||
if (this.rendered) {
|
|
||||||
var captionNode = this.cmpEl.find('.caption');
|
|
||||||
|
|
||||||
if (captionNode.length > 0) {
|
|
||||||
captionNode.text(caption);
|
|
||||||
} else {
|
|
||||||
this.cmpEl.find('button:first').addBack().filter('button').text(caption);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
setMenu: function (m) {
|
|
||||||
if (m && _.isObject(m) && _.isFunction(m.render)){
|
|
||||||
this.menu = m;
|
|
||||||
if (this.rendered)
|
|
||||||
this.menu.render(this.cmpEl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,394 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* (c) Copyright Ascensio System SIA 2010-2019
|
|
||||||
*
|
|
||||||
* This program is a free software product. You can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
|
||||||
* version 3 as published by the Free Software Foundation. In accordance with
|
|
||||||
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
|
||||||
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
|
||||||
* of any third-party rights.
|
|
||||||
*
|
|
||||||
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
|
||||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
|
||||||
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
|
||||||
*
|
|
||||||
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
|
|
||||||
* street, Riga, Latvia, EU, LV-1050.
|
|
||||||
*
|
|
||||||
* The interactive user interfaces in modified source and object code versions
|
|
||||||
* of the Program must display Appropriate Legal Notices, as required under
|
|
||||||
* Section 5 of the GNU AGPL version 3.
|
|
||||||
*
|
|
||||||
* Pursuant to Section 7(b) of the License you must retain the original Product
|
|
||||||
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
|
||||||
* grant you any rights under trademark law for use of our trademarks.
|
|
||||||
*
|
|
||||||
* All the Product's GUI elements, including illustrations and icon sets, as
|
|
||||||
* well as technical writing content are licensed under the terms of the
|
|
||||||
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
|
||||||
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* MenuItem.js
|
|
||||||
*
|
|
||||||
* A base class for all menu items that require menu-related functionality such as click handling,
|
|
||||||
* sub-menus, icons, etc.
|
|
||||||
*
|
|
||||||
* Created by Alexander Yuzhin on 1/27/14
|
|
||||||
* Copyright (c) 2018 Ascensio System SIA. All rights reserved.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default template
|
|
||||||
*
|
|
||||||
* Simple menu item:
|
|
||||||
* <li><a href="#">Caption</a></li>
|
|
||||||
*
|
|
||||||
* Separator:
|
|
||||||
* <li class="divider"></li>
|
|
||||||
*
|
|
||||||
* Menu item with sub-menu:
|
|
||||||
* <li class="dropdown-submenu">
|
|
||||||
* <a href="#">Sub-menu item</a>
|
|
||||||
* <ul class="dropdown-menu"></ul>
|
|
||||||
* </li>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Example usage:
|
|
||||||
*
|
|
||||||
* new Common.UI.MenuItem({
|
|
||||||
* caption: 'View Compact Toolbar',
|
|
||||||
* checkable: true,
|
|
||||||
* menu: {
|
|
||||||
* items: [
|
|
||||||
* { caption: 'Menu item 1', value: 'value-1' },
|
|
||||||
* { caption: 'Menu item 2', value: 'value-2' },
|
|
||||||
* new Common.UI.MenuItem({ caption: 'Menu item 3', value: 'value-3' })
|
|
||||||
* ]
|
|
||||||
* }
|
|
||||||
* });
|
|
||||||
*
|
|
||||||
* @property {Object} value
|
|
||||||
*
|
|
||||||
* @property {Common.UI.Menu} menu
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
if (Common === undefined)
|
|
||||||
var Common = {};
|
|
||||||
|
|
||||||
define([
|
|
||||||
'common/main/lib/component/BaseView',
|
|
||||||
'common/main/lib/component/ToggleManager'
|
|
||||||
], function () {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
Common.UI.MenuItem = Common.UI.BaseView.extend({
|
|
||||||
options : {
|
|
||||||
id : null,
|
|
||||||
cls : '',
|
|
||||||
style : '',
|
|
||||||
hint : false,
|
|
||||||
checkable : false,
|
|
||||||
checked : false,
|
|
||||||
allowDepress: false,
|
|
||||||
disabled : false,
|
|
||||||
value : null,
|
|
||||||
toggleGroup : null,
|
|
||||||
iconCls : '',
|
|
||||||
menu : null,
|
|
||||||
canFocused : true,
|
|
||||||
dataHint : '',
|
|
||||||
dataHintDirection: '',
|
|
||||||
dataHintOffset: ''
|
|
||||||
},
|
|
||||||
|
|
||||||
tagName : 'li',
|
|
||||||
|
|
||||||
template: _.template([
|
|
||||||
'<a id="<%= id %>" style="<%= style %>" <% if(options.canFocused) { %> tabindex="-1" type="menuitem" <% }; if(!_.isUndefined(options.stopPropagation)) { %> data-stopPropagation="true" <% }; if(!_.isUndefined(options.dataHint)) { %> data-hint="<%= options.dataHint %>" <% }; if(!_.isUndefined(options.dataHintDirection)) { %> data-hint-direction="<%= options.dataHintDirection %>" <% }; if(!_.isUndefined(options.dataHintOffset)) { %> data-hint-offset="<%= options.dataHintOffset %>" <% }; %> >',
|
|
||||||
'<% if (!_.isEmpty(iconCls)) { %>',
|
|
||||||
'<span class="menu-item-icon <%= iconCls %>"></span>',
|
|
||||||
'<% } %>',
|
|
||||||
'<%= caption %>',
|
|
||||||
'</a>'
|
|
||||||
].join('')),
|
|
||||||
|
|
||||||
initialize : function(options) {
|
|
||||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
|
||||||
|
|
||||||
var me = this;
|
|
||||||
|
|
||||||
this.id = me.options.id || Common.UI.getId();
|
|
||||||
this.cls = me.options.cls;
|
|
||||||
this.style = me.options.style;
|
|
||||||
this.caption = me.options.caption;
|
|
||||||
this.menu = me.options.menu || null;
|
|
||||||
this.checkable = me.options.checkable;
|
|
||||||
this.checked = me.options.checked;
|
|
||||||
me.allowDepress = me.options.allowDepress;
|
|
||||||
this.disabled = me.options.disabled;
|
|
||||||
this.value = me.options.value;
|
|
||||||
this.toggleGroup = me.options.toggleGroup;
|
|
||||||
this.template = me.options.template || this.template;
|
|
||||||
this.iconCls = me.options.iconCls;
|
|
||||||
this.hint = me.options.hint;
|
|
||||||
this.rendered = false;
|
|
||||||
|
|
||||||
if (this.menu !== null && !(this.menu instanceof Common.UI.Menu) && !(this.menu instanceof Common.UI.MenuSimple)) {
|
|
||||||
this.menu = new Common.UI.Menu(_.extend({}, me.options.menu));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (me.options.el)
|
|
||||||
this.render();
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function() {
|
|
||||||
var me = this,
|
|
||||||
el = me.$el || $(this.el);
|
|
||||||
|
|
||||||
me.trigger('render:before', me);
|
|
||||||
|
|
||||||
if (me.caption === '--') {
|
|
||||||
el.addClass('divider');
|
|
||||||
} else {
|
|
||||||
if (!this.rendered) {
|
|
||||||
el.off('click');
|
|
||||||
Common.UI.ToggleManager.unregister(me);
|
|
||||||
|
|
||||||
el.html(this.template({
|
|
||||||
id : me.id,
|
|
||||||
caption : me.caption,
|
|
||||||
iconCls : me.iconCls,
|
|
||||||
style : me.style,
|
|
||||||
options : me.options
|
|
||||||
}));
|
|
||||||
|
|
||||||
if (me.menu) {
|
|
||||||
el.addClass('dropdown-submenu');
|
|
||||||
|
|
||||||
me.menu.render(el);
|
|
||||||
el.mouseenter(_.bind(me.menu.alignPosition, me.menu));
|
|
||||||
// el.focusin(_.bind(me.onFocusItem, me));
|
|
||||||
el.focusout(_.bind(me.onBlurItem, me));
|
|
||||||
el.hover(
|
|
||||||
_.bind(me.onHoverItem, me),
|
|
||||||
_.bind(me.onUnHoverItem, me)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
var firstChild = el.children(':first');
|
|
||||||
|
|
||||||
if (this.checkable && firstChild) {
|
|
||||||
firstChild.toggleClass('checkable', this.checkable);
|
|
||||||
firstChild.toggleClass('no-checkmark', this.options.checkmark===false);
|
|
||||||
firstChild.toggleClass('checked', this.checked);
|
|
||||||
if (!_.isEmpty(this.iconCls)) {
|
|
||||||
firstChild.css('background-image', 'none');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (me.options.hint) {
|
|
||||||
el.attr('data-toggle', 'tooltip');
|
|
||||||
el.tooltip({
|
|
||||||
title : me.options.hint,
|
|
||||||
placement : me.options.hintAnchor||function(tip, element) {
|
|
||||||
var pos = this.getPosition(),
|
|
||||||
actualWidth = tip.offsetWidth,
|
|
||||||
actualHeight = tip.offsetHeight,
|
|
||||||
innerWidth = Common.Utils.innerWidth(),
|
|
||||||
innerHeight = Common.Utils.innerHeight();
|
|
||||||
var top = pos.top,
|
|
||||||
left = pos.left + pos.width + 2;
|
|
||||||
if (top + actualHeight > innerHeight) {
|
|
||||||
top = innerHeight - actualHeight - 2;
|
|
||||||
}
|
|
||||||
if (left + actualWidth > innerWidth) {
|
|
||||||
left = pos.left - actualWidth - 2;
|
|
||||||
}
|
|
||||||
$(tip).offset({top: top,left: left}).addClass('in');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.disabled)
|
|
||||||
el.toggleClass('disabled', this.disabled);
|
|
||||||
|
|
||||||
el.on('click', _.bind(this.onItemClick, this));
|
|
||||||
el.on('mousedown', _.bind(this.onItemMouseDown, this));
|
|
||||||
|
|
||||||
Common.UI.ToggleManager.register(me);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
me.cmpEl = el;
|
|
||||||
me.rendered = true;
|
|
||||||
|
|
||||||
me.trigger('render:after', me);
|
|
||||||
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
setCaption: function(caption, noencoding) {
|
|
||||||
this.caption = caption;
|
|
||||||
|
|
||||||
if (this.rendered)
|
|
||||||
this.cmpEl.find('a').contents().last()[0].textContent = (noencoding) ? caption : Common.Utils.String.htmlEncode(caption);
|
|
||||||
},
|
|
||||||
|
|
||||||
setIconCls: function(iconCls) {
|
|
||||||
if (this.rendered && !_.isEmpty(this.iconCls)) {
|
|
||||||
var firstChild = this.cmpEl.children(':first');
|
|
||||||
if (firstChild) {
|
|
||||||
firstChild.find('.menu-item-icon').removeClass(this.iconCls).addClass(iconCls);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.iconCls = iconCls;
|
|
||||||
},
|
|
||||||
|
|
||||||
setChecked: function(check, suppressEvent) {
|
|
||||||
this.toggle(check, suppressEvent);
|
|
||||||
},
|
|
||||||
|
|
||||||
isChecked: function() {
|
|
||||||
return this.checked;
|
|
||||||
},
|
|
||||||
|
|
||||||
setDisabled: function(disabled) {
|
|
||||||
this.disabled = !!disabled;
|
|
||||||
|
|
||||||
if (this.rendered)
|
|
||||||
this.cmpEl.toggleClass('disabled', this.disabled);
|
|
||||||
},
|
|
||||||
|
|
||||||
isDisabled: function() {
|
|
||||||
return this.disabled;
|
|
||||||
},
|
|
||||||
|
|
||||||
toggle: function(toggle, suppressEvent) {
|
|
||||||
var state = toggle === undefined ? !this.checked : !!toggle;
|
|
||||||
|
|
||||||
if (this.checkable) {
|
|
||||||
this.checked = state;
|
|
||||||
|
|
||||||
if (this.rendered) {
|
|
||||||
var firstChild = this.cmpEl.children(':first');
|
|
||||||
|
|
||||||
if (firstChild) {
|
|
||||||
firstChild.toggleClass('checked', this.checked);
|
|
||||||
if (!_.isEmpty(this.iconCls)) {
|
|
||||||
firstChild.css('background-image', 'none');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!suppressEvent)
|
|
||||||
this.trigger('toggle', this, state);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onItemMouseDown: function(e) {
|
|
||||||
if (e.which != 1) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
e.stopPropagation();
|
|
||||||
},
|
|
||||||
|
|
||||||
onItemClick: function(e) {
|
|
||||||
if (e.which != 1 && (e.which !== undefined || this.menu))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!this.disabled && (this.allowDepress || !(this.checked && this.toggleGroup)) && !this.menu)
|
|
||||||
this.setChecked(!this.checked);
|
|
||||||
|
|
||||||
if (this.menu) {
|
|
||||||
if (e.target.id == this.id) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.menu.isOver)
|
|
||||||
this.cmpEl.removeClass('over');
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.disabled) {
|
|
||||||
this.trigger('click', this, e);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onHoverItem: function(e) {
|
|
||||||
this._doHover(e);
|
|
||||||
// $('a', this.cmpEl).focus();
|
|
||||||
},
|
|
||||||
|
|
||||||
onUnHoverItem: function(e) {
|
|
||||||
this._doUnHover(e);
|
|
||||||
// $('a', this.cmpEl).blur();
|
|
||||||
},
|
|
||||||
|
|
||||||
// onFocusItem: function(e) {
|
|
||||||
// this._doHover(e);
|
|
||||||
// },
|
|
||||||
|
|
||||||
onBlurItem: function(e) {
|
|
||||||
this._doUnHover(e);
|
|
||||||
},
|
|
||||||
|
|
||||||
_doHover: function(e) {
|
|
||||||
var me = this;
|
|
||||||
|
|
||||||
if (me.menu && !me.disabled) {
|
|
||||||
clearTimeout(me.hideMenuTimer);
|
|
||||||
|
|
||||||
me.cmpEl.trigger('show.bs.dropdown');
|
|
||||||
me.expandMenuTimer = _.delay(function(){
|
|
||||||
me.cmpEl.addClass('over');
|
|
||||||
me.cmpEl.trigger('shown.bs.dropdown');
|
|
||||||
}, 200);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_doUnHover: function(e) {
|
|
||||||
var me = this;
|
|
||||||
if (me.cmpEl.hasClass('dropdown-submenu') && me.cmpEl.hasClass('over') &&
|
|
||||||
(e && e.relatedTarget && me.cmpEl.find(e.relatedTarget).length>0 || me.cmpEl.hasClass('focused-submenu'))) {
|
|
||||||
// When focus go from menuItem to it's submenu don't hide this submenu
|
|
||||||
me.cmpEl.removeClass('focused-submenu');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (me.menu && !me.disabled) {
|
|
||||||
clearTimeout(me.expandMenuTimer);
|
|
||||||
|
|
||||||
me.hideMenuTimer = _.delay(function(){
|
|
||||||
if (!me.menu.isOver)
|
|
||||||
me.cmpEl.removeClass('over');
|
|
||||||
}, 200);
|
|
||||||
|
|
||||||
if (e && e.type !== 'focusout') { // when mouseleave from clicked menu item with submenu
|
|
||||||
var focused = me.cmpEl.children(':focus');
|
|
||||||
if (focused.length>0) {
|
|
||||||
focused.blur();
|
|
||||||
me.cmpEl.closest('ul').focus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Common.UI.MenuItemSeparator = function(options) {
|
|
||||||
options = options || {};
|
|
||||||
options.caption = '--';
|
|
||||||
return new Common.UI.MenuItem(options);
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -1,180 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* (c) Copyright Ascensio System SIA 2010-2019
|
|
||||||
*
|
|
||||||
* This program is a free software product. You can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
|
||||||
* version 3 as published by the Free Software Foundation. In accordance with
|
|
||||||
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
|
||||||
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
|
||||||
* of any third-party rights.
|
|
||||||
*
|
|
||||||
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
|
||||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
|
||||||
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
|
||||||
*
|
|
||||||
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
|
|
||||||
* street, Riga, Latvia, EU, LV-1050.
|
|
||||||
*
|
|
||||||
* The interactive user interfaces in modified source and object code versions
|
|
||||||
* of the Program must display Appropriate Legal Notices, as required under
|
|
||||||
* Section 5 of the GNU AGPL version 3.
|
|
||||||
*
|
|
||||||
* Pursuant to Section 7(b) of the License you must retain the original Product
|
|
||||||
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
|
||||||
* grant you any rights under trademark law for use of our trademarks.
|
|
||||||
*
|
|
||||||
* All the Product's GUI elements, including illustrations and icon sets, as
|
|
||||||
* well as technical writing content are licensed under the terms of the
|
|
||||||
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
|
||||||
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Scroller.js
|
|
||||||
*
|
|
||||||
* Created by Alexander Yuzhin on 3/14/14
|
|
||||||
* Copyright (c) 2018 Ascensio System SIA. All rights reserved.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (Common === undefined)
|
|
||||||
var Common = {};
|
|
||||||
|
|
||||||
define([
|
|
||||||
'vendor/perfect-scrollbar/src/jquery.mousewheel',
|
|
||||||
'test/unit-tests/common/main/lib/mods/perfectscrollbar',
|
|
||||||
'test/unit-tests/common/main/lib/component/BaseView'
|
|
||||||
], function () { 'use strict';
|
|
||||||
|
|
||||||
Common.UI.Scroller = (function(){
|
|
||||||
var mouseCapture;
|
|
||||||
|
|
||||||
return _.extend(Common.UI.BaseView.extend({
|
|
||||||
options: {
|
|
||||||
wheelSpeed : 20,
|
|
||||||
wheelPropagation : false,
|
|
||||||
minScrollbarLength : null,
|
|
||||||
useBothWheelAxes : false,
|
|
||||||
useKeyboard : true,
|
|
||||||
suppressScrollX : false,
|
|
||||||
suppressScrollY : false,
|
|
||||||
scrollXMarginOffset : 5,
|
|
||||||
scrollYMarginOffset : 5,
|
|
||||||
includePadding : true,
|
|
||||||
includeMargin : true,
|
|
||||||
alwaysVisibleX : false,
|
|
||||||
alwaysVisibleY : false
|
|
||||||
},
|
|
||||||
|
|
||||||
initialize: function(options) {
|
|
||||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
|
||||||
|
|
||||||
if (this.options.el) {
|
|
||||||
this.render();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function() {
|
|
||||||
var me = this;
|
|
||||||
|
|
||||||
me.cmpEl = me.$el || $(this.el);
|
|
||||||
|
|
||||||
if (!me.rendered) {
|
|
||||||
me.cmpEl.perfectScrollbar(_.extend({}, me.options));
|
|
||||||
me.rendered = true;
|
|
||||||
|
|
||||||
this.setAlwaysVisibleX(me.options.alwaysVisibleX);
|
|
||||||
this.setAlwaysVisibleY(me.options.alwaysVisibleY);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
remove: function() {
|
|
||||||
this.destroy();
|
|
||||||
Backbone.View.prototype.remove.call(this);
|
|
||||||
},
|
|
||||||
|
|
||||||
update: function(config) {
|
|
||||||
var options = this.options;
|
|
||||||
if (config) {
|
|
||||||
this.destroy();
|
|
||||||
options = _.extend(this.options, config);
|
|
||||||
this.cmpEl.perfectScrollbar(options);
|
|
||||||
} else {
|
|
||||||
this.cmpEl.perfectScrollbar('update');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setAlwaysVisibleX(options.alwaysVisibleX);
|
|
||||||
this.setAlwaysVisibleY(options.alwaysVisibleY);
|
|
||||||
|
|
||||||
// Emulate capture scroller
|
|
||||||
var mouseDownHandler = function(e) {
|
|
||||||
mouseCapture = true;
|
|
||||||
|
|
||||||
var upHandler = function(e) {
|
|
||||||
$(document).unbind('mouseup', upHandler);
|
|
||||||
_.delay(function() {
|
|
||||||
mouseCapture = false;
|
|
||||||
}, 10);
|
|
||||||
};
|
|
||||||
|
|
||||||
$(document).mouseup(upHandler);
|
|
||||||
};
|
|
||||||
|
|
||||||
$('.ps-scrollbar-x-rail, .ps-scrollbar-y-rail, .ps-scrollbar-x, .ps-scrollbar-y', this.cmpEl)
|
|
||||||
.off('mousedown', mouseDownHandler).on('mousedown', mouseDownHandler);
|
|
||||||
},
|
|
||||||
|
|
||||||
destroy: function() {
|
|
||||||
this.cmpEl.perfectScrollbar('destroy');
|
|
||||||
},
|
|
||||||
|
|
||||||
scrollLeft: function(pos) {
|
|
||||||
this.cmpEl.scrollLeft(pos);
|
|
||||||
this.update();
|
|
||||||
},
|
|
||||||
|
|
||||||
scrollTop: function(pos) {
|
|
||||||
this.cmpEl.scrollTop(pos);
|
|
||||||
this.update();
|
|
||||||
},
|
|
||||||
|
|
||||||
getScrollTop: function () {
|
|
||||||
return this.cmpEl.scrollTop();
|
|
||||||
},
|
|
||||||
|
|
||||||
getScrollLeft: function () {
|
|
||||||
return this.cmpEl.scrollLeft();
|
|
||||||
},
|
|
||||||
setAlwaysVisibleX: function(flag) {
|
|
||||||
if (flag) {
|
|
||||||
$(this.el).find('.ps-scrollbar-x-rail').addClass('always-visible-x');
|
|
||||||
$(this.el).find('.ps-scrollbar-x').addClass('always-visible-x');
|
|
||||||
} else {
|
|
||||||
$(this.el).find('.ps-scrollbar-x-rail').removeClass('always-visible-x');
|
|
||||||
$(this.el).find('.ps-scrollbar-x').addClass('always-visible-x');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setAlwaysVisibleY: function(flag) {
|
|
||||||
if (flag) {
|
|
||||||
$(this.el).find('.ps-scrollbar-y-rail').addClass('always-visible-y');
|
|
||||||
$(this.el).find('.ps-scrollbar-y').addClass('always-visible-y');
|
|
||||||
} else {
|
|
||||||
$(this.el).find('.ps-scrollbar-y-rail').removeClass('always-visible-y');
|
|
||||||
$(this.el).find('.ps-scrollbar-y').addClass('always-visible-y');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
isVisible: function() {
|
|
||||||
return $(this.el).find('.ps-scrollbar-y-rail').is(':visible');
|
|
||||||
}
|
|
||||||
|
|
||||||
}), {
|
|
||||||
isMouseCapture: function() {
|
|
||||||
return mouseCapture
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})();
|
|
||||||
});
|
|
|
@ -1,115 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* (c) Copyright Ascensio System SIA 2010-2019
|
|
||||||
*
|
|
||||||
* This program is a free software product. You can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
|
||||||
* version 3 as published by the Free Software Foundation. In accordance with
|
|
||||||
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
|
||||||
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
|
||||||
* of any third-party rights.
|
|
||||||
*
|
|
||||||
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
|
||||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
|
||||||
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
|
||||||
*
|
|
||||||
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
|
|
||||||
* street, Riga, Latvia, EU, LV-1050.
|
|
||||||
*
|
|
||||||
* The interactive user interfaces in modified source and object code versions
|
|
||||||
* of the Program must display Appropriate Legal Notices, as required under
|
|
||||||
* Section 5 of the GNU AGPL version 3.
|
|
||||||
*
|
|
||||||
* Pursuant to Section 7(b) of the License you must retain the original Product
|
|
||||||
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
|
||||||
* grant you any rights under trademark law for use of our trademarks.
|
|
||||||
*
|
|
||||||
* All the Product's GUI elements, including illustrations and icon sets, as
|
|
||||||
* well as technical writing content are licensed under the terms of the
|
|
||||||
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
|
||||||
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* ToggleManager.js
|
|
||||||
*
|
|
||||||
* Created by Alexander Yuzhin on 1/28/14
|
|
||||||
* Copyright (c) 2018 Ascensio System SIA. All rights reserved.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
if (Common === undefined)
|
|
||||||
var Common = {};
|
|
||||||
|
|
||||||
define([
|
|
||||||
'unit-tests/common/main/lib/component/BaseView'
|
|
||||||
], function () {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var groups = {};
|
|
||||||
|
|
||||||
function toggleGroup(cmp, state) {
|
|
||||||
var g, i, l;
|
|
||||||
if (state) {
|
|
||||||
g = groups[cmp.toggleGroup];
|
|
||||||
for (i = 0, l = g.length; i < l; i++) {
|
|
||||||
if (g[i] !== cmp) {
|
|
||||||
if (g[i].isActive) {
|
|
||||||
g[i].isActive() && g[i].toggle(false);
|
|
||||||
} else {
|
|
||||||
g[i].toggle(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private utility class used by component
|
|
||||||
*/
|
|
||||||
Common.UI.ToggleManager = {
|
|
||||||
register: function(cmp) {
|
|
||||||
if (!cmp.toggleGroup) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var group = groups[cmp.toggleGroup];
|
|
||||||
if (!group) {
|
|
||||||
group = groups[cmp.toggleGroup] = [];
|
|
||||||
}
|
|
||||||
group.push(cmp);
|
|
||||||
cmp.on('toggle', toggleGroup);
|
|
||||||
},
|
|
||||||
|
|
||||||
unregister: function(cmp) {
|
|
||||||
if (!cmp.toggleGroup) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var group = groups[cmp.toggleGroup];
|
|
||||||
if (group) {
|
|
||||||
_.without(group, cmp);
|
|
||||||
cmp.off('toggle', toggleGroup);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the toggled components in the passed group or null
|
|
||||||
* @param {String} group
|
|
||||||
* @return {Common.UI.BaseView}
|
|
||||||
*/
|
|
||||||
getToggled: function(group) {
|
|
||||||
var g = groups[group],
|
|
||||||
i = 0,
|
|
||||||
len;
|
|
||||||
if (g) {
|
|
||||||
for (len = g.length; i < len; i++) {
|
|
||||||
if (g[i].pressed === true ||
|
|
||||||
g[i].checked === true) {
|
|
||||||
return g[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -87,7 +87,7 @@ common.controller.CellEditor = new(function(){
|
||||||
editor.$el.find('#ce-cell-name').on( 'keyup', onCellName);
|
editor.$el.find('#ce-cell-name').on( 'keyup', onCellName);
|
||||||
editor.$el.find('textarea#ce-cell-content').on( 'keyup', onKeyupCellEditor);
|
editor.$el.find('textarea#ce-cell-content').on( 'keyup', onKeyupCellEditor);
|
||||||
editor.$el.find('textarea#ce-cell-content').on('blur', onBlurCellEditor);
|
editor.$el.find('textarea#ce-cell-content').on('blur', onBlurCellEditor);
|
||||||
editor.$el.find('button#ce-btn-expand').on('click', expandEditorField);/*,
|
//editor.$el.find('button#ce-btn-expand').on('click', expandEditorField);/*,
|
||||||
/*'click button#ce-func-label': onInsertFunction*/
|
/*'click button#ce-func-label': onInsertFunction*/
|
||||||
}
|
}
|
||||||
function createController() {
|
function createController() {
|
||||||
|
@ -102,7 +102,7 @@ common.controller.CellEditor = new(function(){
|
||||||
}
|
}
|
||||||
function onLayoutResize(o, r) {
|
function onLayoutResize(o, r) {
|
||||||
if (r == 'cell:edit') {
|
if (r == 'cell:edit') {
|
||||||
if (Math.floor(editor.$el.height()) > 19) {
|
/*if (Math.floor(editor.$el.height()) > 19) {
|
||||||
if (!editor.$btnexpand.hasClass('btn-collapse')) {
|
if (!editor.$btnexpand.hasClass('btn-collapse')) {
|
||||||
editor.$el.addClass('expanded');
|
editor.$el.addClass('expanded');
|
||||||
editor.$btnexpand['addClass']('btn-collapse');
|
editor.$btnexpand['addClass']('btn-collapse');
|
||||||
|
@ -110,11 +110,11 @@ common.controller.CellEditor = new(function(){
|
||||||
|
|
||||||
o && common.localStorage.setItem('sse-celleditor-height', editor.$el.height());
|
o && common.localStorage.setItem('sse-celleditor-height', editor.$el.height());
|
||||||
o && common.localStorage.setBool('sse-celleditor-expand', true);
|
o && common.localStorage.setBool('sse-celleditor-expand', true);
|
||||||
} else {
|
} else {*/
|
||||||
editor.$el.removeClass('expanded');
|
editor.$el.removeClass('expanded');
|
||||||
editor.$btnexpand['removeClass']('btn-collapse');
|
editor.$btnexpand['removeClass']('btn-collapse');
|
||||||
o && common.localStorage.setBool('sse-celleditor-expand', false);
|
o && common.localStorage.setBool('sse-celleditor-expand', false);
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function onLaunch(){
|
function onLaunch(){
|
||||||
|
|
|
@ -1,77 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* (c) Copyright Ascensio System SIA 2010-2019
|
|
||||||
*
|
|
||||||
* This program is a free software product. You can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
|
||||||
* version 3 as published by the Free Software Foundation. In accordance with
|
|
||||||
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
|
||||||
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
|
||||||
* of any third-party rights.
|
|
||||||
*
|
|
||||||
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
|
||||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
|
||||||
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
|
||||||
*
|
|
||||||
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
|
|
||||||
* street, Riga, Latvia, EU, LV-1050.
|
|
||||||
*
|
|
||||||
* The interactive user interfaces in modified source and object code versions
|
|
||||||
* of the Program must display Appropriate Legal Notices, as required under
|
|
||||||
* Section 5 of the GNU AGPL version 3.
|
|
||||||
*
|
|
||||||
* Pursuant to Section 7(b) of the License you must retain the original Product
|
|
||||||
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
|
||||||
* grant you any rights under trademark law for use of our trademarks.
|
|
||||||
*
|
|
||||||
* All the Product's GUI elements, including illustrations and icon sets, as
|
|
||||||
* well as technical writing content are licensed under the terms of the
|
|
||||||
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
|
||||||
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* NotificationCenter.js
|
|
||||||
*
|
|
||||||
* A pub-sub object that can be used to decouple various parts
|
|
||||||
* of an application through event-driven architecture.
|
|
||||||
*
|
|
||||||
* Created by Alexander Yuzhin on 1/21/14
|
|
||||||
* Copyright (c) 2018 Ascensio System SIA. All rights reserved.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Using:
|
|
||||||
*
|
|
||||||
* Common.NotificationCenter.on("foo", function(){
|
|
||||||
* alert("bar");
|
|
||||||
* });
|
|
||||||
*
|
|
||||||
* Common.NotificationCenter.trigger("foo"); // => alert box "bar"
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (Common === undefined)
|
|
||||||
var Common = {};
|
|
||||||
/*if (Backbone === undefined)
|
|
||||||
var Backbone = ;*/
|
|
||||||
Common.NotificationCenter=new( function (Backbone) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var NotificationCenter = function(){};
|
|
||||||
|
|
||||||
// Copy the basic Backbone.Events on to the event aggregator
|
|
||||||
_.extend(NotificationCenter.prototype, Backbone.Events);
|
|
||||||
|
|
||||||
if(typeof Common.NotificationCenter == 'undefined') {
|
|
||||||
// Method to create new Common.NotificationCenter class
|
|
||||||
NotificationCenter.extend = Backbone.Model.extend;
|
|
||||||
|
|
||||||
Common.NotificationCenter = new NotificationCenter();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw ('Native Common.NotificationCenter instance already defined.')
|
|
||||||
}
|
|
||||||
})();
|
|
|
@ -1,565 +0,0 @@
|
||||||
Backbone=new(function(){
|
|
||||||
var resolveNamespace = function(className, root) {
|
|
||||||
var parts = className.split('.'),
|
|
||||||
current = root || window;
|
|
||||||
|
|
||||||
for(var a = 0, b = parts.length; a < b; a++) {
|
|
||||||
current = current[parts[a]] || {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return current;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class Backbone.Application
|
|
||||||
* @cfg {Object} options The list of options available within Application
|
|
||||||
*/
|
|
||||||
var Application = function(options) {
|
|
||||||
_.extend(this, options || {});
|
|
||||||
|
|
||||||
this.eventbus = new EventBus({application: this});
|
|
||||||
|
|
||||||
this.createApplicationNamespace();
|
|
||||||
this.initialize.apply(this, arguments);
|
|
||||||
|
|
||||||
if (this.autoCreate !== false)
|
|
||||||
$($.proxy(this.onReady, this));
|
|
||||||
};
|
|
||||||
|
|
||||||
_.extend(Application.prototype, {
|
|
||||||
/**
|
|
||||||
* @cfg {Object} nameSpace (required)
|
|
||||||
* Define the application namespace
|
|
||||||
*/
|
|
||||||
nameSpace: 'Application',
|
|
||||||
|
|
||||||
models: {},
|
|
||||||
collections: {},
|
|
||||||
controllers: {},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @cfg allocationMap Define the inner structure of our application object
|
|
||||||
* @cfg allocationMap.model The key for models map
|
|
||||||
* @cfg allocationMap.collection The key for collections map
|
|
||||||
* @cfg allocationMap.controller The key for controllers map
|
|
||||||
* @cfg allocationMap.view The key for views map
|
|
||||||
*/
|
|
||||||
allocationMap: {
|
|
||||||
model: 'Models',
|
|
||||||
collection: 'Collections',
|
|
||||||
controller: 'Controllers',
|
|
||||||
view: 'Views'
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to create inner structure of the application using {@link #allocationMap allocationMap} config
|
|
||||||
*/
|
|
||||||
createApplicationNamespace: function() {
|
|
||||||
var nameSpace = window;
|
|
||||||
|
|
||||||
// create global reference in the defined namespace
|
|
||||||
if(this.nameSpace) {
|
|
||||||
// if it wasn't already defined, create it
|
|
||||||
if(typeof nameSpace[this.nameSpace] == 'undefined') {
|
|
||||||
nameSpace[this.nameSpace] = {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// let's have a link to the application namespace
|
|
||||||
// this way we will be able to get all references to Models, Collections and Controllers
|
|
||||||
// using given namespace
|
|
||||||
nameSpace[this.nameSpace] = this;
|
|
||||||
|
|
||||||
_.each(this.allocationMap, function(name, key) {
|
|
||||||
this[name] = this[name] || {};
|
|
||||||
}, this);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function that will be called during application instance creation
|
|
||||||
*/
|
|
||||||
initialize: function() {},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when DOM is ready. This is global callback is used to:
|
|
||||||
* * Used to initialize controllers and execute {@link Backbone.Controller#onLaunch onLaunch} callback
|
|
||||||
* * Execute {@link Backbone.Application#launch launch} callback
|
|
||||||
*/
|
|
||||||
onReady: function() {
|
|
||||||
this.start();
|
|
||||||
},
|
|
||||||
|
|
||||||
start: function() {
|
|
||||||
// initialize controllers
|
|
||||||
this.initializeControllers(this.controllers || {});
|
|
||||||
// call to controller.onLaunch callback
|
|
||||||
this.launchControllers();
|
|
||||||
// call application.launch callback
|
|
||||||
this.launch.call(this);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function that will convert string identifier into the instance reference
|
|
||||||
* @param {String} type Type of instance that should be resolved. See {@link #allocationMap} for valid values
|
|
||||||
* @param {String[]} classes The list of class references
|
|
||||||
* @return {Object} The objects map
|
|
||||||
*/
|
|
||||||
getClasseRefs: function(type, classes) {
|
|
||||||
var hashMap = {},
|
|
||||||
allocationMap = this.allocationMap[type],
|
|
||||||
root = this[allocationMap];
|
|
||||||
|
|
||||||
_.each(classes, function(cls) {
|
|
||||||
hashMap[cls] = resolveNamespace(cls, (cls.indexOf('.') > -1) ? window : root);
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
return hashMap;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function that will loop through all application controllers and create their instances
|
|
||||||
* Additionally, read the list of models and collections from each controller and save the reference within application
|
|
||||||
*/
|
|
||||||
initializeControllers: function(controllers) {
|
|
||||||
this.controllers = {};
|
|
||||||
|
|
||||||
_.each(controllers, function(ctrl) {
|
|
||||||
var root = (ctrl.indexOf('.') > -1) ? window : this[this.allocationMap.controller],
|
|
||||||
classReference = resolveNamespace(ctrl, root),
|
|
||||||
id = ctrl.split('.').pop();
|
|
||||||
|
|
||||||
var controller = new classReference({
|
|
||||||
id: ctrl,
|
|
||||||
application: this
|
|
||||||
});
|
|
||||||
|
|
||||||
controller.views = this.getClasseRefs('view', controller.views || []);
|
|
||||||
|
|
||||||
_.extend(this.models, this.getClasseRefs('model', controller.models || []));
|
|
||||||
_.extend(this.collections, this.getClasseRefs('collection', controller.collections || {}));
|
|
||||||
|
|
||||||
this.buildCollections();
|
|
||||||
this.controllers[ctrl] = controller;
|
|
||||||
}, this);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Launch all controllers using {@link Backbone.Controller#onLaunch callback}
|
|
||||||
*/
|
|
||||||
launchControllers: function() {
|
|
||||||
_.each(this.controllers, function(ctrl, id) {
|
|
||||||
ctrl.onLaunch(this);
|
|
||||||
}, this);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called during application launch
|
|
||||||
* @template
|
|
||||||
*/
|
|
||||||
launch: function() {},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to add event listeners to the {@link #Backbone.EventBus EventBus}
|
|
||||||
*/
|
|
||||||
addListeners: function(listeners, controller) {
|
|
||||||
this.eventbus.addListeners(listeners, controller)
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter to retreive link to the particular controller instance by name
|
|
||||||
* @param {String} name
|
|
||||||
* @return {Backbone.Controller} The controller instance
|
|
||||||
*/
|
|
||||||
getController: function(name) {
|
|
||||||
return this.controllers[name];
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter to retrieve link to the particular model instance by name
|
|
||||||
* If model instance isn't created, create it
|
|
||||||
* @param {String} name
|
|
||||||
* @return {Backbone.Model} The model instance
|
|
||||||
*/
|
|
||||||
getModel: function(name) {
|
|
||||||
this._modelsCache = this._modelsCache || {};
|
|
||||||
|
|
||||||
var model = this._modelsCache[name],
|
|
||||||
modelClass = this.getModelConstructor(name);
|
|
||||||
|
|
||||||
if(!model && modelClass) {
|
|
||||||
model = this.createModel(name);
|
|
||||||
this._modelsCache[name] = model;
|
|
||||||
}
|
|
||||||
|
|
||||||
return model || null;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter to retrieve link to the particular model constructor by name
|
|
||||||
* @param {String} name
|
|
||||||
* @return {Backbone.Model} The model constructor
|
|
||||||
*/
|
|
||||||
getModelConstructor: function(name) {
|
|
||||||
return this.models[name];
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to create new model instance
|
|
||||||
* @param {String} name The name of the model that needs to be created
|
|
||||||
* @param {Object} [options] The list of option that should be passed to the model constructor
|
|
||||||
*/
|
|
||||||
createModel: function(name, options) {
|
|
||||||
var modelClass = this.getModelConstructor(name),
|
|
||||||
model = null;
|
|
||||||
|
|
||||||
if (modelClass)
|
|
||||||
model = new modelClass(_.extend(options || {}));
|
|
||||||
|
|
||||||
return model;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter to retrieve link to the particular collection instance by name
|
|
||||||
* If collection instance isn't created, create it
|
|
||||||
* @param {String} name
|
|
||||||
* @return {Backbone.Collection} The collection instance
|
|
||||||
*/
|
|
||||||
getCollection: function(name) {
|
|
||||||
this._collectionsCache = this._collectionsCache || {};
|
|
||||||
|
|
||||||
var collection = this._collectionsCache[name],
|
|
||||||
collectionClass = this.getCollectionConstructor(name);
|
|
||||||
|
|
||||||
if(!collection && collectionClass) {
|
|
||||||
collection = this.createCollection(name);
|
|
||||||
this._collectionsCache[name] = collection;
|
|
||||||
}
|
|
||||||
|
|
||||||
return collection || null;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter to retrieve link to the particular collection constructor
|
|
||||||
* @param {String} name
|
|
||||||
* @return {Backbone.Collection} The collection constructor
|
|
||||||
*/
|
|
||||||
getCollectionConstructor: function(name) {
|
|
||||||
return this.collections[name];
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to create new collection instance
|
|
||||||
* @param {String} name The name of the collection that needs to be created
|
|
||||||
*/
|
|
||||||
createCollection: function(name) {
|
|
||||||
var collectionClass = this.getCollectionConstructor(name),
|
|
||||||
collection = null;
|
|
||||||
|
|
||||||
if (collectionClass)
|
|
||||||
collection = new collectionClass();
|
|
||||||
|
|
||||||
return collection;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function that will loop throught the list of collection constructors and create instances
|
|
||||||
*/
|
|
||||||
buildCollections: function() {
|
|
||||||
_.each(this.collections, function(collection, alias) {
|
|
||||||
this.getCollection(alias);
|
|
||||||
}, this);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Since we are using Backbone let's make sure that there are no conflicts in namespaces
|
|
||||||
if(typeof Backbone.Application == 'undefined') {
|
|
||||||
Backbone.Application = Application;
|
|
||||||
/**
|
|
||||||
* @method extend
|
|
||||||
* Method to create new Backbone.Application class
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
Backbone.Application.extend = Backbone.Model.extend;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw ('Native Backbone.Application instance already defined.')
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class Backbone.Controller
|
|
||||||
* @cfg {Object} options The list of options available within Controller
|
|
||||||
*/
|
|
||||||
var Controller = function(options) {
|
|
||||||
_.extend(this, options || {});
|
|
||||||
this.initialize.apply(this, arguments);
|
|
||||||
};
|
|
||||||
|
|
||||||
_.extend(Controller.prototype, {
|
|
||||||
name: null,
|
|
||||||
views: {},
|
|
||||||
models: {},
|
|
||||||
collections: {},
|
|
||||||
|
|
||||||
initialize: function(options) {
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add new listener to the application event bus
|
|
||||||
* Delegate to {@link Backbone.Application#addListeners addListeners} callback
|
|
||||||
*/
|
|
||||||
addListeners: function(listeners) {
|
|
||||||
this.getApplication().addListeners(listeners, this);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called after application launch
|
|
||||||
* @template
|
|
||||||
*/
|
|
||||||
onLaunch: function(application) {
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter that will return the reference to the application instance
|
|
||||||
*/
|
|
||||||
getApplication: function() {
|
|
||||||
return this.application;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter that will return the reference to the view instance
|
|
||||||
*/
|
|
||||||
getView: function(name) {
|
|
||||||
return this._viewsCache[name];
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter that will return the reference to the view constructor by name
|
|
||||||
* @param {String} name
|
|
||||||
* @return {Backbone.View} The view constructor
|
|
||||||
*/
|
|
||||||
getViewConstructor: function(name) {
|
|
||||||
return this.views[name];
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to create a new view instance
|
|
||||||
* All views are cached within _viewsCache hash map
|
|
||||||
* @param {String} name
|
|
||||||
* @param {Object} options Options to be passed within view constructor
|
|
||||||
* @return {Backbone.View} The view instance
|
|
||||||
*/
|
|
||||||
createView: function(name, options) {
|
|
||||||
var view = this.getViewConstructor(name),
|
|
||||||
viewOptions = _.extend(options || {}, {
|
|
||||||
alias: name
|
|
||||||
});
|
|
||||||
|
|
||||||
this._viewsCache = this._viewsCache || {};
|
|
||||||
this._viewsCache[name] = new view(viewOptions);
|
|
||||||
|
|
||||||
this._viewsCache[name].options = _.extend({}, viewOptions);
|
|
||||||
|
|
||||||
return this._viewsCache[name];
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method to get model instance reference by name
|
|
||||||
* Delegate to {@link Backbone.Application#getModel getModel} method
|
|
||||||
*/
|
|
||||||
getModel: function(name) {
|
|
||||||
return this.application.getModel(name);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method to get model constructor reference by name
|
|
||||||
* Delegate to {@link Backbone.Application#getModelConstructor getModelConstructor} method
|
|
||||||
*/
|
|
||||||
getModelConstructor: function(name) {
|
|
||||||
return this.application.getModelConstructor(name);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method to create model instance by name
|
|
||||||
* Delegate to {@link Backbone.Application#createModel createModel} method
|
|
||||||
*/
|
|
||||||
createModel: function(name, options) {
|
|
||||||
return this.application.createModel(name)
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delegate method to get collection instance reference by name
|
|
||||||
* Delegate to {@link Backbone.Application#getCollection getCollection} method
|
|
||||||
*/
|
|
||||||
getCollection: function(name) {
|
|
||||||
return this.application.getCollection(name);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delegate method to get collection constructor reference by name
|
|
||||||
* Delegate to {@link Backbone.Application#getCollectionConstructor getCollectionConstructor} method
|
|
||||||
*/
|
|
||||||
getCollectionConstructor: function(name) {
|
|
||||||
return this.application.getCollectionConstructor(name);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delegate method to create collection instance
|
|
||||||
* Delegate to {@link Backbone.Application#createCollection createCollection} method
|
|
||||||
*/
|
|
||||||
createCollection: function(name) {
|
|
||||||
return this.application.createCollection(name);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method to fire cross-controller event
|
|
||||||
* Delegate to {@link Backbone.Application#fireEvent fireEvent} method
|
|
||||||
*/
|
|
||||||
fireEvent: function(selector, event, args) {
|
|
||||||
this.application.eventbus.fireEvent(selector, event, args);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method to bind events from controlling view to controller
|
|
||||||
* probably isn't safe, testing needed
|
|
||||||
*/
|
|
||||||
bindViewEvents: function(view, events) {
|
|
||||||
this.unbindViewEvents(view);
|
|
||||||
|
|
||||||
events = _.isFunction(events) ? events.call(this) : events;
|
|
||||||
|
|
||||||
for (var key in events) {
|
|
||||||
var method = events[key];
|
|
||||||
if (!_.isFunction(method)) method = this[events[key]];
|
|
||||||
|
|
||||||
var match = key.match(/^(\S+)\s*(.*)$/);
|
|
||||||
var eventName = match[1], selector = match[2];
|
|
||||||
method = _.bind(method, this);
|
|
||||||
eventName += '.bindViewEvents' + view.cid;
|
|
||||||
view.$el.on(eventName, selector, method);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method to unbind events from view to controller
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
unbindViewEvents: function(view) {
|
|
||||||
view.$el.off('.bindViewEvents' + view.cid);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if(typeof Backbone.Controller == 'undefined') {
|
|
||||||
Backbone.Controller = Controller;
|
|
||||||
/**
|
|
||||||
* @method extend
|
|
||||||
* Method to create new Backbone.Controller class
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
Backbone.Controller.extend = Backbone.Model.extend;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw ('Native Backbone.Controller instance already defined.')
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class Backbone.EventBus
|
|
||||||
* @cfg {Object} options The list of options available within Controller
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
var EventBus = function(options) {
|
|
||||||
var me = this;
|
|
||||||
|
|
||||||
_.extend(this, options || {});
|
|
||||||
|
|
||||||
_.extend(Backbone.View.prototype, {
|
|
||||||
alias: null,
|
|
||||||
hidden: false,
|
|
||||||
getAlias: function() {
|
|
||||||
return this.options.alias;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Instead of calling View.trigger lets use custom function
|
|
||||||
* It will notify the EventBus about new event
|
|
||||||
*/
|
|
||||||
fireEvent: function(event, args) {
|
|
||||||
this.trigger.apply(this, arguments);
|
|
||||||
me.fireEvent(this.getAlias(), event, args);
|
|
||||||
},
|
|
||||||
hide: function() {
|
|
||||||
this.$el.hide();
|
|
||||||
this.hidden = true;
|
|
||||||
},
|
|
||||||
show: function() {
|
|
||||||
this.$el.show();
|
|
||||||
this.hidden = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
_.extend(EventBus.prototype, {
|
|
||||||
pool: {},
|
|
||||||
/**
|
|
||||||
* Add new listeners to the event bus
|
|
||||||
*/
|
|
||||||
addListeners: function(selectors, controller) {
|
|
||||||
|
|
||||||
this.pool[controller.id] = this.pool[controller.id] || {};
|
|
||||||
var pool = this.pool[controller.id];
|
|
||||||
|
|
||||||
if(_.isArray(selectors)) {
|
|
||||||
_.each(selectors, function(selector) {
|
|
||||||
this.addListeners(selector, controller);
|
|
||||||
}, this)
|
|
||||||
}
|
|
||||||
else if(_.isObject(selectors)) {
|
|
||||||
_.each(selectors, function(listeners, selector) {
|
|
||||||
_.each(listeners, function(listener, event) {
|
|
||||||
pool[selector] = pool[selector] || {};
|
|
||||||
pool[selector][event] = pool[selector][event] || [];
|
|
||||||
pool[selector][event].push(listener);
|
|
||||||
|
|
||||||
}, this);
|
|
||||||
}, this)
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute event listener by given selector and event name
|
|
||||||
*/
|
|
||||||
fireEvent: function(selector, event, args) {
|
|
||||||
var application = this.getApplication();
|
|
||||||
|
|
||||||
_.each(this.pool, function(eventsPoolByAlias, controllerId) {
|
|
||||||
var events = eventsPoolByAlias[selector];
|
|
||||||
|
|
||||||
if(events) {
|
|
||||||
var listeners = events[event],
|
|
||||||
controller = application.getController(controllerId);
|
|
||||||
|
|
||||||
_.each(listeners, function(fn) {
|
|
||||||
fn.apply(controller, args);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}, this);
|
|
||||||
},
|
|
||||||
|
|
||||||
getApplication: function() {
|
|
||||||
return this.application;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Since we are using Backbone let's make sure that there are no conflicts in namespaces
|
|
||||||
if(typeof Backbone.EventBus == 'undefined') {
|
|
||||||
Backbone.EventBus = EventBus;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw ('Native Backbone.Application instance already defined.')
|
|
||||||
}
|
|
||||||
})();
|
|
|
@ -1,346 +0,0 @@
|
||||||
// keymaster.js
|
|
||||||
// (c) 2011-2013 Thomas Fuchs
|
|
||||||
// keymaster.js may be freely distributed under the MIT license.
|
|
||||||
//
|
|
||||||
// changesets: 833cf1a00fe2, e19d5b8a37fe
|
|
||||||
|
|
||||||
;(function(global){
|
|
||||||
var k,
|
|
||||||
_handlers = {},
|
|
||||||
_mods = { 16: false, 18: false, 17: false, 91: false },
|
|
||||||
_scope = 'all',
|
|
||||||
// modifier keys
|
|
||||||
_MODIFIERS = {
|
|
||||||
'⇧': 16, shift: 16,
|
|
||||||
'⌥': 18, alt: 18, option: 18,
|
|
||||||
'⌃': 17, ctrl: 17, control: 17,
|
|
||||||
'⌘': 91, command: 91
|
|
||||||
},
|
|
||||||
// special keys
|
|
||||||
_MAP = {
|
|
||||||
backspace: 8, tab: 9, clear: 12,
|
|
||||||
enter: 13, 'return': 13,
|
|
||||||
esc: 27, escape: 27, space: 32,
|
|
||||||
left: 37, up: 38,
|
|
||||||
right: 39, down: 40,
|
|
||||||
del: 46, 'delete': 46,
|
|
||||||
home: 36, end: 35,
|
|
||||||
pageup: 33, pagedown: 34,
|
|
||||||
',': 188, '.': 190, '/': 191,
|
|
||||||
'`': 192, '-': 189, '=': 187,
|
|
||||||
';': 186, '\'': 222,
|
|
||||||
'[': 219, ']': 221, '\\': 220,
|
|
||||||
'ff-': 173, 'ff=': 61
|
|
||||||
},
|
|
||||||
code = function(x){
|
|
||||||
return _MAP[x] || x.toUpperCase().charCodeAt(0);
|
|
||||||
},
|
|
||||||
_downKeys = [];
|
|
||||||
var locked;
|
|
||||||
|
|
||||||
for(k=1;k<20;k++) _MAP['f'+k] = 111+k;
|
|
||||||
|
|
||||||
// IE doesn't support Array#indexOf, so have a simple replacement
|
|
||||||
function index(array, item){
|
|
||||||
var i = array.length;
|
|
||||||
while(i--) if(array[i]===item) return i;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// for comparing mods before unassignment
|
|
||||||
function compareArray(a1, a2) {
|
|
||||||
if (a1.length != a2.length) return false;
|
|
||||||
for (var i = 0; i < a1.length; i++) {
|
|
||||||
if (a1[i] !== a2[i]) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var modifierMap = {
|
|
||||||
16:'shiftKey',
|
|
||||||
18:'altKey',
|
|
||||||
17:'ctrlKey',
|
|
||||||
91:'metaKey'
|
|
||||||
};
|
|
||||||
function updateModifierKey(event) {
|
|
||||||
for(k in _mods) _mods[k] = event[modifierMap[k]];
|
|
||||||
};
|
|
||||||
|
|
||||||
// handle keydown event
|
|
||||||
function dispatch(event) {
|
|
||||||
var key, handler, k, i, modifiersMatch, scope;
|
|
||||||
key = event.keyCode;
|
|
||||||
|
|
||||||
if (Common.UI.HintManager.isHintVisible()) {
|
|
||||||
if (key === 112) {
|
|
||||||
Common.UI.HintManager.clearHints();
|
|
||||||
} else if (key !== 27) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index(_downKeys, key) == -1) {
|
|
||||||
_downKeys.push(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if a modifier key, set the key.<modifierkeyname> property to true and return
|
|
||||||
if(key == 93 || key == 224) key = 91; // right command on webkit, command on Gecko
|
|
||||||
if(key in _mods) {
|
|
||||||
_mods[key] = true;
|
|
||||||
// 'assignKey' from inside this closure is exported to window.key
|
|
||||||
for(k in _MODIFIERS) if(_MODIFIERS[k] == key) assignKey[k] = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
updateModifierKey(event);
|
|
||||||
|
|
||||||
// see if we need to ignore the keypress (filter() can can be overridden)
|
|
||||||
// by default ignore key presses if a select, textarea, or input is focused
|
|
||||||
if(!assignKey.filter.call(this, event)) return;
|
|
||||||
|
|
||||||
// abort if no potentially matching shortcuts found
|
|
||||||
if (!(key in _handlers)) return;
|
|
||||||
|
|
||||||
scope = getScope();
|
|
||||||
|
|
||||||
// for each potential shortcut
|
|
||||||
for (i = 0; i < _handlers[key].length; i++) {
|
|
||||||
handler = _handlers[key][i];
|
|
||||||
|
|
||||||
// see if it's in the current scope
|
|
||||||
if(handler.scope == scope || handler.scope == 'all'){
|
|
||||||
// check if modifiers match if any
|
|
||||||
modifiersMatch = handler.mods.length > 0;
|
|
||||||
for(k in _mods)
|
|
||||||
if((!_mods[k] && index(handler.mods, +k) > -1) ||
|
|
||||||
(_mods[k] && index(handler.mods, +k) == -1)) modifiersMatch = false;
|
|
||||||
// call the handler and stop the event if neccessary
|
|
||||||
if((handler.mods.length == 0 && !_mods[16] && !_mods[18] && !_mods[17] && !_mods[91]) || modifiersMatch){
|
|
||||||
if(locked===true || handler.locked || handler.method(event, handler)===false){
|
|
||||||
if(event.preventDefault) event.preventDefault();
|
|
||||||
else event.returnValue = false;
|
|
||||||
if(event.stopPropagation) event.stopPropagation();
|
|
||||||
if(event.cancelBubble) event.cancelBubble = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// unset modifier keys on keyup
|
|
||||||
function clearModifier(event){
|
|
||||||
var key = event.keyCode, k,
|
|
||||||
i = index(_downKeys, key);
|
|
||||||
|
|
||||||
// remove key from _downKeys
|
|
||||||
if (i >= 0) {
|
|
||||||
_downKeys.splice(i, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(key == 93 || key == 224) key = 91;
|
|
||||||
if(key in _mods) {
|
|
||||||
_mods[key] = false;
|
|
||||||
for(k in _MODIFIERS) if(_MODIFIERS[k] == key) assignKey[k] = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function resetModifiers() {
|
|
||||||
for(k in _mods) _mods[k] = false;
|
|
||||||
for(k in _MODIFIERS) assignKey[k] = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
// parse and assign shortcut
|
|
||||||
function assignKey(key, scope, method){
|
|
||||||
var keys, mods;
|
|
||||||
keys = getKeys(key);
|
|
||||||
if (method === undefined) {
|
|
||||||
method = scope;
|
|
||||||
scope = 'all';
|
|
||||||
}
|
|
||||||
|
|
||||||
// for each shortcut
|
|
||||||
for (var i = 0; i < keys.length; i++) {
|
|
||||||
// set modifier keys if any
|
|
||||||
mods = [];
|
|
||||||
key = keys[i].split('+');
|
|
||||||
if (key.length > 1){
|
|
||||||
mods = getMods(key);
|
|
||||||
key = [key[key.length-1]];
|
|
||||||
}
|
|
||||||
// convert to keycode and...
|
|
||||||
key = key[0]
|
|
||||||
key = code(key);
|
|
||||||
// ...store handler
|
|
||||||
if (!(key in _handlers)) _handlers[key] = [];
|
|
||||||
_handlers[key].push({ shortcut: keys[i], scope: scope, method: method, key: keys[i], mods: mods });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// unbind all handlers for given key in current scope
|
|
||||||
function unbindKey(key, scope) {
|
|
||||||
var multipleKeys, keys,
|
|
||||||
mods = [],
|
|
||||||
i, j, obj;
|
|
||||||
|
|
||||||
multipleKeys = getKeys(key);
|
|
||||||
|
|
||||||
for (j = 0; j < multipleKeys.length; j++) {
|
|
||||||
keys = multipleKeys[j].split('+');
|
|
||||||
|
|
||||||
if (keys.length > 1) {
|
|
||||||
mods = getMods(keys);
|
|
||||||
key = keys[keys.length - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
key = code(key);
|
|
||||||
|
|
||||||
if (scope === undefined) {
|
|
||||||
scope = getScope();
|
|
||||||
}
|
|
||||||
if (!_handlers[key]) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (i in _handlers[key]) {
|
|
||||||
obj = _handlers[key][i];
|
|
||||||
// only clear handlers if correct scope and mods match
|
|
||||||
if (obj.scope === scope && compareArray(obj.mods, mods)) {
|
|
||||||
_handlers[key][i] = {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Returns true if the key with code 'keyCode' is currently down
|
|
||||||
// Converts strings into key codes.
|
|
||||||
function isPressed(keyCode) {
|
|
||||||
if (typeof(keyCode)=='string') {
|
|
||||||
keyCode = code(keyCode);
|
|
||||||
}
|
|
||||||
return index(_downKeys, keyCode) != -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPressedKeyCodes() {
|
|
||||||
return _downKeys.slice(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function filter(event){
|
|
||||||
var tagName = (event.target || event.srcElement).tagName;
|
|
||||||
// ignore keypressed in any elements that support keyboard data input
|
|
||||||
return !(tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA');
|
|
||||||
}
|
|
||||||
|
|
||||||
// initialize key.<modifier> to false
|
|
||||||
for(k in _MODIFIERS) assignKey[k] = false;
|
|
||||||
|
|
||||||
// set current scope (default 'all')
|
|
||||||
function setScope(scope){ _scope = scope || 'all' };
|
|
||||||
function getScope(){ return _scope || 'all' };
|
|
||||||
|
|
||||||
// delete all handlers for a given scope
|
|
||||||
function deleteScope(scope){
|
|
||||||
var key, handlers, i;
|
|
||||||
|
|
||||||
for (key in _handlers) {
|
|
||||||
handlers = _handlers[key];
|
|
||||||
for (i = 0; i < handlers.length; ) {
|
|
||||||
if (handlers[i].scope === scope) handlers.splice(i, 1);
|
|
||||||
else i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// abstract key logic for assign and unassign
|
|
||||||
function getKeys(key) {
|
|
||||||
var keys;
|
|
||||||
key = key.replace(/\s/g, '');
|
|
||||||
keys = key.split(',');
|
|
||||||
if ((keys[keys.length - 1]) == '') {
|
|
||||||
keys[keys.length - 2] += ',';
|
|
||||||
}
|
|
||||||
return keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
// abstract mods logic for assign and unassign
|
|
||||||
function getMods(key) {
|
|
||||||
var mods = key.slice(0, key.length - 1);
|
|
||||||
for (var mi = 0; mi < mods.length; mi++)
|
|
||||||
mods[mi] = _MODIFIERS[mods[mi]];
|
|
||||||
return mods;
|
|
||||||
}
|
|
||||||
|
|
||||||
// cross-browser events
|
|
||||||
function addEvent(object, event, method) {
|
|
||||||
if (object.addEventListener)
|
|
||||||
object.addEventListener(event, method, false);
|
|
||||||
else if(object.attachEvent)
|
|
||||||
object.attachEvent('on'+event, function(){ method(window.event) });
|
|
||||||
};
|
|
||||||
|
|
||||||
// set the handlers globally on document
|
|
||||||
addEvent(document, 'keydown', function(event) { dispatch(event) }); // Passing _scope to a callback to ensure it remains the same by execution. Fixes #48
|
|
||||||
addEvent(document, 'keyup', clearModifier);
|
|
||||||
|
|
||||||
// reset modifiers to false whenever the window is (re)focused.
|
|
||||||
addEvent(window, 'focus', resetModifiers);
|
|
||||||
|
|
||||||
// store previously defined key
|
|
||||||
var previousKey = global.key;
|
|
||||||
|
|
||||||
// restore previously defined key and return reference to our key object
|
|
||||||
function noConflict() {
|
|
||||||
var k = global.key;
|
|
||||||
global.key = previousKey;
|
|
||||||
return k;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setKeyOptions(key, scope, option, value) {
|
|
||||||
var keys, mods = [], i, obj;
|
|
||||||
var multipleKeys = getKeys(key);
|
|
||||||
|
|
||||||
for (var j = multipleKeys.length; j--; ) {
|
|
||||||
keys = multipleKeys[j].split('+');
|
|
||||||
|
|
||||||
if (keys.length > 1) {
|
|
||||||
mods = getMods(keys);
|
|
||||||
key = keys[keys.length - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
key = code(key);
|
|
||||||
|
|
||||||
if (scope === undefined) {
|
|
||||||
scope = getScope();
|
|
||||||
}
|
|
||||||
if (_handlers[key]) {
|
|
||||||
for (i in _handlers[key]) {
|
|
||||||
obj = _handlers[key][i];
|
|
||||||
if (obj.scope === scope && compareArray(obj.mods, mods)) {
|
|
||||||
_handlers[key][i][option] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function suspend(key, scope) {
|
|
||||||
key ? setKeyOptions(key, scope, 'locked', true) : (locked = true);
|
|
||||||
}
|
|
||||||
|
|
||||||
function resume(key, scope) {
|
|
||||||
key ? setKeyOptions(key, scope, 'locked', false) : (locked = false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// set window.key and window.key.set/get/deleteScope, and the default filter
|
|
||||||
global.key = assignKey;
|
|
||||||
global.key.setScope = setScope;
|
|
||||||
global.key.getScope = getScope;
|
|
||||||
global.key.deleteScope = deleteScope;
|
|
||||||
global.key.filter = filter;
|
|
||||||
global.key.isPressed = isPressed;
|
|
||||||
global.key.getPressedKeyCodes = getPressedKeyCodes;
|
|
||||||
global.key.noConflict = noConflict;
|
|
||||||
global.key.unbind = unbindKey;
|
|
||||||
global.key.suspend = suspend;
|
|
||||||
global.key.resume = resume;
|
|
||||||
|
|
||||||
if(typeof module !== 'undefined') module.exports = key;
|
|
||||||
|
|
||||||
})(this);
|
|
|
@ -1,34 +0,0 @@
|
||||||
# HG changeset patch
|
|
||||||
# User Alexey Musinov
|
|
||||||
# Date 1415710176 -10800
|
|
||||||
# Tue Nov 11 15:49:36 2014 +0300
|
|
||||||
# Node ID 784fe548cf4cbfc0a6c96b295ae83c551ce22166
|
|
||||||
# Parent 07b43d47bcf8afe8a2dabc8a0bce8c7dab3bd498
|
|
||||||
[Common] â perfect-scrollbar - ñêðîëèíã íàä 'textarea' è 'input' ïåðåäàåòñÿ â ýòè ýëåìåíòû.
|
|
||||||
|
|
||||||
diff -r 07b43d47bcf8 -r 784fe548cf4c apps/common/main/lib/mods/perfect-scrollbar.js
|
|
||||||
--- a/apps/common/main/lib/mods/perfect-scrollbar.js Mon Nov 10 19:37:33 2014 +0300
|
|
||||||
+++ b/apps/common/main/lib/mods/perfect-scrollbar.js Tue Nov 11 15:49:36 2014 +0300
|
|
||||||
@@ -313,6 +313,22 @@
|
|
||||||
var deltaX = e.deltaX * e.deltaFactor || deprecatedDeltaX,
|
|
||||||
deltaY = e.deltaY * e.deltaFactor || deprecatedDeltaY;
|
|
||||||
|
|
||||||
+ if (e && e.target && (e.target.type === 'textarea' || e.target.type === 'input')) {
|
|
||||||
+ e.stopImmediatePropagation();
|
|
||||||
+ e.preventDefault();
|
|
||||||
+
|
|
||||||
+ var scroll = $(e.target).scrollTop(), wheelDeltaY = 0;
|
|
||||||
+ if (e.originalEvent) {
|
|
||||||
+ if (e.originalEvent.wheelDelta) wheelDeltaY = e.originalEvent.wheelDelta / -40;
|
|
||||||
+ if (e.originalEvent.deltaY) wheelDeltaY = e.originalEvent.deltaY;
|
|
||||||
+ if (e.originalEvent.detail) wheelDeltaY = e.originalEvent.detail;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ $(e.target).scrollTop(scroll - wheelDeltaY);
|
|
||||||
+
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
shouldPrevent = false;
|
|
||||||
if (!settings.useBothWheelAxes) {
|
|
||||||
// deltaX will only be used for horizontal scrolling and deltaY will
|
|
|
@ -1,48 +0,0 @@
|
||||||
diff -r 5047272bb302 apps/common/main/lib/mods/perfect-scrollbar.js
|
|
||||||
--- a/apps/common/main/lib/mods/perfect-scrollbar.js Fri Sep 12 18:17:33 2014 +0400
|
|
||||||
+++ b/apps/common/main/lib/mods/perfect-scrollbar.js Fri Sep 12 18:18:56 2014 +0400
|
|
||||||
@@ -146,7 +146,12 @@
|
|
||||||
|
|
||||||
var updateScrollbarCss = function () {
|
|
||||||
$scrollbarXRail.css({left: $this.scrollLeft(), bottom: scrollbarXBottom - $this.scrollTop(), width: containerWidth, display: scrollbarXActive ? "inherit": "none"});
|
|
||||||
- $scrollbarYRail.css({top: $this.scrollTop(), right: scrollbarYRight - $this.scrollLeft(), height: containerHeight, display: scrollbarYActive ? "inherit": "none"});
|
|
||||||
+
|
|
||||||
+ if ($scrollbarYRail.hasClass('in-scrolling'))
|
|
||||||
+ $scrollbarYRail.css({/*top: $this.scrollTop(),*/ right: scrollbarYRight - $this.scrollLeft(), height: containerHeight, display: scrollbarYActive ? "inherit": "none"});
|
|
||||||
+ else
|
|
||||||
+ $scrollbarYRail.css({top: $this.scrollTop(), right: scrollbarYRight - $this.scrollLeft(), height: containerHeight, display: scrollbarYActive ? "inherit": "none"});
|
|
||||||
+
|
|
||||||
$scrollbarX.css({left: scrollbarXLeft, width: scrollbarXWidth});
|
|
||||||
$scrollbarY.css({top: scrollbarYTop, height: scrollbarYHeight});
|
|
||||||
};
|
|
||||||
@@ -229,6 +234,15 @@
|
|
||||||
currentPageY = e.pageY;
|
|
||||||
currentTop = $scrollbarY.position().top;
|
|
||||||
$scrollbarYRail.addClass('in-scrolling');
|
|
||||||
+
|
|
||||||
+ var padding = parseInt($scrollbarYRail.offsetParent().css('padding-top'));
|
|
||||||
+ var rect = $scrollbarYRail[0].getBoundingClientRect();
|
|
||||||
+ $scrollbarYRail.css({
|
|
||||||
+ position: 'fixed',
|
|
||||||
+ left: rect.left,
|
|
||||||
+ top: rect.top - padding
|
|
||||||
+ });
|
|
||||||
+
|
|
||||||
e.stopPropagation();
|
|
||||||
e.preventDefault();
|
|
||||||
});
|
|
||||||
@@ -244,6 +258,14 @@
|
|
||||||
$(document).bind('mouseup' + eventClassName, function (e) {
|
|
||||||
if ($scrollbarYRail.hasClass('in-scrolling')) {
|
|
||||||
$scrollbarYRail.removeClass('in-scrolling');
|
|
||||||
+
|
|
||||||
+ $scrollbarYRail.css({
|
|
||||||
+ position: '',
|
|
||||||
+ left: '',
|
|
||||||
+ top: ''
|
|
||||||
+ });
|
|
||||||
+
|
|
||||||
+ updateScrollbarCss();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
diff -r daaf445d707b apps/common/main/lib/mods/perfect-scrollbar.js
|
|
||||||
--- a/apps/common/main/lib/mods/perfect-scrollbar.js Mon Jun 15 15:25:53 2015 +0300
|
|
||||||
+++ b/apps/common/main/lib/mods/perfect-scrollbar.js Thu Jun 18 13:29:36 2015 +0300
|
|
||||||
// change thumb event
|
|
||||||
@@ -197,6 +197,10 @@
|
|
||||||
}
|
|
||||||
|
|
||||||
updateScrollbarCss();
|
|
||||||
+
|
|
||||||
+ if (settings.onChange) {
|
|
||||||
+ settings.onChange(this);
|
|
||||||
+ }
|
|
||||||
};
|
|
||||||
|
|
||||||
var bindMouseScrollXHandler = function () {
|
|
|
@ -1,103 +0,0 @@
|
||||||
diff -r c7981f4f7e09 apps/common/main/lib/mods/perfect-scrollbar.js
|
|
||||||
--- a/apps/common/main/lib/mods/perfect-scrollbar.js Tue Oct 07 11:32:00 2014 +0400
|
|
||||||
+++ b/apps/common/main/lib/mods/perfect-scrollbar.js Wed Oct 08 11:37:27 2014 +0400
|
|
||||||
// Use margins of scrollbarYRail when calculate scrollbarYRail height (scrollbarYRailHeight) and top position
|
|
||||||
@@ -28,7 +28,8 @@
|
|
||||||
suppressScrollY: false,
|
|
||||||
scrollXMarginOffset: 0,
|
|
||||||
scrollYMarginOffset: 0,
|
|
||||||
- includePadding: false
|
|
||||||
+ includePadding: false,
|
|
||||||
+ includeMargin: true
|
|
||||||
};
|
|
||||||
|
|
||||||
var getEventClassName = (function () {
|
|
||||||
@@ -97,11 +98,12 @@
|
|
||||||
scrollbarYHeight,
|
|
||||||
scrollbarYTop,
|
|
||||||
scrollbarYRight = parseInt($scrollbarYRail.css('right'), 10),
|
|
||||||
+ scrollbarYRailHeight,
|
|
||||||
eventClassName = getEventClassName();
|
|
||||||
|
|
||||||
var updateContentScrollTop = function (currentTop, deltaY) {
|
|
||||||
var newTop = currentTop + deltaY,
|
|
||||||
- maxTop = containerHeight - scrollbarYHeight;
|
|
||||||
+ maxTop = scrollbarYRailHeight - scrollbarYHeight;
|
|
||||||
|
|
||||||
if (newTop < 0) {
|
|
||||||
scrollbarYTop = 0;
|
|
||||||
@@ -113,7 +115,7 @@
|
|
||||||
scrollbarYTop = newTop;
|
|
||||||
}
|
|
||||||
|
|
||||||
- var scrollTop = parseInt(scrollbarYTop * (contentHeight - containerHeight) / (containerHeight - scrollbarYHeight), 10);
|
|
||||||
+ var scrollTop = parseInt(scrollbarYTop * (contentHeight - containerHeight) / (scrollbarYRailHeight - scrollbarYHeight), 10);
|
|
||||||
$this.scrollTop(scrollTop);
|
|
||||||
$scrollbarXRail.css({bottom: scrollbarXBottom - scrollTop});
|
|
||||||
};
|
|
||||||
@@ -148,9 +150,9 @@
|
|
||||||
$scrollbarXRail.css({left: $this.scrollLeft(), bottom: scrollbarXBottom - $this.scrollTop(), width: containerWidth, display: scrollbarXActive ? "inherit": "none"});
|
|
||||||
|
|
||||||
if ($scrollbarYRail.hasClass('in-scrolling'))
|
|
||||||
- $scrollbarYRail.css({/*top: $this.scrollTop(),*/ right: scrollbarYRight - $this.scrollLeft(), height: containerHeight, display: scrollbarYActive ? "inherit": "none"});
|
|
||||||
+ $scrollbarYRail.css({/*top: $this.scrollTop(),*/ right: scrollbarYRight - $this.scrollLeft(), height: scrollbarYRailHeight, display: scrollbarYActive ? "inherit": "none"});
|
|
||||||
else
|
|
||||||
- $scrollbarYRail.css({top: $this.scrollTop(), right: scrollbarYRight - $this.scrollLeft(), height: containerHeight, display: scrollbarYActive ? "inherit": "none"});
|
|
||||||
+ $scrollbarYRail.css({top: $this.scrollTop(), right: scrollbarYRight - $this.scrollLeft(), height: scrollbarYRailHeight, display: scrollbarYActive ? "inherit": "none"});
|
|
||||||
|
|
||||||
$scrollbarX.css({left: scrollbarXLeft, width: scrollbarXWidth});
|
|
||||||
$scrollbarY.css({top: scrollbarYTop, height: scrollbarYHeight});
|
|
||||||
@@ -159,6 +161,7 @@
|
|
||||||
var updateBarSizeAndPosition = function () {
|
|
||||||
containerWidth = settings.includePadding ? $this.innerWidth() : $this.width();
|
|
||||||
containerHeight = settings.includePadding ? $this.innerHeight() : $this.height();
|
|
||||||
+ scrollbarYRailHeight = containerHeight - (settings.includeMargin ? (parseInt($scrollbarYRail.css('margin-top')) + parseInt($scrollbarYRail.css('margin-bottom'))): 0);
|
|
||||||
contentWidth = $this.prop('scrollWidth');
|
|
||||||
contentHeight = $this.prop('scrollHeight');
|
|
||||||
|
|
||||||
@@ -176,8 +179,8 @@
|
|
||||||
|
|
||||||
if (!settings.suppressScrollY && containerHeight + settings.scrollYMarginOffset < contentHeight) {
|
|
||||||
scrollbarYActive = true;
|
|
||||||
- scrollbarYHeight = getSettingsAdjustedThumbSize(parseInt(containerHeight * containerHeight / contentHeight, 10));
|
|
||||||
- scrollbarYTop = parseInt($this.scrollTop() * (containerHeight - scrollbarYHeight) / (contentHeight - containerHeight), 10);
|
|
||||||
+ scrollbarYHeight = getSettingsAdjustedThumbSize(parseInt(scrollbarYRailHeight * containerHeight / contentHeight, 10));
|
|
||||||
+ scrollbarYTop = parseInt($this.scrollTop() * (scrollbarYRailHeight - scrollbarYHeight) / (contentHeight - containerHeight), 10);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
scrollbarYActive = false;
|
|
||||||
@@ -186,8 +189,8 @@
|
|
||||||
$this.scrollTop(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
- if (scrollbarYTop >= containerHeight - scrollbarYHeight) {
|
|
||||||
- scrollbarYTop = containerHeight - scrollbarYHeight;
|
|
||||||
+ if (scrollbarYTop >= scrollbarYRailHeight - scrollbarYHeight) {
|
|
||||||
+ scrollbarYTop = scrollbarYRailHeight - scrollbarYHeight;
|
|
||||||
}
|
|
||||||
if (scrollbarXLeft >= containerWidth - scrollbarXWidth) {
|
|
||||||
scrollbarXLeft = containerWidth - scrollbarXWidth;
|
|
||||||
@@ -235,12 +238,12 @@
|
|
||||||
currentTop = $scrollbarY.position().top;
|
|
||||||
$scrollbarYRail.addClass('in-scrolling');
|
|
||||||
|
|
||||||
- var padding = parseInt($scrollbarYRail.offsetParent().css('padding-top'));
|
|
||||||
+ var margin = parseInt($scrollbarYRail.css('margin-top'));
|
|
||||||
var rect = $scrollbarYRail[0].getBoundingClientRect();
|
|
||||||
$scrollbarYRail.css({
|
|
||||||
position: 'fixed',
|
|
||||||
left: rect.left,
|
|
||||||
- top: rect.top - padding
|
|
||||||
+ top: rect.top - margin
|
|
||||||
});
|
|
||||||
|
|
||||||
e.stopPropagation();
|
|
||||||
@@ -419,7 +422,7 @@
|
|
||||||
$scrollbarYRail.bind('click' + eventClassName, function (e) {
|
|
||||||
var halfOfScrollbarLength = parseInt(scrollbarYHeight / 2, 10),
|
|
||||||
positionTop = e.pageY - $scrollbarYRail.offset().top - halfOfScrollbarLength,
|
|
||||||
- maxPositionTop = containerHeight - scrollbarYHeight,
|
|
||||||
+ maxPositionTop = scrollbarYRailHeight - scrollbarYHeight,
|
|
||||||
positionRatio = positionTop / maxPositionTop;
|
|
||||||
|
|
||||||
if (positionRatio < 0) {
|
|
|
@ -1,89 +0,0 @@
|
||||||
From d16a11fb136ef9ff06d20810e56e4a944173c977 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Julia Radzhabova
|
|
||||||
Date: Fri, 19 Apr 2019 17:54:45 +0300
|
|
||||||
Subject: [PATCH] [Common] perfect-scrollbar: set width and position for
|
|
||||||
scrollbarXRail based on margins.
|
|
||||||
|
|
||||||
---
|
|
||||||
apps/common/main/lib/mods/perfect-scrollbar.js | 18 ++++++++++--------
|
|
||||||
1 file changed, 10 insertions(+), 8 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/apps/common/main/lib/mods/perfect-scrollbar.js b/apps/common/main/lib/mods/perfect-scrollbar.js
|
|
||||||
index 9b6f650..778009d 100644
|
|
||||||
--- a/apps/common/main/lib/mods/perfect-scrollbar.js
|
|
||||||
+++ b/apps/common/main/lib/mods/perfect-scrollbar.js
|
|
||||||
@@ -95,6 +95,7 @@
|
|
||||||
scrollbarXWidth,
|
|
||||||
scrollbarXLeft,
|
|
||||||
scrollbarXBottom = parseInt($scrollbarXRail.css('bottom'), 10),
|
|
||||||
+ scrollbarXRailWidth,
|
|
||||||
scrollbarYHeight,
|
|
||||||
scrollbarYTop,
|
|
||||||
scrollbarYRight = parseInt($scrollbarYRail.css('right'), 10),
|
|
||||||
@@ -122,7 +123,7 @@
|
|
||||||
|
|
||||||
var updateContentScrollLeft = function (currentLeft, deltaX) {
|
|
||||||
var newLeft = currentLeft + deltaX,
|
|
||||||
- maxLeft = containerWidth - scrollbarXWidth;
|
|
||||||
+ maxLeft = scrollbarXRailWidth - scrollbarXWidth;
|
|
||||||
|
|
||||||
if (newLeft < 0) {
|
|
||||||
scrollbarXLeft = 0;
|
|
||||||
@@ -134,7 +135,7 @@
|
|
||||||
scrollbarXLeft = newLeft;
|
|
||||||
}
|
|
||||||
|
|
||||||
- var scrollLeft = parseInt(scrollbarXLeft * (contentWidth - containerWidth) / (containerWidth - scrollbarXWidth), 10);
|
|
||||||
+ var scrollLeft = parseInt(scrollbarXLeft * (contentWidth - containerWidth) / (scrollbarXRailWidth - scrollbarXWidth), 10);
|
|
||||||
$this.scrollLeft(scrollLeft);
|
|
||||||
$scrollbarYRail.css({right: scrollbarYRight - scrollLeft});
|
|
||||||
};
|
|
||||||
@@ -147,7 +148,7 @@
|
|
||||||
};
|
|
||||||
|
|
||||||
var updateScrollbarCss = function () {
|
|
||||||
- $scrollbarXRail.css({left: $this.scrollLeft(), bottom: scrollbarXBottom - $this.scrollTop(), width: containerWidth, display: scrollbarXActive ? "inherit": "none"});
|
|
||||||
+ $scrollbarXRail.css({left: $this.scrollLeft(), bottom: scrollbarXBottom - $this.scrollTop(), width: scrollbarXRailWidth, display: scrollbarXActive ? "inherit": "none"});
|
|
||||||
|
|
||||||
if ($scrollbarYRail.hasClass('in-scrolling'))
|
|
||||||
$scrollbarYRail.css({/*top: $this.scrollTop(),*/ right: scrollbarYRight - $this.scrollLeft(), height: scrollbarYRailHeight, display: scrollbarYActive ? "inherit": "none"});
|
|
||||||
@@ -162,13 +163,14 @@
|
|
||||||
containerWidth = settings.includePadding ? $this.innerWidth() : $this.width();
|
|
||||||
containerHeight = settings.includePadding ? $this.innerHeight() : $this.height();
|
|
||||||
scrollbarYRailHeight = containerHeight - (settings.includeMargin ? (parseInt($scrollbarYRail.css('margin-top')) + parseInt($scrollbarYRail.css('margin-bottom'))): 0);
|
|
||||||
+ scrollbarXRailWidth = containerWidth - (settings.includeMargin ? (parseInt($scrollbarXRail.css('margin-left')) + parseInt($scrollbarXRail.css('margin-right'))): 0);
|
|
||||||
contentWidth = $this.prop('scrollWidth');
|
|
||||||
contentHeight = $this.prop('scrollHeight');
|
|
||||||
|
|
||||||
if (!settings.suppressScrollX && containerWidth + settings.scrollXMarginOffset < contentWidth) {
|
|
||||||
scrollbarXActive = true;
|
|
||||||
- scrollbarXWidth = getSettingsAdjustedThumbSize(parseInt(containerWidth * containerWidth / contentWidth, 10));
|
|
||||||
- scrollbarXLeft = parseInt($this.scrollLeft() * (containerWidth - scrollbarXWidth) / (contentWidth - containerWidth), 10);
|
|
||||||
+ scrollbarXWidth = getSettingsAdjustedThumbSize(parseInt(scrollbarXRailWidth * containerWidth / contentWidth, 10));
|
|
||||||
+ scrollbarXLeft = parseInt($this.scrollLeft() * (scrollbarXRailWidth - scrollbarXWidth) / (contentWidth - containerWidth), 10);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
scrollbarXActive = false;
|
|
||||||
@@ -192,8 +194,8 @@
|
|
||||||
if (scrollbarYTop >= scrollbarYRailHeight - scrollbarYHeight) {
|
|
||||||
scrollbarYTop = scrollbarYRailHeight - scrollbarYHeight;
|
|
||||||
}
|
|
||||||
- if (scrollbarXLeft >= containerWidth - scrollbarXWidth) {
|
|
||||||
- scrollbarXLeft = containerWidth - scrollbarXWidth;
|
|
||||||
+ if (scrollbarXLeft >= scrollbarXRailWidth - scrollbarXWidth) {
|
|
||||||
+ scrollbarXLeft = scrollbarXRailWidth - scrollbarXWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateScrollbarCss();
|
|
||||||
@@ -461,7 +463,7 @@
|
|
||||||
$scrollbarXRail.bind('click' + eventClassName, function (e) {
|
|
||||||
var halfOfScrollbarLength = parseInt(scrollbarXWidth / 2, 10),
|
|
||||||
positionLeft = e.pageX - $scrollbarXRail.offset().left - halfOfScrollbarLength,
|
|
||||||
- maxPositionLeft = containerWidth - scrollbarXWidth,
|
|
||||||
+ maxPositionLeft = scrollbarXRailWidth - scrollbarXWidth,
|
|
||||||
positionRatio = positionLeft / maxPositionLeft;
|
|
||||||
|
|
||||||
if (positionRatio < 0) {
|
|
||||||
--
|
|
||||||
2.6.1.windows.1
|
|
||||||
|
|
|
@ -1,658 +0,0 @@
|
||||||
/* Copyright (c) 2012, 2014 Hyeonje Alex Jun and other contributors
|
|
||||||
* Licensed under the MIT License
|
|
||||||
*/
|
|
||||||
(function (factory) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
if (typeof define === 'function' && define.amd) {
|
|
||||||
// AMD. Register as an anonymous module.
|
|
||||||
define(['jquery'], factory);
|
|
||||||
} else if (typeof exports === 'object') {
|
|
||||||
// Node/CommonJS
|
|
||||||
factory(require('jquery'));
|
|
||||||
} else {
|
|
||||||
// Browser globals
|
|
||||||
factory(jQuery);
|
|
||||||
}
|
|
||||||
}(function ($) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
// The default settings for the plugin
|
|
||||||
var defaultSettings = {
|
|
||||||
wheelSpeed: 10,
|
|
||||||
wheelPropagation: false,
|
|
||||||
minScrollbarLength: null,
|
|
||||||
useBothWheelAxes: false,
|
|
||||||
useKeyboard: true,
|
|
||||||
suppressScrollX: false,
|
|
||||||
suppressScrollY: false,
|
|
||||||
scrollXMarginOffset: 0,
|
|
||||||
scrollYMarginOffset: 0,
|
|
||||||
includePadding: false,
|
|
||||||
includeMargin: true
|
|
||||||
};
|
|
||||||
|
|
||||||
var getEventClassName = (function () {
|
|
||||||
var incrementingId = 0;
|
|
||||||
return function () {
|
|
||||||
var id = incrementingId;
|
|
||||||
incrementingId += 1;
|
|
||||||
return '.perfect-scrollbar-' + id;
|
|
||||||
};
|
|
||||||
}());
|
|
||||||
|
|
||||||
$.fn.perfectScrollbar = function (suppliedSettings, option) {
|
|
||||||
|
|
||||||
return this.each(function () {
|
|
||||||
// Use the default settings
|
|
||||||
var settings = $.extend(true, {}, defaultSettings),
|
|
||||||
$this = $(this);
|
|
||||||
|
|
||||||
if (typeof suppliedSettings === "object") {
|
|
||||||
// But over-ride any supplied
|
|
||||||
$.extend(true, settings, suppliedSettings);
|
|
||||||
} else {
|
|
||||||
// If no settings were supplied, then the first param must be the option
|
|
||||||
option = suppliedSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Catch options
|
|
||||||
|
|
||||||
if (option === 'update') {
|
|
||||||
if ($this.data('perfect-scrollbar-update')) {
|
|
||||||
$this.data('perfect-scrollbar-update')();
|
|
||||||
}
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
else if (option === 'destroy') {
|
|
||||||
if ($this.data('perfect-scrollbar-destroy')) {
|
|
||||||
$this.data('perfect-scrollbar-destroy')();
|
|
||||||
}
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this.data('perfect-scrollbar')) {
|
|
||||||
// if there's already perfect-scrollbar
|
|
||||||
return $this.data('perfect-scrollbar');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Or generate new perfectScrollbar
|
|
||||||
|
|
||||||
// Set class to the container
|
|
||||||
$this.addClass('ps-container oo');
|
|
||||||
|
|
||||||
var $scrollbarXRail = $("<div class='ps-scrollbar-x-rail'></div>").appendTo($this),
|
|
||||||
$scrollbarYRail = $("<div class='ps-scrollbar-y-rail'></div>").appendTo($this),
|
|
||||||
$scrollbarX = $("<div class='ps-scrollbar-x'></div>").appendTo($scrollbarXRail),
|
|
||||||
$scrollbarY = $("<div class='ps-scrollbar-y'></div>").appendTo($scrollbarYRail),
|
|
||||||
scrollbarXActive,
|
|
||||||
scrollbarYActive,
|
|
||||||
containerWidth,
|
|
||||||
containerHeight,
|
|
||||||
contentWidth,
|
|
||||||
contentHeight,
|
|
||||||
scrollbarXWidth,
|
|
||||||
scrollbarXLeft,
|
|
||||||
scrollbarXBottom = parseInt($scrollbarXRail.css('bottom'), 10),
|
|
||||||
scrollbarXRailWidth,
|
|
||||||
scrollbarYHeight,
|
|
||||||
scrollbarYTop,
|
|
||||||
scrollbarYRight = parseInt($scrollbarYRail.css('right'), 10),
|
|
||||||
scrollbarYRailHeight,
|
|
||||||
eventClassName = getEventClassName();
|
|
||||||
|
|
||||||
var updateContentScrollTop = function (currentTop, deltaY) {
|
|
||||||
var newTop = currentTop + deltaY,
|
|
||||||
maxTop = scrollbarYRailHeight - scrollbarYHeight;
|
|
||||||
|
|
||||||
if (newTop < 0) {
|
|
||||||
scrollbarYTop = 0;
|
|
||||||
}
|
|
||||||
else if (newTop > maxTop) {
|
|
||||||
scrollbarYTop = maxTop;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
scrollbarYTop = newTop;
|
|
||||||
}
|
|
||||||
|
|
||||||
var scrollTop = parseInt(scrollbarYTop * (contentHeight - containerHeight) / (scrollbarYRailHeight - scrollbarYHeight), 10);
|
|
||||||
$this.scrollTop(scrollTop);
|
|
||||||
$scrollbarXRail.css({bottom: scrollbarXBottom - scrollTop});
|
|
||||||
};
|
|
||||||
|
|
||||||
var updateContentScrollLeft = function (currentLeft, deltaX) {
|
|
||||||
var newLeft = currentLeft + deltaX,
|
|
||||||
maxLeft = scrollbarXRailWidth - scrollbarXWidth;
|
|
||||||
|
|
||||||
if (newLeft < 0) {
|
|
||||||
scrollbarXLeft = 0;
|
|
||||||
}
|
|
||||||
else if (newLeft > maxLeft) {
|
|
||||||
scrollbarXLeft = maxLeft;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
scrollbarXLeft = newLeft;
|
|
||||||
}
|
|
||||||
|
|
||||||
var scrollLeft = parseInt(scrollbarXLeft * (contentWidth - containerWidth) / (scrollbarXRailWidth - scrollbarXWidth), 10);
|
|
||||||
$this.scrollLeft(scrollLeft);
|
|
||||||
$scrollbarYRail.css({right: scrollbarYRight - scrollLeft});
|
|
||||||
};
|
|
||||||
|
|
||||||
var getSettingsAdjustedThumbSize = function (thumbSize) {
|
|
||||||
if (settings.minScrollbarLength) {
|
|
||||||
thumbSize = Math.max(thumbSize, settings.minScrollbarLength);
|
|
||||||
}
|
|
||||||
return thumbSize;
|
|
||||||
};
|
|
||||||
|
|
||||||
var updateScrollbarCss = function () {
|
|
||||||
$scrollbarXRail.css({left: $this.scrollLeft(), bottom: scrollbarXBottom - $this.scrollTop(), width: scrollbarXRailWidth, display: scrollbarXActive ? "inherit": "none"});
|
|
||||||
|
|
||||||
if ($scrollbarYRail.hasClass('in-scrolling'))
|
|
||||||
$scrollbarYRail.css({/*top: $this.scrollTop(),*/ right: scrollbarYRight - $this.scrollLeft(), height: scrollbarYRailHeight, display: scrollbarYActive ? "inherit": "none"});
|
|
||||||
else
|
|
||||||
$scrollbarYRail.css({top: $this.scrollTop(), right: scrollbarYRight - $this.scrollLeft(), height: scrollbarYRailHeight, display: scrollbarYActive ? "inherit": "none"});
|
|
||||||
|
|
||||||
$scrollbarX && $scrollbarX.css({left: scrollbarXLeft, width: scrollbarXWidth});
|
|
||||||
$scrollbarY && $scrollbarY.css({top: scrollbarYTop, height: scrollbarYHeight});
|
|
||||||
};
|
|
||||||
|
|
||||||
var updateBarSizeAndPosition = function () {
|
|
||||||
containerWidth = settings.includePadding ? $this.innerWidth() : $this.width();
|
|
||||||
containerHeight = settings.includePadding ? $this.innerHeight() : $this.height();
|
|
||||||
scrollbarYRailHeight = containerHeight - (settings.includeMargin ? (parseInt($scrollbarYRail.css('margin-top')) + parseInt($scrollbarYRail.css('margin-bottom'))): 0);
|
|
||||||
scrollbarXRailWidth = containerWidth - (settings.includeMargin ? (parseInt($scrollbarXRail.css('margin-left')) + parseInt($scrollbarXRail.css('margin-right'))): 0);
|
|
||||||
contentWidth = $this.prop('scrollWidth');
|
|
||||||
contentHeight = $this.prop('scrollHeight');
|
|
||||||
|
|
||||||
if (!settings.suppressScrollX && containerWidth + settings.scrollXMarginOffset < contentWidth) {
|
|
||||||
scrollbarXActive = true;
|
|
||||||
scrollbarXWidth = getSettingsAdjustedThumbSize(parseInt(scrollbarXRailWidth * containerWidth / contentWidth, 10));
|
|
||||||
scrollbarXLeft = parseInt($this.scrollLeft() * (scrollbarXRailWidth - scrollbarXWidth) / (contentWidth - containerWidth), 10);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
scrollbarXActive = false;
|
|
||||||
scrollbarXWidth = 0;
|
|
||||||
scrollbarXLeft = 0;
|
|
||||||
$this.scrollLeft(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!settings.suppressScrollY && containerHeight + settings.scrollYMarginOffset < contentHeight) {
|
|
||||||
scrollbarYActive = true;
|
|
||||||
scrollbarYHeight = getSettingsAdjustedThumbSize(parseInt(scrollbarYRailHeight * containerHeight / contentHeight, 10));
|
|
||||||
scrollbarYTop = parseInt($this.scrollTop() * (scrollbarYRailHeight - scrollbarYHeight) / (contentHeight - containerHeight), 10);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
scrollbarYActive = false;
|
|
||||||
scrollbarYHeight = 0;
|
|
||||||
scrollbarYTop = 0;
|
|
||||||
$this.scrollTop(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scrollbarYTop >= scrollbarYRailHeight - scrollbarYHeight) {
|
|
||||||
scrollbarYTop = scrollbarYRailHeight - scrollbarYHeight;
|
|
||||||
}
|
|
||||||
if (scrollbarXLeft >= scrollbarXRailWidth - scrollbarXWidth) {
|
|
||||||
scrollbarXLeft = scrollbarXRailWidth - scrollbarXWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateScrollbarCss();
|
|
||||||
|
|
||||||
if (settings.onChange) {
|
|
||||||
settings.onChange(this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var bindMouseScrollXHandler = function () {
|
|
||||||
var currentLeft,
|
|
||||||
currentPageX;
|
|
||||||
|
|
||||||
$scrollbarX.bind('mousedown' + eventClassName, function (e) {
|
|
||||||
currentPageX = e.pageX;
|
|
||||||
currentLeft = $scrollbarX.position().left;
|
|
||||||
$scrollbarXRail.addClass('in-scrolling');
|
|
||||||
e.stopPropagation();
|
|
||||||
e.preventDefault();
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).bind('mousemove' + eventClassName, function (e) {
|
|
||||||
if ($scrollbarXRail.hasClass('in-scrolling')) {
|
|
||||||
updateContentScrollLeft(currentLeft, e.pageX - currentPageX);
|
|
||||||
e.stopPropagation();
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).bind('mouseup' + eventClassName, function (e) {
|
|
||||||
if ($scrollbarXRail.hasClass('in-scrolling')) {
|
|
||||||
$scrollbarXRail.removeClass('in-scrolling');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
currentLeft =
|
|
||||||
currentPageX = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
var bindMouseScrollYHandler = function () {
|
|
||||||
var currentTop,
|
|
||||||
currentPageY;
|
|
||||||
|
|
||||||
$scrollbarY.bind('mousedown' + eventClassName, function (e) {
|
|
||||||
currentPageY = e.pageY;
|
|
||||||
currentTop = $scrollbarY.position().top;
|
|
||||||
$scrollbarYRail.addClass('in-scrolling');
|
|
||||||
|
|
||||||
var margin = parseInt($scrollbarYRail.css('margin-top'));
|
|
||||||
var rect = $scrollbarYRail[0].getBoundingClientRect();
|
|
||||||
$scrollbarYRail.css({
|
|
||||||
position: 'fixed',
|
|
||||||
left: rect.left,
|
|
||||||
top: rect.top - margin
|
|
||||||
});
|
|
||||||
|
|
||||||
e.stopPropagation();
|
|
||||||
e.preventDefault();
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).bind('mousemove' + eventClassName, function (e) {
|
|
||||||
if ($scrollbarYRail.hasClass('in-scrolling')) {
|
|
||||||
updateContentScrollTop(currentTop, e.pageY - currentPageY);
|
|
||||||
e.stopPropagation();
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).bind('mouseup' + eventClassName, function (e) {
|
|
||||||
if ($scrollbarYRail.hasClass('in-scrolling')) {
|
|
||||||
$scrollbarYRail.removeClass('in-scrolling');
|
|
||||||
|
|
||||||
$scrollbarYRail.css({
|
|
||||||
position: '',
|
|
||||||
left: '',
|
|
||||||
top: ''
|
|
||||||
});
|
|
||||||
|
|
||||||
updateScrollbarCss();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
currentTop =
|
|
||||||
currentPageY = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
// check if the default scrolling should be prevented.
|
|
||||||
var shouldPreventDefault = function (deltaX, deltaY) {
|
|
||||||
var scrollTop = $this.scrollTop();
|
|
||||||
if (deltaX === 0) {
|
|
||||||
if (!scrollbarYActive) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ((scrollTop === 0 && deltaY > 0) || (scrollTop >= contentHeight - containerHeight && deltaY < 0)) {
|
|
||||||
return !settings.wheelPropagation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var scrollLeft = $this.scrollLeft();
|
|
||||||
if (deltaY === 0) {
|
|
||||||
if (!scrollbarXActive) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ((scrollLeft === 0 && deltaX < 0) || (scrollLeft >= contentWidth - containerWidth && deltaX > 0)) {
|
|
||||||
return !settings.wheelPropagation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// bind handlers
|
|
||||||
var bindMouseWheelHandler = function () {
|
|
||||||
// FIXME: Backward compatibility.
|
|
||||||
// After e.deltaFactor applied, wheelSpeed should have smaller value.
|
|
||||||
// Currently, there's no way to change the settings after the scrollbar initialized.
|
|
||||||
// But if the way is implemented in the future, wheelSpeed should be reset.
|
|
||||||
settings.wheelSpeed /= 10;
|
|
||||||
|
|
||||||
var shouldPrevent = false;
|
|
||||||
$this.bind('mousewheel' + eventClassName, function (e, deprecatedDelta, deprecatedDeltaX, deprecatedDeltaY) {
|
|
||||||
Common.NotificationCenter.trigger('hints:clear');
|
|
||||||
var deltaX = e.deltaX * e.deltaFactor || deprecatedDeltaX,
|
|
||||||
deltaY = e.deltaY * e.deltaFactor || deprecatedDeltaY;
|
|
||||||
|
|
||||||
if (e && e.target && (e.target.type === 'textarea' || e.target.type === 'input')) {
|
|
||||||
e.stopImmediatePropagation();
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
var scroll = $(e.target).scrollTop(), wheelDeltaY = 0;
|
|
||||||
if (e.originalEvent) {
|
|
||||||
if (e.originalEvent.wheelDelta) wheelDeltaY = e.originalEvent.wheelDelta;
|
|
||||||
else if (e.originalEvent.deltaY) wheelDeltaY = -e.originalEvent.deltaY*40;
|
|
||||||
else if (e.originalEvent.detail) wheelDeltaY = e.originalEvent.detail;
|
|
||||||
} else {
|
|
||||||
wheelDeltaY = (e.wheelDelta !== undefined) ? e.wheelDelta : e.deltaY;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$(e.target).scrollTop(scroll - wheelDeltaY);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
shouldPrevent = false;
|
|
||||||
if (!settings.useBothWheelAxes) {
|
|
||||||
// deltaX will only be used for horizontal scrolling and deltaY will
|
|
||||||
// only be used for vertical scrolling - this is the default
|
|
||||||
$this.scrollTop($this.scrollTop() - (deltaY * settings.wheelSpeed));
|
|
||||||
$this.scrollLeft($this.scrollLeft() + (deltaX * settings.wheelSpeed));
|
|
||||||
} else if (scrollbarYActive && !scrollbarXActive) {
|
|
||||||
// only vertical scrollbar is active and useBothWheelAxes option is
|
|
||||||
// active, so let's scroll vertical bar using both mouse wheel axes
|
|
||||||
if (deltaY) {
|
|
||||||
$this.scrollTop($this.scrollTop() - (deltaY * settings.wheelSpeed));
|
|
||||||
} else {
|
|
||||||
$this.scrollTop($this.scrollTop() + (deltaX * settings.wheelSpeed));
|
|
||||||
}
|
|
||||||
shouldPrevent = true;
|
|
||||||
} else if (scrollbarXActive && !scrollbarYActive) {
|
|
||||||
// useBothWheelAxes and only horizontal bar is active, so use both
|
|
||||||
// wheel axes for horizontal bar
|
|
||||||
if (deltaX) {
|
|
||||||
$this.scrollLeft($this.scrollLeft() + (deltaX * settings.wheelSpeed));
|
|
||||||
} else {
|
|
||||||
$this.scrollLeft($this.scrollLeft() - (deltaY * settings.wheelSpeed));
|
|
||||||
}
|
|
||||||
shouldPrevent = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// update bar position
|
|
||||||
updateBarSizeAndPosition();
|
|
||||||
|
|
||||||
shouldPrevent = (shouldPrevent || shouldPreventDefault(deltaX, deltaY));
|
|
||||||
if (shouldPrevent) {
|
|
||||||
e.stopPropagation();
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// fix Firefox scroll problem
|
|
||||||
$this.bind('MozMousePixelScroll' + eventClassName, function (e) {
|
|
||||||
if (shouldPrevent) {
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var bindKeyboardHandler = function () {
|
|
||||||
var hovered = false;
|
|
||||||
$this.bind('mouseenter' + eventClassName, function (e) {
|
|
||||||
hovered = true;
|
|
||||||
});
|
|
||||||
$this.bind('mouseleave' + eventClassName, function (e) {
|
|
||||||
hovered = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
var shouldPrevent = false;
|
|
||||||
$(document).bind('keydown' + eventClassName, function (e) {
|
|
||||||
if (!hovered || $(document.activeElement).is(":input,[contenteditable]")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var deltaX = 0,
|
|
||||||
deltaY = 0;
|
|
||||||
|
|
||||||
switch (e.which) {
|
|
||||||
case 37: // left
|
|
||||||
deltaX = -30;
|
|
||||||
break;
|
|
||||||
case 38: // up
|
|
||||||
deltaY = 30;
|
|
||||||
break;
|
|
||||||
case 39: // right
|
|
||||||
deltaX = 30;
|
|
||||||
break;
|
|
||||||
case 40: // down
|
|
||||||
deltaY = -30;
|
|
||||||
break;
|
|
||||||
case 33: // page up
|
|
||||||
deltaY = 90;
|
|
||||||
break;
|
|
||||||
case 32: // space bar
|
|
||||||
case 34: // page down
|
|
||||||
deltaY = -90;
|
|
||||||
break;
|
|
||||||
case 35: // end
|
|
||||||
deltaY = -containerHeight;
|
|
||||||
break;
|
|
||||||
case 36: // home
|
|
||||||
deltaY = containerHeight;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this.scrollTop($this.scrollTop() - deltaY);
|
|
||||||
$this.scrollLeft($this.scrollLeft() + deltaX);
|
|
||||||
|
|
||||||
shouldPrevent = shouldPreventDefault(deltaX, deltaY);
|
|
||||||
if (shouldPrevent) {
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var bindRailClickHandler = function () {
|
|
||||||
var stopPropagation = function (e) { e.stopPropagation(); };
|
|
||||||
|
|
||||||
$scrollbarY.bind('click' + eventClassName, stopPropagation);
|
|
||||||
$scrollbarYRail.bind('click' + eventClassName, function (e) {
|
|
||||||
var halfOfScrollbarLength = parseInt(scrollbarYHeight / 2, 10),
|
|
||||||
positionTop = e.pageY - $scrollbarYRail.offset().top - halfOfScrollbarLength,
|
|
||||||
maxPositionTop = scrollbarYRailHeight - scrollbarYHeight,
|
|
||||||
positionRatio = positionTop / maxPositionTop;
|
|
||||||
|
|
||||||
if (positionRatio < 0) {
|
|
||||||
positionRatio = 0;
|
|
||||||
} else if (positionRatio > 1) {
|
|
||||||
positionRatio = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this.scrollTop((contentHeight - containerHeight) * positionRatio);
|
|
||||||
});
|
|
||||||
|
|
||||||
$scrollbarX.bind('click' + eventClassName, stopPropagation);
|
|
||||||
$scrollbarXRail.bind('click' + eventClassName, function (e) {
|
|
||||||
var halfOfScrollbarLength = parseInt(scrollbarXWidth / 2, 10),
|
|
||||||
positionLeft = e.pageX - $scrollbarXRail.offset().left - halfOfScrollbarLength,
|
|
||||||
maxPositionLeft = scrollbarXRailWidth - scrollbarXWidth,
|
|
||||||
positionRatio = positionLeft / maxPositionLeft;
|
|
||||||
|
|
||||||
if (positionRatio < 0) {
|
|
||||||
positionRatio = 0;
|
|
||||||
} else if (positionRatio > 1) {
|
|
||||||
positionRatio = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this.scrollLeft((contentWidth - containerWidth) * positionRatio);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// bind mobile touch handler
|
|
||||||
var bindMobileTouchHandler = function () {
|
|
||||||
var applyTouchMove = function (differenceX, differenceY) {
|
|
||||||
$this.scrollTop($this.scrollTop() - differenceY);
|
|
||||||
$this.scrollLeft($this.scrollLeft() - differenceX);
|
|
||||||
|
|
||||||
// update bar position
|
|
||||||
updateBarSizeAndPosition();
|
|
||||||
};
|
|
||||||
|
|
||||||
var startCoords = {},
|
|
||||||
startTime = 0,
|
|
||||||
speed = {},
|
|
||||||
breakingProcess = null,
|
|
||||||
inGlobalTouch = false;
|
|
||||||
|
|
||||||
$(window).bind("touchstart" + eventClassName, function (e) {
|
|
||||||
inGlobalTouch = true;
|
|
||||||
});
|
|
||||||
$(window).bind("touchend" + eventClassName, function (e) {
|
|
||||||
inGlobalTouch = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
$this.bind("touchstart" + eventClassName, function (e) {
|
|
||||||
var touch = e.originalEvent.targetTouches[0];
|
|
||||||
|
|
||||||
startCoords.pageX = touch.pageX;
|
|
||||||
startCoords.pageY = touch.pageY;
|
|
||||||
|
|
||||||
startTime = (new Date()).getTime();
|
|
||||||
|
|
||||||
if (breakingProcess !== null) {
|
|
||||||
clearInterval(breakingProcess);
|
|
||||||
}
|
|
||||||
|
|
||||||
e.stopPropagation();
|
|
||||||
});
|
|
||||||
$this.bind("touchmove" + eventClassName, function (e) {
|
|
||||||
if (!inGlobalTouch && e.originalEvent.targetTouches.length === 1) {
|
|
||||||
var touch = e.originalEvent.targetTouches[0];
|
|
||||||
|
|
||||||
var currentCoords = {};
|
|
||||||
currentCoords.pageX = touch.pageX;
|
|
||||||
currentCoords.pageY = touch.pageY;
|
|
||||||
|
|
||||||
var differenceX = currentCoords.pageX - startCoords.pageX,
|
|
||||||
differenceY = currentCoords.pageY - startCoords.pageY;
|
|
||||||
|
|
||||||
applyTouchMove(differenceX, differenceY);
|
|
||||||
startCoords = currentCoords;
|
|
||||||
|
|
||||||
var currentTime = (new Date()).getTime();
|
|
||||||
|
|
||||||
var timeGap = currentTime - startTime;
|
|
||||||
if (timeGap > 0) {
|
|
||||||
speed.x = differenceX / timeGap;
|
|
||||||
speed.y = differenceY / timeGap;
|
|
||||||
startTime = currentTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$this.bind("touchend" + eventClassName, function (e) {
|
|
||||||
clearInterval(breakingProcess);
|
|
||||||
breakingProcess = setInterval(function () {
|
|
||||||
if (Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) {
|
|
||||||
clearInterval(breakingProcess);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
applyTouchMove(speed.x * 30, speed.y * 30);
|
|
||||||
|
|
||||||
speed.x *= 0.8;
|
|
||||||
speed.y *= 0.8;
|
|
||||||
}, 10);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var bindScrollHandler = function () {
|
|
||||||
$this.bind('scroll' + eventClassName, function (e) {
|
|
||||||
updateBarSizeAndPosition();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var destroy = function () {
|
|
||||||
$this.unbind(eventClassName);
|
|
||||||
$(window).unbind(eventClassName);
|
|
||||||
$(document).unbind(eventClassName);
|
|
||||||
$this.data('perfect-scrollbar', null);
|
|
||||||
$this.data('perfect-scrollbar-update', null);
|
|
||||||
$this.data('perfect-scrollbar-destroy', null);
|
|
||||||
$scrollbarX.remove();
|
|
||||||
$scrollbarY.remove();
|
|
||||||
$scrollbarXRail.remove();
|
|
||||||
$scrollbarYRail.remove();
|
|
||||||
|
|
||||||
// clean all variables
|
|
||||||
$scrollbarX =
|
|
||||||
$scrollbarY =
|
|
||||||
containerWidth =
|
|
||||||
containerHeight =
|
|
||||||
contentWidth =
|
|
||||||
contentHeight =
|
|
||||||
scrollbarXWidth =
|
|
||||||
scrollbarXLeft =
|
|
||||||
scrollbarXBottom =
|
|
||||||
scrollbarYHeight =
|
|
||||||
scrollbarYTop =
|
|
||||||
scrollbarYRight = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
var ieSupport = function (version) {
|
|
||||||
$this.addClass('ie').addClass('ie' + version);
|
|
||||||
|
|
||||||
var bindHoverHandlers = function () {
|
|
||||||
var mouseenter = function () {
|
|
||||||
$(this).addClass('hover');
|
|
||||||
};
|
|
||||||
var mouseleave = function () {
|
|
||||||
$(this).removeClass('hover');
|
|
||||||
};
|
|
||||||
$this.bind('mouseenter' + eventClassName, mouseenter).bind('mouseleave' + eventClassName, mouseleave);
|
|
||||||
$scrollbarXRail.bind('mouseenter' + eventClassName, mouseenter).bind('mouseleave' + eventClassName, mouseleave);
|
|
||||||
$scrollbarYRail.bind('mouseenter' + eventClassName, mouseenter).bind('mouseleave' + eventClassName, mouseleave);
|
|
||||||
$scrollbarX.bind('mouseenter' + eventClassName, mouseenter).bind('mouseleave' + eventClassName, mouseleave);
|
|
||||||
$scrollbarY.bind('mouseenter' + eventClassName, mouseenter).bind('mouseleave' + eventClassName, mouseleave);
|
|
||||||
};
|
|
||||||
|
|
||||||
var fixIe6ScrollbarPosition = function () {
|
|
||||||
updateScrollbarCss = function () {
|
|
||||||
$scrollbarX.css({left: scrollbarXLeft + $this.scrollLeft(), bottom: scrollbarXBottom, width: scrollbarXWidth});
|
|
||||||
$scrollbarY.css({top: scrollbarYTop + $this.scrollTop(), right: scrollbarYRight, height: scrollbarYHeight});
|
|
||||||
$scrollbarX.hide().show();
|
|
||||||
$scrollbarY.hide().show();
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
if (version === 6) {
|
|
||||||
bindHoverHandlers();
|
|
||||||
fixIe6ScrollbarPosition();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var supportsTouch = (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch);
|
|
||||||
|
|
||||||
var initialize = function () {
|
|
||||||
var ieMatch = navigator.userAgent.toLowerCase().match(/(msie) ([\w.]+)/);
|
|
||||||
if (ieMatch && ieMatch[1] === 'msie') {
|
|
||||||
// must be executed at first, because 'ieSupport' may addClass to the container
|
|
||||||
ieSupport(parseInt(ieMatch[2], 10));
|
|
||||||
}
|
|
||||||
|
|
||||||
updateBarSizeAndPosition();
|
|
||||||
bindScrollHandler();
|
|
||||||
bindMouseScrollXHandler();
|
|
||||||
bindMouseScrollYHandler();
|
|
||||||
bindRailClickHandler();
|
|
||||||
if (supportsTouch) {
|
|
||||||
bindMobileTouchHandler();
|
|
||||||
}
|
|
||||||
if ($this.mousewheel) {
|
|
||||||
bindMouseWheelHandler();
|
|
||||||
}
|
|
||||||
if (settings.useKeyboard) {
|
|
||||||
bindKeyboardHandler();
|
|
||||||
}
|
|
||||||
$this.data('perfect-scrollbar', $this);
|
|
||||||
$this.data('perfect-scrollbar-update', updateBarSizeAndPosition);
|
|
||||||
$this.data('perfect-scrollbar-destroy', destroy);
|
|
||||||
};
|
|
||||||
|
|
||||||
// initialize
|
|
||||||
initialize();
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}));
|
|
Loading…
Reference in a new issue