webapps added
This commit is contained in:
parent
a4bf803b7c
commit
741b10515d
21
.hgignore
Normal file
21
.hgignore
Normal file
|
@ -0,0 +1,21 @@
|
|||
syntax: glob
|
||||
|
||||
.idea
|
||||
Thumbs.db
|
||||
.DS_Store
|
||||
deploy
|
||||
build/node_modules
|
||||
apps/documenteditor/embed/resources/less/node_modules
|
||||
apps/presentationeditor/embed/resources/less/node_modules
|
||||
apps/spreadsheeteditor/embed/resources/less/node_modules
|
||||
apps/documenteditor/mobile/resources/sass/.sass-cache
|
||||
apps/spreadsheeteditor/mobile/resources/sass/.sass-cache
|
||||
|
||||
|
||||
# test documents
|
||||
apps/presentationeditor/embed/document
|
||||
apps/presentationeditor/main/document
|
||||
apps/presentationeditor/mobile/document
|
||||
apps/spreadsheeteditor/embed/offlinedocs
|
||||
apps/spreadsheeteditor/main/offlinedocs
|
||||
apps/spreadsheeteditor/mobile/offlinedocs
|
679
apps/api/documents/api.js
Normal file
679
apps/api/documents/api.js
Normal file
|
@ -0,0 +1,679 @@
|
|||
/**
|
||||
* Copyright (c) Ascensio System SIA 2013. All rights reserved
|
||||
*
|
||||
* http://www.onlyoffice.com
|
||||
*/
|
||||
|
||||
;(function(DocsAPI, window, document, undefined) {
|
||||
|
||||
/*
|
||||
|
||||
# Full #
|
||||
|
||||
config = {
|
||||
type: 'desktop or mobile',
|
||||
width: '100% by default',
|
||||
height: '100% by default',
|
||||
documentType: 'text' | 'spreadsheet' | 'presentation',
|
||||
document: {
|
||||
title: 'document title',
|
||||
url: 'document url'
|
||||
fileType: 'document file type',
|
||||
options: <advanced options>,
|
||||
key: 'key',
|
||||
vkey: 'vkey',
|
||||
info: {
|
||||
author: 'author name',
|
||||
folder: 'path to document',
|
||||
created: '<creation date>',
|
||||
sharingSettings: [
|
||||
{
|
||||
user: 'user name',
|
||||
permissions: '<permissions>',
|
||||
isLink: false
|
||||
},
|
||||
...
|
||||
]
|
||||
},
|
||||
permissions: {
|
||||
edit: <can edit>, // default = true
|
||||
download: <can download>,
|
||||
reader: <can view in readable mode>
|
||||
review: <can review> // default = edit,
|
||||
print: <can print> // default = true
|
||||
}
|
||||
},
|
||||
editorConfig: {
|
||||
mode: 'view or edit',
|
||||
lang: <language code>,
|
||||
canCoAuthoring: <can coauthoring documents>,
|
||||
canAutosave: <can autosave documents>,
|
||||
canBackToFolder: <can return to folder> - deprecated. use "customization.goback" parameter,
|
||||
createUrl: 'create document url',
|
||||
sharingSettingsUrl: 'document sharing settings url',
|
||||
fileChoiceUrl: 'mail merge sources url',
|
||||
callbackUrl: <url for connection between sdk and portal>,
|
||||
mergeFolderUrl: 'folder for saving merged file',
|
||||
licenseUrl: <url for license>,
|
||||
customerId: <customer id>,
|
||||
|
||||
user: {
|
||||
id: 'user id',
|
||||
firstname: 'user first name',
|
||||
lastname: 'user last name'
|
||||
},
|
||||
recent: [
|
||||
{
|
||||
title: 'document title',
|
||||
url: 'document url',
|
||||
folder: 'path to document'
|
||||
},
|
||||
...
|
||||
],
|
||||
templates: [
|
||||
{
|
||||
name: 'template name',
|
||||
icon: 'template icon url',
|
||||
url: 'http://...'
|
||||
},
|
||||
...
|
||||
],
|
||||
customization: {
|
||||
logo: {
|
||||
image: url,
|
||||
imageEmbedded: url,
|
||||
url: http://...
|
||||
},
|
||||
backgroundColor: 'header background color',
|
||||
textColor: 'header text color',
|
||||
customer: {
|
||||
name: 'SuperPuper',
|
||||
address: 'New-York, 125f-25',
|
||||
mail: 'support@gmail.com',
|
||||
www: 'www.superpuper.com',
|
||||
info: 'Some info',
|
||||
logo: ''
|
||||
},
|
||||
about: false,
|
||||
feedback: {
|
||||
visible: false,
|
||||
url: http://...
|
||||
},
|
||||
goback: {
|
||||
url: 'http://...',
|
||||
text: 'Go to London'
|
||||
},
|
||||
chat: false,
|
||||
comments: false
|
||||
}
|
||||
},
|
||||
events: {
|
||||
'onReady': <document ready callback>,
|
||||
'onBack': <back to folder callback>,
|
||||
'onDocumentStateChange': <document state changed callback>,
|
||||
'onSave': <save request callback>
|
||||
}
|
||||
}
|
||||
|
||||
# Embedded #
|
||||
|
||||
config = {
|
||||
type: 'embedded',
|
||||
width: '100% by default',
|
||||
height: '100% by default',
|
||||
documentType: 'text' | 'spreadsheet' | 'presentation',
|
||||
document: {
|
||||
title: 'document title',
|
||||
url: 'document url',
|
||||
fileType: 'document file type',
|
||||
key: 'key',
|
||||
vkey: 'vkey'
|
||||
},
|
||||
editorConfig: {
|
||||
licenseUrl: <url for license>,
|
||||
customerId: <customer id>,
|
||||
embedded: {
|
||||
embedUrl: 'url',
|
||||
fullscreenUrl: 'url',
|
||||
saveUrl: 'url',
|
||||
shareUrl: 'url',
|
||||
toolbarDocked: 'top or bottom'
|
||||
}
|
||||
},
|
||||
events: {
|
||||
'onReady': <document ready callback>,
|
||||
'onBack': <back to folder callback>,
|
||||
'onError': <error callback>,
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// TODO: allow several instances on one page simultaneously
|
||||
|
||||
DocsAPI.DocEditor = function(placeholderId, config) {
|
||||
var _self = this,
|
||||
_config = config || {};
|
||||
|
||||
extend(_config, DocsAPI.DocEditor.defaultConfig);
|
||||
_config.editorConfig.canUseHistory = _config.events && !!_config.events.onRequestHistory;
|
||||
_config.editorConfig.canHistoryClose = _config.events && !!_config.events.onRequestHistoryClose;
|
||||
_config.editorConfig.canSendEmailAddresses = _config.events && !!_config.events.onRequestEmailAddresses;
|
||||
_config.editorConfig.canRequestEditRights = _config.events && !!_config.events.onRequestEditRights;
|
||||
|
||||
var onMouseUp = function (evt) {
|
||||
_processMouse(evt);
|
||||
};
|
||||
|
||||
var _attachMouseEvents = function() {
|
||||
if (window.addEventListener) {
|
||||
window.addEventListener("mouseup", onMouseUp, false)
|
||||
} else if (window.attachEvent) {
|
||||
window.attachEvent("onmouseup", onMouseUp);
|
||||
}
|
||||
};
|
||||
|
||||
var _detachMouseEvents = function() {
|
||||
if (window.removeEventListener) {
|
||||
window.removeEventListener("mouseup", onMouseUp, false)
|
||||
} else if (window.detachEvent) {
|
||||
window.detachEvent("onmouseup", onMouseUp);
|
||||
}
|
||||
};
|
||||
|
||||
var _onReady = function() {
|
||||
if (_config.type === 'mobile') {
|
||||
document.body.onfocus = function(e) {
|
||||
setTimeout(function(){
|
||||
iframe.contentWindow.focus();
|
||||
|
||||
_sendCommand({
|
||||
command: 'resetFocus',
|
||||
data: {}
|
||||
})
|
||||
}, 10);
|
||||
};
|
||||
}
|
||||
|
||||
_attachMouseEvents();
|
||||
|
||||
if (_config.editorConfig) {
|
||||
_init(_config.editorConfig);
|
||||
}
|
||||
|
||||
if (_config.document) {
|
||||
_openDocument(_config.document);
|
||||
}
|
||||
};
|
||||
|
||||
var _callLocalStorage = function(data) {
|
||||
if (data.cmd == 'get') {
|
||||
if (data.keys && data.keys.length) {
|
||||
var af = data.keys.split(','), re = af[0];
|
||||
for (i = 0; ++i < af.length;)
|
||||
re += '|' + af[i];
|
||||
|
||||
re = new RegExp(re); k = {};
|
||||
for (i in localStorage)
|
||||
if (re.test(i)) k[i] = localStorage[i];
|
||||
} else {
|
||||
k = localStorage;
|
||||
}
|
||||
|
||||
_sendCommand({
|
||||
command: 'internalCommand',
|
||||
data: {
|
||||
type: 'localstorage',
|
||||
keys: k
|
||||
}
|
||||
});
|
||||
} else
|
||||
if (data.cmd == 'set') {
|
||||
var k = data.keys, i;
|
||||
for (i in k) {
|
||||
localStorage.setItem(i, k[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var _onMessage = function(msg) {
|
||||
if (msg) {
|
||||
var events = _config.events || {},
|
||||
handler = events[msg.event],
|
||||
res;
|
||||
|
||||
if (msg.event === 'onRequestEditRights' && !handler) {
|
||||
_applyEditRights(false, 'handler is\'n defined');
|
||||
} else
|
||||
if (msg.event === 'onInternalMessage' && msg.data && msg.data.type == 'localstorage') {
|
||||
_callLocalStorage(msg.data.data);
|
||||
} else {
|
||||
if (msg.event === 'onReady') {
|
||||
_onReady();
|
||||
}
|
||||
|
||||
if (handler) {
|
||||
res = handler.call(_self, { target: _self, data: msg.data });
|
||||
if (msg.event === 'onSave' && res !== false) {
|
||||
_processSaveResult(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var _checkConfigParams = function() {
|
||||
if (_config.document) {
|
||||
if (!_config.document.url || ((typeof _config.document.fileType !== 'string' || _config.document.fileType=='') &&
|
||||
(typeof _config.documentType !== 'string' || _config.documentType==''))) {
|
||||
window.alert("One or more required parameter for the config object is not set");
|
||||
return false;
|
||||
}
|
||||
|
||||
var appMap = {
|
||||
'text': 'docx',
|
||||
'text-pdf': 'pdf',
|
||||
'spreadsheet': 'xlsx',
|
||||
'presentation': 'pptx'
|
||||
}, app;
|
||||
|
||||
if (typeof _config.documentType === 'string' && _config.documentType != '') {
|
||||
app = appMap[_config.documentType.toLowerCase()];
|
||||
if (!app) {
|
||||
window.alert("The \"documentType\" parameter for the config object is invalid. Please correct it.");
|
||||
return false;
|
||||
} else if (typeof _config.document.fileType !== 'string' || _config.document.fileType == '') {
|
||||
_config.document.fileType = app;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof _config.document.fileType === 'string' && _config.document.fileType != '') {
|
||||
var type = /^(?:(xls|xlsx|ods|csv|xlst|xlsy|gsheet)|(pps|ppsx|ppt|pptx|odp|pptt|ppty|gslides)|(doc|docx|doct|odt|gdoc|txt|rtf|pdf|mht|htm|html|epub|djvu|xps))$/
|
||||
.exec(_config.document.fileType);
|
||||
if (!type) {
|
||||
window.alert("The \"document.fileType\" parameter for the config object is invalid. Please correct it.");
|
||||
return false;
|
||||
} else if (typeof _config.documentType !== 'string' || _config.documentType == ''){
|
||||
if (typeof type[1] === 'string') _config.documentType = 'spreadsheet'; else
|
||||
if (typeof type[2] === 'string') _config.documentType = 'presentation'; else
|
||||
if (typeof type[3] === 'string') _config.documentType = 'text';
|
||||
}
|
||||
}
|
||||
|
||||
var type = /^(?:(pdf|djvu|xps))$/.exec(_config.document.fileType);
|
||||
if (type && typeof type[1] === 'string') {
|
||||
if (!_config.document.permissions)
|
||||
_config.document.permissions = {};
|
||||
_config.document.permissions.edit = false;
|
||||
}
|
||||
|
||||
if (!_config.document.title || _config.document.title=='')
|
||||
_config.document.title = 'Unnamed.' + _config.document.fileType;
|
||||
|
||||
if (!_config.document.key) {
|
||||
_config.document.key = 'xxxxxxxxxxxxxxxxxxxx'.replace(/[x]/g, function (c) {var r = Math.random() * 16 | 0; return r.toString(16);});
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
(function() {
|
||||
var result = /[\?\&]placement=(\w+)&?/.exec(window.location.search);
|
||||
if (!!result && result.length) {
|
||||
if (result[1] == 'desktop') {
|
||||
_config.editorConfig.targetApp = result[1];
|
||||
_config.editorConfig.canBackToFolder = false;
|
||||
_config.editorConfig.canUseHistory = false;
|
||||
if (!_config.editorConfig.customization) _config.editorConfig.customization = {};
|
||||
_config.editorConfig.customization.about = false;
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
var target = document.getElementById(placeholderId),
|
||||
iframe;
|
||||
|
||||
if (target && _checkConfigParams()) {
|
||||
iframe = createIframe(_config);
|
||||
target.parentNode && target.parentNode.replaceChild(iframe, target);
|
||||
this._msgDispatcher = new MessageDispatcher(_onMessage, this);
|
||||
}
|
||||
|
||||
/*
|
||||
cmd = {
|
||||
command: 'commandName',
|
||||
data: <command specific data>
|
||||
}
|
||||
*/
|
||||
var _sendCommand = function(cmd) {
|
||||
if (iframe && iframe.contentWindow)
|
||||
postMessage(iframe.contentWindow, cmd);
|
||||
};
|
||||
|
||||
var _init = function(editorConfig) {
|
||||
_sendCommand({
|
||||
command: 'init',
|
||||
data: {
|
||||
config: editorConfig
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var _openDocument = function(doc) {
|
||||
_sendCommand({
|
||||
command: 'openDocument',
|
||||
data: {
|
||||
doc: doc
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var _showError = function(title, msg) {
|
||||
_showMessage(title, msg, "error");
|
||||
};
|
||||
|
||||
// severity could be one of: "error", "info" or "warning"
|
||||
var _showMessage = function(title, msg, severity) {
|
||||
if (typeof severity !== 'string') {
|
||||
severity = "info";
|
||||
}
|
||||
_sendCommand({
|
||||
command: 'showMessage',
|
||||
data: {
|
||||
title: title,
|
||||
msg: msg,
|
||||
severity: severity
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var _applyEditRights = function(allowed, message) {
|
||||
_sendCommand({
|
||||
command: 'applyEditRights',
|
||||
data: {
|
||||
allowed: allowed,
|
||||
message: message
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var _processSaveResult = function(result, message) {
|
||||
_sendCommand({
|
||||
command: 'processSaveResult',
|
||||
data: {
|
||||
result: result,
|
||||
message: message
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// TODO: remove processRightsChange, use denyEditingRights
|
||||
var _processRightsChange = function(enabled, message) {
|
||||
_sendCommand({
|
||||
command: 'processRightsChange',
|
||||
data: {
|
||||
enabled: enabled,
|
||||
message: message
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var _denyEditingRights = function(message) {
|
||||
_sendCommand({
|
||||
command: 'processRightsChange',
|
||||
data: {
|
||||
enabled: false,
|
||||
message: message
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var _refreshHistory = function(data, message) {
|
||||
_sendCommand({
|
||||
command: 'refreshHistory',
|
||||
data: {
|
||||
data: data,
|
||||
message: message
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var _setHistoryData = function(data, message) {
|
||||
_sendCommand({
|
||||
command: 'setHistoryData',
|
||||
data: {
|
||||
data: data,
|
||||
message: message
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var _setEmailAddresses = function(data) {
|
||||
_sendCommand({
|
||||
command: 'setEmailAddresses',
|
||||
data: {
|
||||
data: data
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var _processMailMerge = function(enabled, message) {
|
||||
_sendCommand({
|
||||
command: 'processMailMerge',
|
||||
data: {
|
||||
enabled: enabled,
|
||||
message: message
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var _downloadAs = function() {
|
||||
_sendCommand({
|
||||
command: 'downloadAs'
|
||||
});
|
||||
};
|
||||
|
||||
var _processMouse = function(evt) {
|
||||
var r = iframe.getBoundingClientRect();
|
||||
var data = {
|
||||
type: evt.type,
|
||||
x: evt.x - r.left,
|
||||
y: evt.y - r.top
|
||||
};
|
||||
|
||||
_sendCommand({
|
||||
command: 'processMouse',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
var _serviceCommand = function(command, data) {
|
||||
_sendCommand({
|
||||
command: 'internalCommand',
|
||||
data: {
|
||||
command: command,
|
||||
data: data
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
showError : _showError,
|
||||
showMessage : _showMessage,
|
||||
applyEditRights : _applyEditRights,
|
||||
processSaveResult : _processSaveResult,
|
||||
processRightsChange : _processRightsChange,
|
||||
denyEditingRights : _denyEditingRights,
|
||||
refreshHistory : _refreshHistory,
|
||||
setHistoryData : _setHistoryData,
|
||||
setEmailAddresses : _setEmailAddresses,
|
||||
processMailMerge : _processMailMerge,
|
||||
downloadAs : _downloadAs,
|
||||
serviceCommand : _serviceCommand,
|
||||
attachMouseEvents : _attachMouseEvents,
|
||||
detachMouseEvents : _detachMouseEvents
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
DocsAPI.DocEditor.defaultConfig = {
|
||||
type: 'desktop',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
editorConfig: {
|
||||
lang: 'en',
|
||||
canCoAuthoring: true,
|
||||
customization: {
|
||||
about: false,
|
||||
feedback: false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DocsAPI.DocEditor.version = function() {
|
||||
return '3.0b##BN#';
|
||||
};
|
||||
|
||||
MessageDispatcher = function(fn, scope) {
|
||||
var _fn = fn,
|
||||
_scope = scope || window;
|
||||
|
||||
var _bindEvents = function() {
|
||||
if (window.addEventListener) {
|
||||
window.addEventListener("message", function(msg) {
|
||||
_onMessage(msg);
|
||||
}, false)
|
||||
}
|
||||
else if (window.attachEvent) {
|
||||
window.attachEvent("onmessage", function(msg) {
|
||||
_onMessage(msg);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var _onMessage = function(msg) {
|
||||
// TODO: check message origin
|
||||
if (msg && window.JSON) {
|
||||
|
||||
try {
|
||||
var msg = window.JSON.parse(msg.data);
|
||||
if (_fn) {
|
||||
_fn.call(_scope, msg);
|
||||
}
|
||||
} catch(e) {}
|
||||
}
|
||||
};
|
||||
|
||||
_bindEvents.call(this);
|
||||
};
|
||||
|
||||
function getBasePath() {
|
||||
var scripts = document.getElementsByTagName('script'),
|
||||
match;
|
||||
|
||||
for (var i = scripts.length - 1; i >= 0; i--) {
|
||||
match = scripts[i].src.match(/(.*)api\/documents\/api.js/i);
|
||||
if (match) {
|
||||
return match[1];
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
function getExtensionPath() {
|
||||
if ("undefined" == typeof(extensionParams) || null == extensionParams["url"])
|
||||
return null;
|
||||
return extensionParams["url"] + "apps/";
|
||||
}
|
||||
|
||||
function getAppPath(config) {
|
||||
var extensionPath = getExtensionPath(),
|
||||
path = extensionPath ? extensionPath : getBasePath(),
|
||||
appMap = {
|
||||
'text': 'documenteditor',
|
||||
'text-pdf': 'documenteditor',
|
||||
'spreadsheet': 'spreadsheeteditor',
|
||||
'presentation': 'presentationeditor'
|
||||
},
|
||||
app = appMap['text'];
|
||||
|
||||
if (typeof config.documentType === 'string') {
|
||||
app = appMap[config.documentType.toLowerCase()];
|
||||
} else
|
||||
if (!!config.document && typeof config.document.fileType === 'string') {
|
||||
var type = /^(?:(xls|xlsx|ods|csv|xlst|xlsy|gsheet)|(pps|ppsx|ppt|pptx|odp|pptt|ppty|gslides))$/
|
||||
.exec(config.document.fileType);
|
||||
if (type) {
|
||||
if (typeof type[1] === 'string') app = appMap['spreadsheet']; else
|
||||
if (typeof type[2] === 'string') app = appMap['presentation'];
|
||||
}
|
||||
}
|
||||
|
||||
path += app + "/";
|
||||
path += config.type === "mobile"
|
||||
? "mobile"
|
||||
: config.type === "embedded"
|
||||
? "embed"
|
||||
: "main";
|
||||
path += "/index.html";
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
function getAppParameters(config) {
|
||||
var params = "?_dc=0";
|
||||
|
||||
if (config.editorConfig && config.editorConfig.lang)
|
||||
params += "&lang=" + config.editorConfig.lang;
|
||||
|
||||
if (config.editorConfig && config.editorConfig.targetApp!=='desktop') {
|
||||
if ( (typeof(config.editorConfig.customization) == 'object') && config.editorConfig.customization.loaderName) {
|
||||
if (config.editorConfig.customization.loaderName !== 'none') params += "&customer=" + config.editorConfig.customization.loaderName;
|
||||
} else
|
||||
params += "&customer=ONLYOFFICE";
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
function createIframe(config) {
|
||||
var iframe = document.createElement("iframe");
|
||||
|
||||
iframe.src = getAppPath(config) + getAppParameters(config);
|
||||
iframe.width = config.width;
|
||||
iframe.height = config.height;
|
||||
iframe.align = "top";
|
||||
iframe.frameBorder = 0;
|
||||
iframe.name = "frameEditor";
|
||||
iframe.allowFullscreen = true;
|
||||
iframe.setAttribute("allowfullscreen",""); // for IE11
|
||||
iframe.setAttribute("onmousewheel",""); // for Safari on Mac
|
||||
return iframe;
|
||||
}
|
||||
|
||||
function postMessage(wnd, msg) {
|
||||
if (wnd && wnd.postMessage && window.JSON) {
|
||||
// TODO: specify explicit origin
|
||||
wnd.postMessage(window.JSON.stringify(msg), "*");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function extend(dest, src) {
|
||||
for (var prop in src) {
|
||||
if (src.hasOwnProperty(prop)) {
|
||||
if (typeof dest[prop] === 'undefined') {
|
||||
dest[prop] = src[prop];
|
||||
} else
|
||||
if (typeof dest[prop] === 'object' &&
|
||||
typeof src[prop] === 'object') {
|
||||
extend(dest[prop], src[prop])
|
||||
}
|
||||
}
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
})(window.DocsAPI = window.DocsAPI || {}, window, document);
|
||||
|
25
apps/api/documents/cache-scripts.html
Normal file
25
apps/api/documents/cache-scripts.html
Normal file
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>ONLYOFFICE Documents</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
|
||||
<meta name="description" content="" />
|
||||
<meta name="keywords" content="" />
|
||||
<style type="text/css"></style>
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript" src="../../../vendor/jquery/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../../../vendor/requirejs/require.js"></script>
|
||||
<script type="text/javascript" src="../../../vendor/sockjs/sockjs.min.js"></script>
|
||||
<script type="text/javascript" src="../../../vendor/xregexp/xregexp-all-min.js"></script>
|
||||
<script type="text/javascript" src="../../../sdk/Common/AllFonts.js"></script>
|
||||
<script type="text/javascript" src="../../../sdk/Word/sdk-all.js"></script>
|
||||
<div id="editor_sdk">
|
||||
<script type="text/javascript">
|
||||
var editor = new asc_docs_api("editor_sdk");
|
||||
editor.asc_SetFontsPath("../../../sdk/Fonts/");
|
||||
editor.LoadFontsFromServer();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
352
apps/api/documents/index.html
Normal file
352
apps/api/documents/index.html
Normal file
|
@ -0,0 +1,352 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>ONLYOFFICE Documents</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=IE8"/>
|
||||
<meta name="description" content="" />
|
||||
<meta name="keywords" content="" />
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-touch-fullscreen" content="yes">
|
||||
|
||||
<style type="text/css">
|
||||
html {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#wrap {
|
||||
position:absolute;
|
||||
left:0;
|
||||
top:0;
|
||||
right:0;
|
||||
bottom:0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="wrap">
|
||||
<div id="placeholder"></div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="api.js"></script>
|
||||
<script>
|
||||
(function() {
|
||||
|
||||
// Url parameters
|
||||
|
||||
var urlParams = getUrlParams(),
|
||||
cfg = getEditorConfig(urlParams),
|
||||
doc = getDocumentData(urlParams);
|
||||
|
||||
// Document Editor
|
||||
|
||||
var docEditor = new DocsAPI.DocEditor('placeholder', {
|
||||
type: urlParams['type'],
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
documentType: urlParams['doctype'] || 'text',
|
||||
document: doc,
|
||||
editorConfig: cfg,
|
||||
events: {
|
||||
'onReady': onDocEditorReady,
|
||||
'onDocumentStateChange': onDocumentStateChange,
|
||||
'onRequestEditRights': onRequestEditRights,
|
||||
'onRequestHistory': onRequestHistory,
|
||||
'onRequestHistoryData': onRequestHistoryData,
|
||||
'onRequestEmailAddresses': onRequestEmailAddresses,
|
||||
'onRequestStartMailMerge': onRequestStartMailMerge,
|
||||
'onRequestHistoryClose': onRequestHistoryClose,
|
||||
'onSave': onDocumentSave,
|
||||
'onError': onError
|
||||
}
|
||||
});
|
||||
|
||||
// Document Editor event handlers
|
||||
|
||||
function onRequestEmailAddresses() {
|
||||
docEditor.setEmailAddresses({emailAddresses: ['aaa@mail.ru'], createEmailAccountUrl: 'http://ya.ru'});
|
||||
}
|
||||
|
||||
function onRequestHistory() {
|
||||
docEditor.refreshHistory({
|
||||
'currentVersion': 3,
|
||||
'history': [
|
||||
{
|
||||
'user': {
|
||||
id: '8952d4ee-e8a5-42bf-86f0-6cd77801ec15',
|
||||
name: 'Татьяна Щербакова'
|
||||
},
|
||||
'changes': null,
|
||||
'created': '1/18/2015 6:38 PM',
|
||||
'version': 1,
|
||||
'versionGroup': 1,
|
||||
'key': 'wyX9AwRq_677SWKjhfk='
|
||||
},
|
||||
{
|
||||
'user': {
|
||||
id: '8952d4ee-e8a5-42bf-86f0-6cd77801ec15',
|
||||
name: 'Татьяна Щербакова'
|
||||
},
|
||||
'changes': [
|
||||
{
|
||||
'user': {
|
||||
id: '8952d4ee-e8a5-42bf-86f0-6cd77801ec15',
|
||||
name: 'Татьяна Щербакова'
|
||||
},
|
||||
'created': '1/19/2015 6:30 PM'
|
||||
},
|
||||
{
|
||||
'user': {
|
||||
'id': '8952d4ee-e8a5-42bf-11f0-6cd77801ec15',
|
||||
'name': 'Александр Трофимов'
|
||||
},
|
||||
'created': '1/19/2015 6:32 PM'
|
||||
},
|
||||
{
|
||||
'user': {
|
||||
id: '8952d4ee-e8a5-42bf-86f0-6cd77801ec15',
|
||||
name: 'Татьяна Щербакова'
|
||||
},
|
||||
'created': '1/19/2015 6:38 PM'
|
||||
}
|
||||
],
|
||||
'created': '2/19/2015 6:38 PM',
|
||||
'version': 2,
|
||||
'versionGroup': 1,
|
||||
'key': 'wyX9AwRq_677SWKjhfk='
|
||||
},
|
||||
{
|
||||
'user': {
|
||||
id: '895255ee-e8a5-42bf-86f0-6cd77801ec15',
|
||||
name: 'Me'
|
||||
},
|
||||
'changes': null,
|
||||
'created': '2/21/2015 6:38 PM',
|
||||
'version': 3,
|
||||
'versionGroup': 2,
|
||||
'key': 'wyX9AwRq_677SWKjhfk='
|
||||
},
|
||||
{
|
||||
'user': {
|
||||
id: '8952d4ee-e8a5-42bf-11f0-6cd77801ec15',
|
||||
name: 'Александр Трофимов'
|
||||
},
|
||||
'changes': null,
|
||||
'created': '2/22/2015 6:37 PM',
|
||||
'version': 4,
|
||||
'versionGroup': 3,
|
||||
'key': 'wyX9AwRq_677SWKjhfk='
|
||||
},
|
||||
{
|
||||
'user': {
|
||||
id: '8952d4ee-e8a5-42bf-11f0-6cd33801ec15',
|
||||
name: 'Леонид Орлов'
|
||||
},
|
||||
'changes': null,
|
||||
'created': '2/24/2015 6:29 PM',
|
||||
'version': 5,
|
||||
'versionGroup': 3,
|
||||
'key': 'wyX9AwRq_677SWKjhfk='
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
function onRequestHistoryData(revision) {
|
||||
docEditor.setHistoryData(
|
||||
{
|
||||
'version': revision.data,
|
||||
'url': 'http://isa2',
|
||||
'urlDiff': 'http://isa2'
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function onRequestStartMailMerge() {
|
||||
docEditor.processMailMerge(true, 'some error message');
|
||||
}
|
||||
|
||||
function onRequestHistoryClose() {
|
||||
// reload page
|
||||
}
|
||||
|
||||
function onDocEditorReady(event) {
|
||||
if (event.target) {
|
||||
//console.log('Ready! Editor: ', event.target);
|
||||
}
|
||||
}
|
||||
|
||||
function onDocumentStateChange(event) {
|
||||
var isModified = event.data;
|
||||
//console.log(isModified);
|
||||
}
|
||||
|
||||
function onRequestEditRights(event) {
|
||||
// occurs whenever the user tryes to enter edit mode
|
||||
docEditor.applyEditRights(true, "Someone is editing this document right now. Please try again later.");
|
||||
}
|
||||
|
||||
function onDocumentSave(event) {
|
||||
var url = event.data;
|
||||
// if you want to async save process return false
|
||||
// and call api.processSaveResult when ready
|
||||
}
|
||||
|
||||
function onError(event) {
|
||||
// critical error happened
|
||||
// examine event.data.errorCode and event.data.errorDescription for details
|
||||
}
|
||||
|
||||
function onDownloadAs(event) {
|
||||
// return url of downloaded doc
|
||||
// console.log(event.data);
|
||||
}
|
||||
|
||||
|
||||
// helpers
|
||||
|
||||
function getUrlParams() {
|
||||
var e,
|
||||
a = /\+/g, // Regex for replacing addition symbol with a space
|
||||
r = /([^&=]+)=?([^&]*)/g,
|
||||
d = function (s) { return decodeURIComponent(s.replace(a, " ")); },
|
||||
q = window.location.search.substring(1),
|
||||
urlParams = {};
|
||||
|
||||
while (e = r.exec(q))
|
||||
urlParams[d(e[1])] = d(e[2]);
|
||||
|
||||
return urlParams;
|
||||
}
|
||||
|
||||
function getDocumentData(urlParams) {
|
||||
return {
|
||||
key: urlParams["key"],
|
||||
url: urlParams["url"] || '_offline_',
|
||||
title: urlParams["title"],
|
||||
fileType: urlParams["filetype"],
|
||||
vkey: urlParams["vkey"],
|
||||
permissions: {
|
||||
edit: true,
|
||||
download: true,
|
||||
reader: true
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getEditorConfig(urlParams) {
|
||||
return {
|
||||
mode : urlParams["mode"] || 'edit',
|
||||
lang : urlParams["lang"] || 'en',
|
||||
canCoAuthoring : true,
|
||||
createUrl : 'http://www.example.com/create',
|
||||
|
||||
user: {
|
||||
id: urlParams["userid"] || 'uid-901', firstname: urlParams["userfname"] || 'Mitchell', lastname: urlParams["userlname"] || 'Hamish'
|
||||
},
|
||||
recent : [
|
||||
{title: 'Memory.docx', url: 'http://onlyoffice.com', folder: 'Document Editor'},
|
||||
{title: 'Description.doc', url: 'http://onlyoffice.com', folder: 'Document Editor'},
|
||||
{title: 'DocEditor_right.xsl', url: 'http://onlyoffice.com', folder: 'Spreadsheet Editor'},
|
||||
{title: 'api.rtf', url: 'http://onlyoffice.com', folder: 'Unnamed folder'}
|
||||
],
|
||||
// templates : [
|
||||
// {name: 'Contracts', icon: '../../api/documents/resources/templates/contracts.png', url: 'http://...'},
|
||||
// {name: 'Letter', icon: '../../api/documents/resources/templates/letter.png', url: 'http://...'},
|
||||
// {name: 'List', icon: '../../api/documents/resources/templates/list.png', url: 'http://...'},
|
||||
// {name: 'Plan', icon: '../../api/documents/resources/templates/plan.png', url: 'http://...'}
|
||||
// ],
|
||||
embedded : {
|
||||
embedUrl : 'http://onlyoffice.com/embed',
|
||||
fullscreenUrl : 'http://onlyoffice.com/fullscreen',
|
||||
saveUrl : 'http://onlyoffice.com/download',
|
||||
shareUrl : 'http://tl.com/72b4la97',
|
||||
toolbarDocked : 'top'
|
||||
}
|
||||
,customization: {
|
||||
// logo: {
|
||||
// image: 'https://dylnrgbh910l3.cloudfront.net/studio/tag/i8.8.237/skins/default/images/onlyoffice_logo/editor_logo_general.png', // default size 86 x 20
|
||||
// imageEmbedded: 'https://d2hw9csky753gb.cloudfront.net/studio/tag/i8.8.237/skins/default/images/onlyoffice_logo/editor_embedded_logo.png', // default size 124 x 20
|
||||
// url: 'http://...'
|
||||
// },
|
||||
// backgroundColor: '#ffffff',
|
||||
// textColor: '#ff0000',
|
||||
// customer: {
|
||||
// name: 'SuperPuper',
|
||||
// address: 'New-York, 125f-25',
|
||||
// mail: 'support@gmail.com',
|
||||
// www: 'www.superpuper.com',
|
||||
// info: 'Some info',
|
||||
// logo: 'https://img.imgsmail.ru/r/default/portal/0.1.29/logo.png' // default size 216 x 35
|
||||
// },
|
||||
// goback: {text: 'Go To London', url: 'http://...'},
|
||||
about: true,
|
||||
feedback: true
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Mobile version
|
||||
|
||||
function isMobile(){
|
||||
var prefixes = {
|
||||
ios: 'i(?:Pad|Phone|Pod)(?:.*)CPU(?: iPhone)? OS ',
|
||||
android: '(Android |HTC_|Silk/)',
|
||||
blackberry: 'BlackBerry(?:.*)Version\/',
|
||||
rimTablet: 'RIM Tablet OS ',
|
||||
webos: '(?:webOS|hpwOS)\/',
|
||||
bada: 'Bada\/'
|
||||
},
|
||||
i, prefix, match;
|
||||
|
||||
for (i in prefixes){
|
||||
if (prefixes.hasOwnProperty(i)) {
|
||||
prefix = prefixes[i];
|
||||
|
||||
if (navigator.userAgent.match(new RegExp('(?:'+prefix+')([^\\s;]+)')))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
var fixSize = function() {
|
||||
var wrapEl = document.getElementById('wrap');
|
||||
if (wrapEl){
|
||||
wrapEl.style.height = screen.availHeight + 'px';
|
||||
window.scrollTo(0, -1);
|
||||
wrapEl.style.height = window.innerHeight + 'px';
|
||||
}
|
||||
};
|
||||
|
||||
var fixIpadLandscapeIos7 = function() {
|
||||
if (navigator.userAgent.match(/iPad;.*CPU.*OS 7_\d/i)) {
|
||||
var wrapEl = document.getElementById('wrap');
|
||||
if (wrapEl){
|
||||
wrapEl.style.position = "fixed";
|
||||
wrapEl.style.bottom = 0;
|
||||
wrapEl.style.width = "100%";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (isMobile()){
|
||||
window.addEventListener('load', fixSize);
|
||||
window.addEventListener('resize', fixSize);
|
||||
|
||||
fixIpadLandscapeIos7();
|
||||
}
|
||||
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
157
apps/api/documents/index.html.desktop
Normal file
157
apps/api/documents/index.html.desktop
Normal file
|
@ -0,0 +1,157 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>ONLYOFFICE Documents</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=IE8"/>
|
||||
<meta name="description" content="" />
|
||||
<meta name="keywords" content="" />
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-touch-fullscreen" content="yes">
|
||||
|
||||
<style type="text/css">
|
||||
html {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#wrap {
|
||||
position:absolute;
|
||||
left:0;
|
||||
top:0;
|
||||
right:0;
|
||||
bottom:0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="wrap">
|
||||
<div id="placeholder"></div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="api.js"></script>
|
||||
<script>
|
||||
(function() {
|
||||
|
||||
// Url parameters
|
||||
|
||||
var urlParams = getUrlParams(),
|
||||
cfg = getEditorConfig(urlParams),
|
||||
doc = getDocumentData(urlParams);
|
||||
|
||||
// Document Editor
|
||||
|
||||
var docEditor = new DocsAPI.DocEditor('placeholder', {
|
||||
type: urlParams['type'],
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
documentType: urlParams['doctype'] || 'text',
|
||||
document: doc,
|
||||
editorConfig: cfg
|
||||
});
|
||||
|
||||
|
||||
// helpers
|
||||
|
||||
function getUrlParams() {
|
||||
var e,
|
||||
a = /\+/g, // Regex for replacing addition symbol with a space
|
||||
r = /([^&=]+)=?([^&]*)/g,
|
||||
d = function (s) { return decodeURIComponent(s.replace(a, " ")); },
|
||||
q = window.location.search.substring(1),
|
||||
urlParams = {};
|
||||
|
||||
while (e = r.exec(q))
|
||||
urlParams[d(e[1])] = d(e[2]);
|
||||
|
||||
return urlParams;
|
||||
}
|
||||
|
||||
function getDocumentData(urlParams) {
|
||||
return {
|
||||
key: urlParams["key"],
|
||||
url: urlParams["url"] || '_offline_',
|
||||
title: urlParams["title"],
|
||||
fileType: urlParams["filetype"],
|
||||
vkey: urlParams["vkey"],
|
||||
permissions: {
|
||||
edit: true,
|
||||
download: true
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getEditorConfig(urlParams) {
|
||||
return {
|
||||
mode : urlParams["mode"] || 'edit',
|
||||
lang : urlParams["lang"] || 'en',
|
||||
user: {
|
||||
id: urlParams["userid"], firstname: urlParams["userfname"], lastname: urlParams["userlname"]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Mobile version
|
||||
|
||||
function isMobile(){
|
||||
var prefixes = {
|
||||
ios: 'i(?:Pad|Phone|Pod)(?:.*)CPU(?: iPhone)? OS ',
|
||||
android: '(Android |HTC_|Silk/)',
|
||||
blackberry: 'BlackBerry(?:.*)Version\/',
|
||||
rimTablet: 'RIM Tablet OS ',
|
||||
webos: '(?:webOS|hpwOS)\/',
|
||||
bada: 'Bada\/'
|
||||
},
|
||||
i, prefix, match;
|
||||
|
||||
for (i in prefixes){
|
||||
if (prefixes.hasOwnProperty(i)) {
|
||||
prefix = prefixes[i];
|
||||
|
||||
if (navigator.userAgent.match(new RegExp('(?:'+prefix+')([^\\s;]+)')))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
var fixSize = function() {
|
||||
var wrapEl = document.getElementById('wrap');
|
||||
if (wrapEl){
|
||||
wrapEl.style.height = screen.availHeight + 'px';
|
||||
window.scrollTo(0, -1);
|
||||
wrapEl.style.height = window.innerHeight + 'px';
|
||||
}
|
||||
};
|
||||
|
||||
var fixIpadLandscapeIos7 = function() {
|
||||
if (navigator.userAgent.match(/iPad;.*CPU.*OS 7_\d/i)) {
|
||||
var wrapEl = document.getElementById('wrap');
|
||||
if (wrapEl){
|
||||
wrapEl.style.position = "fixed";
|
||||
wrapEl.style.bottom = 0;
|
||||
wrapEl.style.width = "100%";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (isMobile()){
|
||||
window.addEventListener('load', fixSize);
|
||||
window.addEventListener('resize', fixSize);
|
||||
|
||||
fixIpadLandscapeIos7();
|
||||
}
|
||||
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
BIN
apps/api/documents/resources/templates/contracts.png
Normal file
BIN
apps/api/documents/resources/templates/contracts.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.3 KiB |
BIN
apps/api/documents/resources/templates/letter.png
Normal file
BIN
apps/api/documents/resources/templates/letter.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
BIN
apps/api/documents/resources/templates/list.png
Normal file
BIN
apps/api/documents/resources/templates/list.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
BIN
apps/api/documents/resources/templates/plan.png
Normal file
BIN
apps/api/documents/resources/templates/plan.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.6 KiB |
54
apps/common/Analytics.js
Normal file
54
apps/common/Analytics.js
Normal file
|
@ -0,0 +1,54 @@
|
|||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
Common.component = Common.component || {};
|
||||
|
||||
Common.Analytics = Common.component.Analytics = new(function() {
|
||||
var _category;
|
||||
|
||||
return {
|
||||
initialize: function(id, category) {
|
||||
|
||||
if (typeof id === 'undefined')
|
||||
throw 'Analytics: invalid id.';
|
||||
|
||||
if (typeof category === 'undefined' || Object.prototype.toString.apply(category) !== '[object String]')
|
||||
throw 'Analytics: invalid category type.';
|
||||
|
||||
_category = category;
|
||||
|
||||
$('head').append(
|
||||
'<script type="text/javascript">' +
|
||||
'var _gaq = _gaq || [];' +
|
||||
'_gaq.push(["_setAccount", "' + id + '"]);' +
|
||||
'_gaq.push(["_trackPageview"]);' +
|
||||
'(function() {' +
|
||||
'var ga = document.createElement("script"); ga.type = "text/javascript"; ga.async = true;' +
|
||||
'ga.src = ("https:" == document.location.protocol ? "https://ssl" : "http://www") + ".google-analytics.com/ga.js";' +
|
||||
'var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(ga, s);' +
|
||||
'})();' +
|
||||
'</script>'
|
||||
);
|
||||
},
|
||||
|
||||
trackEvent: function(action, label, value) {
|
||||
|
||||
if (typeof action !== 'undefined' && Object.prototype.toString.apply(action) !== '[object String]')
|
||||
throw 'Analytics: invalid action type.';
|
||||
|
||||
if (typeof label !== 'undefined' && Object.prototype.toString.apply(label) !== '[object String]')
|
||||
throw 'Analytics: invalid label type.';
|
||||
|
||||
if (typeof value !== 'undefined' && !(Object.prototype.toString.apply(value) === '[object Number]' && isFinite(value)))
|
||||
throw 'Analytics: invalid value type.';
|
||||
|
||||
if (typeof _gaq === 'undefined')
|
||||
return;
|
||||
|
||||
if (_category === 'undefined')
|
||||
throw 'Analytics is not initialized.';
|
||||
|
||||
_gaq.push(['_trackEvent', _category, action, label, value]);
|
||||
}
|
||||
}
|
||||
})();
|
203
apps/common/Gateway.js
Normal file
203
apps/common/Gateway.js
Normal file
|
@ -0,0 +1,203 @@
|
|||
if (Common === undefined) {
|
||||
var Common = {};
|
||||
}
|
||||
|
||||
Common.Gateway = new(function() {
|
||||
var me = this,
|
||||
$me = $(me);
|
||||
|
||||
var commandMap = {
|
||||
'init': function(data) {
|
||||
$me.trigger('init', data);
|
||||
},
|
||||
|
||||
'openDocument': function(data) {
|
||||
$me.trigger('opendocument', data);
|
||||
},
|
||||
|
||||
'showMessage': function(data) {
|
||||
$me.trigger('showmessage', data);
|
||||
},
|
||||
|
||||
'applyEditRights': function(data) {
|
||||
$me.trigger('applyeditrights', data);
|
||||
},
|
||||
|
||||
'processSaveResult': function(data) {
|
||||
$me.trigger('processsaveresult', data);
|
||||
},
|
||||
|
||||
'processRightsChange': function(data) {
|
||||
$me.trigger('processrightschange', data);
|
||||
},
|
||||
|
||||
'refreshHistory': function(data) {
|
||||
$me.trigger('refreshhistory', data);
|
||||
},
|
||||
|
||||
'setHistoryData': function(data) {
|
||||
$me.trigger('sethistorydata', data);
|
||||
},
|
||||
|
||||
'setEmailAddresses': function(data) {
|
||||
$me.trigger('setemailaddresses', data);
|
||||
},
|
||||
|
||||
'processMailMerge': function(data) {
|
||||
$me.trigger('processmailmerge', data);
|
||||
},
|
||||
|
||||
'downloadAs': function() {
|
||||
$me.trigger('downloadas');
|
||||
},
|
||||
|
||||
'processMouse': function(data) {
|
||||
$me.trigger('processmouse', data);
|
||||
},
|
||||
|
||||
'internalCommand': function(data) {
|
||||
$me.trigger('internalcommand', data);
|
||||
},
|
||||
|
||||
'resetFocus': function(data) {
|
||||
$me.trigger('resetfocus', data);
|
||||
}
|
||||
};
|
||||
|
||||
var _postMessage = function(msg) {
|
||||
// TODO: specify explicit origin
|
||||
if (window.parent && window.JSON) {
|
||||
window.parent.postMessage(window.JSON.stringify(msg), "*");
|
||||
}
|
||||
};
|
||||
|
||||
var _onMessage = function(msg) {
|
||||
// TODO: check message origin
|
||||
var data = msg.data;
|
||||
if (Object.prototype.toString.apply(data) !== '[object String]' || !window.JSON) {
|
||||
return;
|
||||
}
|
||||
|
||||
var cmd, handler;
|
||||
|
||||
try {
|
||||
cmd = window.JSON.parse(data)
|
||||
} catch(e) {
|
||||
cmd = '';
|
||||
}
|
||||
|
||||
if (cmd) {
|
||||
handler = commandMap[cmd.command];
|
||||
if (handler) {
|
||||
handler.call(this, cmd.data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var fn = function(e) { _onMessage(e); };
|
||||
|
||||
if (window.attachEvent) {
|
||||
window.attachEvent('onmessage', fn);
|
||||
} else {
|
||||
window.addEventListener('message', fn, false);
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
ready: function() {
|
||||
_postMessage({ event: 'onReady' });
|
||||
},
|
||||
|
||||
save: function(url) {
|
||||
_postMessage({
|
||||
event: 'onSave',
|
||||
data: url
|
||||
});
|
||||
},
|
||||
|
||||
requestEditRights: function() {
|
||||
_postMessage({ event: 'onRequestEditRights' });
|
||||
},
|
||||
|
||||
requestHistory: function() {
|
||||
_postMessage({ event: 'onRequestHistory' });
|
||||
},
|
||||
|
||||
requestHistoryData: function(revision) {
|
||||
_postMessage({
|
||||
event: 'onRequestHistoryData',
|
||||
data: revision
|
||||
});
|
||||
},
|
||||
|
||||
requestEmailAddresses: function() {
|
||||
_postMessage({ event: 'onRequestEmailAddresses' });
|
||||
},
|
||||
|
||||
requestStartMailMerge: function() {
|
||||
_postMessage({event: 'onRequestStartMailMerge'});
|
||||
},
|
||||
|
||||
requestHistoryClose: function(revision) {
|
||||
_postMessage({event: 'onRequestHistoryClose'});
|
||||
},
|
||||
|
||||
reportError: function(code, description) {
|
||||
_postMessage({
|
||||
event: 'onError',
|
||||
data: {
|
||||
errorCode: code,
|
||||
errorDescription: description
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
sendInfo: function(info) {
|
||||
_postMessage({
|
||||
event: 'onInfo',
|
||||
data: info
|
||||
});
|
||||
},
|
||||
|
||||
setDocumentModified: function(modified) {
|
||||
_postMessage({
|
||||
event: 'onDocumentStateChange',
|
||||
data: modified
|
||||
});
|
||||
},
|
||||
|
||||
internalMessage: function(type, data) {
|
||||
_postMessage({
|
||||
event: 'onInternalMessage',
|
||||
data: {
|
||||
type: type,
|
||||
data: data
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
updateVersion: function() {
|
||||
_postMessage({ event: 'onOutdatedVersion' });
|
||||
},
|
||||
|
||||
downloadAs: function(url) {
|
||||
_postMessage({
|
||||
event: 'onDownloadAs',
|
||||
data: url
|
||||
});
|
||||
},
|
||||
|
||||
collaborativeChanges: function() {
|
||||
_postMessage({event: 'onCollaborativeChanges'});
|
||||
},
|
||||
|
||||
on: function(event, handler){
|
||||
var localHandler = function(event, data){
|
||||
handler.call(me, data)
|
||||
};
|
||||
|
||||
$me.on(event, localHandler);
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
56
apps/common/IrregularStack.js
Normal file
56
apps/common/IrregularStack.js
Normal file
|
@ -0,0 +1,56 @@
|
|||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
Common.IrregularStack = function(config) {
|
||||
|
||||
var _stack = [];
|
||||
|
||||
var _compare = function(obj1, obj2){
|
||||
if (typeof obj1 === 'object' && typeof obj2 === 'object' && window.JSON)
|
||||
return window.JSON.stringify(obj1) === window.JSON.stringify(obj2);
|
||||
return obj1 === obj2;
|
||||
}
|
||||
|
||||
config = config || {};
|
||||
var _strongCompare = config.strongCompare || _compare;
|
||||
var _weakCompare = config.weakCompare || _compare;
|
||||
|
||||
var _indexOf = function(obj, compare) {
|
||||
for (var i = _stack.length - 1; i >= 0; i--) {
|
||||
if (compare(_stack[i], obj))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
var _push = function(obj) {
|
||||
_stack.push(obj);
|
||||
}
|
||||
|
||||
var _pop = function(obj) {
|
||||
var index = _indexOf(obj, _strongCompare);
|
||||
if (index != -1) {
|
||||
var removed = _stack.splice(index, 1);
|
||||
return removed[0];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var _get = function(obj) {
|
||||
var index = _indexOf(obj, _weakCompare);
|
||||
if (index != -1)
|
||||
return _stack[index];
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var _exist = function(obj) {
|
||||
return !(_indexOf(obj, _strongCompare) < 0);
|
||||
}
|
||||
|
||||
return {
|
||||
push: _push,
|
||||
pop: _pop,
|
||||
get: _get,
|
||||
exist: _exist
|
||||
}
|
||||
};
|
BIN
apps/common/embed/resources/img/glyphicons.png
Normal file
BIN
apps/common/embed/resources/img/glyphicons.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.8 KiB |
521
apps/common/embed/resources/less/common.less
Normal file
521
apps/common/embed/resources/less/common.less
Normal file
|
@ -0,0 +1,521 @@
|
|||
// Core variables and mixins
|
||||
@import "../../../../../vendor/bootstrap/less/variables.less";
|
||||
|
||||
@icon-font-path: "../../../../../vendor/bootstrap/dist/fonts/";
|
||||
|
||||
@import "../../../../../vendor/bootstrap/less/mixins.less";
|
||||
|
||||
// Reset
|
||||
@import "../../../../../vendor/bootstrap/less/normalize.less";
|
||||
@import "../../../../../vendor/bootstrap/less/print.less";
|
||||
|
||||
// Core CSS
|
||||
@import "../../../../../vendor/bootstrap/less/scaffolding.less";
|
||||
@import "../../../../../vendor/bootstrap/less/type.less";
|
||||
//@import "code.less";
|
||||
//@import "grid.less";
|
||||
//@import "tables.less";
|
||||
@import "../../../../../vendor/bootstrap/less/forms.less";
|
||||
@import "../../../../../vendor/bootstrap/less/buttons.less";
|
||||
|
||||
// Components
|
||||
@import "../../../../../vendor/bootstrap/less/component-animations.less";
|
||||
@import "../../../../../vendor/bootstrap/less/glyphicons.less";
|
||||
//@import "dropdowns.less";
|
||||
//@import "button-groups.less";
|
||||
//@import "input-groups.less";
|
||||
//@import "navs.less";
|
||||
//@import "navbar.less";
|
||||
//@import "breadcrumbs.less";
|
||||
//@import "pagination.less";
|
||||
//@import "pager.less";
|
||||
@import "../../../../../vendor/bootstrap/less/labels.less";
|
||||
//@import "badges.less";
|
||||
//@import "jumbotron.less";
|
||||
//@import "thumbnails.less";
|
||||
@import "../../../../../vendor/bootstrap/less/alerts.less";
|
||||
//@import "progress-bars.less";
|
||||
//@import "media.less";
|
||||
//@import "list-group.less";
|
||||
//@import "panels.less";
|
||||
//@import "wells.less";
|
||||
//@import "close.less";
|
||||
|
||||
// Components w/ JavaScript
|
||||
@import "../../../../../vendor/bootstrap/less/modals.less";
|
||||
@import "../../../../../vendor/bootstrap/less/tooltip.less";
|
||||
@import "../../../../../vendor/bootstrap/less/popovers.less";
|
||||
//@import "carousel.less";
|
||||
|
||||
// Utility classes
|
||||
@import "../../../../../vendor/bootstrap/less/utilities.less";
|
||||
@import "../../../../../vendor/bootstrap/less/responsive-utilities.less";
|
||||
|
||||
|
||||
@toolbarBorderColor: #929292;
|
||||
@toolbarBorderShadowColor: #FAFAFA;
|
||||
@toolbarTopColor: #EBEBEB;
|
||||
@toolbarBottomColor: #CCCCCC;
|
||||
@toolbarHoverColor: #7698DE;
|
||||
@toolbarFontSize: 12px;
|
||||
@controlBtnHoverTopColor: #6180C4;
|
||||
@controlBtnHoverBottomColor: #8AACF1;
|
||||
@iconSpriteCommonPath: "../../../../common/embed/resources/img/glyphicons.png";
|
||||
|
||||
.input-xs {
|
||||
.input-size(@input-height-small - 8px; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);
|
||||
}
|
||||
|
||||
.embed-body {
|
||||
-moz-user-select: -moz-none;
|
||||
-khtml-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
|
||||
font-size: @toolbarFontSize;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// Document Viewer
|
||||
// -------------------------
|
||||
.viewer {
|
||||
position: absolute;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
||||
&.top {
|
||||
top: 32px;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
&.bottom {
|
||||
top: 0;
|
||||
bottom: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
// Toolbar
|
||||
// -------------------------
|
||||
.toolbar {
|
||||
position: fixed;
|
||||
font-size: @toolbarFontSize;
|
||||
min-width: 340px;
|
||||
z-index: 100;
|
||||
#gradient > .vertical(@toolbarTopColor, @toolbarBottomColor);
|
||||
|
||||
&.top {
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
|
||||
-webkit-box-shadow: inset 0 -1px 0 @toolbarBorderColor, inset 0 1px 0 @toolbarBorderShadowColor;
|
||||
//-moz-box-shadow: inset 0 -1px 0 @toolbarBorderColor, inset 0 1px 0 @toolbarBorderShadowColor;
|
||||
box-shadow: inset 0 -1px 0 @toolbarBorderColor, inset 0 1px 0 @toolbarBorderShadowColor;
|
||||
}
|
||||
|
||||
&.bottom {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
|
||||
-webkit-box-shadow: inset 0 1px 0 @toolbarBorderColor, inset 0 2px 0 @toolbarBorderShadowColor;
|
||||
//-moz-box-shadow: inset 0 1px 0 @toolbarBorderColor, inset 0 2px 0 @toolbarBorderShadowColor;
|
||||
box-shadow: inset 0 1px 0 @toolbarBorderColor, inset 0 2px 0 @toolbarBorderShadowColor;
|
||||
}
|
||||
|
||||
ul {
|
||||
position: absolute;
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
li {
|
||||
input {
|
||||
display: inline-block;
|
||||
width: 25px;
|
||||
padding: 0;
|
||||
height: 25px;
|
||||
margin: 3px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.text {
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
&.left {
|
||||
left: 0;
|
||||
|
||||
li {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
&.right {
|
||||
right: 0;
|
||||
|
||||
li {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
.separator {
|
||||
height: 24px;
|
||||
margin: 4px 9px;
|
||||
border-right: 1px solid @toolbarBorderShadowColor;
|
||||
border-left: 1px solid @toolbarBorderColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Logo
|
||||
// -------------------------
|
||||
a.brand-logo {
|
||||
display: block;
|
||||
background-image: url("@{iconSpriteCommonPath}");
|
||||
width: 124px;
|
||||
height: 20px;
|
||||
margin: 5px 0 0 10px;
|
||||
background-position: 0 -100px;
|
||||
}
|
||||
|
||||
// Sprite icons path
|
||||
// -------------------------
|
||||
[class^="control-icon-"],
|
||||
[class*=" control-icon-"] {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
vertical-align: text-top;
|
||||
background-image: url("@{iconSpriteCommonPath}");
|
||||
background-repeat: no-repeat;
|
||||
margin-top: -2px;
|
||||
}
|
||||
|
||||
[class^="overlay-icon-"],
|
||||
[class*=" overlay-icon-"] {
|
||||
display: inline-block;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
vertical-align: text-top;
|
||||
background-image: url("@{iconSpriteCommonPath}");
|
||||
background-repeat: no-repeat;
|
||||
opacity: .3;
|
||||
}
|
||||
|
||||
.control-icon-share { background-position: 0 0; }
|
||||
.control-icon-embed { background-position: 0 -20px; }
|
||||
.control-icon-fullscreen { background-position: 0 -40px; }
|
||||
.control-icon-close { background-position: 0 -60px; }
|
||||
.control-icon-save { background-position: 0 -80px; }
|
||||
|
||||
.overlay-icon-zoom-in { background-position: 0 -120px; }
|
||||
.overlay-icon-zoom-out { background-position: -32px -120px; }
|
||||
|
||||
// Control buttons
|
||||
// -------------------------
|
||||
.control-btn {
|
||||
display: inline-block;
|
||||
padding: 1px 5px;
|
||||
font-size: @toolbarFontSize;
|
||||
line-height: 20px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 2px;
|
||||
margin: 4px 5px 0 0;
|
||||
|
||||
i {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
&.no-caption {
|
||||
padding: 1px 2px;
|
||||
|
||||
i {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Hover state
|
||||
&:hover {
|
||||
color: @toolbarHoverColor;
|
||||
text-decoration: none;
|
||||
text-shadow: 0 1px 0 @toolbarBorderShadowColor;
|
||||
|
||||
.control-icon-share { background-position: -20px 0; }
|
||||
.control-icon-embed { background-position: -20px -20px; }
|
||||
.control-icon-fullscreen { background-position: -20px -40px; }
|
||||
.control-icon-close { background-position: -20px -60px; }
|
||||
.control-icon-save { background-position: -20px -80px; }
|
||||
}
|
||||
|
||||
// Focus state for keyboard and accessibility
|
||||
&:focus {
|
||||
.tab-focus();
|
||||
outline: none;
|
||||
}
|
||||
|
||||
// Active state
|
||||
&.active,
|
||||
&:active {
|
||||
color: #ffffff;
|
||||
outline: none;
|
||||
border: 1px solid darken(@controlBtnHoverTopColor, 5%);
|
||||
#gradient > .vertical(@controlBtnHoverTopColor, @controlBtnHoverBottomColor);
|
||||
text-shadow: 0 1px 0 darken(@toolbarBorderColor, 20%);
|
||||
|
||||
.control-icon-share { background-position: -40px 0; }
|
||||
.control-icon-embed { background-position: -40px -20px; }
|
||||
.control-icon-fullscreen { background-position: -40px -40px; }
|
||||
.control-icon-close { background-position: -40px -60px; }
|
||||
.control-icon-save { background-position: -40px -80px; }
|
||||
}
|
||||
}
|
||||
|
||||
// Overlay control
|
||||
// -------------------------
|
||||
.overlay-controls {
|
||||
position: absolute;
|
||||
bottom: 55px;
|
||||
z-index: 10;
|
||||
left: 50%;
|
||||
|
||||
ul {
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
margin: 0 auto;
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
|
||||
&:first-child {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.overlay {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
line-height: 0;
|
||||
outline: none;
|
||||
|
||||
&:hover {
|
||||
[class^="overlay-icon-"],
|
||||
[class*=" overlay-icon-"] {
|
||||
opacity: .6;
|
||||
}
|
||||
}
|
||||
|
||||
&.active,
|
||||
&:active {
|
||||
[class^="overlay-icon-"],
|
||||
[class*=" overlay-icon-"] {
|
||||
opacity: .8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Error mask
|
||||
// -------------------------
|
||||
.errormask {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
border: none;
|
||||
background-color: #f4f4f4;
|
||||
z-index: 30002;
|
||||
|
||||
.error-body {
|
||||
position: relative;
|
||||
top: 40%;
|
||||
width: 400px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: #FFFFFF;
|
||||
border: 1px solid #C0C0C0;
|
||||
|
||||
.title {
|
||||
font-weight: bold;
|
||||
font-size: 1.6em;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Share popover
|
||||
// -------------------------
|
||||
.popover{
|
||||
.popover-content {
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
&.hyperlink {
|
||||
.popover-content {
|
||||
padding: 5px 10px;
|
||||
|
||||
p {
|
||||
display: block;
|
||||
word-wrap: break-word;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.share {
|
||||
width: 280px;
|
||||
|
||||
.share-link {
|
||||
margin-bottom: 5px;
|
||||
|
||||
.caption {
|
||||
margin-top: 3px;
|
||||
margin-right: 8px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
input[readonly] {
|
||||
display: inline-block;
|
||||
font-size: 1em;
|
||||
padding: 0 4px;
|
||||
margin-right: 5px;
|
||||
border-radius: 0;
|
||||
cursor: text;
|
||||
background-color: #fff;
|
||||
-moz-user-select: text;
|
||||
-khtml-user-select: text;
|
||||
-webkit-user-select: text;
|
||||
-ms-user-select: text;
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
.input-xs {
|
||||
width: 130px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
.share-buttons {
|
||||
ul {
|
||||
width: 244px;
|
||||
height: 25px;
|
||||
list-style-type: none;
|
||||
margin: 5px 0 0;
|
||||
overflow: hidden;
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
float: left;
|
||||
margin: 1px 5px 0 0;
|
||||
vertical-align: middle;
|
||||
|
||||
&.share-mail {
|
||||
float: right;
|
||||
padding-right: 1px;
|
||||
margin: 0;
|
||||
|
||||
a {
|
||||
min-width: 64px;
|
||||
}
|
||||
|
||||
.glyphicon {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
&.share-twitter {
|
||||
max-width: 93px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.embed {
|
||||
width: 270px;
|
||||
|
||||
.size-manual {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.caption {
|
||||
margin-top: 2px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
input {
|
||||
display: inline-block;
|
||||
font-size: 1em;
|
||||
padding: 0 4px;
|
||||
border-radius: 0;
|
||||
margin: 0;
|
||||
margin-top: -1px;
|
||||
|
||||
&.input-xs {
|
||||
width: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 238px;
|
||||
resize: none;
|
||||
cursor: auto;
|
||||
font-size: 1em;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
float: right;
|
||||
margin: 10px 0 15px;
|
||||
width: 86px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Modals
|
||||
// -------------------------
|
||||
.modal {
|
||||
.modal-header {
|
||||
padding: 5px 15px;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
border-top: none;
|
||||
}
|
||||
}
|
87
apps/common/locale.js
Normal file
87
apps/common/locale.js
Normal file
|
@ -0,0 +1,87 @@
|
|||
if (Common === undefined) {
|
||||
var Common = {};
|
||||
}
|
||||
|
||||
Common.Locale = new(function() {
|
||||
var l10n = {};
|
||||
|
||||
var _createXMLHTTPObject = function() {
|
||||
var xmlhttp;
|
||||
try {
|
||||
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
|
||||
}
|
||||
catch (e) {
|
||||
try {
|
||||
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
|
||||
}
|
||||
catch (E) {
|
||||
xmlhttp = false;
|
||||
}
|
||||
}
|
||||
if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
|
||||
xmlhttp = new XMLHttpRequest();
|
||||
}
|
||||
return xmlhttp;
|
||||
};
|
||||
|
||||
var _applyLocalization = function() {
|
||||
try {
|
||||
for (var prop in l10n) {
|
||||
var p = prop.split('.');
|
||||
if (p && p.length > 2) {
|
||||
|
||||
var obj = window;
|
||||
for (var i = 0; i < p.length - 1; ++i) {
|
||||
if (obj[p[i]] === undefined) {
|
||||
obj[p[i]] = new Object();
|
||||
}
|
||||
obj = obj[p[i]];
|
||||
}
|
||||
|
||||
if (obj) {
|
||||
obj[p[p.length - 1]] = l10n[prop];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
};
|
||||
|
||||
var _get = function(prop, scope) {
|
||||
var res = '';
|
||||
if (scope && scope.name) {
|
||||
res = l10n[scope.name + '.' + prop];
|
||||
}
|
||||
|
||||
return res || (scope ? eval(scope.name).prototype[prop] : '');
|
||||
};
|
||||
|
||||
var _getUrlParameterByName = function(name) {
|
||||
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
|
||||
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
|
||||
results = regex.exec(location.search);
|
||||
return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
|
||||
};
|
||||
|
||||
try {
|
||||
var langParam = _getUrlParameterByName('lang');
|
||||
var xhrObj = _createXMLHTTPObject();
|
||||
if (xhrObj && langParam) {
|
||||
var lang = langParam.split("-")[0];
|
||||
xhrObj.open('GET', 'locale/' + lang + '.json', false);
|
||||
xhrObj.send('');
|
||||
l10n = eval("(" + xhrObj.responseText + ")");
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
|
||||
return {
|
||||
apply: _applyLocalization,
|
||||
get: _get
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
|
22
apps/common/main/lib/collection/ChatMessages.js
Normal file
22
apps/common/main/lib/collection/ChatMessages.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* ChatMessages.js
|
||||
*
|
||||
* Collection
|
||||
*
|
||||
* Created by Maxim Kadushkin on 01 March 2014
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
define([
|
||||
'backbone',
|
||||
'common/main/lib/model/ChatMessage'
|
||||
], function(Backbone){
|
||||
'use strict';
|
||||
|
||||
!Common.Collections && (Common.Collections = {});
|
||||
|
||||
Common.Collections.ChatMessages = Backbone.Collection.extend({
|
||||
model: Common.Models.ChatMessage
|
||||
});
|
||||
});
|
48
apps/common/main/lib/collection/Comments.js
Normal file
48
apps/common/main/lib/collection/Comments.js
Normal file
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* Comments.js
|
||||
*
|
||||
* Created by Alexey Musinov on 17.01.14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
Common.Collections = Common.Collections || {};
|
||||
|
||||
define([
|
||||
'underscore',
|
||||
'backbone',
|
||||
'common/main/lib/model/Comment'
|
||||
], function(_, Backbone){
|
||||
'use strict';
|
||||
|
||||
Common.Collections.Comments = Backbone.Collection.extend({
|
||||
model: Common.Models.Comment,
|
||||
|
||||
clearEditing: function () {
|
||||
this.each(function(comment) {
|
||||
comment.set('editText', false);
|
||||
comment.set('editTextInPopover', false);
|
||||
comment.set('showReply', false);
|
||||
comment.set('showReplyInPopover', false);
|
||||
comment.set('hideAddReply', false);
|
||||
});
|
||||
},
|
||||
|
||||
getCommentsReplysCount: function(userid) {
|
||||
var cnt = 0;
|
||||
this.each(function(comment) {
|
||||
if (comment.get('userid')==userid) cnt++;
|
||||
var rpl = comment.get('replys');
|
||||
if (rpl && rpl.length>0) {
|
||||
rpl.forEach(function(reply) {
|
||||
if (reply.get('userid')==userid) cnt ++;
|
||||
});
|
||||
}
|
||||
});
|
||||
return cnt;
|
||||
}
|
||||
});
|
||||
});
|
27
apps/common/main/lib/collection/Fonts.js
Normal file
27
apps/common/main/lib/collection/Fonts.js
Normal file
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* Fonts.js
|
||||
*
|
||||
* Created by Alexander Yuzhin on 2/11/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
Common.Collections = Common.Collections || {};
|
||||
|
||||
define([
|
||||
'backbone',
|
||||
'common/main/lib/model/Font'
|
||||
], function(Backbone){ 'use strict';
|
||||
Common.Collections.Fonts = Backbone.Collection.extend({
|
||||
model: Common.Models.Font,
|
||||
comparator: function(item1, item2) {
|
||||
var n1 = item1.get('name').toLowerCase(),
|
||||
n2 = item2.get('name').toLowerCase();
|
||||
if (n1==n2) return 0;
|
||||
return (n1<n2) ? -1 : 1;
|
||||
}
|
||||
});
|
||||
});
|
30
apps/common/main/lib/collection/HistoryVersions.js
Normal file
30
apps/common/main/lib/collection/HistoryVersions.js
Normal file
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* User: Julia.Radzhabova
|
||||
* Date: 05.03.15
|
||||
* Time: 17:05
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
Common.Collections = Common.Collections || {};
|
||||
|
||||
define([
|
||||
'underscore',
|
||||
'backbone',
|
||||
'common/main/lib/model/HistoryVersion'
|
||||
], function(_, Backbone){
|
||||
'use strict';
|
||||
|
||||
Common.Collections.HistoryVersions = Backbone.Collection.extend({
|
||||
model: Common.Models.HistoryVersion,
|
||||
|
||||
findRevision: function(revision) {
|
||||
return this.findWhere({revision: revision});
|
||||
},
|
||||
|
||||
findRevisions: function(revision) {
|
||||
return this.where({revision: revision});
|
||||
}
|
||||
});
|
||||
});
|
24
apps/common/main/lib/collection/ReviewChanges.js
Normal file
24
apps/common/main/lib/collection/ReviewChanges.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* ReviewChanges.js
|
||||
*
|
||||
* Created by Julia.Radzhabova on 05.08.15
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
Common.Collections = Common.Collections || {};
|
||||
|
||||
define([
|
||||
'underscore',
|
||||
'backbone',
|
||||
'common/main/lib/model/ReviewChange'
|
||||
], function(_, Backbone){
|
||||
'use strict';
|
||||
|
||||
Common.Collections.ReviewChanges = Backbone.Collection.extend({
|
||||
model: Common.Models.ReviewChange
|
||||
});
|
||||
});
|
28
apps/common/main/lib/collection/TextArt.js
Normal file
28
apps/common/main/lib/collection/TextArt.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Created by Julia.Radzhabova on 09.07.15
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
Common.Collections = Common.Collections || {};
|
||||
|
||||
define([
|
||||
'backbone'
|
||||
], function(Backbone){
|
||||
'use strict';
|
||||
|
||||
Common.Collections.TextArt = Backbone.Collection.extend({
|
||||
model: Backbone.Model.extend({
|
||||
defaults: function() {
|
||||
return {
|
||||
id: Common.UI.getId(),
|
||||
imageUrl: null,
|
||||
data: null
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
|
49
apps/common/main/lib/collection/Users.js
Normal file
49
apps/common/main/lib/collection/Users.js
Normal file
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* Users.js
|
||||
*
|
||||
* Collection
|
||||
*
|
||||
* Created by Maxim Kadushkin on 27 February 2014
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
define([
|
||||
'backbone',
|
||||
'common/main/lib/model/User'
|
||||
], function(Backbone){
|
||||
'use strict';
|
||||
|
||||
Common.Collections = Common.Collections || {};
|
||||
|
||||
Common.Collections.Users = Backbone.Collection.extend({
|
||||
model: Common.Models.User,
|
||||
|
||||
getOnlineCount: function() {
|
||||
var count = 0;
|
||||
this.each(function(user){
|
||||
user.online && count++;
|
||||
});
|
||||
|
||||
return count;
|
||||
},
|
||||
|
||||
findUser: function(id) {
|
||||
return this.find(
|
||||
function(model){
|
||||
return model.get('id') == id;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Common.Collections.HistoryUsers = Backbone.Collection.extend({
|
||||
model: Common.Models.User,
|
||||
|
||||
findUser: function(id) {
|
||||
return this.find(
|
||||
function(model){
|
||||
return model.get('id') == id;
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
83
apps/common/main/lib/component/BaseView.js
Normal file
83
apps/common/main/lib/component/BaseView.js
Normal file
|
@ -0,0 +1,83 @@
|
|||
/**
|
||||
* BaseView.js
|
||||
*
|
||||
* Created by Alexander Yuzhin on 1/17/14
|
||||
* Copyright (c) 2014 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,
|
||||
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,
|
||||
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");
|
||||
}
|
||||
});
|
||||
});
|
463
apps/common/main/lib/component/Button.js
Normal file
463
apps/common/main/lib/component/Button.js
Normal file
|
@ -0,0 +1,463 @@
|
|||
/**
|
||||
* Button.js
|
||||
*
|
||||
* Created by Alexander Yuzhin on 1/20/14
|
||||
* Copyright (c) 2014 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="btn-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="btn-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="btn-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([
|
||||
'common/main/lib/component/BaseView',
|
||||
'common/main/lib/component/ToggleManager'
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
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
|
||||
},
|
||||
|
||||
template: _.template([
|
||||
'<% if (menu == null) { %>',
|
||||
'<button type="button" class="btn <%= cls %>" id="<%= id %>" style="<%= style %>">',
|
||||
'<span class="caption"><%= caption %></span>',
|
||||
'<% if (iconCls != "") { %>',
|
||||
'<span class="btn-icon <%= iconCls %>"> </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">',
|
||||
'<span class="caption"><%= caption %></span>',
|
||||
'<% if (iconCls != "") { %>',
|
||||
'<span class="btn-icon <%= iconCls %>"> </span>',
|
||||
'<% } %>',
|
||||
'<span class="caret img-commonctrl"></span>',
|
||||
'</button>',
|
||||
'</div>',
|
||||
'<% } else { %>',
|
||||
'<div class="btn-group split" id="<%= id %>" style="<%= style %>">',
|
||||
'<button type="button" class="btn <%= cls %>">',
|
||||
'<span class="caption"><%= caption %></span>',
|
||||
'<% if (iconCls != "") { %>',
|
||||
'<span class="btn-icon <%= iconCls %>"> </span>',
|
||||
'<% } %>',
|
||||
'</button>',
|
||||
'<button type="button" class="btn <%= cls %> dropdown-toggle" data-toggle="dropdown">',
|
||||
'<span class="caret img-commonctrl"></span>',
|
||||
'<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.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();
|
||||
}
|
||||
},
|
||||
|
||||
render: function(parentEl) {
|
||||
var me = this;
|
||||
|
||||
me.trigger('render:before', me);
|
||||
|
||||
me.cmpEl = $(me.el);
|
||||
|
||||
if (parentEl) {
|
||||
me.setElement(parentEl, false);
|
||||
|
||||
if (!me.rendered) {
|
||||
me.cmpEl = $(this.template({
|
||||
id : me.id,
|
||||
cls : me.cls,
|
||||
iconCls : me.iconCls,
|
||||
menu : me.menu,
|
||||
split : me.split,
|
||||
disabled : me.disabled,
|
||||
pressed : me.pressed,
|
||||
caption : me.caption,
|
||||
style : me.style
|
||||
}));
|
||||
|
||||
if (me.menu && _.isFunction(me.menu.render))
|
||||
me.menu.render(me.cmpEl);
|
||||
|
||||
parentEl.html(me.cmpEl);
|
||||
}
|
||||
}
|
||||
|
||||
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');
|
||||
|
||||
me.cmpEl.attr('data-toggle', 'tooltip');
|
||||
me.cmpEl.tooltip({
|
||||
title : me.options.hint,
|
||||
placement : me.options.hintAnchor||'cursor'
|
||||
});
|
||||
|
||||
if (modalParents.length > 0) {
|
||||
me.cmpEl.data('bs.tooltip').tip().css('z-index', parseInt(modalParents.css('z-index')) + 10);
|
||||
}
|
||||
}
|
||||
|
||||
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.cmpEl.data('bs.tooltip');
|
||||
if (tip) {
|
||||
if (tip.dontShow===undefined)
|
||||
tip.dontShow = true;
|
||||
|
||||
tip.hide();
|
||||
}
|
||||
}
|
||||
me.trigger('click', me, e);
|
||||
}
|
||||
};
|
||||
|
||||
var doSplitSelect = function(select, e) {
|
||||
if (!select) {
|
||||
// Is mouse under button
|
||||
var isUnderMouse = false;
|
||||
|
||||
_.each($('button', el), function(el){
|
||||
if ($(el).is(':hover')) {
|
||||
isUnderMouse = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if (!isUnderMouse) {
|
||||
el.removeClass('over');
|
||||
$('button', el).removeClass('over');
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
$('[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.cmpEl.data('bs.tooltip');
|
||||
if (tip) {
|
||||
if (tip.dontShow===undefined)
|
||||
tip.dontShow = true;
|
||||
|
||||
tip.hide();
|
||||
}
|
||||
}
|
||||
var isOpen = el.hasClass('open');
|
||||
doSplitSelect(!isOpen, e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var doSetActiveState = function(e, state) {
|
||||
if (isSplit) {
|
||||
doSplitSelect(state, e);
|
||||
} else {
|
||||
el.toggleClass('active', state);
|
||||
$('button', el).toggleClass('active', state);
|
||||
}
|
||||
};
|
||||
|
||||
var onMouseDown = function (e) {
|
||||
doSplitSelect(true, e);
|
||||
$(document).on('mouseup', onMouseUp);
|
||||
};
|
||||
|
||||
var onMouseUp = function (e) {
|
||||
doSplitSelect(false, e);
|
||||
$(document).off('mouseup', onMouseUp);
|
||||
};
|
||||
|
||||
var onAfterHideMenu = function(e) {
|
||||
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));
|
||||
}
|
||||
|
||||
el.on('hide.bs.dropdown', _.bind(doSplitSelect, me, false));
|
||||
el.on('show.bs.dropdown', _.bind(doSplitSelect, me, true));
|
||||
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) {
|
||||
if (!me.disabled) {
|
||||
me.cmpEl.removeClass('over');
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
},
|
||||
|
||||
isActive: function() {
|
||||
if (this.enableToggle)
|
||||
return this.pressed;
|
||||
|
||||
return this.cmpEl.hasClass('active')
|
||||
},
|
||||
|
||||
setDisabled: function(disabled) {
|
||||
if (this.rendered) {
|
||||
var el = this.cmpEl,
|
||||
isGroup = el.hasClass('btn-group');
|
||||
|
||||
disabled = (disabled===true);
|
||||
|
||||
if (disabled !== el.hasClass('disabled')) {
|
||||
var decorateBtn = function(button) {
|
||||
button.toggleClass('disabled', disabled);
|
||||
(disabled) ? button.attr({disabled: disabled}) : button.removeAttr('disabled');
|
||||
};
|
||||
|
||||
decorateBtn(el);
|
||||
isGroup && decorateBtn(el.children('button'));
|
||||
}
|
||||
|
||||
if (disabled) {
|
||||
var tip = this.cmpEl.data('bs.tooltip');
|
||||
if (tip) {
|
||||
tip.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.disabled = disabled;
|
||||
},
|
||||
|
||||
isDisabled: function() {
|
||||
return this.disabled;
|
||||
},
|
||||
|
||||
setIconCls: function(cls) {
|
||||
var btnIconEl = $(this.el).find('span.btn-icon'),
|
||||
oldCls = this.iconCls;
|
||||
|
||||
this.iconCls = cls;
|
||||
btnIconEl.removeClass(oldCls);
|
||||
btnIconEl.addClass(cls || '');
|
||||
},
|
||||
|
||||
setVisible: function(visible) {
|
||||
if (this.cmpEl) this.cmpEl.toggleClass('hidden', !visible);
|
||||
},
|
||||
|
||||
updateHint: function(hint) {
|
||||
this.options.hint = hint;
|
||||
|
||||
var cmpEl = this.cmpEl,
|
||||
modalParents = cmpEl.closest('.asc-window');
|
||||
|
||||
cmpEl.attr('data-toggle', 'tooltip');
|
||||
cmpEl.tooltip('destroy').tooltip({
|
||||
title : hint,
|
||||
placement : this.options.hintAnchor || 'cursor'
|
||||
});
|
||||
|
||||
if (modalParents.length > 0) {
|
||||
cmpEl.data('bs.tooltip').tip().css('z-index', parseInt(modalParents.css('z-index')) + 10);
|
||||
}
|
||||
},
|
||||
|
||||
setCaption: function(caption) {
|
||||
if (this.caption != caption) {
|
||||
this.caption = caption;
|
||||
|
||||
if (this.rendered) {
|
||||
var captionNode = this.cmpEl.find('button:first > .caption').andSelf().filter('button > .caption');
|
||||
|
||||
if (captionNode.length > 0) {
|
||||
captionNode.text(caption);
|
||||
} else {
|
||||
this.cmpEl.find('button:first').andSelf().filter('button').text(caption);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
156
apps/common/main/lib/component/CheckBox.js
Normal file
156
apps/common/main/lib/component/CheckBox.js
Normal file
|
@ -0,0 +1,156 @@
|
|||
/**
|
||||
* CheckBox.js
|
||||
*
|
||||
* Created by Julia Radzhabova on 1/24/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Single checkbox field. Can be used as a direct replacement for traditional checkbox fields.
|
||||
* Checkboxes may be given an optional {@link #labelText} which will be displayed immediately after checkbox.
|
||||
*
|
||||
* Example usage:
|
||||
* new Common.UI.CheckBox({
|
||||
* el : $('#id'),
|
||||
* labelText : 'someText',
|
||||
* value : true
|
||||
* });
|
||||
*
|
||||
* # Values
|
||||
*
|
||||
* The main value of a checkbox is a boolean, indicating whether or not the checkbox is checked.
|
||||
* To check the checkbox use setValue(...) function with parameters:
|
||||
*
|
||||
* - `true`
|
||||
* - `'true'`
|
||||
* - `'1'`
|
||||
* - `1`
|
||||
* - 'checked'
|
||||
*
|
||||
* Checkbox can be in indeterminate state. Use setValue('indeterminate').
|
||||
*
|
||||
* Any other value will uncheck the checkbox.
|
||||
*
|
||||
* To get the checkbox state use getValue() function. It can return 'checked' / 'unchecked' / 'indeterminate'.
|
||||
*
|
||||
* @property {Boolean} disabled
|
||||
* True if this checkbox is disabled.
|
||||
*
|
||||
* disabled: false,
|
||||
*
|
||||
* **/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'common/main/lib/component/BaseView',
|
||||
'underscore'
|
||||
], function (base, _) {
|
||||
'use strict';
|
||||
|
||||
Common.UI.CheckBox = Common.UI.BaseView.extend({
|
||||
|
||||
options : {
|
||||
labelText: ''
|
||||
},
|
||||
|
||||
disabled : false,
|
||||
rendered : false,
|
||||
indeterminate: false,
|
||||
checked : false,
|
||||
value : 'unchecked',
|
||||
|
||||
template : _.template('<label class="checkbox-indeterminate"><input type="button" class="img-commonctrl"><span><%= labelText %></span></label>'),
|
||||
|
||||
initialize : function(options) {
|
||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
||||
|
||||
var me = this,
|
||||
el = $(this.el);
|
||||
|
||||
this.render();
|
||||
|
||||
if (this.options.disabled)
|
||||
this.setDisabled(this.options.disabled);
|
||||
|
||||
if (this.options.value!==undefined)
|
||||
this.setValue(this.options.value, true);
|
||||
|
||||
// handle events
|
||||
this.$chk.on('click', _.bind(this.onItemCheck, this));
|
||||
},
|
||||
|
||||
render: function () {
|
||||
var el = $(this.el);
|
||||
el.html(this.template({
|
||||
labelText: this.options.labelText
|
||||
}));
|
||||
|
||||
this.$chk = el.find('input[type=button]');
|
||||
this.$label = el.find('label');
|
||||
|
||||
this.rendered = true;
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
setDisabled: function(disabled) {
|
||||
if (disabled !== this.disabled) {
|
||||
this.$label.toggleClass('disabled', disabled);
|
||||
(disabled) ? this.$chk.attr({disabled: disabled}) : this.$chk.removeAttr('disabled');
|
||||
}
|
||||
|
||||
this.disabled = disabled;
|
||||
},
|
||||
|
||||
isDisabled: function() {
|
||||
return this.disabled;
|
||||
},
|
||||
|
||||
onItemCheck: function (e) {
|
||||
if (!this.disabled) {
|
||||
if (this.indeterminate){
|
||||
this.indeterminate = false;
|
||||
this.setValue(false);
|
||||
} else {
|
||||
this.setValue(!this.checked);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
setRawValue: function(value) {
|
||||
this.checked = (value === true || value === 'true' || value === '1' || value === 1 || value === 'checked');
|
||||
this.indeterminate = (value === 'indeterminate');
|
||||
|
||||
this.$chk.toggleClass('checked', this.checked);
|
||||
this.$chk.toggleClass('indeterminate', this.indeterminate);
|
||||
|
||||
this.value = this.indeterminate ? 'indeterminate' : (this.checked ? 'checked' : 'unchecked');
|
||||
},
|
||||
|
||||
setValue: function(value, suspendchange) {
|
||||
if (this.rendered) {
|
||||
this.lastValue = this.value;
|
||||
this.setRawValue(value);
|
||||
if (suspendchange !== true && this.lastValue !== value)
|
||||
this.trigger('change', this, this.value, this.lastValue);
|
||||
} else {
|
||||
this.options.value = value;
|
||||
}
|
||||
},
|
||||
|
||||
getValue: function() {
|
||||
return this.value;
|
||||
},
|
||||
|
||||
isChecked: function () {
|
||||
return this.checked;
|
||||
},
|
||||
|
||||
setCaption: function(text) {
|
||||
this.$label.find('span').text(text);
|
||||
}
|
||||
});
|
||||
});
|
40
apps/common/main/lib/component/ColorButton.js
Normal file
40
apps/common/main/lib/component/ColorButton.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'common/main/lib/component/Button'
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
Common.UI.ColorButton = Common.UI.Button.extend({
|
||||
options : {
|
||||
hint: false,
|
||||
enableToggle: false
|
||||
},
|
||||
|
||||
template: _.template([
|
||||
'<div class="btn-group" id="<%= id %>">',
|
||||
'<button type="button" class="btn btn-color dropdown-toggle <%= cls %>" data-toggle="dropdown" style="<%= style %>">',
|
||||
'<span> </span>',
|
||||
'</button>',
|
||||
'</div>'
|
||||
].join('')),
|
||||
|
||||
setColor: function(color) {
|
||||
var border_color, clr,
|
||||
span = $(this.cmpEl).find('button span');
|
||||
this.color = color;
|
||||
|
||||
if ( color== 'transparent' ) {
|
||||
border_color = '#BEBEBE';
|
||||
clr = color;
|
||||
span.addClass('color-transparent');
|
||||
} else {
|
||||
border_color = 'transparent';
|
||||
clr = (typeof(color) == 'object') ? '#'+color.color : '#'+color;
|
||||
span.removeClass('color-transparent');
|
||||
}
|
||||
span.css({'background-color': clr, 'border-color': border_color});
|
||||
}
|
||||
});
|
||||
});
|
105
apps/common/main/lib/component/ColorPalette.js
Normal file
105
apps/common/main/lib/component/ColorPalette.js
Normal file
|
@ -0,0 +1,105 @@
|
|||
/**
|
||||
* ColorPalette.js
|
||||
*
|
||||
* Created by Alexander Yuzhin on 2/20/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'common/main/lib/component/BaseView'
|
||||
], function () { 'use strict';
|
||||
|
||||
Common.UI.ColorPalette = Common.UI.BaseView.extend({
|
||||
options: {
|
||||
allowReselect: true,
|
||||
cls: '',
|
||||
style: ''
|
||||
},
|
||||
|
||||
template:_.template([
|
||||
'<div class="palette-color">',
|
||||
'<% _.each(colors, function(color, index) { %>',
|
||||
'<span class="color-item" data-color="<%= color %>" style="background-color: #<%= color %>;"></span>',
|
||||
'<% }) %>',
|
||||
'</div>'
|
||||
].join('')),
|
||||
|
||||
initialize : function(options) {
|
||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
||||
|
||||
var me = this;
|
||||
|
||||
this.id = me.options.id;
|
||||
this.cls = me.options.cls;
|
||||
this.style = me.options.style;
|
||||
this.colors = me.options.colors || [];
|
||||
this.value = me.options.value;
|
||||
|
||||
if (me.options.el) {
|
||||
me.render();
|
||||
}
|
||||
},
|
||||
|
||||
render: function (parentEl) {
|
||||
var me = this;
|
||||
|
||||
if (!me.rendered) {
|
||||
this.cmpEl = $(this.template({
|
||||
id : this.id,
|
||||
cls : this.cls,
|
||||
style : this.style,
|
||||
colors : this.colors
|
||||
}));
|
||||
|
||||
if (parentEl) {
|
||||
this.setElement(parentEl, false);
|
||||
parentEl.html(this.cmpEl);
|
||||
} else {
|
||||
$(this.el).html(this.cmpEl);
|
||||
}
|
||||
} else {
|
||||
this.cmpEl = $(this.el);
|
||||
}
|
||||
|
||||
if (!me.rendered) {
|
||||
var el = this.cmpEl;
|
||||
|
||||
el.on('click', 'span.color-item', _.bind(this.itemClick, this));
|
||||
}
|
||||
|
||||
me.rendered = true;
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
itemClick: function(e) {
|
||||
var item = $(e.target);
|
||||
|
||||
this.select(item.attr('data-color'));
|
||||
},
|
||||
|
||||
select: function(color, suppressEvent) {
|
||||
if (this.value != color) {
|
||||
var me = this;
|
||||
|
||||
// Remove selection with other elements
|
||||
$('span.color-item', this.cmpEl).removeClass('selected');
|
||||
|
||||
this.value = color;
|
||||
|
||||
if (color && /#?[a-fA-F0-9]{6}/.test(color)) {
|
||||
color = /#?([a-fA-F0-9]{6})/.exec(color)[1].toUpperCase();
|
||||
|
||||
$('span[data-color=' + color + ']', this.cmpEl).addClass('selected');
|
||||
|
||||
if (!suppressEvent)
|
||||
me.trigger('select', me, this.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
183
apps/common/main/lib/component/ComboBorderSize.js
Normal file
183
apps/common/main/lib/component/ComboBorderSize.js
Normal file
|
@ -0,0 +1,183 @@
|
|||
/**
|
||||
* ComboBorderSize.js
|
||||
*
|
||||
* Created by Julia Radzhabova on 2/10/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Using template
|
||||
*
|
||||
* <div class="input-group input-group-nr combobox combo-border-size" id="id-combobox">
|
||||
* <div class="form-control"></div>
|
||||
* <div style="display: table-cell;"></div>
|
||||
* <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></button>
|
||||
* <ul class="dropdown-menu"></ul>
|
||||
* </div>
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'common/main/lib/component/ComboBox'
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
Common.UI.BordersModel = Backbone.Model.extend({
|
||||
defaults: function() {
|
||||
return {
|
||||
value: null,
|
||||
displayValue: null,
|
||||
pxValue: null,
|
||||
id: Common.UI.getId(),
|
||||
offsety: undefined
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Common.UI.BordersStore = Backbone.Collection.extend({
|
||||
model: Common.UI.BordersModel
|
||||
});
|
||||
|
||||
Common.UI.ComboBorderSize = Common.UI.ComboBox.extend(_.extend({
|
||||
template: _.template([
|
||||
'<div class="input-group combobox combo-border-size input-group-nr <%= cls %>" id="<%= id %>" style="<%= style %>">',
|
||||
'<div class="form-control" style="<%= style %>"></div>',
|
||||
'<div style="display: table-cell;"></div>',
|
||||
'<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"><span class="caret img-commonctrl"></span></button>',
|
||||
'<ul class="dropdown-menu <%= menuCls %>" style="<%= menuStyle %>" role="menu">',
|
||||
'<% _.each(items, function(item) { %>',
|
||||
'<li id="<%= item.id %>" data-value="<%= item.value %>"><a tabindex="-1" type="menuitem">',
|
||||
'<span><%= item.displayValue %></span>',
|
||||
'<% if (item.offsety!==undefined) { %>',
|
||||
'<img src="data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" align="right" style="background-position: 0 -<%= item.offsety %>px;">',
|
||||
'<% } %>',
|
||||
'</a></li>',
|
||||
'<% }); %>',
|
||||
'</ul>',
|
||||
'</div>'
|
||||
].join('')),
|
||||
|
||||
initialize : function(options) {
|
||||
Common.UI.ComboBox.prototype.initialize.call(this, _.extend({
|
||||
editable: false,
|
||||
store: new Common.UI.BordersStore(),
|
||||
data: [
|
||||
{displayValue: this.txtNoBorders, value: 0, pxValue: 0 },
|
||||
{displayValue: '0.5 pt', value: 0.5, pxValue: 0.5, offsety: 0},
|
||||
{displayValue: '1 pt', value: 1, pxValue: 1, offsety: 20},
|
||||
{displayValue: '1.5 pt', value: 1.5, pxValue: 2, offsety: 40},
|
||||
{displayValue: '2.25 pt', value: 2.25,pxValue: 3, offsety: 60},
|
||||
{displayValue: '3 pt', value: 3, pxValue: 4, offsety: 80},
|
||||
{displayValue: '4.5 pt', value: 4.5, pxValue: 5, offsety: 100},
|
||||
{displayValue: '6 pt', value: 6, pxValue: 6, offsety: 120}
|
||||
],
|
||||
menuStyle: 'min-width: 150px;'
|
||||
}, options));
|
||||
},
|
||||
|
||||
render : function(parentEl) {
|
||||
Common.UI.ComboBox.prototype.render.call(this, parentEl);
|
||||
return this;
|
||||
},
|
||||
|
||||
itemClicked: function (e) {
|
||||
var el = $(e.currentTarget).parent();
|
||||
|
||||
this._selectedItem = this.store.findWhere({
|
||||
id: el.attr('id')
|
||||
});
|
||||
if (this._selectedItem) {
|
||||
$('.selected', $(this.el)).removeClass('selected');
|
||||
el.addClass('selected');
|
||||
this.updateFormControl(this._selectedItem);
|
||||
|
||||
this.trigger('selected', this, _.extend({}, this._selectedItem.toJSON()), e);
|
||||
e.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
updateFormControl: function(record) {
|
||||
var formcontrol = $(this.el).find('.form-control');
|
||||
|
||||
if (record.get('value')>0) {
|
||||
formcontrol[0].innerHTML = '';
|
||||
formcontrol.removeClass('text').addClass('image');
|
||||
formcontrol.css('background-position', '0 -' + record.get('offsety') + 'px');
|
||||
} else {
|
||||
formcontrol[0].innerHTML = this.txtNoBorders;
|
||||
formcontrol.removeClass('image').addClass('text');
|
||||
}
|
||||
},
|
||||
|
||||
setValue: function(value) {
|
||||
this._selectedItem = (value===null || value===undefined) ? undefined : _.find(this.store.models, function(item) {
|
||||
if ( value<item.attributes.value+0.01 && value>item.attributes.value-0.01) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
$('.selected', $(this.el)).removeClass('selected');
|
||||
|
||||
if (this._selectedItem) {
|
||||
this.updateFormControl(this._selectedItem);
|
||||
$('#' + this._selectedItem.get('id'), $(this.el)).addClass('selected');
|
||||
} else {
|
||||
var formcontrol = $(this.el).find('.form-control');
|
||||
formcontrol[0].innerHTML = '';
|
||||
formcontrol.removeClass('image').addClass('text');
|
||||
}
|
||||
},
|
||||
|
||||
txtNoBorders: 'No Borders'
|
||||
}, Common.UI.ComboBorderSize || {}));
|
||||
|
||||
Common.UI.ComboBorderSizeEditable = Common.UI.ComboBox.extend(_.extend({
|
||||
template: _.template([
|
||||
'<span class="input-group combobox combo-border-size input-group-nr <%= cls %>" id="<%= id %>" style="<%= style %>">',
|
||||
'<input type="text" class="form-control text">',
|
||||
'<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"><span class="caret img-commonctrl"></span></button>',
|
||||
'<ul class="dropdown-menu <%= menuCls %>" style="<%= menuStyle %>" role="menu">',
|
||||
'<% _.each(items, function(item) { %>',
|
||||
'<li id="<%= item.id %>" data-value="<%= item.value %>"><a tabindex="-1" type="menuitem">',
|
||||
'<span><%= item.displayValue %></span>',
|
||||
'<% if (item.offsety!==undefined) { %>',
|
||||
'<img src="data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" align="right" style="background-position: 0 -<%= item.offsety %>px;">',
|
||||
'<% } %>',
|
||||
'</a></li>',
|
||||
'<% }); %>',
|
||||
'</ul>',
|
||||
'</span>'
|
||||
].join('')),
|
||||
|
||||
initialize : function(options) {
|
||||
this.txtNoBorders = options.txtNoBorders || this.txtNoBorders;
|
||||
|
||||
Common.UI.ComboBox.prototype.initialize.call(this, _.extend({
|
||||
editable: true,
|
||||
store: new Common.UI.BordersStore(),
|
||||
data: [
|
||||
{displayValue: this.txtNoBorders, value: 0, pxValue: 0 },
|
||||
{displayValue: '0.5 pt', value: 0.5, pxValue: 0.5, offsety: 0},
|
||||
{displayValue: '1 pt', value: 1, pxValue: 1, offsety: 20},
|
||||
{displayValue: '1.5 pt', value: 1.5, pxValue: 2, offsety: 40},
|
||||
{displayValue: '2.25 pt', value: 2.25,pxValue: 3, offsety: 60},
|
||||
{displayValue: '3 pt', value: 3, pxValue: 4, offsety: 80},
|
||||
{displayValue: '4.5 pt', value: 4.5, pxValue: 5, offsety: 100},
|
||||
{displayValue: '6 pt', value: 6, pxValue: 6, offsety: 120}
|
||||
],
|
||||
menuStyle: 'min-width: 150px;'
|
||||
}, options));
|
||||
},
|
||||
|
||||
render : function(parentEl) {
|
||||
Common.UI.ComboBox.prototype.render.call(this, parentEl);
|
||||
return this;
|
||||
},
|
||||
|
||||
txtNoBorders: 'No Borders'
|
||||
}, Common.UI.ComboBorderSizeEditable || {}));
|
||||
});
|
503
apps/common/main/lib/component/ComboBox.js
Normal file
503
apps/common/main/lib/component/ComboBox.js
Normal file
|
@ -0,0 +1,503 @@
|
|||
/**
|
||||
* ComboBox.js
|
||||
*
|
||||
* Created by Alexander Yuzhin on 1/22/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Using template
|
||||
*
|
||||
* <div class="input-group input-group-nr combobox" id="id-combobox">
|
||||
* <input type="text" class="form-control">
|
||||
* <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></button>
|
||||
* <ul class="dropdown-menu"></ul>
|
||||
* </div>
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'common/main/lib/component/BaseView',
|
||||
'common/main/lib/component/Scroller'
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
Common.UI.ComboBoxModel = Backbone.Model.extend({
|
||||
defaults: function() {
|
||||
return {
|
||||
id: Common.UI.getId(),
|
||||
value: null,
|
||||
displayValue: null
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Common.UI.ComboBoxStore = Backbone.Collection.extend({
|
||||
model: Common.UI.ComboBoxModel
|
||||
});
|
||||
|
||||
Common.UI.ComboBox = Common.UI.BaseView.extend((function() {
|
||||
return {
|
||||
options : {
|
||||
id : null,
|
||||
cls : '',
|
||||
style : '',
|
||||
hint : false,
|
||||
editable : true,
|
||||
disabled : false,
|
||||
menuCls : '',
|
||||
menuStyle : '',
|
||||
displayField: 'displayValue',
|
||||
valueField : 'value'
|
||||
},
|
||||
|
||||
template: _.template([
|
||||
'<span class="input-group combobox <%= cls %>" id="<%= id %>" style="<%= style %>">',
|
||||
'<input type="text" class="form-control">',
|
||||
'<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"><span class="caret img-commonctrl"></span></button>',
|
||||
'<ul class="dropdown-menu <%= menuCls %>" style="<%= menuStyle %>" role="menu">',
|
||||
'<% _.each(items, function(item) { %>',
|
||||
'<li id="<%= item.id %>" data-value="<%= item.value %>"><a tabindex="-1" type="menuitem"><%= scope.getDisplayValue(item) %></a></li>',
|
||||
'<% }); %>',
|
||||
'</ul>',
|
||||
'</span>'
|
||||
].join('')),
|
||||
|
||||
initialize : function(options) {
|
||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
||||
|
||||
var me = this,
|
||||
el = $(this.el);
|
||||
|
||||
this.id = me.options.id || Common.UI.getId();
|
||||
this.cls = me.options.cls;
|
||||
this.style = me.options.style;
|
||||
this.menuCls = me.options.menuCls;
|
||||
this.menuStyle = me.options.menuStyle;
|
||||
this.template = me.options.template || me.template;
|
||||
this.hint = me.options.hint;
|
||||
this.editable = me.options.editable;
|
||||
this.disabled = me.options.disabled;
|
||||
this.store = me.options.store || new Common.UI.ComboBoxStore();
|
||||
this.displayField = me.options.displayField;
|
||||
this.valueField = me.options.valueField;
|
||||
me.rendered = me.options.rendered || false;
|
||||
|
||||
this.lastValue = null;
|
||||
|
||||
me.store.add(me.options.data);
|
||||
|
||||
if (me.options.el) {
|
||||
me.render();
|
||||
}
|
||||
},
|
||||
|
||||
render : function(parentEl) {
|
||||
var me = this;
|
||||
|
||||
if (!me.rendered) {
|
||||
this.cmpEl = $(this.template({
|
||||
id : this.id,
|
||||
cls : this.cls,
|
||||
style : this.style,
|
||||
menuCls : this.menuCls,
|
||||
menuStyle : this.menuStyle,
|
||||
items : this.store.toJSON(),
|
||||
scope : me
|
||||
}));
|
||||
|
||||
if (parentEl) {
|
||||
this.setElement(parentEl, false);
|
||||
parentEl.html(this.cmpEl);
|
||||
} else {
|
||||
$(this.el).html(this.cmpEl);
|
||||
}
|
||||
} else {
|
||||
this.cmpEl = $(this.el);
|
||||
}
|
||||
|
||||
if (!me.rendered) {
|
||||
var el = this.cmpEl;
|
||||
|
||||
this._input = el.find('input');
|
||||
this._button = el.find('.btn');
|
||||
|
||||
el.on('click', 'a', _.bind(this.itemClicked, this));
|
||||
el.on('mousedown', 'a', _.bind(this.itemMouseDown, this));
|
||||
|
||||
if (this.editable) {
|
||||
el.on('change', 'input', _.bind(this.onInputChanged, this));
|
||||
el.on('keydown', 'input', _.bind(this.onInputKeyDown, this));
|
||||
el.on('focusin', 'input', _.bind(this.onInputFocusIn, this));
|
||||
el.on('click', '.form-control', _.bind(this.onEditableInputClick, this));
|
||||
} else {
|
||||
el.on('click', '.form-control', _.bind(this.onInputClick, this));
|
||||
this._input.attr('readonly', 'readonly');
|
||||
this._input.attr('data-can-copy', false);
|
||||
}
|
||||
|
||||
if (me.options.hint) {
|
||||
el.attr('data-toggle', 'tooltip');
|
||||
el.tooltip({
|
||||
title : me.options.hint,
|
||||
placement : me.options.hintAnchor||'cursor'
|
||||
});
|
||||
}
|
||||
|
||||
el.on('show.bs.dropdown', _.bind(me.onBeforeShowMenu, me));
|
||||
el.on('shown.bs.dropdown', _.bind(me.onAfterShowMenu, me));
|
||||
el.on('hide.bs.dropdown', _.bind(me.onBeforeHideMenu, me));
|
||||
el.on('hidden.bs.dropdown', _.bind(me.onAfterHideMenu, me));
|
||||
el.on('keydown.after.bs.dropdown', _.bind(me.onAfterKeydownMenu, me));
|
||||
|
||||
Common.NotificationCenter.on('menumanager:hideall', _.bind(me.closeMenu, me));
|
||||
|
||||
this.scroller = new Common.UI.Scroller({
|
||||
el: $('.dropdown-menu', me.cmpEl),
|
||||
minScrollbarLength : 40,
|
||||
scrollYMarginOffset: 30,
|
||||
includePadding : true
|
||||
});
|
||||
|
||||
// set default selection
|
||||
this.setDefaultSelection();
|
||||
|
||||
this.listenTo(this.store, 'reset', this.onResetItems);
|
||||
}
|
||||
|
||||
me.rendered = true;
|
||||
if (me.disabled) me.setDisabled(me.disabled);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
setData: function(data) {
|
||||
this.store.reset([]);
|
||||
this.store.add(data);
|
||||
|
||||
this.setRawValue('');
|
||||
this.onResetItems();
|
||||
},
|
||||
|
||||
openMenu: function(delay) {
|
||||
var me = this;
|
||||
|
||||
_.delay(function(){
|
||||
me.cmpEl.addClass('open')
|
||||
}, delay || 0);
|
||||
},
|
||||
|
||||
closeMenu: function() {
|
||||
this.cmpEl.removeClass('open');
|
||||
},
|
||||
|
||||
isMenuOpen: function() {
|
||||
return this.cmpEl.hasClass('open');
|
||||
},
|
||||
|
||||
onBeforeShowMenu: function(e) {
|
||||
this.trigger('show:before', this, e);
|
||||
if (this.options.hint) {
|
||||
var tip = this.cmpEl.data('bs.tooltip');
|
||||
if (tip) {
|
||||
if (tip.dontShow===undefined)
|
||||
tip.dontShow = true;
|
||||
tip.hide();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onAfterShowMenu: function(e) {
|
||||
var $list = $(this.el).find('ul'),
|
||||
$selected = $list.find('> li.selected');
|
||||
|
||||
if ($selected.length) {
|
||||
var itemTop = $selected.position().top,
|
||||
itemHeight = $selected.height(),
|
||||
listHeight = $list.height();
|
||||
|
||||
if (itemTop < 0 || itemTop + itemHeight > listHeight) {
|
||||
$list.scrollTop($list.scrollTop() + itemTop + itemHeight - (listHeight/2));
|
||||
}
|
||||
}
|
||||
|
||||
if (this.scroller)
|
||||
this.scroller.update();
|
||||
|
||||
this.trigger('show:after', this, e);
|
||||
},
|
||||
|
||||
onBeforeHideMenu: function(e) {
|
||||
this.trigger('hide:before', this, e);
|
||||
|
||||
if (Common.UI.Scroller.isMouseCapture())
|
||||
e.preventDefault();
|
||||
},
|
||||
|
||||
onAfterHideMenu: function(e) {
|
||||
this.cmpEl.find('.dropdown-toggle').blur();
|
||||
this.trigger('hide:after', this, e);
|
||||
},
|
||||
|
||||
onAfterKeydownMenu: function(e) {
|
||||
if (e.keyCode == Common.UI.Keys.RETURN) {
|
||||
$(e.target).click();
|
||||
var me = this;
|
||||
if (this.rendered) {
|
||||
if (Common.Utils.isIE)
|
||||
this._input.trigger('change', { onkeydown: true });
|
||||
else
|
||||
this._input.blur();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (e.keyCode == Common.UI.Keys.ESC && this.isMenuOpen()) {
|
||||
this.closeMenu();
|
||||
this.onAfterHideMenu(e);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
onInputKeyDown: function(e) {
|
||||
var me = this;
|
||||
|
||||
if (e.keyCode == Common.UI.Keys.ESC){
|
||||
this.closeMenu();
|
||||
this.onAfterHideMenu(e);
|
||||
} else if (e.keyCode == Common.UI.Keys.UP || e.keyCode == Common.UI.Keys.DOWN) {
|
||||
if (!this.isMenuOpen())
|
||||
this.openMenu();
|
||||
|
||||
_.delay(function() {
|
||||
me._skipInputChange = true;
|
||||
me.cmpEl.find('ul li:first a').focus();
|
||||
}, 10);
|
||||
} else
|
||||
me._skipInputChange = false;
|
||||
},
|
||||
|
||||
onInputFocusIn: function(e) {
|
||||
this.trigger('combo:focusin', this, e);
|
||||
},
|
||||
|
||||
onInputChanged: function(e, extra) {
|
||||
// skip processing for internally-generated synthetic event
|
||||
// to avoid double processing
|
||||
if (extra && extra.synthetic)
|
||||
return;
|
||||
|
||||
if (this._skipInputChange) {
|
||||
this._skipInputChange = false; return;
|
||||
}
|
||||
|
||||
var val = $(e.target).val(),
|
||||
record = {};
|
||||
|
||||
if (this.lastValue === val) {
|
||||
if (extra && extra.onkeydown)
|
||||
this.trigger('combo:blur', this, e);
|
||||
return;
|
||||
}
|
||||
|
||||
record[this.valueField] = val;
|
||||
|
||||
this.trigger('changed:before', this, record, e);
|
||||
|
||||
if (e.isDefaultPrevented())
|
||||
return;
|
||||
|
||||
var obj;
|
||||
this._selectedItem = this.store.findWhere((obj={}, obj[this.displayField]=val, obj));
|
||||
|
||||
if (this._selectedItem) {
|
||||
record = this._selectedItem.toJSON();
|
||||
$('.selected', $(this.el)).removeClass('selected');
|
||||
$('#' + this._selectedItem.get('id'), $(this.el)).addClass('selected');
|
||||
}
|
||||
|
||||
// trigger changed event
|
||||
this.trigger('changed:after', this, record, e);
|
||||
},
|
||||
|
||||
onInputClick: function(e) {
|
||||
if (this._button)
|
||||
this._button.dropdown('toggle');
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
},
|
||||
|
||||
onEditableInputClick: function(e) {
|
||||
if (this.options.hint) {
|
||||
var tip = this.cmpEl.data('bs.tooltip');
|
||||
if (tip) {
|
||||
if (tip.dontShow===undefined)
|
||||
tip.dontShow = true;
|
||||
tip.hide();
|
||||
}
|
||||
}
|
||||
if (this.isMenuOpen() && e.which == 1)
|
||||
e.stopPropagation();
|
||||
},
|
||||
|
||||
setDefaultSelection: function () {
|
||||
if (!this.rendered)
|
||||
return;
|
||||
|
||||
var val = this._input.val(),
|
||||
obj;
|
||||
|
||||
if (val) {
|
||||
this._selectedItem = this.store.findWhere((obj={}, obj[this.displayField]=val, obj));
|
||||
|
||||
if (this._selectedItem) {
|
||||
$('.selected', $(this.el)).removeClass('selected');
|
||||
$('#' + this._selectedItem.get('id'), $(this.el)).addClass('selected');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
setDisabled: function(disabled) {
|
||||
this.disabled = disabled;
|
||||
|
||||
if (!this.rendered)
|
||||
return;
|
||||
|
||||
disabled
|
||||
? this._input.attr('disabled', true)
|
||||
: this._input.removeAttr('disabled');
|
||||
|
||||
this.cmpEl.toggleClass('disabled', disabled);
|
||||
this._button.toggleClass('disabled', disabled);
|
||||
},
|
||||
|
||||
isDisabled: function() {
|
||||
return this.disabled;
|
||||
},
|
||||
|
||||
setRawValue: function(value) {
|
||||
if (this.rendered) {
|
||||
this._input.val(value).trigger('change', { synthetic: true });
|
||||
this.lastValue = (value!==null && value !== undefined) ? value.toString() : value;
|
||||
}
|
||||
},
|
||||
|
||||
getRawValue: function() {
|
||||
return this.rendered ? this._input.val() : null;
|
||||
},
|
||||
|
||||
setValue: function(value) {
|
||||
if (!this.rendered)
|
||||
return;
|
||||
|
||||
var obj;
|
||||
this._selectedItem = this.store.findWhere((obj={}, obj[this.valueField]=value, obj));
|
||||
|
||||
$('.selected', $(this.el)).removeClass('selected');
|
||||
|
||||
if (this._selectedItem) {
|
||||
this.setRawValue(this._selectedItem.get(this.displayField));
|
||||
$('#' + this._selectedItem.get('id'), $(this.el)).addClass('selected');
|
||||
} else {
|
||||
this.setRawValue(value);
|
||||
}
|
||||
},
|
||||
|
||||
getValue: function() {
|
||||
if (!this.rendered)
|
||||
return null;
|
||||
|
||||
if (this._selectedItem && !_.isUndefined(this._selectedItem.get(this.valueField))) {
|
||||
return this._selectedItem.get(this.valueField);
|
||||
}
|
||||
|
||||
return this._input.val();
|
||||
},
|
||||
|
||||
getDisplayValue: function(record) {
|
||||
return Common.Utils.String.htmlEncode(record[this.displayField]);
|
||||
},
|
||||
|
||||
getSelectedRecord: function() {
|
||||
if (!this.rendered)
|
||||
return null;
|
||||
|
||||
if (this._selectedItem && !_.isUndefined(this._selectedItem.get(this.valueField))) {
|
||||
return _.extend({}, this._selectedItem.toJSON());
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
selectRecord: function(record) {
|
||||
if (!this.rendered || !record)
|
||||
return;
|
||||
|
||||
this._selectedItem = record;
|
||||
|
||||
$('.selected', $(this.el)).removeClass('selected');
|
||||
this.setRawValue(this._selectedItem.get(this.displayField));
|
||||
$('#' + this._selectedItem.get('id'), $(this.el)).addClass('selected');
|
||||
},
|
||||
|
||||
itemClicked: function (e) {
|
||||
var el = $(e.target).closest('li');
|
||||
|
||||
this._selectedItem = this.store.findWhere({
|
||||
id: el.attr('id')
|
||||
});
|
||||
|
||||
if (this._selectedItem) {
|
||||
// set input text and trigger input change event marked as synthetic
|
||||
this.lastValue = this._selectedItem.get(this.displayField);
|
||||
this._input.val(this.lastValue).trigger('change', { synthetic: true });
|
||||
|
||||
$('.selected', $(this.el)).removeClass('selected');
|
||||
el.addClass('selected');
|
||||
|
||||
// trigger changed event
|
||||
this.trigger('selected', this, _.extend({}, this._selectedItem.toJSON()), e);
|
||||
|
||||
e.preventDefault();
|
||||
}
|
||||
this._isMouseDownMenu = false;
|
||||
},
|
||||
|
||||
itemMouseDown: function(e) {
|
||||
if (e.which != 1) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
return false;
|
||||
}
|
||||
this._isMouseDownMenu = true;
|
||||
},
|
||||
|
||||
onResetItems: function() {
|
||||
$(this.el).find('ul').html(_.template([
|
||||
'<% _.each(items, function(item) { %>',
|
||||
'<li id="<%= item.id %>" data-value="<%= item.value %>"><a tabindex="-1" type="menuitem"><%= scope.getDisplayValue(item) %></a></li>',
|
||||
'<% }); %>'
|
||||
].join(''), {
|
||||
items: this.store.toJSON(),
|
||||
scope: this
|
||||
}));
|
||||
|
||||
if (!_.isUndefined(this.scroller)) {
|
||||
this.scroller.destroy();
|
||||
delete this.scroller;
|
||||
}
|
||||
this.scroller = new Common.UI.Scroller({
|
||||
el: $('.dropdown-menu', this.cmpEl),
|
||||
minScrollbarLength : 40,
|
||||
scrollYMarginOffset: 30,
|
||||
includePadding : true
|
||||
});
|
||||
}
|
||||
}
|
||||
})());
|
||||
});
|
474
apps/common/main/lib/component/ComboBoxFonts.js
Normal file
474
apps/common/main/lib/component/ComboBoxFonts.js
Normal file
|
@ -0,0 +1,474 @@
|
|||
/**
|
||||
* ComboBoxFonts.js
|
||||
*
|
||||
* Created by Alexander Yuzhin on 2/11/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
var FONT_TYPE_RECENT = 4;
|
||||
|
||||
define([
|
||||
'common/main/lib/component/ComboBox'
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
Common.UI.ComboBoxFonts = Common.UI.ComboBox.extend((function() {
|
||||
var iconWidth = 302,
|
||||
iconHeight = FONT_THUMBNAIL_HEIGHT || 26,
|
||||
isRetina = window.devicePixelRatio > 1,
|
||||
thumbCanvas = document.createElement('canvas'),
|
||||
thumbContext = thumbCanvas.getContext('2d'),
|
||||
thumbPath = '../../../sdk/Common/Images/fonts_thumbnail.png',
|
||||
thumbPath2x = '../../../sdk/Common/Images/fonts_thumbnail@2x.png',
|
||||
listItemHeight = 36;
|
||||
|
||||
if (typeof window['AscDesktopEditor'] === 'object') {
|
||||
thumbPath = window['AscDesktopEditor'].getFontsSprite();
|
||||
thumbPath2x = window['AscDesktopEditor'].getFontsSprite(true);
|
||||
}
|
||||
|
||||
thumbCanvas.height = isRetina ? iconHeight * 2 : iconHeight;
|
||||
thumbCanvas.width = isRetina ? iconWidth * 2 : iconWidth;
|
||||
|
||||
return {
|
||||
template: _.template([
|
||||
'<div class="input-group combobox fonts <%= cls %>" id="<%= id %>" style="<%= style %>">',
|
||||
'<input type="text" class="form-control">',
|
||||
'<div style="display: table-cell;"></div>',
|
||||
'<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"><span class="caret img-commonctrl"></span></button>',
|
||||
'<ul class="dropdown-menu <%= menuCls %>" style="<%= menuStyle %>" role="menu">',
|
||||
'<li class="divider">',
|
||||
'<% _.each(items, function(item) { %>',
|
||||
'<li id="<%= item.id %>">',
|
||||
'<a class="font-item" tabindex="-1" type="menuitem" style="vertical-align:middle; margin: 0 0 0 -10px; height:<%=scope.getListItemHeight()%>px;"/>',
|
||||
'</li>',
|
||||
'<% }); %>',
|
||||
'</ul>',
|
||||
'</div>'
|
||||
].join('')),
|
||||
|
||||
initialize : function(options) {
|
||||
Common.UI.ComboBox.prototype.initialize.call(this, _.extend(options, {
|
||||
displayField: 'name'
|
||||
}));
|
||||
|
||||
this.recent = _.isNumber(options.recent) ? options.recent : 3;
|
||||
this.bindUpdateVisibleFontsTiles = _.bind(this.updateVisibleFontsTiles, this);
|
||||
|
||||
Common.NotificationCenter.on('fonts:change', _.bind(this.onApiChangeFont, this));
|
||||
Common.NotificationCenter.on('fonts:load', _.bind(this.fillFonts, this));
|
||||
},
|
||||
|
||||
render : function(parentEl) {
|
||||
var oldRawValue = null;
|
||||
|
||||
if (!_.isUndefined(this._input)) {
|
||||
oldRawValue = this._input.val();
|
||||
}
|
||||
|
||||
Common.UI.ComboBox.prototype.render.call(this, parentEl);
|
||||
|
||||
this.setRawValue(oldRawValue);
|
||||
|
||||
this._input.on('keyup', _.bind(this.onInputKeyUp, this));
|
||||
this._input.on('keydown', _.bind(this.onInputKeyDown, this));
|
||||
|
||||
this.scroller.update({alwaysVisibleY: true, onChange:this.bindUpdateVisibleFontsTiles});
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
onAfterKeydownMenu: function(e) {
|
||||
var me = this;
|
||||
if (e.keyCode == Common.UI.Keys.RETURN) {
|
||||
if ($(e.target).closest('input').length) { // enter in input field
|
||||
if (this.lastValue !== this._input.val())
|
||||
this._input.trigger('change');
|
||||
} else { // enter in dropdown list
|
||||
$(e.target).click();
|
||||
if (this.rendered) {
|
||||
if (Common.Utils.isIE)
|
||||
this._input.trigger('change', { onkeydown: true });
|
||||
else
|
||||
this._input.blur();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else if (e.keyCode == Common.UI.Keys.ESC && this.isMenuOpen()) {
|
||||
this._input.val(this.lastValue);
|
||||
setTimeout(function() {
|
||||
me.closeMenu();
|
||||
me.onAfterHideMenu(e);
|
||||
}, 10);
|
||||
return false;
|
||||
} else if ((e.keyCode == Common.UI.Keys.HOME || e.keyCode == Common.UI.Keys.END || e.keyCode == Common.UI.Keys.BACKSPACE) && this.isMenuOpen()) {
|
||||
setTimeout(function() {
|
||||
me._input.focus();
|
||||
}, 10);
|
||||
}
|
||||
|
||||
this.updateVisibleFontsTiles();
|
||||
},
|
||||
|
||||
onInputKeyUp: function(e) {
|
||||
if (e.keyCode != Common.UI.Keys.RETURN && e.keyCode !== Common.UI.Keys.SHIFT &&
|
||||
e.keyCode !== Common.UI.Keys.CTRL && e.keyCode !== Common.UI.Keys.ALT &&
|
||||
e.keyCode !== Common.UI.Keys.LEFT && e.keyCode !== Common.UI.Keys.RIGHT &&
|
||||
e.keyCode !== Common.UI.Keys.HOME && e.keyCode !== Common.UI.Keys.END &&
|
||||
e.keyCode !== Common.UI.Keys.ESC &&
|
||||
e.keyCode !== Common.UI.Keys.INSERT && e.keyCode !== Common.UI.Keys.TAB){
|
||||
e.stopPropagation();
|
||||
this.selectCandidate(e.keyCode == Common.UI.Keys.DELETE || e.keyCode == Common.UI.Keys.BACKSPACE);
|
||||
if (this._selectedItem) {
|
||||
var me = this;
|
||||
setTimeout(function() {
|
||||
var input = me._input[0],
|
||||
text = me._selectedItem.get(me.displayField),
|
||||
inputVal = input.value;
|
||||
if (me.rendered) {
|
||||
if (document.selection) { // IE
|
||||
document.selection.createRange().text = text;
|
||||
} else if (input.selectionStart || input.selectionStart == '0') { //FF и Webkit
|
||||
input.value = text;
|
||||
input.selectionStart = inputVal.length;
|
||||
input.selectionEnd = text.length;
|
||||
}
|
||||
}
|
||||
}, 10);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onInputKeyDown: function(e) {
|
||||
var me = this;
|
||||
|
||||
if (e.keyCode == Common.UI.Keys.ESC){
|
||||
this._input.val(this.lastValue);
|
||||
setTimeout(function() {
|
||||
me.closeMenu();
|
||||
me.onAfterHideMenu(e);
|
||||
}, 10);
|
||||
} else if (e.keyCode != Common.UI.Keys.RETURN && e.keyCode != Common.UI.Keys.CTRL && e.keyCode != Common.UI.Keys.SHIFT && e.keyCode != Common.UI.Keys.ALT){
|
||||
if (!this.isMenuOpen())
|
||||
this.openMenu();
|
||||
|
||||
if (e.keyCode == Common.UI.Keys.UP || e.keyCode == Common.UI.Keys.DOWN) {
|
||||
_.delay(function() {
|
||||
var selected = me.cmpEl.find('ul li.selected a');
|
||||
|
||||
if (selected.length<=0)
|
||||
selected = me.cmpEl.find('ul li:not(.divider):first a');
|
||||
|
||||
me._skipInputChange = true;
|
||||
selected.focus();
|
||||
me.updateVisibleFontsTiles();
|
||||
}, 10);
|
||||
} else
|
||||
me._skipInputChange = false;
|
||||
}
|
||||
},
|
||||
|
||||
onInputChanged: function(e, extra) {
|
||||
// skip processing for internally-generated synthetic event
|
||||
// to avoid double processing
|
||||
if (extra && extra.synthetic)
|
||||
return;
|
||||
|
||||
if (this._skipInputChange) {
|
||||
this._skipInputChange = false; return;
|
||||
}
|
||||
|
||||
if (this._isMouseDownMenu) {
|
||||
this._isMouseDownMenu = false; return;
|
||||
}
|
||||
|
||||
var val = $(e.target).val(),
|
||||
record = {};
|
||||
|
||||
if (this.lastValue === val) {
|
||||
if (extra && extra.onkeydown)
|
||||
this.trigger('combo:blur', this, e);
|
||||
return;
|
||||
}
|
||||
|
||||
record[this.valueField] = val;
|
||||
record[this.displayField] = val;
|
||||
|
||||
this.trigger('changed:before', this, record, e);
|
||||
|
||||
if (e.isDefaultPrevented())
|
||||
return;
|
||||
|
||||
if (this._selectedItem) {
|
||||
record[this.valueField] = this._selectedItem.get(this.displayField);
|
||||
this.setRawValue(record[this.valueField]);
|
||||
this.trigger('selected', this, _.extend({}, this._selectedItem.toJSON()), e);
|
||||
this.addItemToRecent(this._selectedItem);
|
||||
this.closeMenu();
|
||||
} else {
|
||||
this.setRawValue(record[this.valueField]);
|
||||
record['isNewFont'] = true;
|
||||
this.trigger('selected', this, record, e);
|
||||
this.closeMenu();
|
||||
}
|
||||
|
||||
// trigger changed event
|
||||
this.trigger('changed:after', this, record, e);
|
||||
},
|
||||
|
||||
getImageUri: function(opts) {
|
||||
if (opts.cloneid) {
|
||||
var img = $(this.el).find('ul > li#'+opts.cloneid + ' img');
|
||||
return img != null ? img[0].src : undefined;
|
||||
}
|
||||
|
||||
if (isRetina) {
|
||||
thumbContext.clearRect(0, 0, iconWidth * 2, iconHeight * 2);
|
||||
thumbContext.drawImage(this.spriteThumbs, 0, -FONT_THUMBNAIL_HEIGHT * 2 * opts.imgidx);
|
||||
} else {
|
||||
thumbContext.clearRect(0, 0, iconWidth, iconHeight);
|
||||
thumbContext.drawImage(this.spriteThumbs, 0, -FONT_THUMBNAIL_HEIGHT * opts.imgidx);
|
||||
}
|
||||
|
||||
return thumbCanvas.toDataURL();
|
||||
},
|
||||
|
||||
getImageWidth: function() {
|
||||
return iconWidth;
|
||||
},
|
||||
|
||||
getImageHeight: function() {
|
||||
return iconHeight;
|
||||
},
|
||||
|
||||
getListItemHeight: function() {
|
||||
return listItemHeight;
|
||||
},
|
||||
|
||||
loadSprite: function(callback) {
|
||||
if (callback) {
|
||||
this.spriteThumbs = new Image();
|
||||
this.spriteThumbs.onload = callback;
|
||||
this.spriteThumbs.src = (window.devicePixelRatio > 1) ? thumbPath2x : thumbPath;
|
||||
}
|
||||
},
|
||||
|
||||
fillFonts: function(store, select) {
|
||||
var me = this;
|
||||
|
||||
this.loadSprite(function() {
|
||||
me.store.set(store.toJSON());
|
||||
|
||||
me.rendered = false;
|
||||
me.render($(me.el));
|
||||
|
||||
me._fontsArray = me.store.toJSON();
|
||||
|
||||
if (me.recent > 0) {
|
||||
me.store.on('add', me.onInsertItem, me);
|
||||
me.store.on('remove', me.onRemoveItem, me);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
onApiChangeFont: function(font) {
|
||||
var name = (_.isFunction(font.get_Name) ? font.get_Name() : font.asc_getName());
|
||||
|
||||
if (this.getRawValue() !== name) {
|
||||
var record = this.store.findWhere({
|
||||
name: name
|
||||
});
|
||||
|
||||
$('.selected', $(this.el)).removeClass('selected');
|
||||
|
||||
if (record) {
|
||||
this.setRawValue(record.get(this.displayField));
|
||||
var itemNode = $('#' + record.get('id'), $(this.el)),
|
||||
menuNode = $('ul.dropdown-menu', this.cmpEl);
|
||||
|
||||
if (itemNode && menuNode) {
|
||||
itemNode.addClass('selected');
|
||||
if (this.recent<=0)
|
||||
menuNode.scrollTop(itemNode.offset().top - menuNode.offset().top);
|
||||
}
|
||||
} else {
|
||||
this.setRawValue(name);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
itemClicked: function (e) {
|
||||
var el = $(e.target).closest('li');
|
||||
var record = this.store.findWhere({id: el.attr('id')});
|
||||
this.addItemToRecent(record);
|
||||
|
||||
Common.UI.ComboBox.prototype.itemClicked.apply(this, arguments);
|
||||
},
|
||||
|
||||
onInsertItem: function(item) {
|
||||
$(this.el).find('ul').prepend(_.template([
|
||||
'<li id="<%= item.id %>">',
|
||||
'<a class="font-item" tabindex="-1" type="menuitem" style="vertical-align:middle; margin: 0 0 0 -10px; height:<%=scope.getListItemHeight()%>px;"/>',
|
||||
'</li>'
|
||||
].join(''), {
|
||||
item: item.attributes,
|
||||
scope: this
|
||||
}));
|
||||
},
|
||||
|
||||
onRemoveItem: function(item, store, opts) {
|
||||
$(this.el).find('ul > li#'+item.id).remove();
|
||||
},
|
||||
|
||||
onBeforeShowMenu: function(e) {
|
||||
Common.UI.ComboBox.prototype.onBeforeShowMenu.apply(this, arguments);
|
||||
|
||||
if (!this.getSelectedRecord() && !!this.getRawValue()) {
|
||||
var record = this.store.where({name: this.getRawValue()});
|
||||
if (record && record.length) {
|
||||
this.selectRecord(record[record.length - 1]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onAfterShowMenu: function(e) {
|
||||
if (this.recent > 0) {
|
||||
if (this.scroller && !this._scrollerIsInited) {
|
||||
this.scroller.update();
|
||||
this._scrollerIsInited = true;
|
||||
}
|
||||
$(this.el).find('ul').scrollTop(0);
|
||||
this.trigger('show:after', this, e);
|
||||
} else {
|
||||
Common.UI.ComboBox.prototype.onAfterShowMenu.apply(this, arguments);
|
||||
}
|
||||
|
||||
this.flushVisibleFontsTiles();
|
||||
this.updateVisibleFontsTiles(null, 0);
|
||||
},
|
||||
|
||||
onAfterHideMenu: function(e) {
|
||||
if (this.lastValue !== this._input.val())
|
||||
this._input.val(this.lastValue);
|
||||
|
||||
Common.UI.ComboBox.prototype.onAfterHideMenu.apply(this, arguments);
|
||||
},
|
||||
|
||||
addItemToRecent: function(record) {
|
||||
if (record.get('type') != FONT_TYPE_RECENT &&
|
||||
!this.store.findWhere({name: record.get('name'),type:FONT_TYPE_RECENT})) {
|
||||
var fonts = this.store.where({type:FONT_TYPE_RECENT});
|
||||
if (!(fonts.length < this.recent)) {
|
||||
this.store.remove(fonts[this.recent - 1]);
|
||||
}
|
||||
|
||||
var new_record = record.clone();
|
||||
new_record.set({'type': FONT_TYPE_RECENT, 'id': Common.UI.getId(), cloneid: record.id});
|
||||
this.store.add(new_record, {at:0});
|
||||
}
|
||||
},
|
||||
|
||||
selectCandidate: function(full) {
|
||||
var me = this,
|
||||
inputVal = this._input.val().toLowerCase();
|
||||
|
||||
if (!this._fontsArray)
|
||||
this._fontsArray = this.store.toJSON();
|
||||
|
||||
var font = _.find(this._fontsArray, function(font) {
|
||||
return (full) ? (font[me.displayField].toLowerCase() == inputVal) : (font[me.displayField].toLowerCase().indexOf(inputVal) == 0)
|
||||
});
|
||||
|
||||
if (font) {
|
||||
this._selectedItem = this.store.findWhere({
|
||||
id: font.id
|
||||
});
|
||||
} else
|
||||
this._selectedItem = null;
|
||||
|
||||
$('.selected', $(this.el)).removeClass('selected');
|
||||
|
||||
if (this._selectedItem) {
|
||||
var itemNode = $('#' + this._selectedItem.get('id'), $(this.el)),
|
||||
menuEl = $('ul[role=menu]', $(this.el));
|
||||
|
||||
if (itemNode.length > 0 && menuEl.length > 0) {
|
||||
itemNode.addClass('selected');
|
||||
|
||||
var itemTop = itemNode.position().top,
|
||||
menuTop = menuEl.scrollTop();
|
||||
|
||||
if (itemTop != 0)
|
||||
menuEl.scrollTop(menuTop + itemTop);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
updateVisibleFontsTiles: function(e, scrollY) {
|
||||
var me = this, j = 0, storeCount = me.store.length, index = 0;
|
||||
|
||||
if (!me.tiles) me.tiles = [];
|
||||
if (storeCount !== me.tiles.length) {
|
||||
for (j = me.tiles.length; j < storeCount; ++j) {
|
||||
me.tiles.push(null);
|
||||
}
|
||||
}
|
||||
|
||||
if (_.isUndefined(scrollY)) scrollY = parseInt($(me.el).find('.ps-scrollbar-x-rail').css('bottom'));
|
||||
|
||||
var scrollH = $(me.el).find('.dropdown-menu').height(),
|
||||
count = Math.max(Math.floor(scrollH / listItemHeight) + 3, 0),
|
||||
from = Math.max(Math.floor(-(scrollY / listItemHeight)) - 1, 0),
|
||||
to = from + count;
|
||||
|
||||
var listItems = $(me.el).find('a');
|
||||
|
||||
for (j = 0; j < storeCount; ++j) {
|
||||
if (from <= j && j < to) {
|
||||
if (null === me.tiles[j]) {
|
||||
var fontImage = document.createElement('canvas');
|
||||
var context = fontImage.getContext('2d');
|
||||
|
||||
fontImage.height = isRetina ? iconHeight * 2 : iconHeight;
|
||||
fontImage.width = isRetina ? iconWidth * 2 : iconWidth;
|
||||
|
||||
fontImage.style.width = iconWidth + 'px';
|
||||
fontImage.style.height = iconHeight + 'px';
|
||||
|
||||
index = me.store.at(j).get('imgidx');
|
||||
|
||||
if (isRetina) {
|
||||
context.clearRect(0, 0, iconWidth * 2, iconHeight * 2);
|
||||
context.drawImage(me.spriteThumbs, 0, -FONT_THUMBNAIL_HEIGHT * 2 * index);
|
||||
} else {
|
||||
context.clearRect(0, 0, iconWidth, iconHeight);
|
||||
context.drawImage(me.spriteThumbs, 0, -FONT_THUMBNAIL_HEIGHT * index);
|
||||
}
|
||||
|
||||
me.tiles[j] = fontImage;
|
||||
$(listItems[j]).get(0).appendChild(fontImage);
|
||||
}
|
||||
} else {
|
||||
if (me.tiles[j]) {
|
||||
me.tiles[j].parentNode.removeChild(me.tiles[j]);
|
||||
me.tiles[j] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
flushVisibleFontsTiles: function() {
|
||||
for (var j = this.tiles.length - 1; j >= 0; --j) {
|
||||
if (this.tiles[j]) {
|
||||
this.tiles[j].parentNode.removeChild(this.tiles[j]);
|
||||
this.tiles[j] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})());
|
||||
});
|
433
apps/common/main/lib/component/ComboDataView.js
Normal file
433
apps/common/main/lib/component/ComboDataView.js
Normal file
|
@ -0,0 +1,433 @@
|
|||
/**
|
||||
* ComboDataView.js
|
||||
*
|
||||
* Created by Alexander Yuzhin on 2/13/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'common/main/lib/component/BaseView',
|
||||
'common/main/lib/component/DataView'
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
Common.UI.ComboDataView = Common.UI.BaseView.extend({
|
||||
options : {
|
||||
id : null,
|
||||
cls : '',
|
||||
style : '',
|
||||
hint : false,
|
||||
itemWidth : 80,
|
||||
itemHeight : 40,
|
||||
menuMaxHeight : 300,
|
||||
enableKeyEvents : false,
|
||||
beforeOpenHandler : null,
|
||||
additionalMenuItems : null,
|
||||
showLast: true
|
||||
},
|
||||
|
||||
template: _.template([
|
||||
'<div id="<%= id %>" class="combo-dataview <%= cls %>" style="<%= style %>">',
|
||||
'<div class="view"></div> ',
|
||||
'<div class="button"></div> ',
|
||||
'</div>'
|
||||
].join('')),
|
||||
|
||||
initialize : function(options) {
|
||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
||||
|
||||
this.id = this.options.id || Common.UI.getId();
|
||||
this.cls = this.options.cls;
|
||||
this.style = this.options.style;
|
||||
this.hint = this.options.hint;
|
||||
this.store = this.options.store || new Common.UI.DataViewStore();
|
||||
this.itemWidth = this.options.itemWidth;
|
||||
this.itemHeight = this.options.itemHeight;
|
||||
this.menuMaxHeight = this.options.menuMaxHeight;
|
||||
this.beforeOpenHandler = this.options.beforeOpenHandler;
|
||||
this.showLast = this.options.showLast;
|
||||
this.rootWidth = 0;
|
||||
this.rootHeight = 0;
|
||||
this.rendered = false;
|
||||
|
||||
this.fieldPicker = new Common.UI.DataView({
|
||||
cls: 'field-picker',
|
||||
allowScrollbar: false,
|
||||
itemTemplate : _.template([
|
||||
'<div class="style" id="<%= id %>">',
|
||||
'<img src="<%= imageUrl %>" width="' + this.itemWidth + '" height="' + this.itemHeight + '"/>',
|
||||
'<% if (typeof title !== "undefined") {%>',
|
||||
'<span class="title"><%= title %></span>',
|
||||
'<% } %>',
|
||||
'</div>'
|
||||
].join(''))
|
||||
});
|
||||
|
||||
this.openButton = new Common.UI.Button({
|
||||
cls: 'open-menu',
|
||||
menu: new Common.UI.Menu({
|
||||
menuAlign: 'tl-tl',
|
||||
offset: [0, 3],
|
||||
items: [
|
||||
{template: _.template('<div class="menu-picker-container"></div>')}
|
||||
]
|
||||
})
|
||||
});
|
||||
|
||||
if (this.options.additionalMenuItems != null) {
|
||||
this.openButton.menu.items = this.openButton.menu.items.concat(this.options.additionalMenuItems)
|
||||
}
|
||||
|
||||
this.menuPicker = new Common.UI.DataView({
|
||||
cls: 'menu-picker',
|
||||
parentMenu: this.openButton.menu,
|
||||
restoreHeight: this.menuMaxHeight,
|
||||
style: 'max-height: '+this.menuMaxHeight+'px;',
|
||||
enableKeyEvents: this.options.enableKeyEvents,
|
||||
itemTemplate : _.template([
|
||||
'<div class="style" id="<%= id %>">',
|
||||
'<img src="<%= imageUrl %>" width="' + this.itemWidth + '" height="' + this.itemHeight + '"/>',
|
||||
'<% if (typeof title !== "undefined") {%>',
|
||||
'<span class="title"><%= title %></span>',
|
||||
'<% } %>',
|
||||
'</div>'
|
||||
].join(''))
|
||||
});
|
||||
|
||||
// Handle resize
|
||||
setInterval(_.bind(this.checkSize, this), 500);
|
||||
|
||||
if (this.options.el) {
|
||||
this.render();
|
||||
}
|
||||
},
|
||||
|
||||
render: function(parentEl) {
|
||||
if (!this.rendered) {
|
||||
var me = this;
|
||||
|
||||
me.trigger('render:before', me);
|
||||
|
||||
me.cmpEl = $(me.el);
|
||||
|
||||
var templateEl = me.template({
|
||||
id : me.id,
|
||||
cls : me.cls,
|
||||
style : me.style
|
||||
});
|
||||
|
||||
if (parentEl) {
|
||||
me.setElement(parentEl, false);
|
||||
|
||||
me.cmpEl = $(templateEl);
|
||||
|
||||
parentEl.html(me.cmpEl);
|
||||
} else {
|
||||
me.cmpEl.html(templateEl);
|
||||
}
|
||||
|
||||
me.rootWidth = me.cmpEl.width();
|
||||
me.rootHeight = me.cmpEl.height();
|
||||
|
||||
me.fieldPicker.render($('.view', me.cmpEl));
|
||||
me.openButton.render($('.button', me.cmpEl));
|
||||
me.menuPicker.render($('.menu-picker-container', me.cmpEl));
|
||||
|
||||
if (me.openButton.menu.cmpEl) {
|
||||
if (me.openButton.menu.cmpEl) {
|
||||
me.openButton.menu.menuAlignEl = me.cmpEl;
|
||||
me.openButton.menu.cmpEl.css('min-width', me.itemWidth);
|
||||
me.openButton.menu.on('show:before', _.bind(me.onBeforeShowMenu, me));
|
||||
me.openButton.menu.on('show:after', _.bind(me.onAfterShowMenu, me));
|
||||
me.openButton.cmpEl.on('hide.bs.dropdown', _.bind(me.onBeforeHideMenu, me));
|
||||
me.openButton.cmpEl.on('hidden.bs.dropdown', _.bind(me.onAfterHideMenu, me));
|
||||
}
|
||||
}
|
||||
|
||||
if (me.options.hint) {
|
||||
me.cmpEl.attr('data-toggle', 'tooltip');
|
||||
me.cmpEl.tooltip({
|
||||
title : me.options.hint,
|
||||
placement : me.options.hintAnchor || 'cursor'
|
||||
});
|
||||
}
|
||||
|
||||
me.fieldPicker.on('item:select', _.bind(me.onFieldPickerSelect, me));
|
||||
me.menuPicker.on('item:select', _.bind(me.onMenuPickerSelect, me));
|
||||
me.fieldPicker.on('item:click', _.bind(me.onFieldPickerClick, me));
|
||||
me.menuPicker.on('item:click', _.bind(me.onMenuPickerClick, me));
|
||||
me.fieldPicker.on('item:contextmenu', _.bind(me.onPickerItemContextMenu, me));
|
||||
me.menuPicker.on('item:contextmenu', _.bind(me.onPickerItemContextMenu, me));
|
||||
|
||||
me.fieldPicker.el.addEventListener('contextmenu', _.bind(me.onPickerComboContextMenu, me), false);
|
||||
me.menuPicker.el.addEventListener('contextmenu', _.bind(me.onPickerComboContextMenu, me), false);
|
||||
|
||||
me.onResize();
|
||||
|
||||
me.rendered = true;
|
||||
|
||||
me.trigger('render:after', me);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
checkSize: function() {
|
||||
if (this.cmpEl) {
|
||||
var me = this,
|
||||
width = this.cmpEl.width(),
|
||||
height = this.cmpEl.height();
|
||||
|
||||
if (this.rootWidth != width || this.rootHeight != height) {
|
||||
this.rootWidth = width;
|
||||
this.rootHeight = height;
|
||||
setTimeout(function() {
|
||||
me.openButton.menu.cmpEl.outerWidth();
|
||||
me.rootWidth = me.cmpEl.width();
|
||||
}, 10);
|
||||
this.onResize();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onResize: function() {
|
||||
if (this.openButton) {
|
||||
var button = $('button', this.openButton.cmpEl);
|
||||
button && button.css({
|
||||
width : $('.button', this.cmpEl).width(),
|
||||
height: $('.button', this.cmpEl).height()
|
||||
});
|
||||
|
||||
this.openButton.menu.hide();
|
||||
|
||||
var picker = this.menuPicker;
|
||||
if (picker) {
|
||||
var record = picker.getSelectedRec();
|
||||
|
||||
if (record) {
|
||||
record = record[0];
|
||||
this.fillComboView(record || picker.store.at(0), !!record, true);
|
||||
}
|
||||
|
||||
picker.onResize();
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.isSuspendEvents)
|
||||
this.trigger('resize', this);
|
||||
},
|
||||
|
||||
onBeforeShowMenu: function(e) {
|
||||
var me = this;
|
||||
|
||||
if (_.isFunction(me.beforeOpenHandler)){
|
||||
me.beforeOpenHandler(me, e);
|
||||
} else if (me.openButton.menu.cmpEl) {
|
||||
var itemMargin = 0;
|
||||
|
||||
try {
|
||||
var itemEl = $($('.dropdown-menu .dataview.inner .style', me.cmpEl)[0]);
|
||||
itemMargin = itemEl ? (parseInt(itemEl.css('margin-left')) + parseInt(itemEl.css('margin-right'))) : 0;
|
||||
} catch(e) {}
|
||||
|
||||
me.openButton.menu.cmpEl.css({
|
||||
'width' : Math.round((me.cmpEl.width() + (itemMargin * me.fieldPicker.store.length))/ me.itemWidth - .2) * (me.itemWidth + itemMargin),
|
||||
'min-height': this.cmpEl.height()
|
||||
});
|
||||
}
|
||||
|
||||
if (me.options.hint) {
|
||||
var tip = me.cmpEl.data('bs.tooltip');
|
||||
if (tip) {
|
||||
if (tip.dontShow===undefined)
|
||||
tip.dontShow = true;
|
||||
tip.hide();
|
||||
}
|
||||
}
|
||||
this.menuPicker.selectedBeforeHideRec = null; // for DataView - onKeyDown - Return key
|
||||
},
|
||||
|
||||
onBeforeHideMenu: function(e) {
|
||||
this.trigger('hide:before', this, e);
|
||||
|
||||
if (Common.UI.Scroller.isMouseCapture())
|
||||
e.preventDefault();
|
||||
|
||||
if (this.isStylesNotClosable)
|
||||
return false;
|
||||
},
|
||||
|
||||
onAfterShowMenu: function(e) {
|
||||
var me = this;
|
||||
if (me.menuPicker.scroller) {
|
||||
me.menuPicker.scroller.update({
|
||||
includePadding: true,
|
||||
suppressScrollX: true,
|
||||
alwaysVisibleY: true
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
onAfterHideMenu: function(e) {
|
||||
this.menuPicker.selectedBeforeHideRec = this.menuPicker.getSelectedRec()[0]; // for DataView - onKeyDown - Return key
|
||||
(this.showLast) ? this.menuPicker.showLastSelected() : this.menuPicker.deselectAll();
|
||||
this.trigger('hide:after', this, e);
|
||||
},
|
||||
|
||||
onFieldPickerSelect: function(picker, item, record) {
|
||||
//
|
||||
},
|
||||
|
||||
onMenuPickerSelect: function(picker, item, record, fromKeyDown) {
|
||||
if (this.disabled || fromKeyDown===true) return;
|
||||
|
||||
this.fillComboView(record, false);
|
||||
if (record && !this.isSuspendEvents)
|
||||
this.trigger('select', this, record);
|
||||
},
|
||||
|
||||
onFieldPickerClick: function(dataView, itemView, record) {
|
||||
if (this.disabled) return;
|
||||
|
||||
if (!this.isSuspendEvents)
|
||||
this.trigger('click', this, record);
|
||||
|
||||
if (this.options.hint) {
|
||||
var tip = this.cmpEl.data('bs.tooltip');
|
||||
if (tip) {
|
||||
if (tip.dontShow===undefined)
|
||||
tip.dontShow = true;
|
||||
tip.hide();
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.showLast) this.fieldPicker.deselectAll();
|
||||
},
|
||||
|
||||
onMenuPickerClick: function(dataView, itemView, record) {
|
||||
if (this.disabled) return;
|
||||
|
||||
if (!this.isSuspendEvents)
|
||||
this.trigger('click', this, record);
|
||||
},
|
||||
|
||||
onPickerItemContextMenu: function(dataView, itemView, record, e) {
|
||||
if (this.disabled) return;
|
||||
|
||||
if (!this.isSuspendEvents) {
|
||||
this.trigger('contextmenu', this, record, e);
|
||||
}
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
},
|
||||
|
||||
onPickerComboContextMenu: function(mouseEvent) {
|
||||
if (this.disabled) return;
|
||||
|
||||
if (!this.isSuspendEvents) {
|
||||
this.trigger('contextmenu', this, undefined, mouseEvent);
|
||||
}
|
||||
},
|
||||
|
||||
setDisabled: function(disabled) {
|
||||
this.disabled = disabled;
|
||||
|
||||
if (!this.rendered)
|
||||
return;
|
||||
|
||||
this.cmpEl.toggleClass('disabled', disabled);
|
||||
$('button', this.openButton.cmpEl).toggleClass('disabled', disabled);
|
||||
this.fieldPicker.setDisabled(disabled);
|
||||
},
|
||||
|
||||
isDisabled: function() {
|
||||
return this.disabled;
|
||||
},
|
||||
|
||||
fillComboView: function(record, forceSelect, forceFill) {
|
||||
if (!_.isUndefined(record) && record instanceof Backbone.Model){
|
||||
var me = this,
|
||||
store = me.menuPicker.store,
|
||||
fieldPickerEl = $(me.fieldPicker.el);
|
||||
|
||||
if (store) {
|
||||
if (forceFill || !me.fieldPicker.store.findWhere({'id': record.get('id')})){
|
||||
if (me.itemMarginLeft===undefined) {
|
||||
var div = $($(this.menuPicker.el).find('.inner > div:not(.grouped-data):not(.ps-scrollbar-x-rail):not(.ps-scrollbar-y-rail)')[0]);
|
||||
if (div.length > 0) {
|
||||
me.itemMarginLeft = parseInt(div.css('margin-left'));
|
||||
me.itemMarginRight = parseInt(div.css('margin-right'));
|
||||
me.itemPaddingLeft = parseInt(div.css('padding-left'));
|
||||
me.itemPaddingRight = parseInt(div.css('padding-right'));
|
||||
me.itemBorderLeft = parseInt(div.css('border-left-width'));
|
||||
me.itemBorderRight = parseInt(div.css('border-right-width'));
|
||||
}
|
||||
}
|
||||
|
||||
me.fieldPicker.store.reset([]); // remove all
|
||||
|
||||
var indexRec = store.indexOf(record),
|
||||
countRec = store.length,
|
||||
maxViewCount = Math.floor((fieldPickerEl.width()) / (me.itemWidth + (me.itemMarginLeft || 0) + (me.itemMarginRight || 0) + (me.itemPaddingLeft || 0) + (me.itemPaddingRight || 0) +
|
||||
(me.itemBorderLeft || 0) + (me.itemBorderRight || 0))),
|
||||
newStyles = [];
|
||||
|
||||
if (fieldPickerEl.height() / me.itemHeight > 2)
|
||||
maxViewCount *= Math.floor(fieldPickerEl.height() / me.itemHeight);
|
||||
|
||||
if (indexRec < 0)
|
||||
return;
|
||||
|
||||
indexRec = Math.floor(indexRec / maxViewCount) * maxViewCount;
|
||||
if (countRec - indexRec < maxViewCount)
|
||||
indexRec = Math.max(countRec - maxViewCount, 0);
|
||||
for (var index = indexRec, viewCount = 0; index < countRec && viewCount < maxViewCount; index++, viewCount++) {
|
||||
newStyles.push(store.at(index));
|
||||
}
|
||||
|
||||
me.fieldPicker.store.add(newStyles);
|
||||
}
|
||||
|
||||
if (forceSelect) {
|
||||
var selectRecord = me.fieldPicker.store.findWhere({'id': record.get('id')});
|
||||
if (selectRecord){
|
||||
me.suspendEvents();
|
||||
me.fieldPicker.selectRecord(selectRecord, true);
|
||||
me.resumeEvents();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
selectByIndex: function(index) {
|
||||
if (index < 0)
|
||||
this.fieldPicker.deselectAll();
|
||||
|
||||
this.menuPicker.selectByIndex(index);
|
||||
},
|
||||
|
||||
setItemWidth: function(width) {
|
||||
if (this.itemWidth != width)
|
||||
this.itemWidth = window.devicePixelRatio > 1 ? width / 2 : width;
|
||||
},
|
||||
|
||||
setItemHeight: function(height) {
|
||||
if (this.itemHeight != height)
|
||||
this.itemHeight = window.devicePixelRatio > 1 ? height / 2 : height;
|
||||
},
|
||||
|
||||
removeTips: function() {
|
||||
var picker = this.menuPicker;
|
||||
_.each(picker.dataViewItems, function(item) {
|
||||
var tip = item.$el.data('bs.tooltip');
|
||||
if (tip) (tip.tip()).remove();
|
||||
}, picker);
|
||||
}
|
||||
})
|
||||
});
|
722
apps/common/main/lib/component/DataView.js
Normal file
722
apps/common/main/lib/component/DataView.js
Normal file
|
@ -0,0 +1,722 @@
|
|||
/**
|
||||
* DataView.js
|
||||
*
|
||||
* A mechanism for displaying data using custom layout templates and formatting.
|
||||
*
|
||||
* Created by Alexander Yuzhin on 1/24/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* The View uses an template as its internal templating mechanism, and is bound to an
|
||||
* {@link Common.UI.DataViewStore} so that as the data in the store changes the view is automatically updated
|
||||
* to reflect the changes.
|
||||
*
|
||||
* The example below binds a View to a {@link Common.UI.DataViewStore} and renders it into an el.
|
||||
*
|
||||
* new Common.UI.DataView({
|
||||
* el: $('#id'),
|
||||
* store: new Common.UI.DataViewStore([{value: 1, value: 2}]),
|
||||
* itemTemplate: _.template(['<li id="<%= id %>"><a href="#"><%= value %></a></li>'].join(''))
|
||||
* });
|
||||
*
|
||||
*
|
||||
* @property {Object} el
|
||||
* Backbone el
|
||||
*
|
||||
*
|
||||
* @property {Object} store
|
||||
* The Store class encapsulates a client side cache of Model objects.
|
||||
*
|
||||
*
|
||||
* @property {String} emptyText
|
||||
* The text to display in the view when there is no data to display.
|
||||
*
|
||||
*
|
||||
* @cfg {Object} itemTemplate
|
||||
* The inner portion of the item template to be rendered.
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'common/main/lib/component/BaseView',
|
||||
'common/main/lib/component/Scroller'
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
Common.UI.DataViewGroupModel = Backbone.Model.extend({
|
||||
defaults: function() {
|
||||
return {
|
||||
id: Common.UI.getId(),
|
||||
caption: ''
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Common.UI.DataViewGroupStore = Backbone.Collection.extend({
|
||||
model: Common.UI.DataViewGroupModel
|
||||
});
|
||||
|
||||
Common.UI.DataViewModel = Backbone.Model.extend({
|
||||
defaults: function() {
|
||||
return {
|
||||
id: Common.UI.getId(),
|
||||
selected: false,
|
||||
allowSelected: true,
|
||||
value: null
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Common.UI.DataViewStore = Backbone.Collection.extend({
|
||||
model: Common.UI.DataViewModel
|
||||
});
|
||||
|
||||
Common.UI.DataViewItem = Common.UI.BaseView.extend({
|
||||
options : {
|
||||
},
|
||||
|
||||
template: _.template([
|
||||
'<div id="<%= id %>"><%= value %></div>'
|
||||
].join('')),
|
||||
|
||||
initialize : function(options) {
|
||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
||||
|
||||
var me = this;
|
||||
|
||||
me.template = me.options.template || me.template;
|
||||
|
||||
me.listenTo(me.model, 'change', me.render);
|
||||
me.listenTo(me.model, 'change:selected', me.onSelectChange);
|
||||
me.listenTo(me.model, 'remove', me.remove);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
if (_.isUndefined(this.model.id))
|
||||
return this;
|
||||
|
||||
var el = $(this.el);
|
||||
|
||||
el.html(this.template(this.model.toJSON()));
|
||||
el.addClass('item');
|
||||
el.toggleClass('selected', this.model.get('selected') && this.model.get('allowSelected'));
|
||||
el.off('click').on('click', _.bind(this.onClick, this));
|
||||
el.off('dblclick').on('dblclick', _.bind(this.onDblClick, this));
|
||||
el.off('contextmenu').on('contextmenu', _.bind(this.onContextMenu, this));
|
||||
|
||||
if (!_.isUndefined(this.model.get('cls')))
|
||||
el.addClass(this.model.get('cls'));
|
||||
|
||||
this.trigger('change', this, this.model);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
remove: function() {
|
||||
this.stopListening(this.model);
|
||||
this.trigger('remove', this, this.model);
|
||||
|
||||
Common.UI.BaseView.prototype.remove.call(this);
|
||||
},
|
||||
|
||||
onClick: function(e) {
|
||||
this.trigger('click', this, this.model, e);
|
||||
},
|
||||
|
||||
onDblClick: function(e) {
|
||||
this.trigger('dblclick', this, this.model, e);
|
||||
},
|
||||
|
||||
onContextMenu: function(e) {
|
||||
this.trigger('contextmenu', this, this.model, e);
|
||||
},
|
||||
|
||||
onSelectChange: function(model, selected) {
|
||||
this.trigger('select', this, model, selected);
|
||||
}
|
||||
});
|
||||
|
||||
Common.UI.DataView = Common.UI.BaseView.extend({
|
||||
options : {
|
||||
multiSelect: false,
|
||||
handleSelect: true,
|
||||
enableKeyEvents: true,
|
||||
keyMoveDirection: 'both', // 'vertical', 'horizontal'
|
||||
restoreHeight: 0,
|
||||
emptyText: '',
|
||||
listenStoreEvents: true,
|
||||
allowScrollbar: true,
|
||||
showLast: true,
|
||||
useBSKeydown: false
|
||||
},
|
||||
|
||||
template: _.template([
|
||||
'<div class="dataview inner" style="<%= style %>">',
|
||||
'<% _.each(groups, function(group) { %>',
|
||||
'<div class="grouped-data" id="<%= group.id %>">',
|
||||
'<div class="group-description">',
|
||||
'<span><b><%= group.caption %></b></span>',
|
||||
'</div>',
|
||||
'<div class="group-items-container">',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'<% }); %>',
|
||||
'</div>'
|
||||
].join('')),
|
||||
|
||||
initialize : function(options) {
|
||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
||||
|
||||
var me = this;
|
||||
|
||||
me.template = me.options.template || me.template;
|
||||
me.store = me.options.store || new Common.UI.DataViewStore();
|
||||
me.groups = me.options.groups || null;
|
||||
me.itemTemplate = me.options.itemTemplate || null;
|
||||
me.multiSelect = me.options.multiSelect;
|
||||
me.handleSelect = me.options.handleSelect;
|
||||
me.parentMenu = me.options.parentMenu;
|
||||
me.enableKeyEvents= me.options.enableKeyEvents;
|
||||
me.useBSKeydown = me.options.useBSKeydown; // only with enableKeyEvents && parentMenu
|
||||
me.showLast = me.options.showLast;
|
||||
me.style = me.options.style || '';
|
||||
me.emptyText = me.options.emptyText || '';
|
||||
me.listenStoreEvents= (me.options.listenStoreEvents!==undefined) ? me.options.listenStoreEvents : true;
|
||||
me.allowScrollbar = (me.options.allowScrollbar!==undefined) ? me.options.allowScrollbar : true;
|
||||
me.rendered = false;
|
||||
me.dataViewItems = [];
|
||||
if (me.options.keyMoveDirection=='vertical')
|
||||
me.moveKeys = [Common.UI.Keys.UP, Common.UI.Keys.DOWN];
|
||||
else if (me.options.keyMoveDirection=='horizontal')
|
||||
me.moveKeys = [Common.UI.Keys.LEFT, Common.UI.Keys.RIGHT];
|
||||
else
|
||||
me.moveKeys = [Common.UI.Keys.UP, Common.UI.Keys.DOWN, Common.UI.Keys.LEFT, Common.UI.Keys.RIGHT];
|
||||
|
||||
if (me.options.el)
|
||||
me.render();
|
||||
},
|
||||
|
||||
render: function (parentEl) {
|
||||
var me = this;
|
||||
|
||||
this.trigger('render:before', this);
|
||||
|
||||
this.cmpEl = $(this.el);
|
||||
if (parentEl) {
|
||||
this.setElement(parentEl, false);
|
||||
this.cmpEl = $(this.template({
|
||||
groups: me.groups ? me.groups.toJSON() : null,
|
||||
style: me.style
|
||||
}));
|
||||
|
||||
parentEl.html(this.cmpEl);
|
||||
} else {
|
||||
this.cmpEl.html(this.template({
|
||||
groups: me.groups ? me.groups.toJSON() : null,
|
||||
style: me.style
|
||||
}));
|
||||
}
|
||||
|
||||
if (!this.rendered) {
|
||||
if (this.listenStoreEvents) {
|
||||
this.listenTo(this.store, 'add', this.onAddItem);
|
||||
this.listenTo(this.store, 'reset', this.onResetItems);
|
||||
}
|
||||
this.onResetItems();
|
||||
|
||||
if (this.parentMenu) {
|
||||
this.cmpEl.closest('li').css('height', '100%');
|
||||
this.cmpEl.css('height', '100%');
|
||||
this.parentMenu.on('show:after', _.bind(this.alignPosition, this));
|
||||
}
|
||||
|
||||
if (this.enableKeyEvents && this.parentMenu && this.handleSelect) {
|
||||
if (!me.showLast)
|
||||
this.parentMenu.on('show:before', function(menu) { me.deselectAll(); });
|
||||
this.parentMenu.on('show:after', function(menu) {
|
||||
if (me.showLast) me.showLastSelected();
|
||||
Common.NotificationCenter.trigger('dataview:focus');
|
||||
_.delay(function() {
|
||||
menu.cmpEl.find('.dataview').focus();
|
||||
}, 10);
|
||||
}).on('hide:after', function() {
|
||||
Common.NotificationCenter.trigger('dataview:blur');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (_.isUndefined(this.scroller) && this.allowScrollbar) {
|
||||
this.scroller = new Common.UI.Scroller({
|
||||
el: $(this.el).find('.inner').andSelf().filter('.inner'),
|
||||
useKeyboard: this.enableKeyEvents && !this.handleSelect,
|
||||
minScrollbarLength : 40,
|
||||
wheelSpeed: 10
|
||||
});
|
||||
}
|
||||
|
||||
var modalParents = this.cmpEl.closest('.asc-window');
|
||||
if (modalParents.length > 0) {
|
||||
this.tipZIndex = parseInt(modalParents.css('z-index')) + 10;
|
||||
}
|
||||
|
||||
this.rendered = true;
|
||||
|
||||
this.cmpEl.on('click', function(e){
|
||||
if (/dataview/.test(e.target.className)) return false;
|
||||
});
|
||||
|
||||
this.trigger('render:after', this);
|
||||
return this;
|
||||
},
|
||||
|
||||
setStore: function(store) {
|
||||
if (store) {
|
||||
this.stopListening(this.store);
|
||||
|
||||
this.store = store;
|
||||
|
||||
if (this.listenStoreEvents) {
|
||||
this.listenTo(this.store, 'add', this.onAddItem);
|
||||
this.listenTo(this.store, 'reset', this.onResetItems);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
selectRecord: function(record, suspendEvents) {
|
||||
if (!this.handleSelect)
|
||||
return;
|
||||
|
||||
if (suspendEvents)
|
||||
this.suspendEvents();
|
||||
|
||||
if (!this.multiSelect) {
|
||||
_.each(this.store.where({selected: true}), function(rec){
|
||||
rec.set({selected: false});
|
||||
});
|
||||
|
||||
if (record)
|
||||
record.set({selected: true});
|
||||
} else {
|
||||
if (record)
|
||||
record.set({selected: !record.get('selected')});
|
||||
}
|
||||
|
||||
if (suspendEvents)
|
||||
this.resumeEvents();
|
||||
},
|
||||
|
||||
selectByIndex: function(index, suspendEvents) {
|
||||
if (this.store.length > 0 && index > -1 && index < this.store.length) {
|
||||
this.selectRecord(this.store.at(index), suspendEvents);
|
||||
}
|
||||
},
|
||||
|
||||
deselectAll: function(suspendEvents) {
|
||||
if (suspendEvents)
|
||||
this.suspendEvents();
|
||||
|
||||
_.each(this.store.where({selected: true}), function(record){
|
||||
record.set({selected: false});
|
||||
});
|
||||
|
||||
if (suspendEvents)
|
||||
this.resumeEvents();
|
||||
},
|
||||
|
||||
getSelectedRec: function() {
|
||||
if (this.multiSelect) {
|
||||
|
||||
var items = [];
|
||||
_.each(this.store.where({selected: true}), function(rec){
|
||||
items.push(rec);
|
||||
});
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
return this.store.where({selected: true});
|
||||
},
|
||||
|
||||
onAddItem: function(record, index, opts) {
|
||||
var view = new Common.UI.DataViewItem({
|
||||
template: this.itemTemplate,
|
||||
model: record
|
||||
});
|
||||
|
||||
if (view) {
|
||||
var innerEl = $(this.el).find('.inner').andSelf().filter('.inner');
|
||||
|
||||
if (this.groups && this.groups.length > 0) {
|
||||
var group = this.groups.findWhere({id: record.get('group')});
|
||||
|
||||
if (group) {
|
||||
innerEl = innerEl.find('#' + group.id + ' ' + '.group-items-container');
|
||||
}
|
||||
}
|
||||
|
||||
if (innerEl) {
|
||||
if (opts && opts.at == 0)
|
||||
innerEl.prepend(view.render().el); else
|
||||
innerEl.append(view.render().el);
|
||||
|
||||
innerEl.find('.empty-text').remove();
|
||||
this.dataViewItems.push(view);
|
||||
|
||||
if (record.get('tip')) {
|
||||
var view_el = $(view.el);
|
||||
view_el.attr('data-toggle', 'tooltip');
|
||||
view_el.tooltip({
|
||||
title : record.get('tip'),
|
||||
placement : 'cursor',
|
||||
zIndex : this.tipZIndex
|
||||
});
|
||||
}
|
||||
|
||||
this.listenTo(view, 'change', this.onChangeItem);
|
||||
this.listenTo(view, 'remove', this.onRemoveItem);
|
||||
this.listenTo(view, 'click', this.onClickItem);
|
||||
this.listenTo(view, 'dblclick', this.onDblClickItem);
|
||||
this.listenTo(view, 'select', this.onSelectItem);
|
||||
this.listenTo(view, 'contextmenu', this.onContextMenuItem);
|
||||
|
||||
if (!this.isSuspendEvents)
|
||||
this.trigger('item:add', this, view, record);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onResetItems: function() {
|
||||
_.each(this.dataViewItems, function(item) {
|
||||
var tip = item.$el.data('bs.tooltip');
|
||||
if (tip) (tip.tip()).remove();
|
||||
}, this);
|
||||
|
||||
$(this.el).html(this.template({
|
||||
groups: this.groups ? this.groups.toJSON() : null,
|
||||
style: this.style
|
||||
}));
|
||||
|
||||
if (!_.isUndefined(this.scroller)) {
|
||||
this.scroller.destroy();
|
||||
delete this.scroller;
|
||||
}
|
||||
|
||||
if (this.store.length < 1 && this.emptyText.length > 0)
|
||||
$(this.el).find('.inner').andSelf().filter('.inner').append('<table cellpadding="10" class="empty-text"><tr><td>' + this.emptyText + '</td></tr></table>');
|
||||
|
||||
_.each(this.dataViewItems, function(item) {
|
||||
this.stopListening(item);
|
||||
item.stopListening(item.model);
|
||||
}, this);
|
||||
this.dataViewItems = [];
|
||||
|
||||
this.store.each(this.onAddItem, this);
|
||||
|
||||
if (this.allowScrollbar) {
|
||||
this.scroller = new Common.UI.Scroller({
|
||||
el: $(this.el).find('.inner').andSelf().filter('.inner'),
|
||||
useKeyboard: this.enableKeyEvents && !this.handleSelect,
|
||||
minScrollbarLength : 40,
|
||||
wheelSpeed: 10
|
||||
});
|
||||
}
|
||||
|
||||
this.attachKeyEvents();
|
||||
this.lastSelectedRec = null;
|
||||
this._layoutParams = undefined;
|
||||
},
|
||||
|
||||
onChangeItem: function(view, record) {
|
||||
if (!this.isSuspendEvents) {
|
||||
this.trigger('item:change', this, view, record);
|
||||
}
|
||||
},
|
||||
|
||||
onRemoveItem: function(view, record) {
|
||||
this.stopListening(view);
|
||||
view.stopListening();
|
||||
|
||||
if (this.store.length < 1 && this.emptyText.length > 0) {
|
||||
var el = $(this.el).find('.inner').andSelf().filter('.inner');
|
||||
if ( el.find('.empty-text').length<=0 )
|
||||
el.append('<table cellpadding="10" class="empty-text"><tr><td>' + this.emptyText + '</td></tr></table>');
|
||||
}
|
||||
|
||||
for (var i=0; i < this.dataViewItems.length; i++) {
|
||||
if (_.isEqual(view, this.dataViewItems[i]) ) {
|
||||
this.dataViewItems.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.isSuspendEvents) {
|
||||
this.trigger('item:remove', this, view, record);
|
||||
}
|
||||
},
|
||||
|
||||
onClickItem: function(view, record, e) {
|
||||
if ( this.disabled ) return;
|
||||
|
||||
window._event = e; // for FireFox only
|
||||
|
||||
if (this.showLast) this.selectRecord(record);
|
||||
this.lastSelectedRec = null;
|
||||
|
||||
var tip = view.$el.data('bs.tooltip');
|
||||
if (tip) (tip.tip()).remove();
|
||||
|
||||
if (!this.isSuspendEvents) {
|
||||
this.trigger('item:click', this, view, record, e);
|
||||
}
|
||||
},
|
||||
|
||||
onDblClickItem: function(view, record, e) {
|
||||
if ( this.disabled ) return;
|
||||
|
||||
window._event = e; // for FireFox only
|
||||
|
||||
this.selectRecord(record);
|
||||
this.lastSelectedRec = null;
|
||||
|
||||
if (!this.isSuspendEvents) {
|
||||
this.trigger('item:dblclick', this, view, record, e);
|
||||
}
|
||||
},
|
||||
|
||||
onSelectItem: function(view, record, selected) {
|
||||
if (!this.isSuspendEvents) {
|
||||
this.trigger(selected ? 'item:select' : 'item:deselect', this, view, record, this._fromKeyDown);
|
||||
}
|
||||
},
|
||||
|
||||
onContextMenuItem: function(view, record, e) {
|
||||
if (!this.isSuspendEvents) {
|
||||
this.trigger('item:contextmenu', this, view, record, e);
|
||||
}
|
||||
},
|
||||
|
||||
scrollToRecord: function (record) {
|
||||
var innerEl = $(this.el).find('.inner'),
|
||||
inner_top = innerEl.offset().top,
|
||||
idx = _.indexOf(this.store.models, record),
|
||||
div = (idx>=0) ? $(this.dataViewItems[idx].el) : innerEl.find('#' + record.get('id'));
|
||||
if (div.length<=0) return;
|
||||
|
||||
var div_top = div.offset().top;
|
||||
if (div_top < inner_top || div_top+div.outerHeight() > inner_top + innerEl.height()) {
|
||||
if (this.scroller && this.allowScrollbar) {
|
||||
this.scroller.scrollTop(innerEl.scrollTop() + div_top - inner_top, 0);
|
||||
} else {
|
||||
innerEl.scrollTop(innerEl.scrollTop() + div_top - inner_top);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onKeyDown: function (e, data) {
|
||||
if ( this.disabled ) return;
|
||||
if (data===undefined) data = e;
|
||||
if (_.indexOf(this.moveKeys, data.keyCode)>-1 || data.keyCode==Common.UI.Keys.RETURN) {
|
||||
data.preventDefault();
|
||||
data.stopPropagation();
|
||||
var rec = this.getSelectedRec()[0];
|
||||
if (this.lastSelectedRec===null)
|
||||
this.lastSelectedRec = rec;
|
||||
if (data.keyCode==Common.UI.Keys.RETURN) {
|
||||
this.lastSelectedRec = null;
|
||||
if (this.selectedBeforeHideRec) // only for ComboDataView menuPicker
|
||||
rec = this.selectedBeforeHideRec;
|
||||
this.trigger('item:click', this, this, rec, e);
|
||||
this.trigger('item:select', this, this, rec, e);
|
||||
this.trigger('entervalue', this, rec, e);
|
||||
if (this.parentMenu)
|
||||
this.parentMenu.hide();
|
||||
} else {
|
||||
var idx = _.indexOf(this.store.models, rec);
|
||||
if (idx<0) {
|
||||
if (data.keyCode==Common.UI.Keys.LEFT) {
|
||||
var target = $(e.target).closest('.dropdown-submenu.over');
|
||||
if (target.length>0) {
|
||||
target.removeClass('over');
|
||||
target.find('> a').focus();
|
||||
} else
|
||||
idx = 0;
|
||||
} else
|
||||
idx = 0;
|
||||
} else if (this.options.keyMoveDirection == 'both') {
|
||||
if (this._layoutParams === undefined)
|
||||
this.fillIndexesArray();
|
||||
var topIdx = this.dataViewItems[idx].topIdx,
|
||||
leftIdx = this.dataViewItems[idx].leftIdx;
|
||||
|
||||
idx = undefined;
|
||||
if (data.keyCode==Common.UI.Keys.LEFT) {
|
||||
while (idx===undefined) {
|
||||
leftIdx--;
|
||||
if (leftIdx<0) {
|
||||
var target = $(e.target).closest('.dropdown-submenu.over');
|
||||
if (target.length>0) {
|
||||
target.removeClass('over');
|
||||
target.find('> a').focus();
|
||||
break;
|
||||
} else
|
||||
leftIdx = this._layoutParams.columns-1;
|
||||
}
|
||||
idx = this._layoutParams.itemsIndexes[topIdx][leftIdx];
|
||||
}
|
||||
} else if (data.keyCode==Common.UI.Keys.RIGHT) {
|
||||
while (idx===undefined) {
|
||||
leftIdx++;
|
||||
if (leftIdx>this._layoutParams.columns-1) leftIdx = 0;
|
||||
idx = this._layoutParams.itemsIndexes[topIdx][leftIdx];
|
||||
}
|
||||
} else if (data.keyCode==Common.UI.Keys.UP) {
|
||||
while (idx===undefined) {
|
||||
topIdx--;
|
||||
if (topIdx<0) topIdx = this._layoutParams.rows-1;
|
||||
idx = this._layoutParams.itemsIndexes[topIdx][leftIdx];
|
||||
}
|
||||
} else {
|
||||
while (idx===undefined) {
|
||||
topIdx++;
|
||||
if (topIdx>this._layoutParams.rows-1) topIdx = 0;
|
||||
idx = this._layoutParams.itemsIndexes[topIdx][leftIdx];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
idx = (data.keyCode==Common.UI.Keys.UP || data.keyCode==Common.UI.Keys.LEFT)
|
||||
? Math.max(0, idx-1)
|
||||
: Math.min(this.store.length - 1, idx + 1) ;
|
||||
}
|
||||
|
||||
if (idx !== undefined && idx>=0) rec = this.store.at(idx);
|
||||
if (rec) {
|
||||
this._fromKeyDown = true;
|
||||
this.selectRecord(rec);
|
||||
this._fromKeyDown = false;
|
||||
this.scrollToRecord(rec);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.trigger('item:keydown', this, rec, e);
|
||||
}
|
||||
},
|
||||
|
||||
attachKeyEvents: function() {
|
||||
if (this.enableKeyEvents && this.handleSelect) {
|
||||
var el = $(this.el).find('.inner').andSelf().filter('.inner');
|
||||
el.addClass('canfocused');
|
||||
el.attr('tabindex', '0');
|
||||
el.on((this.parentMenu && this.useBSKeydown) ? 'dataview:keydown' : 'keydown', _.bind(this.onKeyDown, this));
|
||||
}
|
||||
},
|
||||
|
||||
showLastSelected: function() {
|
||||
if ( this.lastSelectedRec) {
|
||||
this.selectRecord(this.lastSelectedRec, true);
|
||||
this.scrollToRecord(this.lastSelectedRec);
|
||||
this.lastSelectedRec = null;
|
||||
} else {
|
||||
var rec = this.getSelectedRec()[0];
|
||||
if (rec) this.scrollToRecord(rec);
|
||||
}
|
||||
},
|
||||
|
||||
setDisabled: function(disabled) {
|
||||
this.disabled = disabled;
|
||||
$(this.el).find('.inner').andSelf().filter('.inner').toggleClass('disabled', disabled);
|
||||
},
|
||||
|
||||
isDisabled: function() {
|
||||
return this.disabled;
|
||||
},
|
||||
|
||||
setEmptyText: function(emptyText) {
|
||||
this.emptyText = emptyText;
|
||||
},
|
||||
|
||||
alignPosition: function() {
|
||||
var menuRoot = (this.parentMenu.cmpEl.attr('role') === 'menu')
|
||||
? this.parentMenu.cmpEl
|
||||
: this.parentMenu.cmpEl.find('[role=menu]'),
|
||||
innerEl = $(this.el).find('.inner').andSelf().filter('.inner'),
|
||||
docH = $(document).height(),
|
||||
menuH = menuRoot.outerHeight(),
|
||||
top = parseInt(menuRoot.css('top'));
|
||||
|
||||
if (menuH > docH) {
|
||||
innerEl.css('max-height', (docH - parseInt(menuRoot.css('padding-top')) - parseInt(menuRoot.css('padding-bottom'))-5) + 'px');
|
||||
if (this.allowScrollbar) this.scroller.update({minScrollbarLength : 40});
|
||||
} else if ( innerEl.height() < this.options.restoreHeight ) {
|
||||
innerEl.css('max-height', (Math.min(docH - parseInt(menuRoot.css('padding-top')) - parseInt(menuRoot.css('padding-bottom'))-5, this.options.restoreHeight)) + 'px');
|
||||
menuH = menuRoot.outerHeight();
|
||||
if (top+menuH > docH) {
|
||||
menuRoot.css('top', 0);
|
||||
}
|
||||
if (this.allowScrollbar) this.scroller.update({minScrollbarLength : 40});
|
||||
}
|
||||
},
|
||||
|
||||
fillIndexesArray: function() {
|
||||
if (this.dataViewItems.length<=0) return;
|
||||
|
||||
var top, left,
|
||||
el = $(this.dataViewItems[0].el),
|
||||
itemW = el.outerWidth() + parseInt(el.css('margin-left')) + parseInt(el.css('margin-right')),
|
||||
itemH = el.outerHeight() + parseInt(el.css('margin-top')) + parseInt(el.css('margin-bottom')),
|
||||
offsetLeft = this.$el.offset().left,
|
||||
offsetTop = this.$el.offset().top,
|
||||
idxOffset = 0;
|
||||
|
||||
this._layoutParams = {
|
||||
itemsIndexes: [],
|
||||
columns: 0,
|
||||
rows: 0
|
||||
};
|
||||
|
||||
if (this.groups && this.groups.length > 0) {
|
||||
var group_desc = this.cmpEl.find('.group-description:first');
|
||||
if (group_desc.length>0)
|
||||
offsetLeft += group_desc.width();
|
||||
}
|
||||
for (var i=0; i<this.dataViewItems.length; i++) {
|
||||
top = Math.floor(($(this.dataViewItems[i].el).offset().top - offsetTop)/itemH) + idxOffset;
|
||||
left = Math.floor(($(this.dataViewItems[i].el).offset().left - offsetLeft)/itemW);
|
||||
if (top<0) {
|
||||
idxOffset = -top;
|
||||
top += idxOffset;
|
||||
}
|
||||
if (top > this._layoutParams.itemsIndexes.length-1) {
|
||||
this._layoutParams.itemsIndexes.push([]);
|
||||
}
|
||||
this._layoutParams.itemsIndexes[top][left] = i;
|
||||
this.dataViewItems[i].topIdx = top;
|
||||
this.dataViewItems[i].leftIdx = left;
|
||||
if (this._layoutParams.columns<left) this._layoutParams.columns = left;
|
||||
}
|
||||
this._layoutParams.rows = this._layoutParams.itemsIndexes.length;
|
||||
this._layoutParams.columns++;
|
||||
},
|
||||
|
||||
onResize: function() {
|
||||
this._layoutParams = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('keydown.dataview', '[data-toggle=dropdown], [role=menu]', function(e) {
|
||||
if (e.keyCode !== Common.UI.Keys.UP && e.keyCode !== Common.UI.Keys.DOWN && e.keyCode !== Common.UI.Keys.LEFT && e.keyCode !== Common.UI.Keys.RIGHT && e.keyCode !== Common.UI.Keys.RETURN) return;
|
||||
|
||||
_.defer(function(){
|
||||
var target = $(e.target).closest('.dropdown-toggle');
|
||||
if (target.length)
|
||||
target.parent().find('.inner.canfocused').trigger('dataview:keydown', e);
|
||||
else {
|
||||
$(e.target).closest('.dropdown-submenu').find('.inner.canfocused').trigger('dataview:keydown', e);
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
});
|
148
apps/common/main/lib/component/DimensionPicker.js
Normal file
148
apps/common/main/lib/component/DimensionPicker.js
Normal file
|
@ -0,0 +1,148 @@
|
|||
/**
|
||||
* DimensionPicker.js
|
||||
*
|
||||
* Created by Alexander Yuzhin on 1/29/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'common/main/lib/component/BaseView'
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
Common.UI.DimensionPicker = Common.UI.BaseView.extend((function(){
|
||||
var me,
|
||||
rootEl,
|
||||
areaMouseCatcher,
|
||||
areaUnHighLighted,
|
||||
areaHighLighted,
|
||||
areaStatus,
|
||||
curColumns = 0,
|
||||
curRows = 0;
|
||||
|
||||
var onMouseMove = function(event){
|
||||
me.setTableSize(
|
||||
Math.ceil((event.offsetX === undefined ? event.originalEvent.layerX : event.offsetX) / me.itemSize),
|
||||
Math.ceil((event.offsetY === undefined ? event.originalEvent.layerY : event.offsetY) / me.itemSize),
|
||||
event
|
||||
);
|
||||
};
|
||||
|
||||
var onMouseLeave = function(event){
|
||||
me.setTableSize(0, 0, event);
|
||||
};
|
||||
|
||||
var onHighLightedMouseClick = function(e){
|
||||
me.trigger('select', me, curColumns, curRows, e);
|
||||
};
|
||||
|
||||
return {
|
||||
options: {
|
||||
itemSize : 18,
|
||||
minRows : 5,
|
||||
minColumns : 5,
|
||||
maxRows : 20,
|
||||
maxColumns : 20
|
||||
},
|
||||
|
||||
template:_.template([
|
||||
'<div style="width: 100%; height: 100%;">',
|
||||
'<div class="dimension-picker-status">0x0</div>',
|
||||
'<div class="dimension-picker-observecontainer">',
|
||||
'<div class="dimension-picker-mousecatcher"></div>',
|
||||
'<div class="dimension-picker-unhighlighted"></div>',
|
||||
'<div class="dimension-picker-highlighted"></div>',
|
||||
'</div>',
|
||||
'</div>'
|
||||
].join('')),
|
||||
|
||||
initialize : function(options) {
|
||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
||||
|
||||
me = this;
|
||||
|
||||
rootEl = $(this.el);
|
||||
|
||||
me.itemSize = me.options.itemSize;
|
||||
me.minRows = me.options.minRows;
|
||||
me.minColumns = me.options.minColumns;
|
||||
me.maxRows = me.options.maxRows;
|
||||
me.maxColumns = me.options.maxColumns;
|
||||
|
||||
this.render();
|
||||
|
||||
if (rootEl){
|
||||
areaMouseCatcher = rootEl.find('.dimension-picker-mousecatcher');
|
||||
areaUnHighLighted = rootEl.find('.dimension-picker-unhighlighted');
|
||||
areaHighLighted = rootEl.find('.dimension-picker-highlighted');
|
||||
areaStatus = rootEl.find('.dimension-picker-status');
|
||||
|
||||
rootEl.css({width: me.minColumns + 'em'});
|
||||
areaMouseCatcher.css('z-index', 1);
|
||||
areaMouseCatcher.width(me.maxColumns + 'em').height(me.maxRows + 'em');
|
||||
areaUnHighLighted.width(me.minColumns + 'em').height(me.minRows + 'em');
|
||||
areaStatus.html(curColumns + ' x ' + curRows);
|
||||
areaStatus.width(areaUnHighLighted.width());
|
||||
}
|
||||
|
||||
areaMouseCatcher.on('mousemove', onMouseMove);
|
||||
areaHighLighted.on('mousemove', onMouseMove);
|
||||
areaUnHighLighted.on('mousemove', onMouseMove);
|
||||
areaMouseCatcher.on('mouseleave', onMouseLeave);
|
||||
areaHighLighted.on('mouseleave', onMouseLeave);
|
||||
areaUnHighLighted.on('mouseleave', onMouseLeave);
|
||||
areaMouseCatcher.on('click', onHighLightedMouseClick);
|
||||
areaHighLighted.on('click', onHighLightedMouseClick);
|
||||
areaUnHighLighted.on('click', onHighLightedMouseClick);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
$(this.el).html(this.template());
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
setTableSize: function(columns, rows, event){
|
||||
if (columns > this.maxColumns) columns = this.maxColumns;
|
||||
if (rows > this.maxRows) rows = this.maxRows;
|
||||
|
||||
if (curColumns != columns || curRows != rows){
|
||||
curColumns = columns;
|
||||
curRows = rows;
|
||||
|
||||
areaHighLighted.width(curColumns + 'em').height(curRows + 'em');
|
||||
areaUnHighLighted.width(
|
||||
((curColumns < me.minColumns)
|
||||
? me.minColumns
|
||||
: ((curColumns + 1 > me.maxColumns)
|
||||
? me.maxColumns
|
||||
: curColumns + 1)) + 'em'
|
||||
).height(((curRows < me.minRows)
|
||||
? me.minRows
|
||||
: ((curRows + 1 > me.maxRows)
|
||||
? me.maxRows
|
||||
: curRows + 1)) + 'em'
|
||||
);
|
||||
|
||||
rootEl.width(areaUnHighLighted.width());
|
||||
areaStatus.html(curColumns + ' x ' + curRows);
|
||||
areaStatus.width(areaUnHighLighted.width());
|
||||
|
||||
me.trigger('change', me, curColumns, curRows, event);
|
||||
}
|
||||
},
|
||||
|
||||
getColumnsCount: function() {
|
||||
return curColumns;
|
||||
},
|
||||
|
||||
getRowsCount: function() {
|
||||
return curRows;
|
||||
}
|
||||
}
|
||||
})())
|
||||
});
|
258
apps/common/main/lib/component/HSBColorPicker.js
Normal file
258
apps/common/main/lib/component/HSBColorPicker.js
Normal file
|
@ -0,0 +1,258 @@
|
|||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'common/main/lib/component/BaseView',
|
||||
'common/main/lib/util/utils'
|
||||
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
Common.UI.HSBColorPicker = Common.UI.BaseView.extend({
|
||||
|
||||
template :
|
||||
_.template(
|
||||
'<div class="hsb-colorpicker">'+
|
||||
'<% if (this.showCurrentColor) { %>'+
|
||||
'<div class="top-panel">'+
|
||||
'<span class="color-value">'+
|
||||
'<span class="transparent-color img-colorpicker"></span>'+
|
||||
'</span>'+
|
||||
'<div class="color-text"></div>'+
|
||||
'</div>'+
|
||||
'<% } %>'+
|
||||
'<div>'+
|
||||
'<div class="cnt-hb img-colorpicker">'+
|
||||
'<div class="cnt-hb-arrow img-colorpicker"></div>'+
|
||||
'</div>'+
|
||||
'<% if (this.changeSaturation) { %>'+
|
||||
'<div class="cnt-root">'+
|
||||
'<div class="cnt-sat img-colorpicker">'+
|
||||
'<div class="cnt-sat-arrow img-colorpicker"></div>'+
|
||||
'</div>'+
|
||||
'</div>'+
|
||||
'<% } %>'+
|
||||
'</div>'+
|
||||
'<% if (this.allowEmptyColor) { %>'+
|
||||
'<div class="empty-color"><%= this.textNoColor %></div>'+
|
||||
'<% } %>'+
|
||||
'</div>'),
|
||||
|
||||
color: '#ff0000',
|
||||
|
||||
options: {
|
||||
allowEmptyColor: false,
|
||||
changeSaturation: true,
|
||||
showCurrentColor: true
|
||||
},
|
||||
|
||||
initialize : function(options) {
|
||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
||||
|
||||
var me = this,
|
||||
el = $(this.el),
|
||||
arrowSatBrightness, arrowHue,
|
||||
areaSatBrightness, areaHue,
|
||||
previewColor, previewTransparentColor, previewColorText,
|
||||
btnNoColor,
|
||||
hueVal = 0,
|
||||
saturationVal = 100,
|
||||
brightnessVal = 100;
|
||||
|
||||
|
||||
me.allowEmptyColor = me.options.allowEmptyColor;
|
||||
me.changeSaturation = me.options.changeSaturation;
|
||||
me.showCurrentColor = me.options.showCurrentColor;
|
||||
|
||||
|
||||
var onUpdateColor = function(hsb, transparent){
|
||||
var rgbColor = new Common.Utils.RGBColor('hsb(' + hsb.h + ',' + hsb.s + ',' + hsb.b + ')'),
|
||||
hexColor = rgbColor.toHex();
|
||||
|
||||
me.color = transparent ? 'transparent' : hexColor;
|
||||
|
||||
refreshUI();
|
||||
|
||||
me.trigger('changecolor', me, me.color);
|
||||
};
|
||||
|
||||
var refreshUI = function(){
|
||||
if (previewColor.length>0 && previewTransparentColor.length>0){
|
||||
if (me.color == 'transparent'){
|
||||
previewTransparentColor.show();
|
||||
} else {
|
||||
previewColor.css("background-color", me.color);
|
||||
previewTransparentColor.hide();
|
||||
}
|
||||
}
|
||||
|
||||
if (areaSatBrightness.length>0)
|
||||
areaSatBrightness.css('background-color', new Common.Utils.RGBColor('hsb('+hueVal+', 100, 100)').toHex());
|
||||
|
||||
if (previewColorText.length>0)
|
||||
previewColorText[0].innerHTML = (me.color == 'transparent') ? me.textNoColor : me.color.toUpperCase();
|
||||
|
||||
if (arrowSatBrightness.length>0 && arrowHue.length>0) {
|
||||
arrowSatBrightness.css('left', saturationVal + '%');
|
||||
arrowSatBrightness.css('top', 100 - brightnessVal + '%');
|
||||
arrowHue.css('top', parseInt(hueVal * 100 / 360.0) + '%');
|
||||
}
|
||||
};
|
||||
|
||||
var onSBAreaMouseMove = function(event, element, eOpts){
|
||||
if (arrowSatBrightness.length>0 && areaSatBrightness.length>0) {
|
||||
var pos = [
|
||||
Math.max(0, Math.min(100, (parseInt((event.pageX - areaSatBrightness.offset().left) / areaSatBrightness.width() * 100)))),
|
||||
Math.max(0, Math.min(100, (parseInt((event.pageY - areaSatBrightness.offset().top) / areaSatBrightness.height() * 100))))
|
||||
];
|
||||
|
||||
arrowSatBrightness.css('left', pos[0] + '%');
|
||||
arrowSatBrightness.css('top', pos[1] + '%');
|
||||
|
||||
saturationVal = pos[0];
|
||||
brightnessVal = 100 - pos[1];
|
||||
|
||||
onUpdateColor({
|
||||
h: hueVal,
|
||||
s: saturationVal,
|
||||
b: brightnessVal
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var onHueAreaMouseMove = function(event, element, eOpts){
|
||||
if (arrowHue&& areaHue) {
|
||||
var pos = Math.max(0, Math.min(100, (parseInt((event.pageY - areaHue.offset().top) / areaHue.height() * 100))));
|
||||
arrowHue.css('top', pos + '%');
|
||||
|
||||
hueVal = parseInt(360 * pos / 100.0);
|
||||
|
||||
onUpdateColor({
|
||||
h: hueVal,
|
||||
s: saturationVal,
|
||||
b: brightnessVal
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var onSBAreaMouseDown = function(event, element, eOpts){
|
||||
$(document).on('mouseup', onSBAreaMouseUp);
|
||||
$(document).on('mousemove', onSBAreaMouseMove);
|
||||
};
|
||||
|
||||
var onSBAreaMouseUp = function(event, element, eOpts){
|
||||
$(document).off('mouseup', onSBAreaMouseUp);
|
||||
$(document).off('mousemove', onSBAreaMouseMove);
|
||||
onSBAreaMouseMove(event, element, eOpts);
|
||||
};
|
||||
|
||||
var onHueAreaMouseDown = function(event, element, eOpts){
|
||||
$(document).on('mouseup', onHueAreaMouseUp);
|
||||
$(document).on('mousemove', onHueAreaMouseMove);
|
||||
onHueAreaMouseMove(event, element, eOpts);
|
||||
};
|
||||
|
||||
var onHueAreaMouseUp = function(event, element, eOpts){
|
||||
$(document).off('mouseup', onHueAreaMouseUp);
|
||||
$(document).off('mousemove', onHueAreaMouseMove);
|
||||
};
|
||||
|
||||
var onNoColorClick = function(cnt){
|
||||
var hsbColor = new Common.util.RGBColor(me.color).toHSB();
|
||||
|
||||
onUpdateColor(hsbColor, true);
|
||||
};
|
||||
|
||||
var onAfterRender = function(ct){
|
||||
var rootEl = $(me.el),
|
||||
hsbColor;
|
||||
|
||||
if (rootEl){
|
||||
arrowSatBrightness = rootEl.find('.cnt-hb-arrow');
|
||||
arrowHue = rootEl.find('.cnt-sat-arrow');
|
||||
areaSatBrightness = rootEl.find('.cnt-hb');
|
||||
areaHue = rootEl.find('.cnt-sat');
|
||||
previewColor = rootEl.find('.color-value');
|
||||
previewColorText = rootEl.find('.color-text');
|
||||
btnNoColor = rootEl.find('.empty-color');
|
||||
|
||||
if (previewColor.length>0){
|
||||
previewTransparentColor = previewColor.find('.transparent-color');
|
||||
}
|
||||
|
||||
if (areaSatBrightness.length>0) {
|
||||
areaSatBrightness.off('mousedown');
|
||||
areaSatBrightness.on('mousedown', onSBAreaMouseDown);
|
||||
}
|
||||
|
||||
if (areaHue.length>0) {
|
||||
areaHue.off('mousedown');
|
||||
areaHue.on('mousedown', onHueAreaMouseDown);
|
||||
}
|
||||
|
||||
if (btnNoColor.length>0) {
|
||||
btnNoColor.off('click');
|
||||
btnNoColor.on('click', onNoColorClick);
|
||||
}
|
||||
|
||||
if (me.color == 'transparent')
|
||||
hsbColor = {h: 0, s: 100, b: 100};
|
||||
else
|
||||
hsbColor = new Common.Utils.RGBColor(me.color).toHSB();
|
||||
|
||||
hueVal = hsbColor.h;
|
||||
saturationVal = hsbColor.s;
|
||||
brightnessVal = hsbColor.b;
|
||||
|
||||
if (hueVal == saturationVal &&
|
||||
hueVal == brightnessVal &&
|
||||
hueVal == 0)
|
||||
saturationVal = 100;
|
||||
|
||||
refreshUI();
|
||||
}
|
||||
};
|
||||
|
||||
me.setColor = function(value){
|
||||
if (me.color == value)
|
||||
return;
|
||||
|
||||
var hsbColor;
|
||||
if (value == 'transparent')
|
||||
hsbColor = {h: 0, s: 100, b: 100};
|
||||
else
|
||||
hsbColor = new Common.Utils.RGBColor(value).toHSB();
|
||||
|
||||
hueVal = hsbColor.h;
|
||||
saturationVal = hsbColor.s;
|
||||
brightnessVal = hsbColor.b;
|
||||
|
||||
if (hueVal == saturationVal &&
|
||||
hueVal == brightnessVal &&
|
||||
hueVal == 0)
|
||||
saturationVal = 100;
|
||||
|
||||
me.color = value;
|
||||
|
||||
refreshUI();
|
||||
};
|
||||
|
||||
me.getColor = function(){
|
||||
return me.color;
|
||||
};
|
||||
|
||||
me.on('render:after', onAfterRender);
|
||||
me.render();
|
||||
},
|
||||
|
||||
render: function () {
|
||||
$(this.el).html(this.template());
|
||||
|
||||
this.trigger('render:after', this);
|
||||
return this;
|
||||
},
|
||||
|
||||
textNoColor: 'No Color'
|
||||
|
||||
});
|
||||
});
|
343
apps/common/main/lib/component/InputField.js
Normal file
343
apps/common/main/lib/component/InputField.js
Normal file
|
@ -0,0 +1,343 @@
|
|||
/**
|
||||
* InputField.js
|
||||
*
|
||||
* Created by Alexander Yuzhin on 4/10/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Using template
|
||||
*
|
||||
* <div class="input-field">
|
||||
* <input type="text" name="range" class="form-control"><span class="input-error"/>
|
||||
* </div>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'common/main/lib/component/BaseView',
|
||||
'common/main/lib/component/Tooltip'
|
||||
], function () { 'use strict';
|
||||
|
||||
Common.UI.InputField = Common.UI.BaseView.extend((function() {
|
||||
return {
|
||||
options : {
|
||||
id : null,
|
||||
cls : '',
|
||||
style : '',
|
||||
value : '',
|
||||
type : 'text',
|
||||
name : '',
|
||||
validation : null,
|
||||
allowBlank : true,
|
||||
placeHolder : '',
|
||||
blankError : null,
|
||||
spellcheck : false,
|
||||
maskExp : '',
|
||||
validateOnChange: false,
|
||||
validateOnBlur: true,
|
||||
disabled: false
|
||||
},
|
||||
|
||||
template: _.template([
|
||||
'<div class="input-field" style="<%= style %>">',
|
||||
'<input ',
|
||||
'type="<%= type %>" ',
|
||||
'name="<%= name %>" ',
|
||||
'spellcheck="<%= spellcheck %>" ',
|
||||
'class="form-control <%= cls %>" ',
|
||||
'placeholder="<%= placeHolder %>" ',
|
||||
'value="<%= value %>"',
|
||||
'>',
|
||||
'<span class="input-error"/>',
|
||||
'</div>'
|
||||
].join('')),
|
||||
|
||||
initialize : function(options) {
|
||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
||||
|
||||
var me = this,
|
||||
el = $(this.el);
|
||||
|
||||
this.id = me.options.id || Common.UI.getId();
|
||||
this.cls = me.options.cls;
|
||||
this.style = me.options.style;
|
||||
this.value = me.options.value;
|
||||
this.type = me.options.type;
|
||||
this.name = me.options.name;
|
||||
this.validation = me.options.validation;
|
||||
this.allowBlank = me.options.allowBlank;
|
||||
this.placeHolder = me.options.placeHolder;
|
||||
this.template = me.options.template || me.template;
|
||||
this.editable = me.options.editable || true;
|
||||
this.disabled = me.options.disabled;
|
||||
this.spellcheck = me.options.spellcheck;
|
||||
this.blankError = me.options.blankError || 'This field is required';
|
||||
this.validateOnChange = me.options.validateOnChange;
|
||||
this.validateOnBlur = me.options.validateOnBlur;
|
||||
this.maxLength = me.options.maxLength;
|
||||
|
||||
me.rendered = me.options.rendered || false;
|
||||
|
||||
if (me.options.el) {
|
||||
me.render();
|
||||
}
|
||||
},
|
||||
|
||||
render : function(parentEl) {
|
||||
var me = this;
|
||||
|
||||
if (!me.rendered) {
|
||||
this.cmpEl = $(this.template({
|
||||
id : this.id,
|
||||
cls : this.cls,
|
||||
style : this.style,
|
||||
value : this.value,
|
||||
type : this.type,
|
||||
name : this.name,
|
||||
placeHolder : this.placeHolder,
|
||||
spellcheck : this.spellcheck,
|
||||
scope : me
|
||||
}));
|
||||
|
||||
if (parentEl) {
|
||||
this.setElement(parentEl, false);
|
||||
parentEl.html(this.cmpEl);
|
||||
} else {
|
||||
$(this.el).html(this.cmpEl);
|
||||
}
|
||||
} else {
|
||||
this.cmpEl = $(this.el);
|
||||
}
|
||||
|
||||
if (!me.rendered) {
|
||||
var el = this.cmpEl;
|
||||
|
||||
this._input = this.cmpEl.find('input').andSelf().filter('input');
|
||||
|
||||
if (this.editable) {
|
||||
this._input.on('blur', _.bind(this.onInputChanged, this));
|
||||
this._input.on('keypress', _.bind(this.onKeyPress, this));
|
||||
this._input.on('keyup', _.bind(this.onKeyUp, this));
|
||||
if (this.validateOnChange) this._input.on('input', _.bind(this.onInputChanging, this));
|
||||
if (this.maxLength) this._input.attr('maxlength', this.maxLength);
|
||||
}
|
||||
|
||||
this.setEditable(this.editable);
|
||||
if (this.disabled)
|
||||
this.setDisabled(this.disabled);
|
||||
|
||||
if (this._input.closest('.asc-window').length>0)
|
||||
var onModalClose = function() {
|
||||
var errorTip = el.find('.input-error').data('bs.tooltip');
|
||||
if (errorTip) errorTip.tip().remove();
|
||||
Common.NotificationCenter.off({'modal:close': onModalClose});
|
||||
};
|
||||
Common.NotificationCenter.on({'modal:close': onModalClose});
|
||||
}
|
||||
|
||||
me.rendered = true;
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_doChange: function(e, extra) {
|
||||
// skip processing for internally-generated synthetic event
|
||||
// to avoid double processing
|
||||
if (extra && extra.synthetic)
|
||||
return;
|
||||
|
||||
var newValue = $(e.target).val(),
|
||||
oldValue = this.value;
|
||||
|
||||
this.trigger('changed:before', this, newValue, oldValue, e);
|
||||
|
||||
if (e.isDefaultPrevented())
|
||||
return;
|
||||
|
||||
this.value = newValue;
|
||||
if (this.validateOnBlur)
|
||||
this.checkValidate();
|
||||
|
||||
// trigger changed event
|
||||
this.trigger('changed:after', this, newValue, oldValue, e);
|
||||
},
|
||||
|
||||
onInputChanged: function(e, extra) {
|
||||
this._doChange(e, extra);
|
||||
},
|
||||
|
||||
onInputChanging: function(e, extra) {
|
||||
var newValue = $(e.target).val(),
|
||||
oldValue = this.value;
|
||||
|
||||
if (e.isDefaultPrevented())
|
||||
return;
|
||||
|
||||
this.value = newValue;
|
||||
if (this.validateOnBlur)
|
||||
this.checkValidate();
|
||||
|
||||
// trigger changing event
|
||||
this.trigger('changing', this, newValue, oldValue, e);
|
||||
},
|
||||
|
||||
onKeyPress: function(e) {
|
||||
this.trigger('keypress:before', this, e);
|
||||
|
||||
if (e.isDefaultPrevented())
|
||||
return;
|
||||
|
||||
if (e.keyCode === Common.UI.Keys.RETURN) {
|
||||
this._doChange(e);
|
||||
} else if (this.options.maskExp && !_.isEmpty(this.options.maskExp.source)){
|
||||
var charCode = String.fromCharCode(e.which);
|
||||
if(!this.options.maskExp.test(charCode) && !e.ctrlKey && e.keyCode !== Common.UI.Keys.DELETE && e.keyCode !== Common.UI.Keys.BACKSPACE &&
|
||||
e.keyCode !== Common.UI.Keys.LEFT && e.keyCode !== Common.UI.Keys.RIGHT && e.keyCode !== Common.UI.Keys.HOME &&
|
||||
e.keyCode !== Common.UI.Keys.END && e.keyCode !== Common.UI.Keys.ESC && e.keyCode !== Common.UI.Keys.INSERT ){
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
this.trigger('keypress:after', this, e);
|
||||
},
|
||||
|
||||
onKeyUp: function(e) {
|
||||
this.trigger('keyup:before', this, e);
|
||||
|
||||
if (e.isDefaultPrevented())
|
||||
return;
|
||||
|
||||
this.trigger('keyup:after', this, e);
|
||||
},
|
||||
|
||||
setEditable: function(editable) {
|
||||
var input = this._input;
|
||||
|
||||
this.editable = editable;
|
||||
|
||||
if (editable && input) {
|
||||
input.removeAttr('readonly');
|
||||
input.removeAttr('data-can-copy');
|
||||
} else {
|
||||
input.attr('readonly', 'readonly');
|
||||
input.attr('data-can-copy', false);
|
||||
}
|
||||
},
|
||||
|
||||
isEditable: function() {
|
||||
return this.editable;
|
||||
},
|
||||
|
||||
setDisabled: function(disabled) {
|
||||
this.disabled = disabled;
|
||||
$(this.el).toggleClass('disabled', disabled);
|
||||
disabled
|
||||
? this._input.attr('disabled', true)
|
||||
: this._input.removeAttr('disabled');
|
||||
},
|
||||
|
||||
isDisabled: function() {
|
||||
return this.disabled;
|
||||
},
|
||||
|
||||
setValue: function(value) {
|
||||
this.value = value;
|
||||
|
||||
if (this.rendered){
|
||||
this._input.val(value);
|
||||
}
|
||||
},
|
||||
|
||||
getValue: function() {
|
||||
return this.value;
|
||||
},
|
||||
|
||||
focus: function() {
|
||||
this._input.focus();
|
||||
},
|
||||
|
||||
checkValidate: function() {
|
||||
var me = this,
|
||||
errors = [];
|
||||
|
||||
if (!me.allowBlank && _.isEmpty(me.value)) {
|
||||
errors.push(me.blankError);
|
||||
}
|
||||
|
||||
if (_.isFunction(me.validation)) {
|
||||
var res = me.validation.call(me, me.value);
|
||||
|
||||
if (res !== true) {
|
||||
errors = _.flatten(errors.concat(res));
|
||||
}
|
||||
}
|
||||
|
||||
if (!_.isEmpty(errors)) {
|
||||
if (me.cmpEl.hasClass('error')) {
|
||||
var errorTip = me.cmpEl.find('.input-error').data('bs.tooltip');
|
||||
if (errorTip) {
|
||||
errorTip.options.title = errors.join('\n');
|
||||
errorTip.setContent();
|
||||
}
|
||||
return errors;
|
||||
} else {
|
||||
me.cmpEl.addClass('error');
|
||||
|
||||
var errorBadge = me.cmpEl.find('.input-error'),
|
||||
modalParents = errorBadge.closest('.asc-window'),
|
||||
errorTip = errorBadge.data('bs.tooltip');
|
||||
|
||||
if (errorTip) errorTip.tip().remove();
|
||||
errorBadge.attr('data-toggle', 'tooltip');
|
||||
errorBadge.removeData('bs.tooltip');
|
||||
errorBadge.tooltip({
|
||||
title : errors.join('\n'),
|
||||
placement : 'cursor'
|
||||
});
|
||||
if (modalParents.length > 0) {
|
||||
errorBadge.data('bs.tooltip').tip().css('z-index', parseInt(modalParents.css('z-index')) + 10);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
} else {
|
||||
me.cmpEl.removeClass('error');
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
showError: function(errors) {
|
||||
var me = this;
|
||||
if (!_.isEmpty(errors)) {
|
||||
me.cmpEl.addClass('error');
|
||||
|
||||
var errorBadge = me.cmpEl.find('.input-error'),
|
||||
modalParents = errorBadge.closest('.asc-window'),
|
||||
errorTip = errorBadge.data('bs.tooltip');
|
||||
|
||||
if (errorTip) errorTip.tip().remove();
|
||||
errorBadge.attr('data-toggle', 'tooltip');
|
||||
errorBadge.removeData('bs.tooltip');
|
||||
errorBadge.tooltip({
|
||||
title : errors.join('\n'),
|
||||
placement : 'cursor'
|
||||
});
|
||||
|
||||
if (modalParents.length > 0) {
|
||||
errorBadge.data('bs.tooltip').tip().css('z-index', parseInt(modalParents.css('z-index')) + 10);
|
||||
}
|
||||
} else {
|
||||
me.cmpEl.removeClass('error');
|
||||
}
|
||||
}
|
||||
}
|
||||
})());
|
||||
});
|
474
apps/common/main/lib/component/Layout.js
Normal file
474
apps/common/main/lib/component/Layout.js
Normal file
|
@ -0,0 +1,474 @@
|
|||
/**
|
||||
* Layout.js
|
||||
*
|
||||
* Created by Maxim Kadushkin on 10 February 2014
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Configuration
|
||||
* -------------
|
||||
*
|
||||
* @selector layout-ct
|
||||
* css class selector for the layout container
|
||||
*
|
||||
* @selector layout-item
|
||||
* css class selector for the layout item
|
||||
*
|
||||
*
|
||||
* @cfg {Object} box
|
||||
* Contains the layout container object
|
||||
*
|
||||
* @cfg {Boolean} stretch
|
||||
* If true, layout item will be stretched to all parent's space free from the static items
|
||||
*
|
||||
* @cfg {Boolean} rely
|
||||
* If true, @width and @height will correspond to DOMElement.width() and DOMElement.height()
|
||||
* If @stretch is true, @rely will be ignored.
|
||||
*
|
||||
* @cfg {Boolean} resizable
|
||||
* reserved
|
||||
*
|
||||
* @cfg {Integer} width
|
||||
* @cfg {Integer} height
|
||||
* Describe static size for the layout item.
|
||||
* For VBoxLayout:
|
||||
* @width = 100%,
|
||||
* @height = DOMElement.height() if rely = true
|
||||
*
|
||||
* For HBoxLayout:
|
||||
* @height = 100%,
|
||||
* @width = DOMElement.width() if rely = true
|
||||
*
|
||||
* If @stretch is true, @width and @height will be ignored.
|
||||
*
|
||||
*
|
||||
* Methods
|
||||
* -------
|
||||
*
|
||||
* @method doLayout
|
||||
* Makes rearrangement of the layout items
|
||||
*
|
||||
*
|
||||
* Example of usage
|
||||
* ----------------
|
||||
*
|
||||
* var $container = $('#hbox-layout');
|
||||
* items = $container.find(' > .layout-item');
|
||||
* var hLayout = new Common.UI.HBoxLayout({
|
||||
* box: $container,
|
||||
* items: [
|
||||
* {el: items[0]},
|
||||
* {el: items[1], stretch: true},
|
||||
* {el: items[2], rely: true}
|
||||
* ]
|
||||
* });
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'backbone'
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
var BaseLayout = function(options) {
|
||||
this.box = null;
|
||||
this.panels = [];
|
||||
this.splitters = [];
|
||||
|
||||
_.extend(this, options || {});
|
||||
};
|
||||
|
||||
var LayoutPanel = function() {
|
||||
return {
|
||||
width : null,
|
||||
height : null,
|
||||
resize : false,
|
||||
stretch : false,
|
||||
rely : false
|
||||
}
|
||||
};
|
||||
|
||||
_.extend(BaseLayout.prototype, Backbone.Events, {
|
||||
initialize: function(options) {
|
||||
this.$parent = this.box.parent();
|
||||
|
||||
this.resize = {
|
||||
eventMove: _.bind(this.resizeMove, this),
|
||||
eventStop: _.bind(this.resizeStop, this)
|
||||
};
|
||||
|
||||
var panel, resizer, stretch = false;
|
||||
options.items.forEach(function(item) {
|
||||
item.el instanceof HTMLElement && (item.el = $(item.el));
|
||||
panel = _.extend(new LayoutPanel(), item);
|
||||
if ( panel.stretch ) {
|
||||
stretch = true;
|
||||
panel.rely = false;
|
||||
panel.resize = false;
|
||||
}
|
||||
|
||||
this.panels.push(panel);
|
||||
|
||||
if (panel.resize) {
|
||||
resizer = {
|
||||
isresizer : true,
|
||||
minpos : panel.resize.min||0,
|
||||
maxpos : panel.resize.max||0,
|
||||
fmin : panel.resize.fmin,
|
||||
fmax : panel.resize.fmax,
|
||||
behaviour : panel.behaviour,
|
||||
index : this.splitters.length
|
||||
};
|
||||
|
||||
if (!stretch) {
|
||||
panel.resize.el =
|
||||
resizer.el = panel.el.after('<div class="layout-resizer after"></div>').next();
|
||||
this.panels.push(resizer);
|
||||
} else {
|
||||
panel.resize.el =
|
||||
resizer.el = panel.el.before('<div class="layout-resizer before"></div>').prev();
|
||||
this.panels.splice(this.panels.length - 1, 0, resizer);
|
||||
}
|
||||
|
||||
this.splitters.push({resizer:resizer});
|
||||
|
||||
panel.resize.hidden && resizer.el.hide();
|
||||
}
|
||||
}, this);
|
||||
|
||||
this.freeze = options.freeze; this.freeze && this.freezePanels(this.freeze);
|
||||
},
|
||||
|
||||
doLayout: function() {
|
||||
},
|
||||
|
||||
getElementHeight: function(el) {
|
||||
return parseInt(el.css('height'));
|
||||
},
|
||||
|
||||
getElementWidth: function(el) {
|
||||
return parseInt(el.css('width'));
|
||||
},
|
||||
|
||||
onSelectStart: function(e) {
|
||||
if (e.preventDefault) e.preventDefault();
|
||||
return false;
|
||||
},
|
||||
|
||||
addHandler: function(elem, type, handler) {
|
||||
if (elem.addEventListener) {
|
||||
elem.addEventListener(type, handler);
|
||||
} else
|
||||
if (elem.attachEvent) {
|
||||
elem.attachEvent('on' + type, handler);
|
||||
} else {
|
||||
elem['on' + type] = handler;
|
||||
}
|
||||
},
|
||||
|
||||
removeHandler: function(elem, type, handler) {
|
||||
if (elem.removeEventListener) {
|
||||
elem.removeEventListener(type, handler);
|
||||
} else
|
||||
if (elem.detachEvent) {
|
||||
elem.detachEvent('on' + type, handler);
|
||||
} else {
|
||||
elem['on' + type] = null;
|
||||
}
|
||||
},
|
||||
|
||||
clearSelection: function() {
|
||||
if (window.getSelection) {
|
||||
var selection = window.getSelection();
|
||||
if (selection.empty) selection.empty(); else
|
||||
if (selection.removeAllRanges) selection.removeAllRanges();
|
||||
} else if (document.selection) {
|
||||
document.selection.empty();
|
||||
}
|
||||
},
|
||||
|
||||
resizeStart: function(e) {
|
||||
this.clearSelection();
|
||||
this.addHandler(window.document, 'selectstart', this.onSelectStart);
|
||||
|
||||
$(document).on({
|
||||
mousemove : this.resize.eventMove,
|
||||
mouseup : this.resize.eventStop
|
||||
});
|
||||
|
||||
var panel = e.data.panel;
|
||||
this.resize.type = e.data.type;
|
||||
this.resize.$el = panel.el;
|
||||
this.resize.min = panel.minpos;
|
||||
this.resize.fmin = panel.fmin;
|
||||
this.resize.fmax = panel.fmax;
|
||||
this.resize.behaviour = panel.behaviour;
|
||||
|
||||
this.resize.$el.addClass('move');
|
||||
|
||||
if (e.data.type == 'vertical') {
|
||||
this.resize.height = parseInt(this.resize.$el.css('height'));
|
||||
this.resize.max = (panel.maxpos > 0 ? panel.maxpos : this.resize.$el.parent().height() + panel.maxpos) - this.resize.height;
|
||||
this.resize.inity = e.pageY - parseInt(e.currentTarget.style.top);
|
||||
} else
|
||||
if (e.data.type == 'horizontal') {
|
||||
this.resize.width = parseInt(this.resize.$el.css('width'));
|
||||
this.resize.max = (panel.maxpos > 0 ? panel.maxpos : this.resize.$el.parent().height() + panel.maxpos) - this.resize.width;
|
||||
this.resize.initx = e.pageX - parseInt(e.currentTarget.style.left);
|
||||
}
|
||||
},
|
||||
|
||||
resizeMove: function(e) {
|
||||
if (this.resize.type == 'vertical') {
|
||||
var prop = 'top',
|
||||
value = e.pageY - this.resize.inity;
|
||||
} else
|
||||
if (this.resize.type == 'horizontal') {
|
||||
prop = 'left';
|
||||
value = e.pageX - this.resize.initx;
|
||||
}
|
||||
|
||||
if (this.resize.fmin && this.resize.fmax) {
|
||||
if (!(value < this.resize.fmin()) && !(value > this.resize.fmax())) {
|
||||
this.resize.$el[0].style[prop] = value + 'px';
|
||||
}
|
||||
} else {
|
||||
|
||||
if (!(value < this.resize.min) && !(value > this.resize.max)) {
|
||||
this.resize.$el[0].style[prop] = value + 'px';
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
resizeStop: function(e) {
|
||||
this.removeHandler(window.document, 'selectstart', this.onSelectStart);
|
||||
|
||||
$(document).off({
|
||||
mousemove : this.resize.eventMove,
|
||||
mouseup : this.resize.eventStop
|
||||
});
|
||||
|
||||
if (this.resize.type == 'vertical') {
|
||||
var prop = 'height';
|
||||
var value = e.pageY - this.resize.inity;
|
||||
} else
|
||||
if (this.resize.type == 'horizontal') {
|
||||
prop = 'width';
|
||||
value = e.pageX - this.resize.initx;
|
||||
}
|
||||
|
||||
if (this.resize.fmin && this.resize.fmax) {
|
||||
value < this.resize.fmin() && (value = this.resize.fmin());
|
||||
value > this.resize.fmax() && (value = this.resize.fmax());
|
||||
} else {
|
||||
value < this.resize.min && (value = this.resize.min);
|
||||
value > this.resize.max && (value = this.resize.max);
|
||||
}
|
||||
|
||||
var panel = null, next = null, oldValue = 0;
|
||||
|
||||
if (this.resize.$el.hasClass('after')) {
|
||||
panel = this.resize.$el.prev();
|
||||
next = this.resize.$el.next();
|
||||
oldValue = parseInt(panel.css(prop));
|
||||
} else {
|
||||
panel = this.resize.$el.next();
|
||||
next = this.resize.$el.next();
|
||||
oldValue = parseInt(panel.css(prop));
|
||||
value = panel.parent()[prop]() - (value + this.resize[prop]);
|
||||
}
|
||||
|
||||
if (this.resize.type == 'vertical')
|
||||
value -= panel.position().top;
|
||||
if (this.resize.type == 'horizontal')
|
||||
value -= panel.position().left;
|
||||
|
||||
panel.css(prop, value + 'px');
|
||||
|
||||
if (this.resize.behaviour) {
|
||||
next.css(prop, parseInt(next.css(prop)) - (value - oldValue));
|
||||
}
|
||||
|
||||
this.resize.$el.removeClass('move');
|
||||
delete this.resize.$el;
|
||||
|
||||
if (this.resize.value != value) {
|
||||
this.doLayout();
|
||||
this.trigger('layout:resizedrag', this);
|
||||
}
|
||||
},
|
||||
|
||||
freezePanels: function (value) {
|
||||
|
||||
this.panels.forEach( function (panel) {
|
||||
|
||||
if (!panel.stretch && panel.resize) {
|
||||
$(panel.resize.el).css('cursor', value ? 'default' : '');
|
||||
}
|
||||
});
|
||||
|
||||
this.freeze = value;
|
||||
},
|
||||
|
||||
setResizeValue: function (index, value) {
|
||||
if (index >= this.splitters.length)
|
||||
return;
|
||||
|
||||
var panel = null, next = null, oldValue = 0,
|
||||
resize = this.splitters[index].resizer,
|
||||
prop = 'height';
|
||||
|
||||
value < resize.fmin() && (value = resize.fmin());
|
||||
value > resize.fmax() && (value = resize.fmax());
|
||||
|
||||
|
||||
if (resize.el.hasClass('after')) {
|
||||
panel = resize.el.prev();
|
||||
next = resize.el.next();
|
||||
oldValue = parseInt(panel.css(prop));
|
||||
} else {
|
||||
panel = resize.el.next();
|
||||
value = panel.parent()[prop]() - (value + resize[prop]);
|
||||
next = resize.el.next();
|
||||
oldValue = parseInt(panel.css(prop));
|
||||
}
|
||||
|
||||
// if (resize.type == 'vertical')
|
||||
value -= panel.position().top;
|
||||
// if (resize.type == 'horizontal')
|
||||
// value -= panel.position().left;
|
||||
|
||||
panel.css(prop, value + 'px');
|
||||
|
||||
if (resize.behaviour) {
|
||||
next.css(prop, parseInt(next.css(prop)) - (value - oldValue));
|
||||
}
|
||||
|
||||
if (resize.value != value) {
|
||||
this.doLayout();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
!Common.UI && (Common.UI = {});
|
||||
|
||||
Common.UI.VBoxLayout = function(options) {
|
||||
BaseLayout.apply(this, arguments);
|
||||
this.initialize.apply(this, arguments);
|
||||
};
|
||||
|
||||
Common.UI.VBoxLayout.prototype = _.extend(new BaseLayout(), {
|
||||
initialize: function(options){
|
||||
BaseLayout.prototype.initialize.call(this,options);
|
||||
|
||||
this.panels.forEach(function(panel){
|
||||
!panel.stretch && !panel.height && (panel.height = this.getElementHeight(panel.el));
|
||||
|
||||
if (panel.isresizer) {
|
||||
panel.el.on('mousedown', {type: 'vertical', panel: panel}, _.bind(this.resizeStart, this));
|
||||
}
|
||||
}, this);
|
||||
|
||||
this.doLayout.call(this);
|
||||
},
|
||||
|
||||
doLayout: function() {
|
||||
var height = 0, stretchable, style;
|
||||
this.panels.forEach(function(panel){
|
||||
if ( !panel.stretch ) {
|
||||
style = panel.el.is(':visible');
|
||||
if ( style ) {
|
||||
height += (panel.rely!==true ? panel.height : this.getElementHeight(panel.el));
|
||||
}
|
||||
|
||||
if (panel.resize && panel.resize.autohide !== false && panel.resize.el) {
|
||||
if (style) {
|
||||
panel.resize.el.show();
|
||||
stretchable && (height += panel.resize.height);
|
||||
} else {
|
||||
panel.resize.el.hide();
|
||||
stretchable && (height -= panel.resize.height);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
stretchable = panel;
|
||||
}
|
||||
}, this);
|
||||
|
||||
stretchable && (stretchable.height = this.$parent.height() - height);
|
||||
|
||||
height = 0;
|
||||
this.panels.forEach(function(panel){
|
||||
if (panel.el.is(':visible')) {
|
||||
style = {top: height};
|
||||
panel.rely!==true && (style.height = panel.height);
|
||||
panel.el.css(style);
|
||||
height += this.getElementHeight(panel.el);
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
});
|
||||
|
||||
Common.UI.HBoxLayout = function(options) {
|
||||
BaseLayout.apply(this, arguments);
|
||||
this.initialize.apply(this, arguments);
|
||||
};
|
||||
|
||||
Common.UI.HBoxLayout.prototype = _.extend(new BaseLayout(), {
|
||||
initialize: function(options){
|
||||
BaseLayout.prototype.initialize.call(this,options);
|
||||
|
||||
this.panels.forEach(function(panel){
|
||||
!panel.stretch && !panel.width && (panel.width = this.getElementWidth(panel.el));
|
||||
|
||||
if (panel.isresizer) {
|
||||
panel.el.on('mousedown', {type: 'horizontal', panel: panel}, _.bind(this.resizeStart, this));
|
||||
}
|
||||
}, this);
|
||||
|
||||
this.doLayout.call(this);
|
||||
},
|
||||
|
||||
doLayout: function(event) {
|
||||
var width = 0, stretchable, style;
|
||||
this.panels.forEach(function(panel){
|
||||
if ( !panel.stretch ) {
|
||||
style = panel.el.is(':visible');
|
||||
if ( style ) {
|
||||
width += (panel.rely!==true ? panel.width : this.getElementWidth(panel.el));
|
||||
}
|
||||
|
||||
if (panel.resize && panel.resize.autohide !== false && panel.resize.el) {
|
||||
if (style) {
|
||||
panel.resize.el.show();
|
||||
stretchable && (width -= panel.resize.width);
|
||||
} else {
|
||||
panel.resize.el.hide();
|
||||
stretchable && (width -= panel.resize.width);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
stretchable = panel;
|
||||
}
|
||||
}, this);
|
||||
|
||||
stretchable && (stretchable.width = this.$parent.width() - width);
|
||||
|
||||
width = 0;
|
||||
this.panels.forEach(function(panel){
|
||||
if (panel.el.is(':visible')) {
|
||||
style = {left: width};
|
||||
panel.rely!==true && (style.width = panel.width);
|
||||
panel.el.css(style);
|
||||
width += this.getElementWidth(panel.el);
|
||||
}
|
||||
},this);
|
||||
}
|
||||
});
|
||||
|
||||
Common.UI.VBoxLayout.prototype.constructor = Common.UI.VBoxLayout;
|
||||
Common.UI.HBoxLayout.prototype.constructor = Common.UI.HBoxLayout;
|
||||
});
|
74
apps/common/main/lib/component/ListView.js
Normal file
74
apps/common/main/lib/component/ListView.js
Normal file
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* ListView.js
|
||||
*
|
||||
* Created by Julia Radzhabova on 2/27/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'common/main/lib/component/DataView'
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
Common.UI.ListView = Common.UI.DataView.extend((function() {
|
||||
return {
|
||||
options: {
|
||||
handleSelect: true,
|
||||
enableKeyEvents: true,
|
||||
showLast: true,
|
||||
simpleAddMode: false,
|
||||
keyMoveDirection: 'vertical',
|
||||
itemTemplate: _.template('<div id="<%= id %>" class="list-item" style=""><%= value %></div>')
|
||||
},
|
||||
|
||||
template: _.template([
|
||||
'<div class="listview inner"></div>'
|
||||
].join('')),
|
||||
|
||||
onResetItems : function() {
|
||||
this.innerEl = null;
|
||||
Common.UI.DataView.prototype.onResetItems.call(this);
|
||||
},
|
||||
|
||||
onAddItem: function(record, index) {
|
||||
var view = new Common.UI.DataViewItem({
|
||||
template: this.itemTemplate,
|
||||
model: record
|
||||
});
|
||||
|
||||
if (!this.innerEl) {
|
||||
this.innerEl = $(this.el).find('.inner');
|
||||
this.innerEl.find('.empty-text').remove();
|
||||
}
|
||||
if (view && this.innerEl) {
|
||||
if (this.options.simpleAddMode) {
|
||||
this.innerEl.append(view.render().el)
|
||||
} else {
|
||||
var idx = _.indexOf(this.store.models, record);
|
||||
var innerDivs = this.innerEl.find('> div');
|
||||
|
||||
if (idx > 0)
|
||||
$(innerDivs.get(idx - 1)).after(view.render().el);
|
||||
else {
|
||||
(innerDivs.length > 0) ? $(innerDivs[idx]).before(view.render().el) : this.innerEl.append(view.render().el);
|
||||
}
|
||||
|
||||
}
|
||||
this.dataViewItems.push(view);
|
||||
this.listenTo(view, 'change', this.onChangeItem);
|
||||
this.listenTo(view, 'remove', this.onRemoveItem);
|
||||
this.listenTo(view, 'click', this.onClickItem);
|
||||
this.listenTo(view, 'dblclick',this.onDblClickItem);
|
||||
this.listenTo(view, 'select', this.onSelectItem);
|
||||
|
||||
if (!this.isSuspendEvents)
|
||||
this.trigger('item:add', this, view, record);
|
||||
}
|
||||
}
|
||||
}
|
||||
})());
|
||||
});
|
131
apps/common/main/lib/component/LoadMask.js
Normal file
131
apps/common/main/lib/component/LoadMask.js
Normal file
|
@ -0,0 +1,131 @@
|
|||
/**
|
||||
* LoadMask.js
|
||||
*
|
||||
* Displays loading mask over selected element(s) or component. Accepts both single and multiple selectors.
|
||||
*
|
||||
* Created by Alexander Yuzhin on 2/7/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @example
|
||||
* new Common.UI.LoadMask({
|
||||
* owner: $('#viewport')
|
||||
* });
|
||||
*
|
||||
* @property {Object} owner
|
||||
*
|
||||
* Component or selector that will be masked.
|
||||
*
|
||||
*
|
||||
* @property {String} title
|
||||
*
|
||||
* @property {String} cls
|
||||
*
|
||||
* @property {String} style
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'common/main/lib/component/BaseView'
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
Common.UI.LoadMask = Common.UI.BaseView.extend((function() {
|
||||
var ownerEl,
|
||||
maskeEl,
|
||||
loaderEl;
|
||||
|
||||
return {
|
||||
options : {
|
||||
cls : '',
|
||||
style : '',
|
||||
title : 'Loading...',
|
||||
owner : document.body
|
||||
},
|
||||
|
||||
template: _.template([
|
||||
'<div id="<%= id %>" class="asc-loadmask-body <%= cls %>" role="presentation" tabindex="-1">',
|
||||
'<div class="asc-loadmask-image"></div>',
|
||||
'<div class="asc-loadmask-title"><%= title %></div>',
|
||||
'</div>'
|
||||
].join('')),
|
||||
|
||||
initialize : function(options) {
|
||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
||||
|
||||
this.template = this.options.template || this.template;
|
||||
this.cls = this.options.cls;
|
||||
this.style = this.options.style;
|
||||
this.title = this.options.title;
|
||||
this.owner = this.options.owner;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return this;
|
||||
},
|
||||
|
||||
show: function(){
|
||||
if (maskeEl || loaderEl)
|
||||
return;
|
||||
|
||||
ownerEl = (this.owner instanceof Common.UI.BaseView) ? $(this.owner.el) : $(this.owner);
|
||||
|
||||
// The owner is already masked
|
||||
if (ownerEl.hasClass('masked'))
|
||||
return this;
|
||||
|
||||
var me = this;
|
||||
|
||||
maskeEl = $('<div class="asc-loadmask"></div>');
|
||||
loaderEl = $(this.template({
|
||||
id : me.id,
|
||||
cls : me.cls,
|
||||
style : me.style,
|
||||
title : me.title
|
||||
}));
|
||||
|
||||
ownerEl.addClass('masked');
|
||||
ownerEl.append(maskeEl);
|
||||
ownerEl.append(loaderEl);
|
||||
|
||||
loaderEl.css({
|
||||
top : Math.round(ownerEl.height() / 2 - (loaderEl.height() + parseInt(loaderEl.css('padding-top')) + parseInt(loaderEl.css('padding-bottom'))) / 2) + 'px',
|
||||
left: Math.round(ownerEl.width() / 2 - (loaderEl.width() + parseInt(loaderEl.css('padding-left')) + parseInt(loaderEl.css('padding-right'))) / 2) + 'px'
|
||||
|
||||
});
|
||||
|
||||
Common.util.Shortcuts.suspendEvents();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
ownerEl && ownerEl.removeClass('masked');
|
||||
maskeEl && maskeEl.remove();
|
||||
loaderEl && loaderEl.remove();
|
||||
maskeEl = null;
|
||||
loaderEl = null;
|
||||
Common.util.Shortcuts.resumeEvents();
|
||||
},
|
||||
|
||||
setTitle: function(title) {
|
||||
this.title = title;
|
||||
|
||||
if (ownerEl && ownerEl.hasClass('masked') && loaderEl){
|
||||
$('.asc-loadmask-title', loaderEl).html(title);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
isVisible: function() {
|
||||
return !_.isEmpty(loaderEl);
|
||||
}
|
||||
}
|
||||
})())
|
||||
});
|
||||
|
56
apps/common/main/lib/component/MaskedField.js
Normal file
56
apps/common/main/lib/component/MaskedField.js
Normal file
|
@ -0,0 +1,56 @@
|
|||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'common/main/lib/component/BaseView'
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
Common.UI.MaskedField = Common.UI.BaseView.extend({
|
||||
options : {
|
||||
maskExp: '',
|
||||
maxLength: 999
|
||||
},
|
||||
|
||||
initialize : function(options) {
|
||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
||||
|
||||
var me = this,
|
||||
el = $(this.el);
|
||||
|
||||
el.addClass('masked-field user-select');
|
||||
el.attr('maxlength', me.options.maxLength);
|
||||
el.on('keypress', function(e) {
|
||||
var charCode = String.fromCharCode(e.which);
|
||||
if(!me.options.maskExp.test(charCode) && !e.ctrlKey && e.keyCode !== Common.UI.Keys.DELETE && e.keyCode !== Common.UI.Keys.BACKSPACE &&
|
||||
e.keyCode !== Common.UI.Keys.LEFT && e.keyCode !== Common.UI.Keys.RIGHT && e.keyCode !== Common.UI.Keys.HOME &&
|
||||
e.keyCode !== Common.UI.Keys.END && e.keyCode !== Common.UI.Keys.ESC && e.keyCode !== Common.UI.Keys.INSERT &&
|
||||
e.keyCode !== Common.UI.Keys.TAB /* || el.val().length>=me.options.maxLength*/){
|
||||
if (e.keyCode==Common.UI.Keys.RETURN) me.trigger('changed', me, el.val());
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
});
|
||||
el.on('input', function(e) {
|
||||
me.trigger('change', me, el.val());
|
||||
});
|
||||
el.on('blur', function(e) {
|
||||
me.trigger('changed', me, el.val());
|
||||
});
|
||||
},
|
||||
|
||||
render : function() {
|
||||
return this;
|
||||
},
|
||||
|
||||
setValue: function(value) {
|
||||
if (this.options.maskExp.test(value) && value.length<=this.options.maxLength)
|
||||
$(this.el).val(value);
|
||||
},
|
||||
|
||||
getValue: function() {
|
||||
$(this.el).val();
|
||||
}
|
||||
});
|
||||
});
|
545
apps/common/main/lib/component/Menu.js
Normal file
545
apps/common/main/lib/component/Menu.js
Normal file
|
@ -0,0 +1,545 @@
|
|||
/**
|
||||
* Menu.js
|
||||
*
|
||||
* A menu object. This is the container to which you may add {@link Common.UI.MenuItem menu items}.
|
||||
*
|
||||
* Created by Alexander Yuzhin on 1/28/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Default template
|
||||
*
|
||||
* <ul class="dropdown-menu" role="menu">
|
||||
* <li><a href="#">item 1</a></li>-->
|
||||
* <li><a href="#">item 2</a></li>-->
|
||||
* <li class="divider"></li>-->
|
||||
* <li><a href="#">item 3</a></li>
|
||||
* </ul>
|
||||
*
|
||||
* A useful classes of menu position
|
||||
*
|
||||
* - `'pull-right'` using for layout menu by right side of a parent
|
||||
*
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* new Common.UI.Menu({
|
||||
* items: [
|
||||
* { caption: 'item 1', value: 1 },
|
||||
* { caption: 'item 1', value: 2 },
|
||||
* { caption: '--' },
|
||||
* { caption: 'item 1', value: 3 },
|
||||
* ]
|
||||
* })
|
||||
*
|
||||
* @property {Object} itemTemplate
|
||||
*
|
||||
* Default template for items
|
||||
*
|
||||
*
|
||||
* @property {Array} items
|
||||
*
|
||||
* Arrow of the {Common.UI.MenuItem} menu items
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'common/main/lib/extend/Bootstrap',
|
||||
'common/main/lib/component/BaseView',
|
||||
'common/main/lib/component/MenuItem',
|
||||
'common/main/lib/component/Scroller'
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
Common.UI.Menu = (function(){
|
||||
var manager = (function(){
|
||||
var active = [],
|
||||
menus = {};
|
||||
|
||||
return {
|
||||
register: function(menu) {
|
||||
menus[menu.id] = menu;
|
||||
menu
|
||||
.on('show:after', function(m) {
|
||||
active.push(m);
|
||||
})
|
||||
.on('hide:after', function(m) {
|
||||
var index = active.indexOf(m);
|
||||
|
||||
if (index > -1)
|
||||
active.splice(index, 1);
|
||||
});
|
||||
},
|
||||
|
||||
unregister: function(menu) {
|
||||
var index = active.indexOf(menu);
|
||||
|
||||
delete menus[menu.id];
|
||||
|
||||
if (index > -1)
|
||||
active.splice(index, 1);
|
||||
|
||||
menu.off('show:after').off('hide:after');
|
||||
},
|
||||
|
||||
hideAll: function() {
|
||||
Common.NotificationCenter.trigger('menumanager:hideall');
|
||||
|
||||
if (active && active.length > 0) {
|
||||
_.each(active, function(menu) {
|
||||
menu.hide();
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
return _.extend(Common.UI.BaseView.extend({
|
||||
options : {
|
||||
cls : '',
|
||||
style : '',
|
||||
itemTemplate: null,
|
||||
items : [],
|
||||
menuAlign : 'tl-bl',
|
||||
menuAlignEl : null,
|
||||
offset : [0, 0],
|
||||
cyclic : true
|
||||
},
|
||||
|
||||
template: _.template([
|
||||
'<ul class="dropdown-menu <%= options.cls %>" style="<%= options.style %>" role="menu"></ul>'
|
||||
].join('')),
|
||||
|
||||
initialize : function(options) {
|
||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
||||
|
||||
var me = this;
|
||||
|
||||
this.id = this.options.id || Common.UI.getId();
|
||||
this.itemTemplate = this.options.itemTemplate || Common.UI.MenuItem.prototype.template;
|
||||
this.rendered = false;
|
||||
this.items = [];
|
||||
this.offset = [0, 0];
|
||||
this.menuAlign = this.options.menuAlign;
|
||||
this.menuAlignEl = this.options.menuAlignEl;
|
||||
|
||||
if (!this.options.cyclic) this.options.cls += ' no-cyclic';
|
||||
|
||||
_.each(this.options.items, function(item) {
|
||||
if (item instanceof Common.UI.MenuItem) {
|
||||
me.items.push(item)
|
||||
} else {
|
||||
me.items.push(
|
||||
new Common.UI.MenuItem(_.extend({
|
||||
tagName : 'li',
|
||||
template: me.itemTemplate
|
||||
}, item))
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
if (this.options.el)
|
||||
this.render();
|
||||
|
||||
manager.register(this);
|
||||
},
|
||||
|
||||
remove: function() {
|
||||
manager.unregister(this);
|
||||
Common.UI.BaseView.prototype.remove.call(this);
|
||||
},
|
||||
|
||||
render: function(parentEl) {
|
||||
var me = this;
|
||||
|
||||
this.trigger('render:before', this);
|
||||
|
||||
this.cmpEl = $(this.el);
|
||||
|
||||
if (parentEl) {
|
||||
this.setElement(parentEl, false);
|
||||
|
||||
if (!me.rendered) {
|
||||
this.cmpEl = $(this.template({
|
||||
options : me.options
|
||||
}));
|
||||
|
||||
parentEl.append(this.cmpEl);
|
||||
}
|
||||
} else {
|
||||
if (!me.rendered) {
|
||||
this.cmpEl = this.template({
|
||||
options : me.options
|
||||
});
|
||||
$(this.el).append(this.cmpEl);
|
||||
}
|
||||
}
|
||||
|
||||
var rootEl = this.cmpEl.parent(),
|
||||
menuRoot = (rootEl.attr('role') === 'menu') ? rootEl : rootEl.find('[role=menu]');
|
||||
|
||||
if (menuRoot) {
|
||||
if (!me.rendered) {
|
||||
_.each(me.items || [], function(item) {
|
||||
menuRoot.append(item.render().el);
|
||||
|
||||
item.on('click', _.bind(me.onItemClick, me));
|
||||
item.on('toggle', _.bind(me.onItemToggle, me));
|
||||
});
|
||||
}
|
||||
|
||||
menuRoot.css({
|
||||
'max-height': me.options.maxHeight||'none',
|
||||
position : 'fixed',
|
||||
right : 'auto',
|
||||
left : -1000,
|
||||
top : -1000
|
||||
});
|
||||
|
||||
this.parentEl = menuRoot.parent();
|
||||
|
||||
this.parentEl.on('show.bs.dropdown', _.bind(me.onBeforeShowMenu, me));
|
||||
this.parentEl.on('shown.bs.dropdown', _.bind(me.onAfterShowMenu, me));
|
||||
this.parentEl.on('hide.bs.dropdown', _.bind(me.onBeforeHideMenu, me));
|
||||
this.parentEl.on('hidden.bs.dropdown', _.bind(me.onAfterHideMenu, me));
|
||||
this.parentEl.on('keydown.after.bs.dropdown', _.bind(me.onAfterKeydownMenu, me));
|
||||
menuRoot.on('scroll', _.bind(me.onScroll, me));
|
||||
|
||||
menuRoot.hover(
|
||||
function(e) { me.isOver = true;},
|
||||
function(e) { me.isOver = false; }
|
||||
);
|
||||
}
|
||||
|
||||
this.rendered = true;
|
||||
|
||||
this.trigger('render:after', this);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
isVisible: function() {
|
||||
return this.rendered && (this.cmpEl.is(':visible'));
|
||||
},
|
||||
|
||||
show: function() {
|
||||
if (this.rendered && this.parentEl && !this.parentEl.hasClass('open')) {
|
||||
this.cmpEl.dropdown('toggle');
|
||||
}
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
if (this.rendered && this.parentEl) {
|
||||
if ( this.parentEl.hasClass('open') )
|
||||
this.cmpEl.dropdown('toggle');
|
||||
else if (this.parentEl.hasClass('over'))
|
||||
this.parentEl.removeClass('over');
|
||||
}
|
||||
},
|
||||
|
||||
insertItem: function(index, item) {
|
||||
var me = this,
|
||||
el = this.cmpEl;
|
||||
|
||||
if (!(item instanceof Common.UI.MenuItem)) {
|
||||
item = new Common.UI.MenuItem(_.extend({
|
||||
tagName : 'li',
|
||||
template: me.itemTemplate
|
||||
}, item));
|
||||
}
|
||||
|
||||
if (index < 0 || index >= me.items.length)
|
||||
me.items.push(item);
|
||||
else
|
||||
me.items.splice(index, 0, item);
|
||||
|
||||
if (this.rendered) {
|
||||
var menuRoot = (el.attr('role') === 'menu')
|
||||
? el
|
||||
: el.find('[role=menu]');
|
||||
|
||||
if (menuRoot) {
|
||||
if (index < 0) {
|
||||
menuRoot.append(item.render().el);
|
||||
} else if (index === 0) {
|
||||
menuRoot.prepend(item.render().el);
|
||||
} else {
|
||||
$('li:nth-child(' + (index+1) + ')', menuRoot).before(item.render().el);
|
||||
}
|
||||
|
||||
item.on('click', _.bind(me.onItemClick, me));
|
||||
item.on('toggle', _.bind(me.onItemToggle, me));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
doLayout: function() {
|
||||
if (this.options.maxHeight > 0) {
|
||||
if (!this.rendered) {
|
||||
this.mustLayout = true;
|
||||
return;
|
||||
}
|
||||
|
||||
var me = this,
|
||||
el = this.cmpEl;
|
||||
|
||||
var menuRoot = (el.attr('role') === 'menu') ? el : el.find('[role=menu]');
|
||||
|
||||
if (!menuRoot.is(':visible')) {
|
||||
var pos = [menuRoot.css('left'), menuRoot.css('top')];
|
||||
menuRoot.css({
|
||||
left : '-1000px',
|
||||
top : '-1000px',
|
||||
display : 'block'
|
||||
});
|
||||
}
|
||||
|
||||
var $items = menuRoot.find('li');
|
||||
|
||||
if ($items.height() * $items.length > this.options.maxHeight) {
|
||||
var scroll = '<div class="menu-scroll top"></div>';
|
||||
menuRoot.prepend(scroll);
|
||||
|
||||
scroll = '<div class="menu-scroll bottom"></div>';
|
||||
menuRoot.append(scroll);
|
||||
|
||||
menuRoot.css({
|
||||
'box-shadow' : 'none',
|
||||
'overflow-y' : 'hidden',
|
||||
'padding-top' : '18px'
|
||||
// 'padding-bottom' : '18px'
|
||||
});
|
||||
|
||||
menuRoot.find('> li:last-of-type').css('margin-bottom',18);
|
||||
|
||||
var addEvent = function( elem, type, fn ) {
|
||||
elem.addEventListener ? elem.addEventListener( type, fn, false ) : elem.attachEvent( "on" + type, fn );
|
||||
};
|
||||
|
||||
var eventname=(/Firefox/i.test(navigator.userAgent))? 'DOMMouseScroll' : 'mousewheel';
|
||||
addEvent(menuRoot[0], eventname, _.bind(this.onMouseWheel,this));
|
||||
menuRoot.find('.menu-scroll').on('click', _.bind(this.onScrollClick, this));
|
||||
}
|
||||
|
||||
if (pos) {
|
||||
menuRoot.css({
|
||||
display : '',
|
||||
left : pos[0],
|
||||
top : pos[1]
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
addItem: function(item) {
|
||||
this.insertItem(-1, item);
|
||||
},
|
||||
|
||||
removeItem: function(item) {
|
||||
var me = this,
|
||||
index = me.items.indexOf(item);
|
||||
|
||||
if (index > -1) {
|
||||
me.items.splice(index, 1);
|
||||
|
||||
item.off('click').off('toggle');
|
||||
item.remove();
|
||||
}
|
||||
},
|
||||
|
||||
removeItems: function(from, len) {
|
||||
if (from > this.items.length-1) return;
|
||||
if (from+len>this.items.length) len = this.items.length - from;
|
||||
|
||||
for (var i=from; i<from+len; i++) {
|
||||
this.items[i].off('click').off('toggle');
|
||||
this.items[i].remove();
|
||||
}
|
||||
this.items.splice(from, len);
|
||||
},
|
||||
|
||||
removeAll: function() {
|
||||
var me = this;
|
||||
|
||||
_.each(me.items, function(item){
|
||||
item.off('click').off('toggle');
|
||||
item.remove();
|
||||
});
|
||||
|
||||
me.items = [];
|
||||
},
|
||||
|
||||
onBeforeShowMenu: function(e) {
|
||||
if (this.mustLayout) {
|
||||
delete this.mustLayout;
|
||||
this.doLayout.call(this);
|
||||
}
|
||||
|
||||
this.trigger('show:before', this, e);
|
||||
this.alignPosition();
|
||||
},
|
||||
|
||||
onAfterShowMenu: function(e) {
|
||||
this.trigger('show:after', this, e);
|
||||
if (this.$el.find('> ul > .menu-scroll').length) {
|
||||
var el = this.$el.find('li .checked')[0];
|
||||
if (el) {
|
||||
var offset = el.offsetTop - this.options.maxHeight / 2;
|
||||
this.scrollMenu(offset < 0 ? 0 : offset);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onBeforeHideMenu: function(e) {
|
||||
this.trigger('hide:before', this, e);
|
||||
|
||||
if (Common.UI.Scroller.isMouseCapture())
|
||||
e.preventDefault();
|
||||
},
|
||||
|
||||
onAfterHideMenu: function(e) {
|
||||
this.trigger('hide:after', this, e);
|
||||
},
|
||||
|
||||
onAfterKeydownMenu: function(e) {
|
||||
if (e.keyCode == Common.UI.Keys.RETURN) {
|
||||
var li = $(e.target).closest('li');
|
||||
if (li.length<=0) li = $(e.target).parent().find('li .dataview');
|
||||
if (li.length>0) li.click();
|
||||
if (!li.hasClass('dropdown-submenu'))
|
||||
Common.UI.Menu.Manager.hideAll();
|
||||
if ( $(e.currentTarget).closest('li').hasClass('dropdown-submenu')) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
} else if (e.keyCode == Common.UI.Keys.UP || e.keyCode == Common.UI.Keys.DOWN) {
|
||||
this.fromKeyDown = true;
|
||||
} else if (e.keyCode == Common.UI.Keys.ESC) {
|
||||
// Common.NotificationCenter.trigger('menu:afterkeydown', e);
|
||||
// return false;
|
||||
}
|
||||
},
|
||||
|
||||
onScroll: function(item, e) {
|
||||
if (this.fromKeyDown) {
|
||||
var menuRoot = (this.cmpEl.attr('role') === 'menu')
|
||||
? this.cmpEl
|
||||
: this.cmpEl.find('[role=menu]');
|
||||
|
||||
menuRoot.find('.menu-scroll.top').css('top', menuRoot.scrollTop() + 'px');
|
||||
menuRoot.find('.menu-scroll.bottom').css('bottom', (-menuRoot.scrollTop()) + 'px');
|
||||
}
|
||||
},
|
||||
|
||||
onItemClick: function(item, e) {
|
||||
if (!item.menu) this.isOver = false;
|
||||
if (item.options.stopPropagation) {
|
||||
e.stopPropagation();
|
||||
var me = this;
|
||||
_.delay(function(){
|
||||
me.$el.parent().parent().find('[data-toggle=dropdown]').focus();
|
||||
}, 10);
|
||||
return;
|
||||
}
|
||||
this.trigger('item:click', this, item, e);
|
||||
},
|
||||
|
||||
onItemToggle: function(item, state, e) {
|
||||
this.trigger('item:toggle', this, item, state, e);
|
||||
},
|
||||
|
||||
onScrollClick: function(e) {
|
||||
this.scrollMenu(/top/.test(e.currentTarget.className));
|
||||
return false;
|
||||
},
|
||||
|
||||
onMouseWheel: function(e) {
|
||||
this.scrollMenu(((e.detail && -e.detail) || e.wheelDelta) > 0);
|
||||
},
|
||||
|
||||
scrollMenu: function(up) {
|
||||
this.fromKeyDown = false;
|
||||
var menuRoot = (this.cmpEl.attr('role') === 'menu')
|
||||
? this.cmpEl
|
||||
: this.cmpEl.find('[role=menu]'),
|
||||
value = typeof(up)==='boolean'
|
||||
? menuRoot.scrollTop() + (up ? -20 : 20)
|
||||
: up;
|
||||
|
||||
menuRoot.scrollTop(value);
|
||||
|
||||
menuRoot.find('.menu-scroll.top').css('top', menuRoot.scrollTop() + 'px');
|
||||
menuRoot.find('.menu-scroll.bottom').css('bottom', (-menuRoot.scrollTop()) + 'px');
|
||||
},
|
||||
|
||||
setOffset: function(offsetX, offsetY) {
|
||||
this.offset[0] = _.isUndefined(offsetX) ? this.offset[0] : offsetX;
|
||||
this.offset[1] = _.isUndefined(offsetY) ? this.offset[1] : offsetY;
|
||||
this.alignPosition();
|
||||
},
|
||||
|
||||
getOffset: function() {
|
||||
return this.offset;
|
||||
},
|
||||
|
||||
alignPosition: function() {
|
||||
var menuRoot = (this.cmpEl.attr('role') === 'menu')
|
||||
? this.cmpEl
|
||||
: this.cmpEl.find('[role=menu]'),
|
||||
menuParent = this.menuAlignEl || menuRoot.parent(),
|
||||
m = this.menuAlign.match(/^([a-z]+)-([a-z]+)/),
|
||||
offset = menuParent.offset(),
|
||||
docW = Math.min($(document).width(), $('body').width()),
|
||||
docH = $(document).height() - 10, // Yep, it's magic number
|
||||
menuW = menuRoot.outerWidth(),
|
||||
menuH = menuRoot.outerHeight(),
|
||||
parentW = menuParent.outerWidth(),
|
||||
parentH = menuParent.outerHeight();
|
||||
|
||||
var posMenu = {
|
||||
'tl': [0, 0],
|
||||
'bl': [0, menuH],
|
||||
'tr': [menuW, 0],
|
||||
'br': [menuW, menuH]
|
||||
};
|
||||
var posParent = {
|
||||
'tl': [0, 0],
|
||||
'tr': [parentW, 0],
|
||||
'bl': [0, parentH],
|
||||
'br': [parentW, parentH]
|
||||
};
|
||||
var left = offset.left - posMenu[m[1]][0] + posParent[m[2]][0] + this.offset[0];
|
||||
var top = offset.top - posMenu[m[1]][1] + posParent[m[2]][1] + this.offset[1];
|
||||
|
||||
if (left + menuW > docW)
|
||||
if (menuParent.is('li.dropdown-submenu')) {
|
||||
left = offset.left - menuW + 2;
|
||||
} else {
|
||||
left = docW - menuW;
|
||||
}
|
||||
|
||||
if (top + menuH > docH)
|
||||
top = docH - menuH;
|
||||
|
||||
if (top < 0)
|
||||
top = 0;
|
||||
|
||||
if (this.options.additionalAlign)
|
||||
this.options.additionalAlign.call(this, menuRoot, left, top);
|
||||
else
|
||||
menuRoot.css({left: left, top: top});
|
||||
}
|
||||
}), {
|
||||
Manager: (function() {
|
||||
return manager;
|
||||
})()
|
||||
})
|
||||
})();
|
||||
});
|
316
apps/common/main/lib/component/MenuItem.js
Normal file
316
apps/common/main/lib/component/MenuItem.js
Normal file
|
@ -0,0 +1,316 @@
|
|||
/**
|
||||
* 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) 2014 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
|
||||
},
|
||||
|
||||
tagName : 'li',
|
||||
|
||||
template: _.template([
|
||||
'<a id="<%= id %>" style="<%= style %>" <% if(options.canFocused) { %> tabindex="-1" type="menuitem" <% }; if(!_.isUndefined(options.stopPropagation)) { %> data-stopPropagation="true" <% }; %> >',
|
||||
'<% 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,
|
||||
el = $(this.el);
|
||||
|
||||
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.rendered = false;
|
||||
|
||||
if (this.menu !== null && !(this.menu instanceof Common.UI.Menu)) {
|
||||
this.menu = new Common.UI.Menu(_.extend({}, me.options.menu));
|
||||
}
|
||||
|
||||
if (me.options.el)
|
||||
this.render();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var me = this,
|
||||
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);
|
||||
|
||||
$(this.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($(this.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('checked', this.checked);
|
||||
if (!_.isEmpty(this.iconCls)) {
|
||||
firstChild.css('background-image', 'none');
|
||||
}
|
||||
}
|
||||
|
||||
if (this.disabled)
|
||||
$(this.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 = $(this.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);
|
||||
},
|
||||
|
||||
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;
|
||||
}
|
||||
},
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Common.UI.MenuItemSeparator = function(options) {
|
||||
options = options || {};
|
||||
options.caption = '--';
|
||||
return new Common.UI.MenuItem(options);
|
||||
};
|
||||
});
|
491
apps/common/main/lib/component/MetricSpinner.js
Normal file
491
apps/common/main/lib/component/MetricSpinner.js
Normal file
|
@ -0,0 +1,491 @@
|
|||
/**
|
||||
* MetricSpinner.js
|
||||
*
|
||||
* Created by Julia Radzhabova on 1/21/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* A text field with a pair of up/down spinner buttons and up/down arrow key event listeners attached for
|
||||
* incrementing/decrementing the value by the {@link #step} value. Provides automatic numeric validation to limit
|
||||
* the value to a range of valid numbers. The range of acceptable number values can be controlled by setting
|
||||
* the {@link #minValue} and {@link #maxValue} configs.
|
||||
*
|
||||
* Example usage:
|
||||
* new Common.UI.MetricSpinner({
|
||||
* el: $('#id'),
|
||||
* minValue : 0,
|
||||
* maxValue : 100,
|
||||
* step : 1,
|
||||
* defaultUnit : 'px',
|
||||
* allowAuto : false,
|
||||
* autoText : 'Auto'
|
||||
* });
|
||||
*
|
||||
*
|
||||
* @property {String} defaultUnit
|
||||
* Name of the unit of measurement. Can be px|em|%|en|ex|pt|in|cm|mm|pc|s|ms.
|
||||
*
|
||||
* defaultUnit: 'px',
|
||||
*
|
||||
* @property {Boolean} allowAuto
|
||||
* True to enable additional field value {@link #autoText}. {@link #autoText} appears when number value of the field
|
||||
* is {@link #minValue} and the user pressed down spinner button or down arrow key.
|
||||
*
|
||||
* allowAuto: false,
|
||||
*
|
||||
* @property {String} autoText
|
||||
* Used when {@link #allowAuto} is true.
|
||||
*
|
||||
* autoText: 'Auto',
|
||||
*
|
||||
* @property {Boolean} disabled
|
||||
* True if this spinner is disabled.
|
||||
*
|
||||
* disabled: false,
|
||||
*
|
||||
* @property {Boolean} hold
|
||||
* If true this spinner fires a mouse down/arrow key down event while the mouse/key is pressed.
|
||||
* The interval between firings depends on {@link #speed} .
|
||||
*
|
||||
* hold: true,
|
||||
*
|
||||
* @property {String} speed
|
||||
* Used when {@link #hold} is true. Can be 'slow', 'medium', 'fast'.
|
||||
*
|
||||
* speed: 'medium',
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'common/main/lib/component/BaseView'
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
Common.UI.MetricSpinner = Common.UI.BaseView.extend({
|
||||
options : {
|
||||
minValue : 0,
|
||||
maxValue : 100,
|
||||
step : 1,
|
||||
defaultUnit : "px",
|
||||
allowAuto : false,
|
||||
autoText : 'Auto',
|
||||
hold : true,
|
||||
speed : 'medium',
|
||||
width : 90,
|
||||
allowDecimal: true
|
||||
},
|
||||
|
||||
disabled : false,
|
||||
value : '0 px',
|
||||
rendered : false,
|
||||
|
||||
template :
|
||||
'<input type="text" class="form-control">' +
|
||||
'<div class="spinner-buttons">' +
|
||||
'<button type="button" class="spinner-up"><i class="img-commonctrl"></i></button>' +
|
||||
'<button type="button" class="spinner-down"><i class="img-commonctrl"></i></button>' +
|
||||
'</div>',
|
||||
|
||||
initialize : function(options) {
|
||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
||||
|
||||
var me = this,
|
||||
el = $(this.el);
|
||||
|
||||
el.addClass('spinner');
|
||||
|
||||
el.on('mousedown', '.spinner-up', _.bind(this.onMouseDown, this, true));
|
||||
el.on('mousedown', '.spinner-down', _.bind(this.onMouseDown, this, false));
|
||||
el.on('mouseup', '.spinner-up', _.bind(this.onMouseUp, this, true));
|
||||
el.on('mouseup', '.spinner-down', _.bind(this.onMouseUp, this, false));
|
||||
el.on('mouseover', '.spinner-up, .spinner-down', _.bind(this.onMouseOver, this));
|
||||
el.on('mouseout', '.spinner-up, .spinner-down', _.bind(this.onMouseOut, this));
|
||||
el.on('keydown', '.form-control', _.bind(this.onKeyDown, this));
|
||||
el.on('keyup', '.form-control', _.bind(this.onKeyUp, this));
|
||||
el.on('blur', '.form-control', _.bind(this.onBlur, this));
|
||||
el.on('input', '.form-control', _.bind(this.onInput, this));
|
||||
if (!this.options.allowDecimal)
|
||||
el.on('keypress', '.form-control', _.bind(this.onKeyPress, this));
|
||||
|
||||
this.switches = {
|
||||
count: 1,
|
||||
enabled: true,
|
||||
fromKeyDown: false
|
||||
};
|
||||
|
||||
if (this.options.speed === 'medium') { this.switches.speed = 300; }
|
||||
else if (this.options.speed === 'fast') { this.switches.speed = 100; }
|
||||
else { this.switches.speed = 500; }
|
||||
|
||||
this.render();
|
||||
|
||||
if (this.options.disabled)
|
||||
this.setDisabled(this.options.disabled);
|
||||
|
||||
if (this.options.value!==undefined)
|
||||
this.value = this.options.value;
|
||||
this.setRawValue(this.value);
|
||||
|
||||
if (this.options.width) {
|
||||
$(this.el).width(this.options.width);
|
||||
}
|
||||
|
||||
if (this.options.defaultValue===undefined)
|
||||
this.options.defaultValue = this.options.minValue;
|
||||
|
||||
this.oldValue = this.options.minValue;
|
||||
this.lastValue = null;
|
||||
},
|
||||
|
||||
render: function () {
|
||||
var el = $(this.el);
|
||||
el.html(this.template);
|
||||
|
||||
this.$input = el.find('.form-control');
|
||||
this.rendered = true;
|
||||
|
||||
if (this.options.tabindex != undefined)
|
||||
this.$input.attr('tabindex', this.options.tabindex);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
setDisabled: function(disabled) {
|
||||
var el = $(this.el);
|
||||
if (disabled !== this.disabled) {
|
||||
el.find('button').toggleClass('disabled', disabled);
|
||||
el.toggleClass('disabled', disabled);
|
||||
(disabled) ? this.$input.attr({disabled: disabled}) : this.$input.removeAttr('disabled');
|
||||
}
|
||||
|
||||
this.disabled = disabled;
|
||||
},
|
||||
|
||||
isDisabled: function() {
|
||||
return this.disabled;
|
||||
},
|
||||
|
||||
setDefaultUnit: function(unit){
|
||||
if (this.options.defaultUnit != unit){
|
||||
var oldUnit = this.options.defaultUnit;
|
||||
this.options.defaultUnit = unit;
|
||||
this.setMinValue(this._recalcUnits(this.options.minValue, oldUnit));
|
||||
this.setMaxValue(this._recalcUnits(this.options.maxValue, oldUnit));
|
||||
this.setValue(this._recalcUnits(this.getNumberValue(), oldUnit), true);
|
||||
}
|
||||
},
|
||||
|
||||
setMinValue: function(unit){
|
||||
this.options.minValue = unit;
|
||||
},
|
||||
|
||||
setMaxValue: function(unit){
|
||||
this.options.maxValue = unit;
|
||||
},
|
||||
|
||||
setStep: function(step){
|
||||
this.options.step = step;
|
||||
},
|
||||
|
||||
getNumberValue: function(){
|
||||
if (this.options.allowAuto && this.value==this.options.autoText)
|
||||
return -1;
|
||||
else
|
||||
return parseFloat(this.value);
|
||||
},
|
||||
|
||||
getUnitValue: function(){
|
||||
return this.options.defaultUnit;
|
||||
},
|
||||
|
||||
getValue: function(){
|
||||
return this.value;
|
||||
},
|
||||
|
||||
setRawValue: function (value) {
|
||||
if (this.$input) this.$input.val(value);
|
||||
},
|
||||
|
||||
setValue: function(value, suspendchange) {
|
||||
var showError = false;
|
||||
this._fromKeyDown = false;
|
||||
this.lastValue = this.value;
|
||||
if ( typeof value === 'undefined' || value === ''){
|
||||
this.value = '';
|
||||
} else if (this.options.allowAuto && (Math.abs(parseFloat(value)+1.)<0.0001 || value==this.options.autoText)) {
|
||||
this.value = this.options.autoText;
|
||||
} else {
|
||||
var number = this._add(parseFloat(value), 0, (this.options.allowDecimal) ? 3 : 0);
|
||||
if ( typeof value === 'undefined' || isNaN(number)) {
|
||||
number = this.oldValue;
|
||||
showError = true;
|
||||
}
|
||||
|
||||
var units = this.options.defaultUnit;
|
||||
|
||||
if ( typeof value.match !== 'undefined'){
|
||||
var searchUnits = value.match(/(px|em|%|en|ex|pt|in|cm|mm|pc|s|ms)$/i);
|
||||
if (null !== searchUnits && searchUnits[0]!=='undefined') {
|
||||
units = searchUnits[0].toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.options.defaultUnit !== units) {
|
||||
number = this._recalcUnits(number, units);
|
||||
}
|
||||
if (number > this.options.maxValue) { number = this.options.maxValue; showError = true; }
|
||||
if (number < this.options.minValue) { number = this.options.minValue; showError = true; }
|
||||
|
||||
this.value = (number + ' ' + this.options.defaultUnit).trim();
|
||||
this.oldValue = number;
|
||||
}
|
||||
if (suspendchange !== true && this.lastValue !== this.value)
|
||||
this.trigger('change', this, this.value, this.lastValue);
|
||||
|
||||
if (suspendchange !== true && showError)
|
||||
this.trigger('inputerror', this, this.value);
|
||||
|
||||
if (this.rendered) {
|
||||
this.setRawValue(this.value);
|
||||
} else {
|
||||
this.options.value = this.value;
|
||||
}
|
||||
},
|
||||
|
||||
onMouseDown: function (type, e) {
|
||||
if ( this.disabled ) return;
|
||||
|
||||
if (e) $(e.currentTarget).addClass('active');
|
||||
if (this.options.hold) {
|
||||
this.switches.fromKeyDown = false;
|
||||
this._startSpin(type, e);
|
||||
}
|
||||
},
|
||||
|
||||
onMouseUp: function (type, e) {
|
||||
if ( this.disabled ) return;
|
||||
|
||||
$(e.currentTarget).removeClass('active');
|
||||
if (this.options.hold)
|
||||
this._stopSpin();
|
||||
else
|
||||
this._step(type);
|
||||
},
|
||||
|
||||
onMouseOver: function (e) {
|
||||
if ( this.disabled ) return;
|
||||
|
||||
$(e.currentTarget).addClass('over');
|
||||
},
|
||||
|
||||
onMouseOut: function (e) {
|
||||
if ( this.disabled ) return;
|
||||
|
||||
$(e.currentTarget).removeClass('active over');
|
||||
if (this.options.hold)
|
||||
this._stopSpin();
|
||||
},
|
||||
|
||||
onKeyDown: function (e) {
|
||||
if ( this.disabled ) return;
|
||||
|
||||
if (this.options.hold && ( e.keyCode==Common.UI.Keys.UP || e.keyCode==Common.UI.Keys.DOWN)) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if (this.switches.timeout===undefined) {
|
||||
this.switches.fromKeyDown = true;
|
||||
this._startSpin(e.keyCode==Common.UI.Keys.UP, e);
|
||||
}
|
||||
} else if (e.keyCode==Common.UI.Keys.RETURN) {
|
||||
if (this.options.defaultUnit && this.options.defaultUnit.length) {
|
||||
var value = this.$input.val();
|
||||
if (this.value != value) {
|
||||
this.onEnterValue();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
this.onEnterValue();
|
||||
}
|
||||
} else {
|
||||
this._fromKeyDown = true;
|
||||
}
|
||||
},
|
||||
|
||||
onKeyUp: function (e) {
|
||||
if ( this.disabled ) return;
|
||||
|
||||
if (e.keyCode==Common.UI.Keys.UP || e.keyCode==Common.UI.Keys.DOWN) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
(this.options.hold) ? this._stopSpin() : this._step(e.keyCode==Common.UI.Keys.UP);
|
||||
}
|
||||
},
|
||||
|
||||
onKeyPress: function (e) {
|
||||
if ( this.disabled ) return;
|
||||
|
||||
var charCode = String.fromCharCode(e.charCode);
|
||||
if (charCode=='.' || charCode==',') {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
} else if(this.options.maskExp && !this.options.maskExp.test(charCode) && !e.ctrlKey &&
|
||||
e.keyCode !== Common.UI.Keys.DELETE && e.keyCode !== Common.UI.Keys.BACKSPACE &&
|
||||
e.keyCode !== Common.UI.Keys.LEFT && e.keyCode !== Common.UI.Keys.RIGHT &&
|
||||
e.keyCode !== Common.UI.Keys.HOME && e.keyCode !== Common.UI.Keys.END &&
|
||||
e.keyCode !== Common.UI.Keys.ESC && e.keyCode !== Common.UI.Keys.RETURN &&
|
||||
e.keyCode !== Common.UI.Keys.INSERT && e.keyCode !== Common.UI.Keys.TAB){
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
},
|
||||
|
||||
onInput: function(e, extra) {
|
||||
if ( this.disabled || e.isDefaultPrevented() ) return;
|
||||
this.trigger('changing', this, $(e.target).val(), e);
|
||||
},
|
||||
|
||||
onEnterValue: function() {
|
||||
if (this.$input) {
|
||||
var val = this.$input.val();
|
||||
this.setValue((val==='') ? this.value : val );
|
||||
this.trigger('entervalue', this);
|
||||
}
|
||||
},
|
||||
|
||||
onBlur: function(e){
|
||||
if (this.$input) {
|
||||
var val = this.$input.val();
|
||||
this.setValue((val==='') ? this.value : val );
|
||||
if (this.options.hold && this.switches.fromKeyDown)
|
||||
this._stopSpin();
|
||||
}
|
||||
},
|
||||
|
||||
_startSpin: function (type, e) {
|
||||
if (!this.disabled) {
|
||||
var divisor = this.switches.count;
|
||||
|
||||
if (divisor === 1) { this._step(type, true); divisor = 1; }
|
||||
else if (divisor < 3) { divisor = 1.5; }
|
||||
else if (divisor < 8) { divisor = 2.5; }
|
||||
else { divisor = 6; }
|
||||
|
||||
this.switches.timeout = setTimeout($.proxy(function() {
|
||||
this._step(type, true);
|
||||
this._startSpin(type);
|
||||
} ,this), this.switches.speed/divisor);
|
||||
this.switches.count++;
|
||||
}
|
||||
},
|
||||
|
||||
_stopSpin: function (e) {
|
||||
if(this.switches.timeout!==undefined){
|
||||
clearTimeout(this.switches.timeout);
|
||||
this.switches.timeout = undefined;
|
||||
this.switches.count = 1;
|
||||
this.trigger('change', this, this.value, this.lastValue);
|
||||
}
|
||||
},
|
||||
|
||||
_increase: function(suspend) {
|
||||
var me = this;
|
||||
if (!me.readOnly) {
|
||||
var val = me.options.step;
|
||||
if (me._fromKeyDown) {
|
||||
val = this.$input.val();
|
||||
val = _.isEmpty(val) ? me.oldValue : parseFloat(val);
|
||||
} else if(me.getValue() !== '') {
|
||||
if (me.options.allowAuto && me.getValue()==me.options.autoText) {
|
||||
val = me.options.minValue-me.options.step;
|
||||
} else
|
||||
val = parseFloat(me.getValue());
|
||||
if (isNaN(val))
|
||||
val = this.oldValue;
|
||||
} else {
|
||||
val = me.options.defaultValue;
|
||||
}
|
||||
me.setValue((this._add(val, me.options.step, (me.options.allowDecimal) ? 3 : 0) + ' ' + this.options.defaultUnit).trim(), suspend);
|
||||
}
|
||||
},
|
||||
|
||||
_decrease: function(suspend) {
|
||||
var me = this;
|
||||
if (!me.readOnly) {
|
||||
var val = me.options.step;
|
||||
if (me._fromKeyDown) {
|
||||
val = this.$input.val();
|
||||
val = _.isEmpty(val) ? me.oldValue : parseFloat(val);
|
||||
} else if(me.getValue() !== '') {
|
||||
if (me.options.allowAuto && me.getValue()==me.options.autoText) {
|
||||
val = me.options.minValue;
|
||||
} else
|
||||
val = parseFloat(me.getValue());
|
||||
|
||||
if (isNaN(val))
|
||||
val = this.oldValue;
|
||||
if (me.options.allowAuto && this._add(val, -me.options.step, (me.options.allowDecimal) ? 3 : 0)<me.options.minValue) {
|
||||
me.setValue(me.options.autoText, true);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
val = me.options.defaultValue;
|
||||
}
|
||||
me.setValue((this._add(val, -me.options.step, (me.options.allowDecimal) ? 3 : 0) + ' ' + this.options.defaultUnit).trim(), suspend);
|
||||
}
|
||||
},
|
||||
|
||||
_step: function (type, suspend) {
|
||||
(type) ? this._increase(suspend) : this._decrease(suspend);
|
||||
},
|
||||
|
||||
_add: function (a, b, precision) {
|
||||
var x = Math.pow(10, precision || (this.options.allowDecimal) ? 2 : 0);
|
||||
return (Math.round(a * x) + Math.round(b * x)) / x;
|
||||
},
|
||||
|
||||
_recalcUnits: function(value, fromUnit){
|
||||
if ( fromUnit.match(/(s|ms)$/i) && this.options.defaultUnit.match(/(s|ms)$/i) ) {
|
||||
var v_out = value;
|
||||
// to sec
|
||||
if (fromUnit=='ms')
|
||||
v_out = v_out/1000.;
|
||||
// from sec
|
||||
if (this.options.defaultUnit=='ms')
|
||||
v_out = v_out*1000;
|
||||
return v_out;
|
||||
}
|
||||
|
||||
if ( fromUnit.match(/(pt|in|cm|mm|pc)$/i)===null || this.options.defaultUnit.match(/(pt|in|cm|mm|pc)$/i)===null)
|
||||
return value;
|
||||
|
||||
var v_out = value;
|
||||
// to mm
|
||||
if (fromUnit=='cm')
|
||||
v_out = v_out*10;
|
||||
else if (fromUnit=='pt')
|
||||
v_out = v_out * 25.4 / 72.0;
|
||||
else if (fromUnit=='in')
|
||||
v_out = v_out * 25.4;
|
||||
else if (fromUnit=='pc')
|
||||
v_out = v_out * 25.4 / 6.0;
|
||||
|
||||
// from mm
|
||||
if (this.options.defaultUnit=='cm')
|
||||
v_out = v_out/10.;
|
||||
else if (this.options.defaultUnit=='pt')
|
||||
v_out = parseFloat((v_out * 72.0 / 25.4).toFixed(3));
|
||||
else if (this.options.defaultUnit=='in')
|
||||
v_out = v_out / 25.4;
|
||||
else if (this.options.defaultUnit=='pc')
|
||||
v_out = v_out * 6.0 / 25.4;
|
||||
|
||||
return v_out;
|
||||
}
|
||||
});
|
||||
});
|
118
apps/common/main/lib/component/MultiSliderGradient.js
Normal file
118
apps/common/main/lib/component/MultiSliderGradient.js
Normal file
|
@ -0,0 +1,118 @@
|
|||
/**
|
||||
* MultiSliderGradient.js
|
||||
*
|
||||
* Created by Julia Radzhabova on 2/19/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
define([
|
||||
'common/main/lib/component/Slider',
|
||||
'underscore'
|
||||
], function (base, _) {
|
||||
'use strict';
|
||||
|
||||
Common.UI.MultiSliderGradient = Common.UI.MultiSlider.extend({
|
||||
|
||||
options : {
|
||||
width: 100,
|
||||
minValue: 0,
|
||||
maxValue: 100,
|
||||
values: [0, 100],
|
||||
colorValues: ['#000000', '#ffffff'],
|
||||
currentThumb: 0
|
||||
},
|
||||
|
||||
disabled: false,
|
||||
|
||||
template : _.template([
|
||||
'<div class="slider multi-slider-gradient">',
|
||||
'<div class="track"></div>',
|
||||
'<% _.each(items, function(item) { %>',
|
||||
'<div class="thumb img-commonctrl" style=""></div>',
|
||||
'<% }); %>',
|
||||
'</div>'
|
||||
].join('')),
|
||||
|
||||
initialize : function(options) {
|
||||
this.styleStr = '';
|
||||
if (Common.Utils.isChrome && Common.Utils.chromeVersion<10 || Common.Utils.isSafari && Common.Utils.safariVersion<5.1)
|
||||
this.styleStr = '-webkit-gradient(linear, left top, right top, color-stop({1}%,{0}), color-stop({3}%,{2})); /* Chrome,Safari4+ */';
|
||||
else if (Common.Utils.isChrome || Common.Utils.isSafari)
|
||||
this.styleStr = '-webkit-linear-gradient(left, {0} {1}%, {2} {3}%)';
|
||||
else if (Common.Utils.isGecko)
|
||||
this.styleStr = '-moz-linear-gradient(left, {0} {1}%, {2} {3}%)';
|
||||
else if (Common.Utils.isOpera && Common.Utils.operaVersion>11.0)
|
||||
this.styleStr = '-o-linear-gradient(left, {0} {1}%, {2} {3}%)';
|
||||
else if (Common.Utils.isIE)
|
||||
this.styleStr = '-ms-linear-gradient(left, {0} {1}%, {2} {3}%)';
|
||||
|
||||
this.colorValues = this.options.colorValues;
|
||||
|
||||
Common.UI.MultiSlider.prototype.initialize.call(this, options);
|
||||
},
|
||||
|
||||
render : function(parentEl) {
|
||||
Common.UI.MultiSlider.prototype.render.call(this, parentEl);
|
||||
|
||||
var me = this,
|
||||
style = '';
|
||||
|
||||
me.trackEl = me.cmpEl.find('.track');
|
||||
|
||||
for (var i=0; i<me.thumbs.length; i++) {
|
||||
me.thumbs[i].thumb.on('dblclick', null, function() {
|
||||
me.trigger('thumbdblclick', me);
|
||||
});
|
||||
}
|
||||
|
||||
if (me.styleStr!=='') {
|
||||
style = Common.Utils.String.format(me.styleStr, me.colorValues[0], 0, me.colorValues[1], 100);
|
||||
me.trackEl.css('background', style);
|
||||
}
|
||||
if (Common.Utils.isIE) {
|
||||
style = Common.Utils.String.format('progid:DXImageTransform.Microsoft.gradient( startColorstr={0}, endColorstr={1},GradientType=1 )',
|
||||
me.colorValues[0], me.colorValues[1]);
|
||||
me.trackEl.css('filter', style);
|
||||
}
|
||||
style = Common.Utils.String.format('linear-gradient(to right, {0} {1}%, {2} {3}%)', me.colorValues[0], 0, me.colorValues[1], 100);
|
||||
me.trackEl.css('background', style);
|
||||
|
||||
me.on('change', _.bind(me.changeGradientStyle, me));
|
||||
},
|
||||
|
||||
setColorValue: function(color, index) {
|
||||
var ind = (index!==undefined) ? index : this.currentThumb;
|
||||
this.colorValues[ind] = color;
|
||||
this.changeGradientStyle();
|
||||
},
|
||||
|
||||
getColorValue: function(index) {
|
||||
var ind = (index!==undefined) ? index : this.currentThumb;
|
||||
return this.colorValues[ind];
|
||||
},
|
||||
|
||||
setValue: function(index, value) {
|
||||
Common.UI.MultiSlider.prototype.setValue.call(this, index, value);
|
||||
this.changeGradientStyle();
|
||||
},
|
||||
|
||||
changeGradientStyle: function() {
|
||||
if (!this.rendered) return;
|
||||
var style;
|
||||
if (this.styleStr!=='') {
|
||||
style = Common.Utils.String.format(this.styleStr, this.colorValues[0], this.getValue(0), this.colorValues[1], this.getValue(1));
|
||||
this.trackEl.css('background', style);
|
||||
}
|
||||
if (Common.Utils.isIE) {
|
||||
style = Common.Utils.String.format('progid:DXImageTransform.Microsoft.gradient( startColorstr={0}, endColorstr={1},GradientType=1 )',
|
||||
this.colorValues[0], this.colorValues[1]);
|
||||
this.trackEl.css('filter', style);
|
||||
}
|
||||
style = Common.Utils.String.format('linear-gradient(to right, {0} {1}%, {2} {3}%)', this.colorValues[0], this.getValue(0), this.colorValues[1], this.getValue(1));
|
||||
this.trackEl.css('background', style);
|
||||
}
|
||||
});
|
||||
});
|
115
apps/common/main/lib/component/RadioBox.js
Normal file
115
apps/common/main/lib/component/RadioBox.js
Normal file
|
@ -0,0 +1,115 @@
|
|||
/**
|
||||
* RadioBox.js
|
||||
*
|
||||
* Created by Julia Radzhabova on 2/26/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* Radiobox can be in two states: true or false.
|
||||
* To get the radiobox state use getValue() function. It can return true/false.
|
||||
*
|
||||
* @property {String} name
|
||||
* The name of the group of radioboxes.
|
||||
*
|
||||
* name: 'group-name',
|
||||
*
|
||||
* @property {Boolean} checked
|
||||
* Initial state of radiobox.
|
||||
*
|
||||
* checked: false,
|
||||
*
|
||||
* **/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'common/main/lib/component/BaseView',
|
||||
'underscore'
|
||||
], function (base, _) {
|
||||
'use strict';
|
||||
|
||||
Common.UI.RadioBox = Common.UI.BaseView.extend({
|
||||
|
||||
options : {
|
||||
labelText: ''
|
||||
},
|
||||
|
||||
disabled : false,
|
||||
rendered : false,
|
||||
|
||||
template : _.template('<label class="radiobox"><input type="button" name="<%= name %>" class="img-commonctrl"><%= labelText %></label>'),
|
||||
|
||||
initialize : function(options) {
|
||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
||||
|
||||
var me = this,
|
||||
el = $(this.el);
|
||||
|
||||
this.name = this.options.name || Common.UI.getId();
|
||||
|
||||
this.render();
|
||||
|
||||
if (this.options.disabled)
|
||||
this.setDisabled(this.options.disabled);
|
||||
|
||||
if (this.options.checked!==undefined)
|
||||
this.setValue(this.options.checked, true);
|
||||
|
||||
// handle events
|
||||
this.$radio.on('click', _.bind(this.onItemCheck, this));
|
||||
},
|
||||
|
||||
render: function () {
|
||||
var el = $(this.el);
|
||||
el.html(this.template({
|
||||
labelText: this.options.labelText,
|
||||
name: this.name
|
||||
}));
|
||||
|
||||
this.$radio = el.find('input[type=button]');
|
||||
this.rendered = true;
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
setDisabled: function(disabled) {
|
||||
if (disabled !== this.disabled) {
|
||||
this.$radio.toggleClass('disabled', disabled);
|
||||
(disabled) ? this.$radio.attr({disabled: disabled}) : this.$radio.removeAttr('disabled');
|
||||
}
|
||||
|
||||
this.disabled = disabled;
|
||||
},
|
||||
|
||||
isDisabled: function() {
|
||||
return this.disabled;
|
||||
},
|
||||
|
||||
onItemCheck: function (e) {
|
||||
if (!this.disabled) this.setValue(true);
|
||||
},
|
||||
|
||||
setRawValue: function(value) {
|
||||
var value = (value === true || value === 'true' || value === '1' || value === 1 );
|
||||
$('input[type=button][name=' + this.name + ']').removeClass('checked');
|
||||
this.$radio.toggleClass('checked', value);
|
||||
},
|
||||
|
||||
setValue: function(value, suspendchange) {
|
||||
if (this.rendered) {
|
||||
var lastValue = this.$radio.hasClass('checked');
|
||||
this.setRawValue(value);
|
||||
if (suspendchange !== true && lastValue !== value)
|
||||
this.trigger('change', this, this.$radio.hasClass('checked'));
|
||||
} else {
|
||||
this.options.checked = value;
|
||||
}
|
||||
},
|
||||
|
||||
getValue: function() {
|
||||
return this.$radio.hasClass('checked');
|
||||
}
|
||||
});
|
||||
});
|
143
apps/common/main/lib/component/Scroller.js
Normal file
143
apps/common/main/lib/component/Scroller.js
Normal file
|
@ -0,0 +1,143 @@
|
|||
/**
|
||||
* Scroller.js
|
||||
*
|
||||
* Created by Alexander Yuzhin on 3/14/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'jmousewheel',
|
||||
'perfectscrollbar',
|
||||
'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 = $(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');
|
||||
}
|
||||
}
|
||||
}), {
|
||||
isMouseCapture: function() {
|
||||
return mouseCapture
|
||||
}
|
||||
})
|
||||
})();
|
||||
});
|
462
apps/common/main/lib/component/Slider.js
Normal file
462
apps/common/main/lib/component/Slider.js
Normal file
|
@ -0,0 +1,462 @@
|
|||
/**
|
||||
* Slider.js
|
||||
*
|
||||
* Created by Julia Radzhabova on 2/18/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Example usage:
|
||||
* new Common.UI.SingleSlider({
|
||||
* el: $('#id'),
|
||||
* minValue : 0,
|
||||
* maxValue : 100,
|
||||
* value : 100
|
||||
* });
|
||||
*
|
||||
*
|
||||
* @property {Boolean} enableKeyEvents
|
||||
* If true slider increase/decrease its value by {@link #step} when arrow key Up/Down or Right/Left is pressed.
|
||||
*
|
||||
* enableKeyEvents: false,
|
||||
*
|
||||
*
|
||||
*
|
||||
* Example usage:
|
||||
* new Common.UI.MultiSlider({
|
||||
* el: $('#id'),
|
||||
* minValue : 0,
|
||||
* maxValue : 100,
|
||||
* values : [0, 100]
|
||||
* });
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'common/main/lib/component/BaseView',
|
||||
'underscore'
|
||||
], function (base, _) {
|
||||
'use strict';
|
||||
|
||||
Common.UI.SingleSlider = Common.UI.BaseView.extend({
|
||||
|
||||
options : {
|
||||
width: 100,
|
||||
minValue: 0,
|
||||
maxValue: 100,
|
||||
step: 1,
|
||||
value: 100,
|
||||
enableKeyEvents: false
|
||||
},
|
||||
|
||||
disabled: false,
|
||||
|
||||
template : _.template([
|
||||
'<div class="slider single-slider" style="">',
|
||||
'<div class="track">',
|
||||
'<div class="track-left img-commonctrl"></div>',
|
||||
'<div class="track-center img-commonctrl"></div>',
|
||||
'<div class="track-right img-commonctrl" style=""></div>',
|
||||
'</div>',
|
||||
'<div class="thumb img-commonctrl" style=""></div>',
|
||||
'<% if (this.options.enableKeyEvents) { %>',
|
||||
'<input type="text" style="position: absolute; top:-10px; width: 1px; height: 1px;">',
|
||||
'<% } %>',
|
||||
'</div>'
|
||||
].join('')),
|
||||
|
||||
initialize : function(options) {
|
||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
||||
|
||||
var me = this,
|
||||
el = $(this.el);
|
||||
|
||||
me.width = me.options.width;
|
||||
me.minValue = me.options.minValue;
|
||||
me.maxValue = me.options.maxValue;
|
||||
me.delta = 100/(me.maxValue - me.minValue);
|
||||
me.step = me.options.step;
|
||||
|
||||
if (me.options.el) {
|
||||
me.render();
|
||||
}
|
||||
|
||||
this.setValue(me.options.value);
|
||||
},
|
||||
|
||||
render : function(parentEl) {
|
||||
var me = this;
|
||||
|
||||
if (!me.rendered) {
|
||||
this.cmpEl = $(this.template({
|
||||
}));
|
||||
|
||||
if (parentEl) {
|
||||
this.setElement(parentEl, false);
|
||||
parentEl.html(this.cmpEl);
|
||||
} else {
|
||||
$(this.el).html(this.cmpEl);
|
||||
}
|
||||
} else {
|
||||
this.cmpEl = $(this.el);
|
||||
}
|
||||
|
||||
this.cmpEl.find('.track-center').width(me.options.width - 14);
|
||||
this.cmpEl.width(me.options.width);
|
||||
|
||||
this.thumb = this.cmpEl.find('.thumb');
|
||||
|
||||
var onMouseUp = function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
var pos = Math.max(0, Math.min(100, (Math.round((e.pageX - me.cmpEl.offset().left - me._dragstart) / me.width * 100))));
|
||||
me.setThumbPosition(pos);
|
||||
|
||||
me.lastValue = me.value;
|
||||
me.value = pos/me.delta + me.minValue;
|
||||
|
||||
me.thumb.removeClass('active');
|
||||
$(document).off('mouseup', onMouseUp);
|
||||
$(document).off('mousemove', onMouseMove);
|
||||
|
||||
me._dragstart = undefined;
|
||||
me.trigger('changecomplete', me, me.value, me.lastValue);
|
||||
};
|
||||
|
||||
var onMouseMove = function (e) {
|
||||
if ( me.disabled ) return;
|
||||
if ( me._dragstart===undefined ) return;
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
var pos = Math.max(0, Math.min(100, (Math.round((e.pageX - me.cmpEl.offset().left - me._dragstart) / me.width * 100))));
|
||||
me.setThumbPosition(pos);
|
||||
|
||||
me.lastValue = me.value;
|
||||
me.value = pos/me.delta + me.minValue;
|
||||
|
||||
if (Math.abs(me.value-me.lastValue)>0.001)
|
||||
me.trigger('change', me, me.value, me.lastValue);
|
||||
};
|
||||
|
||||
var onMouseDown = function (e) {
|
||||
if ( me.disabled ) return;
|
||||
me._dragstart = e.pageX - me.thumb.offset().left - 7;
|
||||
|
||||
me.thumb.addClass('active');
|
||||
$(document).on('mouseup', onMouseUp);
|
||||
$(document).on('mousemove', onMouseMove);
|
||||
|
||||
if (me.options.enableKeyEvents)
|
||||
setTimeout(function() {me.input.focus();}, 10);
|
||||
};
|
||||
|
||||
var onTrackMouseDown = function (e) {
|
||||
if ( me.disabled ) return;
|
||||
|
||||
var pos = Math.max(0, Math.min(100, (Math.round((e.pageX - me.cmpEl.offset().left) / me.width * 100))));
|
||||
me.setThumbPosition(pos);
|
||||
|
||||
me.lastValue = me.value;
|
||||
me.value = pos/me.delta + me.minValue;
|
||||
|
||||
me.trigger('change', me, me.value, me.lastValue);
|
||||
me.trigger('changecomplete', me, me.value, me.lastValue);
|
||||
};
|
||||
|
||||
var updateslider;
|
||||
|
||||
var moveThumb = function(increase) {
|
||||
me.lastValue = me.value;
|
||||
me.value = Math.max(me.minValue, Math.min(me.maxValue, me.value + ((increase) ? me.step : -me.step)));
|
||||
me.setThumbPosition(Math.round((me.value-me.minValue)*me.delta));
|
||||
me.trigger('change', me, me.value, me.lastValue);
|
||||
};
|
||||
|
||||
var onKeyDown = function (e) {
|
||||
if ( me.disabled ) return;
|
||||
|
||||
if (e.keyCode==Common.UI.Keys.UP || e.keyCode==Common.UI.Keys.DOWN || e.keyCode==Common.UI.Keys.LEFT || e.keyCode==Common.UI.Keys.RIGHT) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
el.off('keydown', 'input', onKeyDown);
|
||||
updateslider = setInterval(_.bind(moveThumb, me, e.keyCode==Common.UI.Keys.UP || e.keyCode==Common.UI.Keys.RIGHT), 100);
|
||||
}
|
||||
};
|
||||
|
||||
var onKeyUp = function (e) {
|
||||
if ( me.disabled ) return;
|
||||
|
||||
if (e.keyCode==Common.UI.Keys.UP || e.keyCode==Common.UI.Keys.DOWN || Common.UI.Keys.LEFT || Common.UI.Keys.RIGHT) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
clearInterval(updateslider);
|
||||
moveThumb(e.keyCode==Common.UI.Keys.UP || e.keyCode==Common.UI.Keys.RIGHT);
|
||||
el.on('keydown', 'input', onKeyDown);
|
||||
me.trigger('changecomplete', me, me.value, me.lastValue);
|
||||
}
|
||||
};
|
||||
|
||||
if (!me.rendered) {
|
||||
var el = me.cmpEl;
|
||||
el.on('mousedown', '.thumb', onMouseDown);
|
||||
el.on('mousedown', '.track', onTrackMouseDown);
|
||||
if (this.options.enableKeyEvents) {
|
||||
el.on('keydown', 'input', onKeyDown);
|
||||
el.on('keyup', 'input', onKeyUp);
|
||||
}
|
||||
}
|
||||
|
||||
me.rendered = true;
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
setThumbPosition: function(x) {
|
||||
this.thumb.css({left: x + '%'});
|
||||
},
|
||||
|
||||
setValue: function(value) {
|
||||
this.lastValue = this.value;
|
||||
this.value = Math.max(this.minValue, Math.min(this.maxValue, value));
|
||||
this.setThumbPosition(Math.round((value-this.minValue)*this.delta));
|
||||
},
|
||||
|
||||
getValue: function() {
|
||||
return this.value;
|
||||
},
|
||||
|
||||
setDisabled: function(disabled) {
|
||||
if (disabled !== this.disabled)
|
||||
this.cmpEl.toggleClass('disabled', disabled);
|
||||
this.disabled = disabled;
|
||||
}
|
||||
});
|
||||
|
||||
Common.UI.MultiSlider = Common.UI.BaseView.extend({
|
||||
|
||||
options : {
|
||||
width: 100,
|
||||
minValue: 0,
|
||||
maxValue: 100,
|
||||
values: [0, 100]
|
||||
},
|
||||
|
||||
disabled: false,
|
||||
|
||||
template : _.template([
|
||||
'<div class="slider multi-slider">',
|
||||
'<div class="track">',
|
||||
'<div class="track-left"></div>',
|
||||
'<div class="track-center""></div>',
|
||||
'<div class="track-right" style=""></div>',
|
||||
'</div>',
|
||||
'<% _.each(items, function(item) { %>',
|
||||
'<div class="thumb" style=""></div>',
|
||||
'<% }); %>',
|
||||
'</div>'
|
||||
].join('')),
|
||||
|
||||
initialize : function(options) {
|
||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
||||
|
||||
var me = this,
|
||||
el = $(this.el);
|
||||
|
||||
me.width = me.options.width;
|
||||
me.minValue = me.options.minValue;
|
||||
me.maxValue = me.options.maxValue;
|
||||
me.delta = 100/(me.maxValue - me.minValue);
|
||||
me.thumbs = [];
|
||||
|
||||
if (me.options.el) {
|
||||
me.render();
|
||||
}
|
||||
},
|
||||
|
||||
render : function(parentEl) {
|
||||
var me = this;
|
||||
|
||||
if (!me.rendered) {
|
||||
this.cmpEl = $(this.template({
|
||||
items: this.options.values
|
||||
}));
|
||||
|
||||
if (parentEl) {
|
||||
this.setElement(parentEl, false);
|
||||
parentEl.html(this.cmpEl);
|
||||
} else {
|
||||
$(this.el).html(this.cmpEl);
|
||||
}
|
||||
} else {
|
||||
this.cmpEl = $(this.el);
|
||||
}
|
||||
|
||||
var el = this.cmpEl;
|
||||
el.find('.track-center').width(me.options.width - 14);
|
||||
el.width(me.options.width);
|
||||
|
||||
var onMouseUp = function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
var index = e.data,
|
||||
lastValue = me.thumbs[index].value,
|
||||
minValue = (index-1<0) ? 0 : me.thumbs[index-1].position,
|
||||
maxValue = (index+1<me.thumbs.length) ? me.thumbs[index+1].position : 100,
|
||||
pos = Math.max(minValue, Math.min(maxValue, (Math.round((e.pageX - me.cmpEl.offset().left - me._dragstart) / me.width * 100)))),
|
||||
value = pos/me.delta + me.minValue;
|
||||
|
||||
me.setThumbPosition(index, pos);
|
||||
me.thumbs[index].value = value;
|
||||
|
||||
$(document).off('mouseup', onMouseUp);
|
||||
$(document).off('mousemove', onMouseMove);
|
||||
|
||||
me._dragstart = undefined;
|
||||
me.trigger('changecomplete', me, value, lastValue);
|
||||
};
|
||||
|
||||
var onMouseMove = function (e) {
|
||||
if ( me.disabled ) return;
|
||||
if ( me._dragstart===undefined ) return;
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
var index = e.data,
|
||||
lastValue = me.thumbs[index].value,
|
||||
minValue = (index-1<0) ? 0 : me.thumbs[index-1].position,
|
||||
maxValue = (index+1<me.thumbs.length) ? me.thumbs[index+1].position : 100,
|
||||
pos = Math.max(minValue, Math.min(maxValue, (Math.round((e.pageX - me.cmpEl.offset().left - me._dragstart) / me.width * 100)))),
|
||||
value = pos/me.delta + me.minValue;
|
||||
|
||||
me.setThumbPosition(index, pos);
|
||||
me.thumbs[index].value = value;
|
||||
|
||||
if (Math.abs(value-lastValue)>0.001)
|
||||
me.trigger('change', me, value, lastValue);
|
||||
};
|
||||
|
||||
var onMouseDown = function (e) {
|
||||
if ( me.disabled ) return;
|
||||
|
||||
var index = e.data,
|
||||
thumb = me.thumbs[index].thumb;
|
||||
|
||||
me._dragstart = e.pageX - thumb.offset().left - thumb.width()/2;
|
||||
me.setActiveThumb(index);
|
||||
|
||||
_.each(me.thumbs, function (item, idx) {
|
||||
(index == idx) ? item.thumb.css('z-index', 500) : item.thumb.css('z-index', '');
|
||||
});
|
||||
|
||||
$(document).on('mouseup', null, index, onMouseUp);
|
||||
$(document).on('mousemove', null, index, onMouseMove);
|
||||
};
|
||||
|
||||
var onTrackMouseDown = function (e) {
|
||||
if ( me.disabled ) return;
|
||||
|
||||
var pos = Math.max(0, Math.min(100, (Math.round((e.pageX - me.cmpEl.offset().left) / me.width * 100)))),
|
||||
index = findThumb(pos),
|
||||
lastValue = me.thumbs[index].value,
|
||||
value = pos/me.delta + me.minValue;
|
||||
|
||||
me.setThumbPosition(index, pos);
|
||||
me.thumbs[index].value = value;
|
||||
|
||||
me.trigger('change', me, value, lastValue);
|
||||
me.trigger('changecomplete', me, value, lastValue);
|
||||
};
|
||||
|
||||
var findThumb = function(pos) {
|
||||
var nearest = 100,
|
||||
index = 0,
|
||||
len = me.thumbs.length,
|
||||
dist;
|
||||
|
||||
for (var i=0; i<len; i++) {
|
||||
dist = Math.abs(me.thumbs[i].position - pos);
|
||||
if (Math.abs(dist <= nearest)) {
|
||||
var above = me.thumbs[i + 1];
|
||||
var below = me.thumbs[i - 1];
|
||||
|
||||
if (below !== undefined && pos < below.position) {
|
||||
continue;
|
||||
}
|
||||
if (above !== undefined && pos > above.position) {
|
||||
continue;
|
||||
}
|
||||
index = i;
|
||||
nearest = dist;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
};
|
||||
|
||||
this.$thumbs = el.find('.thumb');
|
||||
_.each(this.$thumbs, function(item, index) {
|
||||
var thumb = $(item);
|
||||
me.thumbs.push({
|
||||
thumb: thumb,
|
||||
index: index
|
||||
});
|
||||
me.setValue(index, me.options.values[index]);
|
||||
thumb.on('mousedown', null, index, onMouseDown);
|
||||
});
|
||||
me.setActiveThumb(0, true);
|
||||
|
||||
if (!me.rendered) {
|
||||
el.on('mousedown', '.track', onTrackMouseDown);
|
||||
}
|
||||
|
||||
me.rendered = true;
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
setActiveThumb: function(index, suspend) {
|
||||
this.currentThumb = index;
|
||||
this.$thumbs.removeClass('active');
|
||||
this.thumbs[index].thumb.addClass('active');
|
||||
if (suspend!==true) this.trigger('thumbclick', this, index);
|
||||
},
|
||||
|
||||
setThumbPosition: function(index, x) {
|
||||
this.thumbs[index].position = x;
|
||||
this.thumbs[index].thumb.css({left: x + '%'});
|
||||
},
|
||||
|
||||
setValue: function(index, value) {
|
||||
this.thumbs[index].value = Math.max(this.minValue, Math.min(this.maxValue, value));
|
||||
this.setThumbPosition(index, Math.round((value-this.minValue)*this.delta));
|
||||
},
|
||||
|
||||
|
||||
getValue: function(index) {
|
||||
return this.thumbs[index].value;
|
||||
},
|
||||
|
||||
getValues: function() {
|
||||
var values = [];
|
||||
_.each (this.thumbs, function(thumb) {
|
||||
values.push(thumb.value);
|
||||
});
|
||||
|
||||
return values;
|
||||
},
|
||||
|
||||
setDisabled: function(disabled) {
|
||||
if (disabled !== this.disabled)
|
||||
this.cmpEl.toggleClass('disabled', disabled);
|
||||
this.disabled = disabled;
|
||||
}
|
||||
});
|
||||
});
|
159
apps/common/main/lib/component/Switcher.js
Normal file
159
apps/common/main/lib/component/Switcher.js
Normal file
|
@ -0,0 +1,159 @@
|
|||
/**
|
||||
* User: Julia.Radzhabova
|
||||
* Date: 26.02.15
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'common/main/lib/component/BaseView',
|
||||
'underscore'
|
||||
], function (base, _) {
|
||||
'use strict';
|
||||
|
||||
Common.UI.Switcher = Common.UI.BaseView.extend({
|
||||
|
||||
options : {
|
||||
width: 25,
|
||||
thumbWidth: 13,
|
||||
value: false
|
||||
},
|
||||
|
||||
disabled: false,
|
||||
|
||||
template : _.template([
|
||||
'<div class="switcher">',
|
||||
'<div class="sw-left"></div>',
|
||||
'<div class="sw-right"></div>',
|
||||
'<div class="thumb"></div>',
|
||||
'</div>'
|
||||
].join('')),
|
||||
|
||||
initialize : function(options) {
|
||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
||||
|
||||
var me = this,
|
||||
el = $(this.el);
|
||||
|
||||
me.width = me.options.width;
|
||||
me.thumbWidth = me.options.thumbWidth;
|
||||
me.delta = (me.width - me.thumbWidth - 2)/2;
|
||||
|
||||
if (me.options.el)
|
||||
me.render();
|
||||
|
||||
this.setValue(me.options.value);
|
||||
},
|
||||
|
||||
render : function(parentEl) {
|
||||
var me = this;
|
||||
|
||||
if (!me.rendered) {
|
||||
this.cmpEl = $(this.template({
|
||||
}));
|
||||
|
||||
if (parentEl) {
|
||||
this.setElement(parentEl, false);
|
||||
parentEl.html(this.cmpEl);
|
||||
} else {
|
||||
$(this.el).html(this.cmpEl);
|
||||
}
|
||||
} else {
|
||||
this.cmpEl = $(this.el);
|
||||
}
|
||||
|
||||
this.thumb = this.cmpEl.find('.thumb');
|
||||
|
||||
this.cmpEl.width(me.width);
|
||||
this.thumb.width(me.thumbWidth);
|
||||
this.cmpEl.find('.sw-left').width(me.width/2);
|
||||
this.cmpEl.find('.sw-right').width(me.width/2);
|
||||
|
||||
var onMouseUp = function (e) {
|
||||
if ( me.disabled ) return;
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
$(document).off('mouseup.switcher', onMouseUp);
|
||||
$(document).off('mousemove.switcher', onMouseMove);
|
||||
|
||||
var pos = Math.round((e.pageX - me._dragstart));
|
||||
me.value = (me.value) ? (pos > -me.delta) : (pos > me.delta);
|
||||
me.cmpEl.toggleClass('on', me.value);
|
||||
me.thumb.css({left: '', right: ''});
|
||||
me.trigger('change', me, me.value);
|
||||
|
||||
me._dragstart = undefined;
|
||||
};
|
||||
|
||||
var onMouseMove = function (e) {
|
||||
if ( me.disabled ) return;
|
||||
if ( me._dragstart===undefined ) return;
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
var pos = Math.round((e.pageX - me._dragstart));
|
||||
if (me.value) {
|
||||
me.thumb.css({right: (pos<1) ? Math.min(me.width-me.thumbWidth - 2, -pos) : 0, left: 'auto'});
|
||||
} else {
|
||||
me.thumb.css({left: (pos>-1) ? Math.min(me.width-me.thumbWidth - 2, pos) : 0, right: 'auto'});
|
||||
}
|
||||
if (!me._isMouseMove) me._isMouseMove = Math.abs(pos)>0;
|
||||
};
|
||||
|
||||
var onMouseDown = function (e) {
|
||||
if ( me.disabled ) return;
|
||||
me._dragstart = e.pageX;
|
||||
me._isMouseMove = false;
|
||||
|
||||
$(document).on('mouseup.switcher', onMouseUp);
|
||||
$(document).on('mousemove.switcher', onMouseMove);
|
||||
};
|
||||
|
||||
var onSwitcherClick = function (e) {
|
||||
if ( me.disabled || me._isMouseMove) { me._isMouseMove = false; return;}
|
||||
|
||||
me.value = !me.value;
|
||||
me.cmpEl.toggleClass('on', me.value);
|
||||
me.trigger('change', me, me.value);
|
||||
};
|
||||
|
||||
if (!me.rendered) {
|
||||
var el = me.cmpEl;
|
||||
el.on('mousedown', '.thumb', onMouseDown);
|
||||
el.on('click', onSwitcherClick);
|
||||
}
|
||||
|
||||
me.rendered = true;
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
setThumbPosition: function(x) {
|
||||
var isOn = (this.value) ? (x < -this.delta) : (x > this.delta);
|
||||
this.thumb.css((isOn) ? {right: 0, left: 'auto'} : {left: 0, right: 'auto'});
|
||||
},
|
||||
|
||||
setValue: function(value) {
|
||||
this.value = (value===true);
|
||||
this.cmpEl.toggleClass('on', this.value);
|
||||
},
|
||||
|
||||
getValue: function() {
|
||||
return this.value;
|
||||
},
|
||||
|
||||
setDisabled: function(disabled) {
|
||||
if (disabled !== this.disabled)
|
||||
this.cmpEl.toggleClass('disabled', disabled);
|
||||
this.disabled = disabled;
|
||||
},
|
||||
|
||||
isDisabled: function() {
|
||||
return this.disabled;
|
||||
}
|
||||
});
|
||||
});
|
75
apps/common/main/lib/component/SynchronizeTip.js
Normal file
75
apps/common/main/lib/component/SynchronizeTip.js
Normal file
|
@ -0,0 +1,75 @@
|
|||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'common/main/lib/component/BaseView'
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
Common.UI.SynchronizeTip = Common.UI.BaseView.extend(_.extend((function() {
|
||||
var tipEl;
|
||||
|
||||
return {
|
||||
options : {
|
||||
target : $(document.body),
|
||||
text : '',
|
||||
placement: 'right'
|
||||
},
|
||||
|
||||
template: _.template([
|
||||
'<div class="synch-tip-root <%= scope.placement %>">',
|
||||
'<div class="asc-synchronizetip">',
|
||||
'<div class="tip-arrow <%= scope.placement %>"></div>',
|
||||
'<div>',
|
||||
'<div class="tip-text" style="width: 260px;"><%= scope.text %></div>',
|
||||
'<div class="close img-commonctrl"></div>',
|
||||
'</div>',
|
||||
'<div class="show-link"><label><%= scope.textDontShow %></label></div>',
|
||||
'</div>',
|
||||
'</div>'
|
||||
].join('')),
|
||||
|
||||
initialize : function(options) {
|
||||
this.textSynchronize += Common.Utils.String.platformKey('Ctrl+S');
|
||||
|
||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
||||
this.target = this.options.target;
|
||||
this.text = !_.isEmpty(this.options.text) ? this.options.text : this.textSynchronize;
|
||||
this.placement = this.options.placement;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
tipEl = $(this.template({ scope: this }));
|
||||
tipEl.find('.close').on('click', _.bind(function() { this.trigger('closeclick');}, this));
|
||||
tipEl.find('.show-link label').on('click', _.bind(function() { this.trigger('dontshowclick');}, this));
|
||||
|
||||
$(document.body).append(tipEl);
|
||||
this.applyPlacement();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
show: function(){
|
||||
if (tipEl) {
|
||||
this.applyPlacement();
|
||||
tipEl.show()
|
||||
} else
|
||||
this.render();
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
if (tipEl) tipEl.hide();
|
||||
},
|
||||
|
||||
applyPlacement: function () {
|
||||
var showxy = this.target.offset();
|
||||
(this.placement == 'top') ? tipEl.css({bottom : $(document).height() - showxy.top + 'px', right: $(document).width() - showxy.left - this.target.width()/2 + 'px'})
|
||||
: tipEl.css({top : showxy.top + this.target.height()/2 + 'px', left: showxy.left + this.target.width() + 'px'});
|
||||
},
|
||||
|
||||
textDontShow : 'Don\'t show this message again',
|
||||
textSynchronize : 'The document has been changed by another user.<br/>Please click to save your changes and reload the updates.'
|
||||
}
|
||||
})(), Common.UI.SynchronizeTip || {}));
|
||||
});
|
||||
|
92
apps/common/main/lib/component/Tab.js
Normal file
92
apps/common/main/lib/component/Tab.js
Normal file
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
* Tab.js
|
||||
*
|
||||
* Created by Maxim Kadushkin on 01 April 2014
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'common/main/lib/component/BaseView'
|
||||
], function (base) {
|
||||
'use strict';
|
||||
|
||||
var Tab = function(opts) {
|
||||
this.active = false;
|
||||
this.label = 'Tab';
|
||||
this.cls = '';
|
||||
this.template = _.template(['<li class="<% if(active){ %>active<% } %> <% if(cls.length){%><%= cls %><%}%>" data-label="<%= label %>">',
|
||||
'<a><%- label %></a>',
|
||||
'</li>'].join(''));
|
||||
|
||||
this.initialize.call(this, opts);
|
||||
return this;
|
||||
};
|
||||
|
||||
_.extend(Tab.prototype, {
|
||||
initialize: function(options) {
|
||||
_.extend(this, options);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var el = this.template(this);
|
||||
this.$el = $(el);
|
||||
|
||||
this.rendered = true;
|
||||
this.disable(this.disabled);
|
||||
return this;
|
||||
},
|
||||
|
||||
isActive: function() {
|
||||
return this.$el.hasClass('active');
|
||||
},
|
||||
|
||||
activate: function(){
|
||||
if (!this.$el.hasClass('active'))
|
||||
this.$el.addClass('active');
|
||||
},
|
||||
|
||||
deactivate: function(){
|
||||
this.$el.removeClass('active');
|
||||
},
|
||||
|
||||
on: function() {
|
||||
this.$el.on.apply(this, arguments);
|
||||
},
|
||||
|
||||
disable: function(val) {
|
||||
this.disabled = val;
|
||||
|
||||
if (this.rendered) {
|
||||
if (val && !this.$el.hasClass('disabled'))
|
||||
this.$el.addClass('disabled'); else
|
||||
this.$el.removeClass('disabled');
|
||||
}
|
||||
},
|
||||
|
||||
addClass: function(cls) {
|
||||
if (cls.length && !this.$el.hasClass(cls))
|
||||
this.$el.addClass(cls);
|
||||
},
|
||||
|
||||
removeClass: function(cls) {
|
||||
if (cls.length && this.$el.hasClass(cls))
|
||||
this.$el.removeClass(cls);
|
||||
},
|
||||
|
||||
hasClass: function(cls) {
|
||||
return this.$el.hasClass(cls);
|
||||
},
|
||||
|
||||
setCaption: function(text) {
|
||||
this.$el.find('> a').text(text);
|
||||
}
|
||||
});
|
||||
|
||||
Common.UI.Tab = Tab;
|
||||
});
|
||||
|
536
apps/common/main/lib/component/TabBar.js
Normal file
536
apps/common/main/lib/component/TabBar.js
Normal file
|
@ -0,0 +1,536 @@
|
|||
/**
|
||||
* TabBar.js
|
||||
*
|
||||
* Created by Maxim Kadushkin on 28 March 2014
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
define([
|
||||
'common/main/lib/component/BaseView',
|
||||
'common/main/lib/component/Tab'
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
var Events = {
|
||||
bind: function () {
|
||||
if (!this.o) this.o = $({});
|
||||
this.o.on.apply(this.o, arguments);
|
||||
},
|
||||
unbind: function () {
|
||||
if (this.o) this.o.off.apply(this.o, arguments);
|
||||
},
|
||||
trigger: function () {
|
||||
if (!this.o) this.o = $({});
|
||||
this.o.trigger.apply(this.o, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
var StateManager = function (options) {
|
||||
this.initialize.call(this, options);
|
||||
};
|
||||
|
||||
_.extend(StateManager.prototype, Events);
|
||||
|
||||
StateManager.prototype.initialize = function (options) {
|
||||
this.bar = options.bar;
|
||||
};
|
||||
|
||||
StateManager.prototype.attach = function (tab) {
|
||||
tab.changeState = $.proxy(function () {
|
||||
this.trigger('tab:change', tab);
|
||||
this.bar.$el.find('ul > li.active').removeClass('active');
|
||||
tab.activate();
|
||||
|
||||
this.bar.trigger('tab:changed', this.bar, this.bar.tabs.indexOf(tab), tab);
|
||||
}, this);
|
||||
|
||||
var dragHelper = new (function() {
|
||||
|
||||
return {
|
||||
bounds: [],
|
||||
drag: undefined,
|
||||
|
||||
calculateBounds: function () {
|
||||
var me = this,
|
||||
length = me.bar.tabs.length,
|
||||
barBounds = me.bar.$bar.get(0).getBoundingClientRect();
|
||||
|
||||
if (barBounds) {
|
||||
me.bounds = [];
|
||||
me.scrollLeft = me.bar.$bar.scrollLeft();
|
||||
me.bar.scrollX = this.scrollLeft;
|
||||
|
||||
for (var i = 0; i < length; ++i) {
|
||||
this.bounds.push(me.bar.tabs[i].$el.get(0).getBoundingClientRect());
|
||||
}
|
||||
|
||||
me.tabBarLeft = me.bounds[0].left;
|
||||
me.tabBarRight = me.bounds[length - 1].right;
|
||||
me.tabBarRight = Math.min(me.tabBarRight, barBounds.right - 1);
|
||||
}
|
||||
},
|
||||
|
||||
setAbsTabs: function () {
|
||||
var me = this, tab = null, length = this.bounds.length;
|
||||
|
||||
for (var i = 0; i < length; ++i) {
|
||||
tab = me.bar.tabs[i].$el;
|
||||
tab.css('position', 'absolute');
|
||||
tab.css('left', (me.bounds[i].left - me.tabBarLeft - this.scrollLeft) + 'px');
|
||||
|
||||
if (tab.hasClass('active')) {
|
||||
tab.css('top', '1px');
|
||||
} else {
|
||||
tab.css('top', '0px');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
updatePositions: function () {
|
||||
this.drag.place = undefined;
|
||||
|
||||
var i, tabBound, center, place = -1, next = -this.scrollLeft,
|
||||
tabsCount = this.bounds.length,
|
||||
dragBound = this.drag.tab.$el.get(0).getBoundingClientRect();
|
||||
|
||||
if (this.drag.moveX - this.drag.mouseX > 0) {
|
||||
for (i = tabsCount - 1; i >= 0; --i) {
|
||||
tabBound = this.bounds[i];
|
||||
center = (tabBound.right + tabBound.left) * 0.5;
|
||||
if (dragBound.left < center && center < dragBound.right) {
|
||||
place = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (-1 === place) {
|
||||
for (i = tabsCount - 1; i >= 0; --i) {
|
||||
tabBound = dragBound;
|
||||
center = (tabBound.right + tabBound.left) * 0.5;
|
||||
if (this.bounds[i].left < center && center < this.bounds[i].right) {
|
||||
place = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
for (i = 0; i < tabsCount; ++i) {
|
||||
tabBound = this.bounds[i];
|
||||
center = (tabBound.right + tabBound.left) * 0.5;
|
||||
if (dragBound.left < center && center < dragBound.right) {
|
||||
place = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (-1 === place) {
|
||||
for (i = 0; i < tabsCount; ++i) {
|
||||
tabBound = dragBound;
|
||||
center = (tabBound.right + tabBound.left) * 0.5;
|
||||
if (this.bounds[i].left < center && center < this.bounds[i].right) {
|
||||
place = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (-1 !== place) {
|
||||
|
||||
this.drag.place = place;
|
||||
|
||||
for (i = 0; i < tabsCount; ++i) {
|
||||
if (i === place) {
|
||||
if (place < this.drag.index) {
|
||||
next += this.drag.tabWidth;
|
||||
}
|
||||
}
|
||||
|
||||
if (place > this.drag.index) {
|
||||
if (i === place + 1) {
|
||||
next += this.drag.tabWidth;
|
||||
}
|
||||
}
|
||||
|
||||
if (i !== this.drag.index) {
|
||||
this.bar.tabs[i].$el.css('left', next + 'px');
|
||||
} else {
|
||||
if (this.drag.index === place) {
|
||||
next += this.drag.tabWidth;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
next += this.bounds[i].width;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
setHook: function(e, bar, tab) {
|
||||
var me = this;
|
||||
|
||||
function dragComplete() {
|
||||
if (!_.isUndefined(me.drag)) {
|
||||
me.drag.tab.$el.css('z-index', '');
|
||||
|
||||
var tab = null;
|
||||
for (var i = me.bar.tabs.length - 1; i >= 0; --i) {
|
||||
tab = me.bar.tabs[i].$el;
|
||||
if (tab) {
|
||||
tab.css('top', '');
|
||||
tab.css('position', '');
|
||||
tab.css('left', '');
|
||||
}
|
||||
}
|
||||
|
||||
if (!_.isUndefined(me.drag.place)) {
|
||||
me.bar.trigger('tab:move', me.drag.index, me.drag.place);
|
||||
me.bar.$bar.scrollLeft(me.scrollLeft);
|
||||
me.bar.scrollX = undefined;
|
||||
} else {
|
||||
me.bar.trigger('tab:move', me.drag.index);
|
||||
me.bar.$bar.scrollLeft(me.scrollLeft);
|
||||
me.bar.scrollX = undefined;
|
||||
}
|
||||
|
||||
me.drag = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function dragMove (e) {
|
||||
if (!_.isUndefined(me.drag)) {
|
||||
me.drag.moveX = e.clientX;
|
||||
var leftPos = Math.max(e.clientX - me.drag.anchorX - me.tabBarLeft - me.scrollLeft, 0);
|
||||
leftPos = Math.min(leftPos, me.tabBarRight - me.tabBarLeft - me.drag.tabWidth - me.scrollLeft);
|
||||
|
||||
me.drag.tab.$el.css('left', leftPos + 'px');
|
||||
me.drag.tab.$el.css('z-index','100');
|
||||
|
||||
me.updatePositions();
|
||||
}
|
||||
}
|
||||
|
||||
function dragDropText (e) { // disable firefox drag&drop
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
if (!_.isUndefined(bar) && !_.isUndefined(tab) && bar.tabs.length > 1) {
|
||||
var index = bar.tabs.indexOf(tab);
|
||||
me.bar = bar;
|
||||
me.drag = {tab: tab, index: index};
|
||||
|
||||
this.calculateBounds();
|
||||
this.setAbsTabs();
|
||||
|
||||
me.drag.moveX = e.clientX;
|
||||
me.drag.mouseX = e.clientX;
|
||||
me.drag.anchorX = e.clientX - this.bounds[index].left;
|
||||
me.drag.tabWidth = this.bounds[index].width;
|
||||
|
||||
document.addEventListener('dragstart',dragDropText);
|
||||
|
||||
$(document).on('mousemove.tabbar', dragMove);
|
||||
$(document).on('mouseup.tabbar', function (e) {
|
||||
dragComplete(e);
|
||||
$(document).off('mouseup.tabbar');
|
||||
$(document).off('mousemove.tabbar');
|
||||
|
||||
document.removeEventListener('dragstart',dragDropText);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
tab.$el.on({
|
||||
click: $.proxy(function () {
|
||||
if (!tab.disabled && !tab.$el.hasClass('active')) {
|
||||
if (tab.control == 'manual') {
|
||||
this.bar.trigger('tab:manual', this.bar, this.bar.tabs.indexOf(tab), tab);
|
||||
} else {
|
||||
tab.changeState();
|
||||
}
|
||||
}
|
||||
}, this),
|
||||
dblclick: $.proxy(function() {
|
||||
this.trigger('tab:dblclick', this, this.tabs.indexOf(tab), tab);
|
||||
}, this.bar),
|
||||
contextmenu: $.proxy(function () {
|
||||
this.trigger('tab:contextmenu', this, this.tabs.indexOf(tab), tab);
|
||||
}, this.bar),
|
||||
mousedown: $.proxy(function (e) {
|
||||
if (this.bar.options.draggable && !_.isUndefined(dragHelper) && (3 !== e.which)) {
|
||||
if (!tab.isLockTheDrag) {
|
||||
dragHelper.setHook(e, this.bar, tab);
|
||||
}
|
||||
}
|
||||
}, this)
|
||||
});
|
||||
};
|
||||
|
||||
StateManager.prototype.detach = function (tab) {
|
||||
tab.$el.off();
|
||||
};
|
||||
|
||||
Common.UI.TabBar = Common.UI.BaseView.extend({
|
||||
config: {
|
||||
placement : 'top',
|
||||
items : [],
|
||||
draggable : false
|
||||
},
|
||||
|
||||
tabs: [],
|
||||
template: _.template('<ul class="nav nav-tabs <%= placement %>" />'),
|
||||
|
||||
initialize : function (options) {
|
||||
_.extend(this.config, options);
|
||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
||||
|
||||
this.saved = [];
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.$el.html(this.template(this.config));
|
||||
this.$bar = this.$el.find('ul');
|
||||
|
||||
var addEvent = function( elem, type, fn ) {
|
||||
elem.addEventListener ? elem.addEventListener( type, fn, false ) : elem.attachEvent( "on" + type, fn );
|
||||
};
|
||||
|
||||
var eventname=(/Firefox/i.test(navigator.userAgent))? 'DOMMouseScroll' : 'mousewheel';
|
||||
addEvent(this.$bar[0], eventname, _.bind(this._onMouseWheel,this));
|
||||
|
||||
this.manager = new StateManager({bar: this});
|
||||
|
||||
this.insert(-1, this.config.items);
|
||||
this.insert(-1, this.saved);
|
||||
delete this.saved;
|
||||
|
||||
this.rendered = true;
|
||||
return this;
|
||||
},
|
||||
|
||||
_onMouseWheel: function(e) {
|
||||
var hidden = this.checkInvisible(true),
|
||||
forward = ((e.detail && -e.detail) || e.wheelDelta) > 0;
|
||||
|
||||
if (forward) {
|
||||
if (hidden.last) {
|
||||
this.setTabVisible('forward');
|
||||
}
|
||||
} else {
|
||||
if (hidden.first) {
|
||||
this.setTabVisible('backward');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
add: function(tabs) {
|
||||
return this.insert(-1, tabs) > 0;
|
||||
},
|
||||
|
||||
insert: function(index, tabs) {
|
||||
var count = 0;
|
||||
if (tabs) {
|
||||
if (!(tabs instanceof Array)) tabs = [tabs];
|
||||
|
||||
if (tabs.length) {
|
||||
count = tabs.length;
|
||||
|
||||
if (this.rendered) {
|
||||
var me = this, tab;
|
||||
|
||||
if (index < 0 || index > me.tabs.length) {
|
||||
for (var i = 0; i < tabs.length; i++) {
|
||||
tab = new Common.UI.Tab(tabs[i]);
|
||||
me.$bar.append(tab.render().$el);
|
||||
me.tabs.push(tab);
|
||||
me.manager.attach(tab);
|
||||
}
|
||||
} else {
|
||||
for (i = tabs.length; i-- > 0 ; ) {
|
||||
tab = new Common.UI.Tab(tabs[i]);
|
||||
|
||||
if (index === 0) {
|
||||
me.$bar.prepend(tab.render().$el);
|
||||
me.tabs.unshift(tab);
|
||||
} else {
|
||||
me.$bar.find('li:nth-child(' + index + ')').before(tab.render().$el);
|
||||
me.tabs.splice(index, 0, tab);
|
||||
}
|
||||
|
||||
me.manager.attach(tab);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.saved.push(tabs)
|
||||
}
|
||||
|
||||
this.checkInvisible();
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
},
|
||||
|
||||
remove: function(index) {
|
||||
if (index >= 0 && index < this.tabs.length) {
|
||||
var tab = this.tabs.splice(index, 1)[0];
|
||||
this.manager.detach(tab);
|
||||
tab.$el.remove();
|
||||
this.checkInvisible();
|
||||
}
|
||||
},
|
||||
|
||||
empty: function(suppress) {
|
||||
var me = this;
|
||||
this.tabs.forEach(function(tab){
|
||||
me.manager.detach(tab);
|
||||
});
|
||||
|
||||
this.$bar.empty();
|
||||
me.tabs = [];
|
||||
|
||||
this.checkInvisible(suppress);
|
||||
},
|
||||
|
||||
setActive: function(t) {
|
||||
if (t instanceof Common.UI.Tab) {
|
||||
tab = t;
|
||||
} else
|
||||
if (typeof t == 'number') {
|
||||
if (t >= 0 && t < this.tabs.length) {
|
||||
var tab = this.tabs[t];
|
||||
}
|
||||
}
|
||||
|
||||
if(tab && tab.control != 'manual' && !tab.disabled && !tab.$el.hasClass('active')){
|
||||
tab.changeState();
|
||||
}
|
||||
|
||||
this.checkInvisible();
|
||||
},
|
||||
|
||||
getActive: function(iselem) {
|
||||
return iselem ? this.$bar.find('> li.active') : this.$bar.find('> li.active').index();
|
||||
},
|
||||
|
||||
getAt: function(index) {
|
||||
return (index >= 0 && index < this.tabs.length) ? this.tabs[index] : undefined;
|
||||
},
|
||||
|
||||
getCount: function() {
|
||||
return this.tabs.length;
|
||||
},
|
||||
|
||||
addClass: function(cls) {
|
||||
if (cls.length && !this.$bar.hasClass(cls))
|
||||
this.$bar.addClass(cls);
|
||||
},
|
||||
|
||||
removeClass: function(cls) {
|
||||
if (cls.length && this.$bar.hasClass(cls))
|
||||
this.$bar.removeClass(cls);
|
||||
},
|
||||
|
||||
hasClass: function(cls) {
|
||||
return this.$bar.hasClass(cls);
|
||||
},
|
||||
|
||||
setTabVisible: function(index, suppress) {
|
||||
if (index <= 0 || index == 'first') {
|
||||
this.$bar.scrollLeft(0);
|
||||
this.checkInvisible(suppress);
|
||||
} else if ( index >= (this.tabs.length - 1) || index == 'last') {
|
||||
var tab = this.tabs[this.tabs.length-1].$el;
|
||||
this.$bar.scrollLeft(this.$bar.scrollLeft() + (tab.position().left + parseInt(tab.css('width')) - this.$bar.width()) + 1);
|
||||
this.checkInvisible(suppress);
|
||||
} else {
|
||||
var rightbound = this.$bar.width(),
|
||||
tab, right, left;
|
||||
|
||||
if (index == 'forward') {
|
||||
for (var i = 0; i < this.tabs.length; i++) {
|
||||
tab = this.tabs[i].$el;
|
||||
right = tab.position().left + parseInt(tab.css('width'));
|
||||
|
||||
if (right > rightbound) {
|
||||
this.$bar.scrollLeft(this.$bar.scrollLeft() + (right - rightbound) + 20);
|
||||
this.checkInvisible(suppress);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (index == 'backward') {
|
||||
for (i = this.tabs.length; i-- > 0; ) {
|
||||
tab = this.tabs[i].$el;
|
||||
left = tab.position().left;
|
||||
|
||||
if (left < 0) {
|
||||
this.$bar.scrollLeft(this.$bar.scrollLeft() + left - 26);
|
||||
this.checkInvisible(suppress);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (typeof index == 'number') {
|
||||
tab = this.tabs[index].$el;
|
||||
left = tab.position().left;
|
||||
right = left + parseInt(tab.css('width'));
|
||||
|
||||
if (left < 0) {
|
||||
this.$bar.scrollLeft(this.$bar.scrollLeft() + left - 26);
|
||||
this.checkInvisible(suppress);
|
||||
} else if (right > rightbound) {
|
||||
this.$bar.scrollLeft(this.$bar.scrollLeft() + (right - rightbound) + 20);
|
||||
this.checkInvisible(suppress);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
checkInvisible: function(suppress) {
|
||||
var result = {
|
||||
first: !this.isTabVisible(0),
|
||||
last: !this.isTabVisible(this.tabs.length-1)
|
||||
};
|
||||
|
||||
!suppress && this.fireEvent('tab:invisible', this, result);
|
||||
return result;
|
||||
},
|
||||
|
||||
hasInvisible: function() {
|
||||
var _left_bound_ = this.$bar.offset().left,
|
||||
_right_bound_ = _left_bound_ + this.$bar.width();
|
||||
|
||||
for (var i = this.tabs.length; i-- > 0; ) {
|
||||
if (!this.isTabVisible(i, _left_bound_, _right_bound_)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
isTabVisible: function(index) {
|
||||
var leftbound = arguments[1] || this.$bar.offset().left,
|
||||
rightbound = arguments[2] || (leftbound + this.$bar.width()),
|
||||
left, right, tab, rect;
|
||||
|
||||
if (index < this.tabs.length && index >= 0) {
|
||||
tab = this.tabs[index].$el;
|
||||
rect = tab.get(0).getBoundingClientRect();
|
||||
left = rect.left;
|
||||
right = rect.right;
|
||||
|
||||
//left = tab.position().left;
|
||||
//right = left + tab.width();
|
||||
|
||||
return !(left < leftbound) && !(right > rightbound);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
794
apps/common/main/lib/component/TableStyler.js
Normal file
794
apps/common/main/lib/component/TableStyler.js
Normal file
|
@ -0,0 +1,794 @@
|
|||
/**
|
||||
* TableStyler.js
|
||||
*
|
||||
* Created by Alexander Yuzhin on 2/28/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'common/main/lib/component/BaseView'
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
Common.UI.CellStyler = Common.UI.BaseView.extend({
|
||||
options : {
|
||||
clickOffset : 10,
|
||||
overwriteStyle : true,
|
||||
maxBorderSize : 6,
|
||||
halfBorderSize : false,
|
||||
defaultBorderSize : 1,
|
||||
defaultBorderColor : '#ccc'
|
||||
},
|
||||
|
||||
template: _.template([
|
||||
'<div id="<%=id%>" class="tablestyler-cell" style="">',
|
||||
'<div class="cell-content" style="">',
|
||||
'<div class="content-text"></div>',
|
||||
'</div>',
|
||||
'</div>'
|
||||
].join('')),
|
||||
|
||||
initialize : function(options) {
|
||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
||||
|
||||
var me = this,
|
||||
divContent = undefined,
|
||||
virtualBorderSize,
|
||||
virtualBorderColor,
|
||||
borderSize = {},
|
||||
borderColor = {},
|
||||
borderAlfa = {};
|
||||
|
||||
me.id = me.options.id || Common.UI.getId();
|
||||
me.clickOffset = me.options.clickOffset;
|
||||
me.overwriteStyle = me.options.overwriteStyle;
|
||||
me.maxBorderSize = me.options.maxBorderSize;
|
||||
me.halfBorderSize = me.options.halfBorderSize;
|
||||
me.defaultBorderSize = me.options.defaultBorderSize;
|
||||
me.defaultBorderColor = me.options.defaultBorderColor;
|
||||
me.col = me.options.col;
|
||||
me.row = me.options.row;
|
||||
|
||||
virtualBorderSize = me.defaultBorderSize;
|
||||
virtualBorderColor = new Common.Utils.RGBColor(me.defaultBorderColor);
|
||||
|
||||
borderSize = {
|
||||
top : virtualBorderSize,
|
||||
right : virtualBorderSize,
|
||||
bottom : virtualBorderSize,
|
||||
left : virtualBorderSize
|
||||
};
|
||||
|
||||
borderColor = {
|
||||
top : virtualBorderColor,
|
||||
right : virtualBorderColor,
|
||||
bottom : virtualBorderColor,
|
||||
left : virtualBorderColor
|
||||
};
|
||||
|
||||
borderAlfa = {
|
||||
top : 1,
|
||||
right : 1,
|
||||
bottom : 1,
|
||||
left : 1
|
||||
};
|
||||
|
||||
me.rendered = false;
|
||||
|
||||
var applyStyle = function(){
|
||||
if (!_.isUndefined(divContent)){
|
||||
var brd = (borderSize.left>0.1 && borderSize.left<1) ? 1 : borderSize.left;
|
||||
var drawLeftSize = Math.abs((me.halfBorderSize) ? ((brd % 2) ? brd - 1: brd) * 0.5 : brd);
|
||||
|
||||
brd = (borderSize.right>0.1 && borderSize.right<1) ? 1 : borderSize.right;
|
||||
var drawRightSize = Math.abs((me.halfBorderSize) ? ((brd % 2) ? brd + 1: brd) * 0.5 : brd);
|
||||
|
||||
brd = (borderSize.top>0.1 && borderSize.top<1) ? 1 : borderSize.top;
|
||||
var drawTopSize = Math.abs((me.halfBorderSize) ? ((brd % 2) ? brd - 1: brd) * 0.5 : brd);
|
||||
|
||||
brd = (borderSize.bottom>0.1 && borderSize.bottom<1) ? 1 : borderSize.bottom;
|
||||
var drawBottomSize = Math.abs((me.halfBorderSize) ? ((brd % 2) ? brd + 1: brd) * 0.5 : brd);
|
||||
|
||||
var value =
|
||||
'inset ' + ((drawLeftSize>0.1 && drawLeftSize<1) ? 1 : drawLeftSize) + 'px' + ' 0' + ' 0 ' + borderColor.left.toRGBA(borderAlfa.left) + ', ' +
|
||||
'inset ' + -1*((drawRightSize>0.1 && drawRightSize<1) ? 1 : drawRightSize) + 'px' + ' 0' + ' 0 ' + borderColor.right.toRGBA(borderAlfa.right) + ', ' +
|
||||
'inset ' + '0 ' + ((drawTopSize>0.1 && drawTopSize<1) ? 1 : drawTopSize) + 'px' + ' 0 ' + borderColor.top.toRGBA(borderAlfa.top) + ', ' +
|
||||
'inset ' + '0 ' + -1*((drawBottomSize>0.1 && drawBottomSize<1) ? 1 : drawBottomSize) + 'px' + ' 0 ' + borderColor.bottom.toRGBA(borderAlfa.bottom);
|
||||
|
||||
divContent.css('box-shadow', value);
|
||||
}
|
||||
};
|
||||
|
||||
me.on('render:after', function(cmp) {
|
||||
if (this.cmpEl){
|
||||
divContent = this.cmpEl.find('.cell-content');
|
||||
|
||||
applyStyle();
|
||||
}
|
||||
|
||||
this.cmpEl.on('click', function(event){
|
||||
var pos = {
|
||||
x: event.pageX - me.cmpEl.offset().left,
|
||||
y: event.pageY - me.cmpEl.offset().top
|
||||
};
|
||||
|
||||
var ptInPoly = function(npol, xp, yp, x, y) {
|
||||
var i, j, c = 0;
|
||||
for (i = 0, j = npol - 1; i < npol; j = i++){
|
||||
if ((((yp [i] <= y) && (y < yp [j])) || ((yp [j] <= y) && (y < yp [i]))) && (x < (xp [j] - xp [i]) * (y - yp [i]) / (yp [j] - yp [i]) + xp [i]))
|
||||
c = !c;
|
||||
}
|
||||
return c;
|
||||
};
|
||||
|
||||
var meWidth = me.cmpEl.outerWidth();
|
||||
var meHeight = me.cmpEl.outerHeight();
|
||||
|
||||
if (ptInPoly(4, [0, meWidth, meWidth-me.clickOffset, me.clickOffset], [0, 0, me.clickOffset, me.clickOffset], pos.x, pos.y)){
|
||||
if (me.overwriteStyle){
|
||||
if (borderSize.top != virtualBorderSize || !borderColor.top.isEqual(virtualBorderColor)){
|
||||
borderSize.top = virtualBorderSize;
|
||||
borderColor.top = virtualBorderColor;
|
||||
borderAlfa.top = (virtualBorderSize<1) ? 0.3 : 1;
|
||||
} else {
|
||||
borderSize.top = 0;
|
||||
}
|
||||
} else {
|
||||
borderSize.top = (borderSize.top > 0) ? 0 : virtualBorderSize;
|
||||
borderColor.top = virtualBorderColor;
|
||||
}
|
||||
|
||||
me.fireEvent('borderclick', me, 't', borderSize.top, borderColor.top.toHex());
|
||||
|
||||
} else if (ptInPoly(4, [meWidth, meWidth, meWidth-me.clickOffset, meWidth-me.clickOffset], [0, meHeight, meHeight-me.clickOffset, me.clickOffset], pos.x, pos.y)){
|
||||
if (me.overwriteStyle){
|
||||
if (borderSize.right != virtualBorderSize || !borderColor.right.isEqual(virtualBorderColor)){
|
||||
borderSize.right = virtualBorderSize;
|
||||
borderColor.right = virtualBorderColor;
|
||||
borderAlfa.right = (virtualBorderSize<1) ? 0.3 : 1;
|
||||
} else {
|
||||
borderSize.right = 0;
|
||||
}
|
||||
} else {
|
||||
borderSize.right = (borderSize.right > 0) ? 0 : virtualBorderSize;
|
||||
borderColor.right = virtualBorderColor;
|
||||
}
|
||||
|
||||
me.fireEvent('borderclick', me, 'r', borderSize.right, borderColor.right.toHex());
|
||||
|
||||
} else if (ptInPoly(4, [0, me.clickOffset, meWidth-me.clickOffset, meWidth], [meHeight, meHeight-me.clickOffset, meHeight-me.clickOffset, meHeight], pos.x, pos.y)){
|
||||
if (me.overwriteStyle){
|
||||
if (borderSize.bottom != virtualBorderSize || !borderColor.bottom.isEqual(virtualBorderColor)){
|
||||
borderSize.bottom = virtualBorderSize;
|
||||
borderColor.bottom = virtualBorderColor;
|
||||
borderAlfa.bottom = (virtualBorderSize<1) ? 0.3 : 1;
|
||||
} else {
|
||||
borderSize.bottom = 0;
|
||||
}
|
||||
} else {
|
||||
borderSize.bottom = (borderSize.bottom > 0) ? 0 : virtualBorderSize;
|
||||
borderColor.bottom = virtualBorderColor;
|
||||
}
|
||||
|
||||
me.fireEvent('borderclick', me, 'b', borderSize.bottom, borderColor.bottom.toHex());
|
||||
|
||||
} else if (ptInPoly(4, [0, me.clickOffset, me.clickOffset, 0], [0, me.clickOffset, meHeight-me.clickOffset, meHeight], pos.x, pos.y)){
|
||||
if (me.overwriteStyle){
|
||||
if (borderSize.left != virtualBorderSize || !borderColor.left.isEqual(virtualBorderColor)){
|
||||
borderSize.left = virtualBorderSize;
|
||||
borderColor.left = virtualBorderColor;
|
||||
borderAlfa.left = (virtualBorderSize<1) ? 0.3 : 1;
|
||||
} else {
|
||||
borderSize.left = 0;
|
||||
}
|
||||
} else {
|
||||
borderSize.left = (borderSize.left > 0) ? 0 : virtualBorderSize;
|
||||
borderColor.left = virtualBorderColor;
|
||||
}
|
||||
|
||||
me.fireEvent('borderclick', me, 'l', borderSize.left, borderColor.left.toHex());
|
||||
}
|
||||
|
||||
applyStyle();
|
||||
});
|
||||
});
|
||||
|
||||
me.setBordersSize = function(borders, size) {
|
||||
size = (size > this.maxBorderSize) ? this.maxBorderSize : size;
|
||||
|
||||
if (borders.indexOf('t') > -1) {
|
||||
borderSize.top = size;
|
||||
borderAlfa.top = (size<1) ? 0.3 : 1;
|
||||
}
|
||||
if (borders.indexOf('r') > -1) {
|
||||
borderSize.right = size;
|
||||
borderAlfa.right = (size<1) ? 0.3 : 1;
|
||||
}
|
||||
if (borders.indexOf('b') > -1) {
|
||||
borderSize.bottom = size;
|
||||
borderAlfa.bottom = (size<1) ? 0.3 : 1;
|
||||
}
|
||||
if (borders.indexOf('l') > -1) {
|
||||
borderSize.left = size;
|
||||
borderAlfa.left = (size<1) ? 0.3 : 1;
|
||||
}
|
||||
|
||||
applyStyle();
|
||||
};
|
||||
|
||||
me.setBordersColor = function(borders, color) {
|
||||
var newColor = new Common.Utils.RGBColor(color);
|
||||
|
||||
if (borders.indexOf('t') > -1)
|
||||
borderColor.top = newColor;
|
||||
if (borders.indexOf('r') > -1)
|
||||
borderColor.right = newColor;
|
||||
if (borders.indexOf('b') > -1)
|
||||
borderColor.bottom = newColor;
|
||||
if (borders.indexOf('l') > -1)
|
||||
borderColor.left = newColor;
|
||||
|
||||
applyStyle();
|
||||
};
|
||||
|
||||
me.getBorderSize = function(border) {
|
||||
switch(border){
|
||||
case 't':
|
||||
return borderSize.top;
|
||||
case 'r':
|
||||
return borderSize.right;
|
||||
case 'b':
|
||||
return borderSize.bottom;
|
||||
case 'l':
|
||||
return borderSize.left;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
me.getBorderColor = function(border) {
|
||||
switch(border){
|
||||
case 't':
|
||||
return borderColor.top.toHex();
|
||||
case 'r':
|
||||
return borderColor.right.toHex();
|
||||
case 'b':
|
||||
return borderColor.bottom.toHex();
|
||||
case 'l':
|
||||
return borderColor.left.toHex();
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
me.setVirtualBorderSize = function(size) {
|
||||
virtualBorderSize = (size > this.maxBorderSize) ? this.maxBorderSize : size;
|
||||
};
|
||||
|
||||
me.setVirtualBorderColor = function(color){
|
||||
var newColor = new Common.Utils.RGBColor(color);
|
||||
|
||||
if (virtualBorderColor.isEqual(newColor))
|
||||
return;
|
||||
|
||||
virtualBorderColor = newColor;
|
||||
};
|
||||
|
||||
me.getVirtualBorderSize = function() {
|
||||
return virtualBorderSize;
|
||||
};
|
||||
|
||||
me.getVirtualBorderColor = function() {
|
||||
return virtualBorderColor.toHex();
|
||||
};
|
||||
|
||||
if (me.options.el) {
|
||||
me.render();
|
||||
}
|
||||
},
|
||||
|
||||
render : function(parentEl) {
|
||||
var me = this;
|
||||
|
||||
this.trigger('render:before', this);
|
||||
|
||||
if (!me.rendered) {
|
||||
this.cmpEl = $(this.template({
|
||||
id: this.id
|
||||
}));
|
||||
|
||||
if (parentEl) {
|
||||
this.setElement(parentEl, false);
|
||||
parentEl.html(this.cmpEl);
|
||||
} else {
|
||||
$(this.el).html(this.cmpEl);
|
||||
}
|
||||
} else {
|
||||
this.cmpEl = $(this.el);
|
||||
}
|
||||
|
||||
me.rendered = true;
|
||||
|
||||
this.trigger('render:after', this);
|
||||
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Common.UI.TableStyler = Common.UI.BaseView.extend({
|
||||
options : {
|
||||
width : 200,
|
||||
height : 200,
|
||||
rows : 2,
|
||||
columns : 2,
|
||||
cellPadding : 10,
|
||||
tablePadding : 10,
|
||||
overwriteStyle : true,
|
||||
maxBorderSize : 6,
|
||||
spacingMode : false,
|
||||
defaultBorderSize : 1,
|
||||
defaultBorderColor : '#ccc'
|
||||
},
|
||||
|
||||
template: _.template([
|
||||
'<div id="<%=scope.id%>" class="table-styler" style="position: relative; width: <%=scope.width%>px; height:<%=scope.height%>px;">',
|
||||
'<div style="position: absolute; left: 0; top: 0; width: <%=scope.tablePadding%>px; height: <%=scope.tablePadding%>px; border-bottom: 1px dotted gray; border-right: 1px dotted gray;"></div>',
|
||||
'<div style="position: absolute; left: <%=scope.tablePadding%>px; top: 0; right: <%=scope.tablePadding%>px; height: <%=scope.tablePadding%>px;">',
|
||||
'<div id="<%=scope.id%>-table-top-border-selector" style="position: absolute; z-index: 1; height: <%=scope.tablePadding%>px; left: 0; right: 0; top: <%=scope.tablePadding * .5%>px;">',
|
||||
'<table width="100%" height="100%">',
|
||||
'<tr>',
|
||||
'<td id="<%=scope.id%>-table-top-border" style="height:50%; border-bottom: <%=borderSize.top%>px solid <%borderColor.top.toHex()%>;"></td>',
|
||||
'</tr>',
|
||||
'<tr>',
|
||||
'<td></td>',
|
||||
'</tr>',
|
||||
'</table>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'<div style="position: absolute; top: 0; right: 0; width: <%=scope.tablePadding%>px; height: <%=scope.tablePadding%>px; border-bottom: 1px dotted gray; border-left: 1px dotted gray;"></div>',
|
||||
|
||||
'<div style="position: absolute; left: 0; top: <%=scope.tablePadding%>px; width: <%=scope.tablePadding%>px; height: <%=scope.height - 2 * scope.tablePadding%>px;">',
|
||||
'<div id="<%=scope.id%>-table-left-border-selector" style="position: absolute; z-index: 1; left: <%=scope.tablePadding * .5%>px; top: 0; bottom: 0; width: <%=scope.tablePadding%>px;">',
|
||||
'<table width="100%" height="100%">',
|
||||
'<tr>',
|
||||
'<td id="<%=scope.id%>-table-left-border" style="border-right: <%=borderSize.left%>px solid <%=borderColor.left.toHex()%>;"></td>',
|
||||
'<td width="50%"></td>',
|
||||
'</tr>',
|
||||
'</table>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'<div style="position: absolute; left: <%=scope.tablePadding%>px; top: <%=scope.tablePadding%>px; right: <%=scope.tablePadding%>px; bottom: <%=scope.tablePadding%>px;">',
|
||||
'<table cols="<%=scope.columns%>" width="100%" height="100%" style="border-collapse: inherit; border-spacing: <%= scope.spacingMode ? scope.cellPadding : 0 %>px;">',
|
||||
'<% for (var row = 0; row < scope.rows; row++) { %>',
|
||||
'<tr>',
|
||||
'<% for (var col = 0; col < scope.columns; col++) { %>',
|
||||
'<td id="<%=scope.id%>-cell-container-<%=col%>-<%=row%>" class="content-box"></td>',
|
||||
'<% } %>',
|
||||
'</tr>',
|
||||
'<% } %>',
|
||||
'</table>',
|
||||
'</div>',
|
||||
'<div style="position: absolute; right: 0; top: <%=scope.tablePadding%>px; width: <%=scope.tablePadding%>px; height: <%=scope.height - 2 * scope.tablePadding%>px;">',
|
||||
'<div id="<%=scope.id%>-table-right-border-selector" style="position: absolute; z-index: 1; right: <%=scope.tablePadding * .5%>px; top: 0; bottom: 0; width: <%=scope.tablePadding%>px;">',
|
||||
'<table width="100%" height="100%">',
|
||||
'<tr>',
|
||||
'<td id="<%=scope.id%>-table-right-border" style="border-right: <%=borderSize.right%>px solid <%=borderColor.right.toHex()%>;"></td>',
|
||||
'<td width="50%"></td>',
|
||||
'</tr>',
|
||||
'</table>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
|
||||
'<div style="position: absolute; left: 0; bottom: 0; width: <%=scope.tablePadding%>px; height: <%=scope.tablePadding%>px; border-top: 1pt dotted gray; border-right: 1pt dotted gray;"></div>',
|
||||
'<div style="position: absolute; left: <%=scope.tablePadding%>px; bottom: 0; right: <%=scope.tablePadding%>px; height: <%=scope.tablePadding%>px;">',
|
||||
'<div id="<%=scope.id%>-table-bottom-border-selector" style="position: absolute; z-index: 1; height: <%=scope.tablePadding%>px; left: 0; right: 0; bottom: <%=scope.tablePadding * .5%>px;">',
|
||||
'<table width="100%" height="100%">',
|
||||
'<tr>',
|
||||
'<td id="<%=scope.id%>-table-bottom-border" style="height:50%; border-bottom: <%=borderSize.bottom%>px solid <%=borderColor.bottom.toHex()%>;"></td>',
|
||||
'</tr>',
|
||||
'<tr>',
|
||||
'<td></td>',
|
||||
'</tr>',
|
||||
'</table>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'<div style="position: absolute; bottom: 0; right: 0; width: <%=scope.tablePadding%>px; height: <%=scope.tablePadding%>px; border-top: 1pt dotted gray; border-left: 1pt dotted gray;"></div>',
|
||||
'</div>'
|
||||
].join('')),
|
||||
|
||||
initialize : function(options) {
|
||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
||||
|
||||
var me = this,
|
||||
topBorder, rightBorder, bottomBorder, leftBorder,
|
||||
topBorderSelector, rightBorderSelector, bottomBorderSelector,
|
||||
leftBorderSelector,
|
||||
virtualBorderSize, virtualBorderColor;
|
||||
|
||||
me.id = me.options.id || Common.UI.getId();
|
||||
me.width = me.options.width;
|
||||
me.height = me.options.height;
|
||||
me.rows = me.options.rows;
|
||||
me.columns = me.options.columns;
|
||||
me.cellPadding = me.options.cellPadding;
|
||||
me.tablePadding = me.options.tablePadding;
|
||||
me.overwriteStyle = me.options.overwriteStyle;
|
||||
me.maxBorderSize = me.options.maxBorderSize;
|
||||
me.spacingMode = me.options.spacingMode;
|
||||
me.defaultBorderSize = me.options.defaultBorderSize;
|
||||
me.defaultBorderColor = me.options.defaultBorderColor;
|
||||
|
||||
virtualBorderSize = (me.defaultBorderSize > me.maxBorderSize) ? me.maxBorderSize : me.defaultBorderSize;
|
||||
virtualBorderColor = new Common.Utils.RGBColor(me.defaultBorderColor);
|
||||
|
||||
var borderSize = {
|
||||
top : virtualBorderSize,
|
||||
right : virtualBorderSize,
|
||||
bottom : virtualBorderSize,
|
||||
left : virtualBorderSize
|
||||
};
|
||||
|
||||
var borderColor = {
|
||||
top : virtualBorderColor,
|
||||
right : virtualBorderColor,
|
||||
bottom : virtualBorderColor,
|
||||
left : virtualBorderColor
|
||||
};
|
||||
|
||||
me.rendered = false;
|
||||
|
||||
var applyStyles = function(){
|
||||
topBorder && topBorder.css('border-bottom', ((borderSize.top > 0.1 && borderSize.top < 1) ? 1 : borderSize.top) + 'px solid ' + borderColor.top.toRGBA((borderSize.top < 1) ? 0.2 : 1));
|
||||
rightBorder && rightBorder.css('border-right', ((borderSize.right > 0.1 && borderSize.right < 1) ? 1 : borderSize.right) + 'px solid ' + borderColor.right.toRGBA((borderSize.right < 1) ? 0.2 : 1));
|
||||
bottomBorder && bottomBorder.css('border-bottom', ((borderSize.bottom > 0.1 && borderSize.bottom < 1) ? 1 : borderSize.bottom) + 'px solid ' + borderColor.bottom.toRGBA((borderSize.bottom < 1) ? 0.2 : 1));
|
||||
leftBorder && leftBorder.css('border-right', ((borderSize.left > 0.1 && borderSize.left < 1) ? 1 : borderSize.left) + 'px solid ' + borderColor.left.toRGBA((borderSize.left < 1) ? 0.2 : 1));
|
||||
redraw(topBorderSelector); redraw(rightBorderSelector);
|
||||
redraw(bottomBorderSelector); redraw(leftBorderSelector);
|
||||
};
|
||||
|
||||
var redraw = function(el) {
|
||||
return el.hide(0, function() {
|
||||
$(this).show();
|
||||
});
|
||||
};
|
||||
|
||||
me.on('render:after', function(cmp) {
|
||||
var meId = me.id;
|
||||
|
||||
topBorder = $('#' + meId + '-table-top-border');
|
||||
rightBorder = $('#' + meId + '-table-right-border');
|
||||
bottomBorder = $('#' + meId + '-table-bottom-border');
|
||||
leftBorder = $('#' + meId + '-table-left-border');
|
||||
topBorderSelector = $('#' + meId + '-table-top-border-selector');
|
||||
rightBorderSelector = $('#' + meId + '-table-right-border-selector');
|
||||
bottomBorderSelector = $('#' + meId + '-table-bottom-border-selector');
|
||||
leftBorderSelector = $('#' + meId + '-table-left-border-selector');
|
||||
|
||||
topBorderSelector.on('click', function(e){
|
||||
if (me.overwriteStyle){
|
||||
if (borderSize.top != virtualBorderSize || !borderColor.top.isEqual(virtualBorderColor)){
|
||||
borderSize.top = virtualBorderSize;
|
||||
borderColor.top = virtualBorderColor;
|
||||
} else {
|
||||
borderSize.top = 0;
|
||||
}
|
||||
} else {
|
||||
borderSize.top = (borderSize.top > 0) ? 0 : virtualBorderSize;
|
||||
borderColor.top = virtualBorderColor;
|
||||
}
|
||||
topBorder.css('border-bottom', ((borderSize.top > 0.1 && borderSize.top < 1) ? 1 : borderSize.top) + 'px solid ' + borderColor.top.toRGBA((borderSize.top < 1) ? 0.2 : 1));
|
||||
redraw(topBorderSelector);
|
||||
|
||||
me.fireEvent('borderclick', me, 't', borderSize.top, borderColor.top.toHex());
|
||||
});
|
||||
|
||||
rightBorderSelector.on('click', function(e){
|
||||
if (me.overwriteStyle){
|
||||
if (borderSize.right != virtualBorderSize || !borderColor.right.isEqual(virtualBorderColor)){
|
||||
borderSize.right = virtualBorderSize;
|
||||
borderColor.right = virtualBorderColor;
|
||||
} else {
|
||||
borderSize.right = 0;
|
||||
}
|
||||
} else {
|
||||
borderSize.right = (borderSize.right > 0) ? 0 : virtualBorderSize;
|
||||
borderColor.right = virtualBorderColor;
|
||||
}
|
||||
rightBorder.css('border-right', ((borderSize.right > 0.1 && borderSize.right < 1) ? 1 : borderSize.right) + 'px solid ' + borderColor.right.toRGBA((borderSize.right < 1) ? 0.2 : 1));
|
||||
redraw(rightBorderSelector);
|
||||
|
||||
me.fireEvent('borderclick', me, 'r', borderSize.right, borderColor.right.toHex());
|
||||
});
|
||||
|
||||
bottomBorderSelector.on('click', function(e){
|
||||
if (me.overwriteStyle){
|
||||
if (borderSize.bottom != virtualBorderSize || !borderColor.bottom.isEqual(virtualBorderColor)){
|
||||
borderSize.bottom = virtualBorderSize;
|
||||
borderColor.bottom = virtualBorderColor;
|
||||
} else {
|
||||
borderSize.bottom = 0;
|
||||
}
|
||||
} else {
|
||||
borderSize.bottom = (borderSize.bottom > 0) ? 0 : virtualBorderSize;
|
||||
borderColor.bottom = virtualBorderColor;
|
||||
}
|
||||
|
||||
bottomBorder.css('border-bottom', ((borderSize.bottom > 0.1 && borderSize.bottom < 1) ? 1 : borderSize.bottom) + 'px solid ' + borderColor.bottom.toRGBA((borderSize.bottom < 1) ? 0.2 : 1));
|
||||
redraw(bottomBorderSelector);
|
||||
|
||||
me.fireEvent('borderclick', me, 'b', borderSize.bottom, borderColor.bottom.toHex());
|
||||
});
|
||||
|
||||
leftBorderSelector.on('click', function(e){
|
||||
if (me.overwriteStyle){
|
||||
if (borderSize.left != virtualBorderSize || !borderColor.left.isEqual(virtualBorderColor)){
|
||||
borderSize.left = virtualBorderSize;
|
||||
borderColor.left = virtualBorderColor;
|
||||
} else {
|
||||
borderSize.left = 0;
|
||||
}
|
||||
} else {
|
||||
borderSize.left = (borderSize.left > 0) ? 0 : virtualBorderSize;
|
||||
borderColor.left = virtualBorderColor;
|
||||
}
|
||||
leftBorder.css('border-right', ((borderSize.left > 0.1 && borderSize.left < 1) ? 1 : borderSize.left) + 'px solid ' + borderColor.left.toRGBA((borderSize.left < 1) ? 0.2 : 1));
|
||||
redraw(leftBorderSelector);
|
||||
|
||||
me.fireEvent('borderclick', me, 'l', borderSize.left, borderColor.left.toHex());
|
||||
});
|
||||
});
|
||||
|
||||
me.getVirtualBorderSize = function(){
|
||||
return virtualBorderSize;
|
||||
};
|
||||
|
||||
me.getVirtualBorderColor = function(){
|
||||
return virtualBorderColor.toHex();
|
||||
};
|
||||
|
||||
me.setVirtualBorderSize = function(size){
|
||||
size = (size > me.maxBorderSize) ? me.maxBorderSize : size;
|
||||
|
||||
virtualBorderSize = size;
|
||||
|
||||
for (var row = 0; row < me.rows; row++){
|
||||
for (var col = 0; col < me.columns; col++){
|
||||
var cell = me.getCell(col, row);
|
||||
cell.setVirtualBorderSize(size);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
me.setVirtualBorderColor = function(color){
|
||||
var newColor = new Common.Utils.RGBColor(color);
|
||||
|
||||
if (virtualBorderColor.isEqual(newColor))
|
||||
return;
|
||||
|
||||
virtualBorderColor = newColor;
|
||||
|
||||
for (var row = 0; row < me.rows; row++){
|
||||
for (var col = 0; col < me.columns; col++){
|
||||
var cell = me.getCell(col, row);
|
||||
cell.setVirtualBorderColor(virtualBorderColor.toHex());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
me.setBordersSize = function(borders, size){
|
||||
size = (size > me.maxBorderSize) ? me.maxBorderSize : size;
|
||||
|
||||
if (borders.indexOf('t') > -1)
|
||||
borderSize.top = size;
|
||||
if (borders.indexOf('r') > -1)
|
||||
borderSize.right = size;
|
||||
if (borders.indexOf('b') > -1)
|
||||
borderSize.bottom = size;
|
||||
if (borders.indexOf('l') > -1)
|
||||
borderSize.left = size;
|
||||
|
||||
applyStyles();
|
||||
};
|
||||
|
||||
me.setBordersColor = function(borders, color){
|
||||
var newColor = new Common.Utils.RGBColor(color);
|
||||
|
||||
if (borders.indexOf('t') > -1)
|
||||
borderColor.top = newColor;
|
||||
if (borders.indexOf('r') > -1)
|
||||
borderColor.right = newColor;
|
||||
if (borders.indexOf('b') > -1)
|
||||
borderColor.bottom = newColor;
|
||||
if (borders.indexOf('l') > -1)
|
||||
borderColor.left = newColor;
|
||||
|
||||
applyStyles();
|
||||
};
|
||||
|
||||
me.getBorderSize = function(border){
|
||||
switch(border){
|
||||
case 't':
|
||||
return borderSize.top;
|
||||
case 'r':
|
||||
return borderSize.right;
|
||||
case 'b':
|
||||
return borderSize.bottom;
|
||||
case 'l':
|
||||
return borderSize.left;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
me.getBorderColor = function(border){
|
||||
switch(border){
|
||||
case 't':
|
||||
return borderColor.top.toHex();
|
||||
case 'r':
|
||||
return borderColor.right.toHex();
|
||||
case 'b':
|
||||
return borderColor.bottom.toHex();
|
||||
case 'l':
|
||||
return borderColor.left.toHex();
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
if (me.options.el) {
|
||||
me.render(null, {
|
||||
borderSize: borderSize,
|
||||
borderColor: borderColor,
|
||||
virtualBorderSize: virtualBorderSize,
|
||||
virtualBorderColor: virtualBorderColor
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
render : function(parentEl) {
|
||||
var me = this,
|
||||
cfg = arguments[1];
|
||||
|
||||
this.trigger('render:before', this);
|
||||
|
||||
if (!me.rendered) {
|
||||
this.cmpEl = $(this.template(_.extend({
|
||||
scope: me
|
||||
}, cfg)));
|
||||
|
||||
if (parentEl) {
|
||||
this.setElement(parentEl, false);
|
||||
this.setElement(parentEl, false);
|
||||
parentEl.html(this.cmpEl);
|
||||
} else {
|
||||
$(this.el).html(this.cmpEl);
|
||||
}
|
||||
} else {
|
||||
this.cmpEl = $(this.el);
|
||||
}
|
||||
|
||||
if (!me.rendered) {
|
||||
var el = this.cmpEl;
|
||||
|
||||
this._cells = [];
|
||||
|
||||
for (var row = 0; row < me.rows; row++) {
|
||||
for (var col = 0; col < me.columns; col++) {
|
||||
var cellStyler = new Common.UI.CellStyler({
|
||||
el : $('#' + me.id + '-cell-container-' + col + '-' + row),
|
||||
overwriteStyle : me.overwriteStyle,
|
||||
halfBorderSize : !me.spacingMode,
|
||||
defaultBorderSize : me.spacingMode ? cfg.virtualBorderSize : 0,
|
||||
defaultBorderColor : cfg.virtualBorderColor.toHex(),
|
||||
id : me.id + '-cell-' + col + '-' + row,
|
||||
col : col,
|
||||
row : row
|
||||
});
|
||||
|
||||
this._cells.push(cellStyler);
|
||||
|
||||
cellStyler.on('borderclick', function(cell, type, size, color){
|
||||
var cellCol, cellRow, curCell;
|
||||
if (type == 't'){
|
||||
if (cell.row > 0){
|
||||
for(cellCol = 0; cellCol < me.columns; cellCol++){
|
||||
curCell = me.getCell(cellCol, cell.row - 1);
|
||||
curCell.setBordersSize('b', size);
|
||||
curCell.setBordersColor('b', color);
|
||||
}
|
||||
}
|
||||
|
||||
for(cellCol = 0; cellCol < me.columns; cellCol++){
|
||||
curCell = me.getCell(cellCol, cell.row);
|
||||
|
||||
if (cell.halfBorderSize && cell.row < 1)
|
||||
curCell.setBordersSize('t', 0);
|
||||
else
|
||||
curCell.setBordersSize('t', size);
|
||||
|
||||
curCell.setBordersColor('t', color);
|
||||
}
|
||||
}
|
||||
else if (type == 'b'){
|
||||
if (cell.row < me.rows - 1){
|
||||
for(cellCol = 0; cellCol < me.columns; cellCol++){
|
||||
curCell = me.getCell(cellCol, cell.row + 1);
|
||||
curCell.setBordersSize('t', size);
|
||||
curCell.setBordersColor('t', color);
|
||||
}
|
||||
}
|
||||
|
||||
for(cellCol = 0; cellCol < me.columns; cellCol++){
|
||||
curCell = me.getCell(cellCol, cell.row);
|
||||
|
||||
if (cell.halfBorderSize && cell.row >= me.rows - 1)
|
||||
curCell.setBordersSize('b', 0);
|
||||
else
|
||||
curCell.setBordersSize('b', size);
|
||||
|
||||
curCell.setBordersColor('b', color);
|
||||
}
|
||||
}
|
||||
else if (type == 'l'){
|
||||
if (cell.col > 0){
|
||||
for(cellRow = 0; cellRow < me.rows; cellRow++){
|
||||
curCell = me.getCell(cell.col - 1, cellRow);
|
||||
curCell.setBordersSize('r', size);
|
||||
curCell.setBordersColor('r', color);
|
||||
}
|
||||
}
|
||||
|
||||
for(cellRow = 0; cellRow < me.rows; cellRow++){
|
||||
curCell = me.getCell(cell.col, cellRow);
|
||||
|
||||
if (cell.halfBorderSize && cell.col < 1)
|
||||
curCell.setBordersSize('l', 0);
|
||||
else
|
||||
curCell.setBordersSize('l', size);
|
||||
|
||||
curCell.setBordersColor('l', color);
|
||||
}
|
||||
}
|
||||
else if (type == 'r'){
|
||||
if (cell.col < me.columns - 1){
|
||||
for(cellRow = 0; cellRow < me.rows; cellRow++){
|
||||
curCell = me.getCell(cell.col + 1, cellRow);
|
||||
curCell.setBordersSize('l', size);
|
||||
curCell.setBordersColor('l', color);
|
||||
}
|
||||
}
|
||||
|
||||
for(cellRow = 0; cellRow < me.rows; cellRow++){
|
||||
curCell = me.getCell(cell.col, cellRow);
|
||||
|
||||
if (cell.halfBorderSize && cell.col >= me.columns - 1)
|
||||
curCell.setBordersSize('r', 0);
|
||||
else
|
||||
curCell.setBordersSize('r', size);
|
||||
|
||||
curCell.setBordersColor('r', color);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
me.rendered = true;
|
||||
|
||||
this.trigger('render:after', this);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
getCell: function(col, row){
|
||||
return _.findWhere(this._cells, {
|
||||
id: this.id + '-cell-' + col + '-' + row
|
||||
})
|
||||
}
|
||||
});
|
||||
});
|
346
apps/common/main/lib/component/ThemeColorPalette.js
Normal file
346
apps/common/main/lib/component/ThemeColorPalette.js
Normal file
|
@ -0,0 +1,346 @@
|
|||
/**
|
||||
* ThemeColorPalette.js
|
||||
*
|
||||
* Created by Julia Radzhabova on 1/28/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'common/main/lib/component/BaseView',
|
||||
'common/main/lib/view/ExtendedColorDialog'
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
Common.UI.ThemeColorPalette = Common.UI.BaseView.extend({
|
||||
options: {
|
||||
dynamiccolors: 10,
|
||||
allowReselect: true,
|
||||
value: '000000'
|
||||
},
|
||||
|
||||
template :
|
||||
_.template(
|
||||
'<div style="padding: 12px;">' +
|
||||
'<% var me = this; %>' +
|
||||
'<% $(colors).each(function(num, item) { %>' +
|
||||
'<% if (me.isBlankSeparator(item)) { %> <div class="palette-color-spacer" style="width:100%;height:8px;float:left;"></div>' +
|
||||
'<% } else if (me.isSeparator(item)) { %> </div><div class="palette-color-separator" style="width:100%;height:1px;float:left;border-bottom: 1px solid #E0E0E0"></div><div style="padding: 12px;">' +
|
||||
'<% } else if (me.isColor(item)) { %> ' +
|
||||
'<a class="palette-color color-<%=item%>" style="background:#<%=item%>" hidefocus="on">' +
|
||||
'<em><span style="background:#<%=item%>;" unselectable="on"> </span></em>' +
|
||||
'</a>' +
|
||||
'<% } else if (me.isTransparent(item)) { %>' +
|
||||
'<a class="color-<%=item%>" hidefocus="on">' +
|
||||
'<em><span unselectable="on"> </span></em>' +
|
||||
'</a>' +
|
||||
'<% } else if (me.isEffect(item)) { %>' +
|
||||
'<a effectid="<%=item.effectId%>" effectvalue="<%=item.effectValue%>" class="palette-color-effect color-<%=item.color%>" style="background:#<%=item.color%>" hidefocus="on">' +
|
||||
'<em><span style="background:#<%=item.color%>;" unselectable="on"> </span></em>' +
|
||||
'</a>' +
|
||||
'<% } else if (me.isCaption(item)) { %>' +
|
||||
'<div class="palette-color-caption" style="width:100%;float:left;font-size: 11px;"><%=item%></div>' +
|
||||
'<% } %>' +
|
||||
'<% }); %>' +
|
||||
'</div>' +
|
||||
'<% if (me.options.dynamiccolors!==undefined) { %>' +
|
||||
'<div class="palette-color-spacer" style="width:100%;height:8px;float:left;"></div><div style="padding: 12px;">' +
|
||||
'<% for (var i=0; i<me.options.dynamiccolors; i++) { %>' +
|
||||
'<a class="color-dynamic-<%=i%> dynamic-empty-color" style="background:#ffffff" color="" hidefocus="on">' +
|
||||
'<em><span unselectable="on"> </span></em></a>' +
|
||||
'<% } %>' +
|
||||
'<% } %>' +
|
||||
'</div>'),
|
||||
|
||||
colorRe: /(?:^|\s)color-(.{6})(?:\s|$)/,
|
||||
selectedCls: 'selected',
|
||||
|
||||
initialize : function(options) {
|
||||
Common.UI.BaseView.prototype.initialize.call(this, options);
|
||||
|
||||
var me = this,
|
||||
el = $(this.el);
|
||||
|
||||
this.colors = me.options.colors || [
|
||||
{color: '000000', effectId: 1}, {color: 'FFFFFF', effectId: 2}, {color: '000000', effectId: 3}, {color: 'FFFFFF', effectId: 4}, {color: '000000', effectId: 5},
|
||||
{color: 'FF0000', effectId: 1}, {color: 'FF6600', effectId: 1}, {color: 'FFFF00', effectId: 2}, {color: 'CCFFCC', effectId: 3}, {color: '008000', effectId: 4},
|
||||
'-', '--', '-',
|
||||
'000000', '5301B3', '980ABD', 'B2275F', 'F83D26', 'F86A1D', 'F7AC16', 'F7CA12', 'FAFF44', 'D6EF39'
|
||||
];
|
||||
|
||||
el.addClass('theme-colorpalette');
|
||||
this.render();
|
||||
|
||||
if (this.options.updateColorsArr)
|
||||
this.updateColors(this.options.updateColorsArr[0], this.options.updateColorsArr[1]);
|
||||
if (this.options.value)
|
||||
this.select(this.options.value, true);
|
||||
this.updateCustomColors();
|
||||
el.closest('.btn-group').on('show.bs.dropdown', _.bind(this.updateCustomColors, this));
|
||||
el.closest('.dropdown-submenu').on('show.bs.dropdown', _.bind(this.updateCustomColors, this));
|
||||
el.on('click', _.bind(this.handleClick, this));
|
||||
},
|
||||
|
||||
render: function () {
|
||||
$(this.el).html(this.template({colors: this.colors}));
|
||||
return this;
|
||||
},
|
||||
|
||||
isBlankSeparator: function(v) {
|
||||
return typeof(v) == 'string' && v == '-';
|
||||
},
|
||||
isSeparator: function(v) {
|
||||
return typeof(v) == 'string' && v == '--';
|
||||
},
|
||||
isColor: function(v) {
|
||||
return typeof(v) == 'string' && (/[0-9A-F]{6}/).test(v);
|
||||
},
|
||||
isTransparent: function(v) {
|
||||
return typeof(v) == 'string' && (v=='transparent');
|
||||
},
|
||||
isCaption: function(v) {
|
||||
return (typeof(v) == 'string' && v!='-' && v!='--' && !(/[0-9A-F]{6}|transparent/).test(v));
|
||||
},
|
||||
isEffect: function(v) {
|
||||
return (typeof(v) == 'object' && v.effectId !== undefined);
|
||||
},
|
||||
|
||||
getColor: function() {
|
||||
return this.value;
|
||||
},
|
||||
|
||||
updateCustomColors: function() {
|
||||
var el = $(this.el);
|
||||
if (el) {
|
||||
var colors = Common.localStorage.getItem('asc.'+Common.localStorage.getId()+'.colors.custom');
|
||||
colors = colors ? colors.split(',') : [];
|
||||
|
||||
var i = -1, colorEl, c = colors.length < this.options.dynamiccolors ? colors.length : this.options.dynamiccolors;
|
||||
while (++i < c) {
|
||||
colorEl = el.find('.color-dynamic-'+ i);
|
||||
colorEl.removeClass('dynamic-empty-color').attr('color', colors[i]);
|
||||
colorEl.find('span').css({
|
||||
'background-color': '#'+colors[i]
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
handleClick : function(e){
|
||||
var me = this;
|
||||
var target = $(e.target).closest('a');
|
||||
var color, cmp;
|
||||
|
||||
if (target.length==0) return;
|
||||
|
||||
if (target.hasClass('color-transparent') ) {
|
||||
$(me.el).find('a.' + me.selectedCls).removeClass(me.selectedCls);
|
||||
target.addClass(me.selectedCls);
|
||||
me.value = 'transparent';
|
||||
me.trigger('select', me, 'transparent');
|
||||
} else if ( !(target[0].className.search('color-dynamic')<0) ) {
|
||||
if (!/dynamic-empty-color/.test(target[0].className)) {
|
||||
$(me.el).find('a.' + me.selectedCls).removeClass(me.selectedCls);
|
||||
target.addClass(me.selectedCls);
|
||||
color = target.attr('color');
|
||||
if (color) me.trigger('select', me, color);
|
||||
|
||||
me.value = color.toUpperCase();
|
||||
} else {
|
||||
setTimeout(function(){
|
||||
me.addNewColor();
|
||||
}, 10);
|
||||
}
|
||||
} else {
|
||||
if (!/^[a-fA-F0-9]{6}$/.test(me.value) || _.indexOf(me.colors, me.value)<0 )
|
||||
me.value = false;
|
||||
|
||||
$(me.el).find('a.' + me.selectedCls).removeClass(me.selectedCls);
|
||||
target.addClass(me.selectedCls);
|
||||
|
||||
color = target[0].className.match(me.colorRe)[1];
|
||||
if ( target.hasClass('palette-color-effect') ) {
|
||||
var effectId = parseInt(target.attr('effectid'));
|
||||
if (color) {
|
||||
me.value = color.toUpperCase();
|
||||
me.trigger('select', me, {color: color, effectId: effectId});
|
||||
}
|
||||
} else {
|
||||
if (/#?[a-fA-F0-9]{6}/.test(color)) {
|
||||
color = /#?([a-fA-F0-9]{6})/.exec(color)[1].toUpperCase();
|
||||
me.value = color;
|
||||
me.trigger('select', me, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
setCustomColor: function(color) {
|
||||
var el = $(this.el);
|
||||
color = /#?([a-fA-F0-9]{6})/.exec(color);
|
||||
if (color) {
|
||||
this.saveCustomColor(color[1]);
|
||||
|
||||
el.find('a.' + this.selectedCls).removeClass(this.selectedCls);
|
||||
|
||||
var child = el.find('.dynamic-empty-color');
|
||||
if (child.length==0) {
|
||||
this.updateCustomColors();
|
||||
child = el.find('.color-dynamic-' + (this.options.dynamiccolors - 1));
|
||||
}
|
||||
|
||||
child.first().removeClass('dynamic-empty-color').addClass(this.selectedCls).attr('color', color[1]);
|
||||
child.first().find('span').css({
|
||||
'background-color': '#'+color[1]
|
||||
});
|
||||
this.select(color[1], true);
|
||||
}
|
||||
},
|
||||
|
||||
saveCustomColor: function(color) {
|
||||
var key_name = 'asc.'+Common.localStorage.getId()+'.colors.custom';
|
||||
var colors = Common.localStorage.getItem(key_name);
|
||||
colors = colors ? colors.split(',') : [];
|
||||
if (colors.push(color) > this.options.dynamiccolors) colors.shift();
|
||||
Common.localStorage.setItem(key_name, colors.join().toUpperCase());
|
||||
},
|
||||
|
||||
addNewColor: function(defcolor) {
|
||||
var me = this;
|
||||
|
||||
var win = new Common.UI.ExtendedColorDialog({
|
||||
});
|
||||
win.on('onmodalresult', function(mr) {
|
||||
me._isdlgopen = false;
|
||||
if (mr==1) {
|
||||
me.setCustomColor(win.getColor());
|
||||
me.fireEvent('select', me, win.getColor());
|
||||
}
|
||||
});
|
||||
me._isdlgopen = true;
|
||||
win.setColor((me.value!==undefined && me.value!==false) ? me.value : ((defcolor!==undefined) ? defcolor : '000000'));
|
||||
win.show();
|
||||
},
|
||||
|
||||
isDialogOpen: function() {
|
||||
return this._isdlgopen == true;
|
||||
},
|
||||
|
||||
select: function(color, suppressEvent) {
|
||||
var el = $(this.el);
|
||||
el.find('a.' + this.selectedCls).removeClass(this.selectedCls);
|
||||
|
||||
if (typeof(color) == 'object' ) {
|
||||
var effectEl;
|
||||
if (color.effectId !== undefined) {
|
||||
effectEl = el.find('a[effectid="'+color.effectId+'"]').first();
|
||||
if (effectEl.length>0) {
|
||||
effectEl.addClass(this.selectedCls);
|
||||
this.value = effectEl[0].className.match(this.colorRe)[1].toUpperCase();
|
||||
} else
|
||||
this.value = false;
|
||||
} else if (color.effectValue !== undefined) {
|
||||
effectEl = el.find('a[effectvalue="'+color.effectValue+'"].color-' + color.color.toUpperCase()).first();
|
||||
if (effectEl.length>0) {
|
||||
effectEl.addClass(this.selectedCls);
|
||||
this.value = effectEl[0].className.match(this.colorRe)[1].toUpperCase();
|
||||
} else
|
||||
this.value = false;
|
||||
}
|
||||
} else {
|
||||
if (/#?[a-fA-F0-9]{6}/.test(color)) {
|
||||
color = /#?([a-fA-F0-9]{6})/.exec(color)[1].toUpperCase();
|
||||
this.value = color;
|
||||
}
|
||||
|
||||
if (/^[a-fA-F0-9]{6}|transparent$/.test(color) && _.indexOf(this.colors, color)>=0 ) {
|
||||
if (_.indexOf(this.colors, this.value)<0) this.value = false;
|
||||
|
||||
if (color != this.value || this.options.allowReselect) {
|
||||
(color == 'transparent') ? el.find('a.color-transparent').addClass(this.selectedCls) : el.find('a.palette-color.color-' + color).first().addClass(this.selectedCls);
|
||||
this.value = color;
|
||||
if (suppressEvent !== true) {
|
||||
this.fireEvent('select', this, color);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var co = el.find('#'+color).first();
|
||||
if (co.length==0)
|
||||
co = el.find('a[color="'+color+'"]').first();
|
||||
if (co.length>0) {
|
||||
co.addClass(this.selectedCls);
|
||||
this.value = color.toUpperCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
updateColors: function(effectcolors, standartcolors) {
|
||||
if (effectcolors===undefined || standartcolors===undefined) return;
|
||||
|
||||
var me = this,
|
||||
el = $(this.el);
|
||||
|
||||
if (me.aColorElements === undefined) {
|
||||
me.aColorElements = el.find('a.palette-color');
|
||||
}
|
||||
if (me.aEffectElements === undefined) {
|
||||
me.aEffectElements = el.find('a.palette-color-effect');
|
||||
}
|
||||
|
||||
var aEl;
|
||||
var aColorIdx = 0,
|
||||
aEffectIdx = 0;
|
||||
|
||||
for (var i=0; i<me.colors.length; i++) {
|
||||
if ( typeof(me.colors[i]) == 'string' && (/[0-9A-F]{6}/).test(me.colors[i]) ) {
|
||||
if (aColorIdx>=standartcolors.length)
|
||||
continue;
|
||||
|
||||
aEl = $(me.aColorElements[aColorIdx]);
|
||||
aEl.removeClass('color-'+me.colors[i]);
|
||||
|
||||
me.colors[i] = standartcolors[aColorIdx].toUpperCase();
|
||||
|
||||
aEl.addClass('color-'+me.colors[i]);
|
||||
aEl.css({background: "#"+me.colors[i]});
|
||||
aEl.find('span').first().css({background: "#"+me.colors[i]});
|
||||
aColorIdx++;
|
||||
} else if ( typeof(me.colors[i]) == 'object' && me.colors[i].effectId !== undefined) {
|
||||
if (aEffectIdx>=effectcolors.length)
|
||||
continue;
|
||||
|
||||
aEl = $(me.aEffectElements[aEffectIdx]);
|
||||
|
||||
effectcolors[aEffectIdx].color = effectcolors[aEffectIdx].color.toUpperCase();
|
||||
|
||||
if ( me.colors[i].color !== effectcolors[aEffectIdx].color ) {
|
||||
aEl.removeClass('color-'+me.colors[i].color);
|
||||
aEl.addClass('color-'+effectcolors[aEffectIdx].color);
|
||||
aEl.css({background: "#"+effectcolors[aEffectIdx].color});
|
||||
aEl.find('span').first().css({background: "#"+effectcolors[aEffectIdx].color});
|
||||
}
|
||||
|
||||
if ( me.colors[i].effectId !== effectcolors[aEffectIdx].effectId )
|
||||
aEl.attr('effectid', '' + effectcolors[aEffectIdx].effectId);
|
||||
if ( me.colors[i].effectValue !== effectcolors[aEffectIdx].effectValue )
|
||||
aEl.attr('effectvalue', '' + effectcolors[aEffectIdx].effectValue);
|
||||
|
||||
me.colors[i] = effectcolors[aEffectIdx];
|
||||
|
||||
aEffectIdx++;
|
||||
}
|
||||
}
|
||||
this.options.updateColorsArr = undefined;
|
||||
},
|
||||
|
||||
clearSelection: function(suppressEvent) {
|
||||
$(this.el).find('a.' + this.selectedCls).removeClass(this.selectedCls);
|
||||
this.value = undefined;
|
||||
}
|
||||
|
||||
});
|
||||
});
|
83
apps/common/main/lib/component/ToggleManager.js
Normal file
83
apps/common/main/lib/component/ToggleManager.js
Normal file
|
@ -0,0 +1,83 @@
|
|||
/**
|
||||
* ToggleManager.js
|
||||
*
|
||||
* Created by Alexander Yuzhin on 1/28/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'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;
|
||||
}
|
||||
}
|
||||
});
|
123
apps/common/main/lib/component/Tooltip.js
Normal file
123
apps/common/main/lib/component/Tooltip.js
Normal file
|
@ -0,0 +1,123 @@
|
|||
/**
|
||||
* Tooltip.js
|
||||
*
|
||||
* Created by Maxim Kadushkin on 14 March 2014
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Configuration
|
||||
* =============
|
||||
*
|
||||
* @cfg {String} title
|
||||
*
|
||||
* @cfg {String} placement
|
||||
* Default value is 'top'.
|
||||
* Describes tooltips position relatively of the parent component
|
||||
* acceptable values: 'top', 'bottom', 'right', 'left', 'top-right/left', 'bottom-right/left', 'cursor'
|
||||
* If placement = 'cursor', tooltip doesn't arrange position relatively
|
||||
* of the parent and shows relatively of the cursor position.
|
||||
*
|
||||
* @cfg {String} offset
|
||||
* The number of pixels to offset the tooltip from the parent component
|
||||
*
|
||||
* @cfg {String} cls
|
||||
* An extra CSS class that will be added to tooltip dom-element.
|
||||
*
|
||||
*
|
||||
* Methods
|
||||
* =======
|
||||
*
|
||||
* @method setTitle
|
||||
*
|
||||
* @method show
|
||||
* @params {Array} at - set predefined position for the tooltip
|
||||
*
|
||||
*
|
||||
* Events
|
||||
* ======
|
||||
*
|
||||
* @event tooltip:show
|
||||
* Fires after the tooltip is shown
|
||||
*
|
||||
* @event tooltip:hide
|
||||
* Fires after the tooltip is hidden
|
||||
*
|
||||
* */
|
||||
|
||||
define([
|
||||
'tip',
|
||||
'backbone'
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
var Tooltip = function(options) {
|
||||
this.$element =
|
||||
this.placement = undefined;
|
||||
this.init.call(this, options);
|
||||
};
|
||||
|
||||
_.extend(Tooltip.prototype, Backbone.Events, {
|
||||
init: function(opts) {
|
||||
this.$element = opts.owner instanceof Backbone.View ? opts.owner.$el : $(opts.owner);
|
||||
this.placement = opts.placement;
|
||||
|
||||
if (this.$element.data('bs.tooltip'))
|
||||
this.$element.removeData('bs.tooltip');
|
||||
|
||||
this.$element.tooltip({
|
||||
title : opts.title,
|
||||
trigger : 'manual',
|
||||
placement : opts.placement,
|
||||
offset : opts.offset,
|
||||
cls : opts.cls,
|
||||
html : opts.html,
|
||||
hideonclick : opts.hideonclick
|
||||
});
|
||||
|
||||
if (opts.hideonclick) {
|
||||
var tip = this.$element.data('bs.tooltip');
|
||||
if (tip) tip.tip().on('click', function() {tip.hide();});
|
||||
}
|
||||
|
||||
this.$element.on('shown.bs.tooltip', _.bind(this.onTipShown, this));
|
||||
this.$element.on('hidden.bs.tooltip', _.bind(this.onTipHidden, this));
|
||||
},
|
||||
|
||||
show: function(at) {
|
||||
this.getBSTip().show(at);
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
this.getBSTip().hide();
|
||||
},
|
||||
|
||||
setTitle: function(title) {
|
||||
var tip = this.getBSTip();
|
||||
if (tip) tip.options.title = title;
|
||||
},
|
||||
|
||||
updateTitle: function() {
|
||||
var tip = this.getBSTip();
|
||||
tip.$tip.find('.tooltip-inner')[tip.options.html ? 'html' : 'text'](tip.options.title);
|
||||
},
|
||||
|
||||
getBSTip: function() {
|
||||
return this.$element.data('bs.tooltip');
|
||||
},
|
||||
|
||||
onTipShown: function() {
|
||||
this.trigger('tooltip:show', this);
|
||||
},
|
||||
|
||||
onTipHidden: function() {
|
||||
this.trigger('tooltip:hide', this);
|
||||
},
|
||||
|
||||
isVisible: function() {
|
||||
return this.getBSTip().tip().is(':visible');
|
||||
}
|
||||
});
|
||||
Common.UI = Common.UI || {};
|
||||
Common.UI.Tooltip = Tooltip;
|
||||
});
|
710
apps/common/main/lib/component/Window.js
Normal file
710
apps/common/main/lib/component/Window.js
Normal file
|
@ -0,0 +1,710 @@
|
|||
/**
|
||||
* Window.js
|
||||
*
|
||||
* Created by Maxim Kadushkin on 24 January 2014
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Usage
|
||||
*
|
||||
* Configuration
|
||||
*
|
||||
* @cfg {Boolean} closable
|
||||
* Doesn't allow user to close window neither ESC nor the 'close' button.
|
||||
*
|
||||
* @cfg {Boolean} header
|
||||
* Prevents window to create header. Default value is 'true'
|
||||
|
||||
* @cfg {Boolean} modal
|
||||
* False if window will not allowed to take over keyboard and mouse input.
|
||||
*
|
||||
* @cfg {String} title
|
||||
*
|
||||
* @cfg {String} tpl
|
||||
* Describes template of window's body
|
||||
*
|
||||
* @cfg {String} cls
|
||||
* Extra class for the root dom-element
|
||||
*
|
||||
* @cfg {Boolean} animate
|
||||
* Makes the window to animate while showing or hiding
|
||||
*
|
||||
* Methods
|
||||
*
|
||||
* @method show
|
||||
* Fires event 'afterender'
|
||||
*
|
||||
* @method close
|
||||
* Fires event 'close'
|
||||
*
|
||||
* @method setSize
|
||||
* Sets new size of the window
|
||||
* @params {Integer} width
|
||||
* @params {Integer} height
|
||||
|
||||
* @method getSize
|
||||
* Returns current size of the window
|
||||
* @returns {Array} [width, height]
|
||||
*
|
||||
* @method getChild
|
||||
* @params {String} selector
|
||||
*
|
||||
*
|
||||
* Events
|
||||
*
|
||||
* @event close
|
||||
*
|
||||
* @event afterender
|
||||
*
|
||||
* Examples
|
||||
* var win = new Common.UI.Window({
|
||||
* title: options.title,
|
||||
* tpl: template
|
||||
* });
|
||||
*
|
||||
* win.on('close', onClose);
|
||||
* win.show()
|
||||
*
|
||||
*
|
||||
* ****************************************
|
||||
* Extends
|
||||
*
|
||||
* @window Common.UI.warning
|
||||
* Shows warning message.
|
||||
* @cfg {String} msg
|
||||
* @cfg {Object} buttons
|
||||
* Use an array for predefined buttons (ok, cancel, yes, no): @example ['yes', 'no']
|
||||
* Use a named array for the custom buttons: {value: caption, ...}
|
||||
* @param {String} value will be returned in callback function
|
||||
* @param {String} caption
|
||||
*
|
||||
* @cfg {Function} callback
|
||||
* @param {String} button
|
||||
* If the window is closed via shortcut or header's close tool, the 'button' will be 'close'
|
||||
*
|
||||
* @example
|
||||
* Common.UI.warning({
|
||||
* msg: 'Unknown error.',
|
||||
* buttons: ['ok'],
|
||||
* callback: function(btn) {
|
||||
* console.log('button was pressed: ' + btn);
|
||||
* }
|
||||
* });
|
||||
*
|
||||
*
|
||||
* @window Common.UI.error
|
||||
* @window Common.UI.info
|
||||
* @window Common.UI.confirm
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'common/main/lib/component/BaseView'
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
Common.UI.Window = Common.UI.BaseView.extend(_.extend((function(){
|
||||
var config = {
|
||||
closable: true,
|
||||
header: true,
|
||||
modal: true,
|
||||
width: 'auto',
|
||||
height: 'auto',
|
||||
title: 'Title',
|
||||
alias: 'Window',
|
||||
cls: '',
|
||||
toolclose: 'close'
|
||||
};
|
||||
|
||||
var template = '<div class="asc-window<%= modal?" modal":"" %><%= cls?" "+cls:"" %>" id="<%= id %>" style="width:<%= width %>px;">' +
|
||||
'<% if (header==true) { %>' +
|
||||
'<div class="header">' +
|
||||
'<% if (closable!==false) %>' +
|
||||
'<div class="tool close img-commonctrl"></div>' +
|
||||
'<% %>' +
|
||||
'<span class="title"><%= title %></span> ' +
|
||||
'</div>' +
|
||||
'<% } %>' +
|
||||
'<div class="body"><%= tpl %></div>' +
|
||||
'</div>';
|
||||
|
||||
function _getMask() {
|
||||
var mask = $('.modals-mask');
|
||||
|
||||
if( mask.length == 0) {
|
||||
mask = $("<div class='modals-mask'>")
|
||||
.appendTo(document.body).hide();
|
||||
mask.attr('counter', 0);
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
function _keydown(event) {
|
||||
if (!this.isLocked() && this.isVisible()) {
|
||||
switch (event.keyCode) {
|
||||
case Common.UI.Keys.ESC:
|
||||
if ( $('.asc-loadmask').length<1 ) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
if (this.initConfig.closable !== false) {
|
||||
this.initConfig.toolclose=='hide' ? this.hide() : this.close();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case Common.UI.Keys.RETURN:
|
||||
if (this.$window.find('.btn.primary').length && $('.asc-loadmask').length<1) {
|
||||
if ((this.initConfig.onprimary || this.onPrimary).call(this)===false) {
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _centre() {
|
||||
if (window.innerHeight == undefined) {
|
||||
var main_width = document.documentElement.offsetWidth;
|
||||
var main_height = document.documentElement.offsetHeight;
|
||||
} else {
|
||||
main_width = window.innerWidth;
|
||||
main_height = window.innerHeight;
|
||||
}
|
||||
|
||||
if (this.initConfig.height == 'auto') {
|
||||
var win_height = parseInt(this.$window.find('.body').css('height'));
|
||||
this.initConfig.header && (win_height += parseInt(this.$window.find('.header').css('height')));
|
||||
} else
|
||||
win_height = this.initConfig.height;
|
||||
|
||||
var win_width = (this.initConfig.width=='auto') ? parseInt(this.$window.find('.body').css('width')) : this.initConfig.width;
|
||||
|
||||
var top = Math.floor(((parseInt(main_height) - parseInt(win_height)) / 2) * 0.9);
|
||||
var left = Math.floor((parseInt(main_width) - parseInt(win_width)) / 2);
|
||||
|
||||
this.$window.css('left',left);
|
||||
this.$window.css('top',top);
|
||||
}
|
||||
|
||||
function _getTransformation(end) {
|
||||
return {
|
||||
'-webkit-transition': '0.3s opacity',
|
||||
'-moz-transition': '0.3s opacity',
|
||||
'-ms-transition': '0.3s opacity',
|
||||
'-o-transition': '0.3s opacity',
|
||||
'opacity': end
|
||||
}
|
||||
}
|
||||
|
||||
/* window drag's functions */
|
||||
function _dragstart(event) {
|
||||
if ( $(event.target).hasClass('close') ) return;
|
||||
Common.UI.Menu.Manager.hideAll();
|
||||
this.dragging.enabled = true;
|
||||
this.dragging.initx = event.pageX - parseInt(this.$window.css('left'));
|
||||
this.dragging.inity = event.pageY - parseInt(this.$window.css('top'));
|
||||
|
||||
if (window.innerHeight == undefined) {
|
||||
var main_width = document.documentElement.offsetWidth;
|
||||
var main_height = document.documentElement.offsetHeight;
|
||||
} else {
|
||||
main_width = window.innerWidth;
|
||||
main_height = window.innerHeight;
|
||||
}
|
||||
|
||||
this.dragging.maxx = main_width - parseInt(this.$window.css("width"));
|
||||
this.dragging.maxy = main_height - parseInt(this.$window.css("height"));
|
||||
|
||||
$(document).on('mousemove', this.binding.drag);
|
||||
$(document).on('mouseup', this.binding.dragStop);
|
||||
|
||||
this.fireEvent('drag', [this, 'start']);
|
||||
|
||||
// event.stopPropagation ? event.stopPropagation() : (event.cancelBubble = true);
|
||||
// event.preventDefault && event.preventDefault();
|
||||
|
||||
// return false;
|
||||
}
|
||||
|
||||
function _mouseup() {
|
||||
$(document).off('mousemove', this.binding.drag);
|
||||
$(document).off('mouseup', this.binding.dragStop);
|
||||
|
||||
this.dragging.enabled = false;
|
||||
this.fireEvent('drag', [this, 'end']);
|
||||
}
|
||||
|
||||
function _mousemove(event) {
|
||||
if (this.dragging.enabled) {
|
||||
var left = event.pageX - this.dragging.initx,
|
||||
top = event.pageY - this.dragging.inity;
|
||||
|
||||
left < 0 ? (left = 0) : left > this.dragging.maxx && (left = this.dragging.maxx);
|
||||
top < 0 ? (top = 0) : top > this.dragging.maxy && (top = this.dragging.maxy);
|
||||
|
||||
this.$window.css({left: left, top: top});
|
||||
}
|
||||
}
|
||||
|
||||
Common.UI.alert = function(options) {
|
||||
var me = this.Window.prototype;
|
||||
var arrBtns = {ok: me.okButtonText, cancel: me.cancelButtonText,
|
||||
yes: me.yesButtonText, no: me.noButtonText,
|
||||
close: me.closeButtonText};
|
||||
|
||||
if (!options.buttons) {
|
||||
options.buttons = {};
|
||||
options.buttons['ok'] = {text: arrBtns['ok'], cls: 'primary'};
|
||||
} else {
|
||||
if (_.isArray(options.buttons)) {
|
||||
if (options.primary==undefined)
|
||||
options.primary = 'ok';
|
||||
var newBtns = {};
|
||||
_.each(options.buttons, function(b){
|
||||
newBtns[b] = {text: (b=='custom') ? options.customButtonText : arrBtns[b], cls: (options.primary==b) ? 'primary' : ''};
|
||||
if (b=='custom')
|
||||
newBtns[b].cls += ' custom';
|
||||
});
|
||||
|
||||
options.buttons = newBtns;
|
||||
}
|
||||
}
|
||||
options.dontshow = options.dontshow || false;
|
||||
|
||||
if (!options.width) options.width = 'auto';
|
||||
|
||||
var template = '<div class="info-box">' +
|
||||
'<div class="icon img-commonctrl <%= iconCls %>" />' +
|
||||
'<div class="text"><span><%= msg %></span>' +
|
||||
'<% if (dontshow) { %><div class="dont-show-checkbox"></div><% } %>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<% if (dontshow) { %><div class="separator horizontal" style="width: 100%;"/><% } %>' +
|
||||
'<div class="footer <% if (dontshow) { %> dontshow <% } %>">' +
|
||||
'<% if (_.size(buttons) > 0) { %>' +
|
||||
'<% for(var bt in buttons) { %>' +
|
||||
'<button class="btn normal dlg-btn <%= buttons[bt].cls %>" result="<%= bt %>"><%= buttons[bt].text %></button>'+
|
||||
'<% } %>' +
|
||||
'<% } else { %>' +
|
||||
'<button class="btn normal dlg-btn primary" result="ok">OK</button>'+
|
||||
'<% } %>' +
|
||||
'</div>';
|
||||
|
||||
var win = new Common.UI.Window({
|
||||
cls: 'alert',
|
||||
title: options.title,
|
||||
width: options.width,
|
||||
onprimary: onKeyDown,
|
||||
tpl: _.template(template, options)
|
||||
}),
|
||||
chDontShow = null;
|
||||
|
||||
function autoSize(window) {
|
||||
var text_cnt = window.getChild('.info-box');
|
||||
var text = window.getChild('.info-box span');
|
||||
var footer = window.getChild('.footer');
|
||||
var header = window.getChild('.header');
|
||||
var body = window.getChild('.body');
|
||||
var icon = window.getChild('.icon');
|
||||
var check = window.getChild('.info-box .dont-show-checkbox');
|
||||
|
||||
if (!options.dontshow) body.css('padding-bottom', '10px');
|
||||
|
||||
if (options.width=='auto') {
|
||||
text_cnt.height(Math.max(text.height() + ((check.length>0) ? (check.height() + parseInt(check.css('margin-top'))) : 0), icon.height()));
|
||||
body.height(parseInt(text_cnt.css('height')) + parseInt(footer.css('height')));
|
||||
window.setSize(text.position().left + text.width() + parseInt(text_cnt.css('padding-right')),
|
||||
parseInt(body.css('height')) + parseInt(header.css('height')));
|
||||
} else {
|
||||
text.css('white-space', 'normal');
|
||||
window.setWidth(options.width);
|
||||
text_cnt.height(Math.max(text.height() + ((check.length>0) ? (check.height() + parseInt(check.css('margin-top'))) : 0), icon.height()));
|
||||
body.height(parseInt(text_cnt.css('height')) + parseInt(footer.css('height')));
|
||||
window.setHeight(parseInt(body.css('height')) + parseInt(header.css('height')));
|
||||
}
|
||||
}
|
||||
|
||||
function onBtnClick(event) {
|
||||
if (options.callback) {
|
||||
options.callback.call(win, event.currentTarget.attributes['result'].value, (chDontShow) ? (chDontShow.getValue() == 'checked') : false);
|
||||
}
|
||||
|
||||
win.close(true);
|
||||
}
|
||||
|
||||
function onKeyDown(event) {
|
||||
onBtnClick({currentTarget: win.getChild('.footer .dlg-btn')[0]});
|
||||
return false;
|
||||
}
|
||||
|
||||
win.on({
|
||||
'render:after': function(obj){
|
||||
obj.getChild('.footer .dlg-btn').on('click', onBtnClick);
|
||||
chDontShow = new Common.UI.CheckBox({
|
||||
el: win.$window.find('.dont-show-checkbox'),
|
||||
labelText: win.textDontShow
|
||||
});
|
||||
autoSize(obj);
|
||||
},
|
||||
show: function(obj) {
|
||||
obj.getChild('.footer .dlg-btn').focus();
|
||||
},
|
||||
close: function() {
|
||||
options.callback && options.callback.call(win, 'close');
|
||||
}
|
||||
});
|
||||
|
||||
win.show();
|
||||
};
|
||||
|
||||
Common.UI.error = function(options) {
|
||||
options = options || {};
|
||||
!options.title && (options.title = this.Window.prototype.textError);
|
||||
|
||||
Common.UI.alert(
|
||||
_.extend(options, {
|
||||
iconCls: 'error'
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
Common.UI.confirm = function(options) {
|
||||
options = options || {};
|
||||
!options.title && (options.title = this.Window.prototype.textConfirmation);
|
||||
|
||||
Common.UI.alert(
|
||||
_.extend(options, {
|
||||
iconCls: 'confirm'
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
Common.UI.info = function(options) {
|
||||
options = options || {};
|
||||
!options.title && (options.title = this.Window.prototype.textInformation);
|
||||
|
||||
Common.UI.alert(
|
||||
_.extend(options, {
|
||||
iconCls: 'info'
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
Common.UI.warning = function(options) {
|
||||
options = options || {};
|
||||
!options.title && (options.title = this.Window.prototype.textWarning);
|
||||
|
||||
Common.UI.alert(
|
||||
_.extend(options, {
|
||||
iconCls: 'warn'
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
return {
|
||||
$window : undefined,
|
||||
$lastmodal : undefined,
|
||||
dragging : {enabled: false},
|
||||
|
||||
initialize : function(options) {
|
||||
this.initConfig = {};
|
||||
this.binding = {};
|
||||
|
||||
_.extend(this.initConfig, config, options || {});
|
||||
|
||||
!this.initConfig.id && (this.initConfig.id = 'window-' + this.cid);
|
||||
!this.initConfig.tpl && (this.initConfig.tpl = '');
|
||||
|
||||
Common.UI.BaseView.prototype.initialize.call(this, this.initConfig);
|
||||
},
|
||||
|
||||
render : function() {
|
||||
var renderto = this.initConfig.renderTo || document.body;
|
||||
$(renderto).append(
|
||||
_.template(template, this.initConfig)
|
||||
);
|
||||
|
||||
this.$window = $('#' + this.initConfig.id);
|
||||
|
||||
this.binding.keydown = _.bind(_keydown,this);
|
||||
// $(document).on('keydown', this.binding.keydown);
|
||||
|
||||
if ( this.initConfig.header ) {
|
||||
this.binding.drag = _.bind(_mousemove, this);
|
||||
this.binding.dragStop = _.bind(_mouseup, this);
|
||||
this.binding.dragStart = _.bind(_dragstart, this);
|
||||
|
||||
var doclose = function() {
|
||||
if ( this.$window.find('.tool.close').hasClass('disabled') ) return;
|
||||
if (this.initConfig.toolcallback)
|
||||
this.initConfig.toolcallback.call(this);
|
||||
else
|
||||
(this.initConfig.toolclose=='hide') ? this.hide() : this.close();
|
||||
};
|
||||
this.$window.find('.header').on('mousedown', this.binding.dragStart);
|
||||
this.$window.find('.tool.close').on('click', _.bind(doclose, this));
|
||||
} else {
|
||||
this.$window.find('.body').css({
|
||||
top:0,
|
||||
'border-radius': '5px'
|
||||
});
|
||||
}
|
||||
|
||||
if (this.initConfig.height == 'auto') {
|
||||
var height = parseInt(this.$window.find('> .body').css('height'));
|
||||
this.initConfig.header && (height += parseInt(this.$window.find('> .header').css('height')));
|
||||
this.$window.height(height);
|
||||
} else {
|
||||
this.$window.css('height',this.initConfig.height);
|
||||
}
|
||||
|
||||
var me = this;
|
||||
Common.NotificationCenter.on('window:close', function() {
|
||||
if (me.$window && me.isVisible()) me.close();
|
||||
});
|
||||
|
||||
this.fireEvent('render:after',this);
|
||||
return this;
|
||||
},
|
||||
|
||||
show: function(x,y) {
|
||||
if (this.initConfig.modal) {
|
||||
var mask = _getMask();
|
||||
if (this.options.animate !== false) {
|
||||
var opacity = mask.css('opacity');
|
||||
mask.css('opacity', 0);
|
||||
mask.attr('counter', parseInt(mask.attr('counter'))+1);
|
||||
mask.show();
|
||||
|
||||
setTimeout(function () {
|
||||
mask.css(_getTransformation(opacity));
|
||||
}, 1);
|
||||
} else {
|
||||
mask.attr('counter', parseInt(mask.attr('counter'))+1);
|
||||
mask.show();
|
||||
}
|
||||
|
||||
Common.NotificationCenter.trigger('modal:show', this);
|
||||
this.$lastmodal = $('.asc-window.modal:not(.dethrone):visible').first().addClass('dethrone');
|
||||
}
|
||||
|
||||
if (!this.$window) {
|
||||
this.render();
|
||||
|
||||
if (_.isNumber(x) && _.isNumber(y)) {
|
||||
this.$window.css('left',Math.floor(x));
|
||||
this.$window.css('top',Math.floor(y));
|
||||
} else
|
||||
_centre.call(this);
|
||||
} else
|
||||
if (!this.$window.is(':visible')) {
|
||||
this.$window.css({opacity: 0});
|
||||
this.$window.show()
|
||||
}
|
||||
|
||||
$(document).on('keydown.' + this.cid, this.binding.keydown);
|
||||
|
||||
var me = this;
|
||||
if (this.options.animate !== false) {
|
||||
this.$window.css({
|
||||
'-webkit-transform': 'scale(0.8)',
|
||||
'-moz-transform': 'scale(0.8)',
|
||||
'-ms-transform': 'scale(0.8)',
|
||||
'-o-transform': 'scale(0.8)',
|
||||
opacity: 0
|
||||
});
|
||||
|
||||
setTimeout(function () {
|
||||
me.$window.css({
|
||||
'-webkit-transition': '0.2s opacity, 0.2s -webkit-transform',
|
||||
'-webkit-transform': 'scale(1)',
|
||||
'-moz-transition': '0.2s opacity, 0.2s -moz-transform',
|
||||
'-moz-transform': 'scale(1)',
|
||||
'-ms-transition': '0.2s opacity, 0.2s -ms-transform',
|
||||
'-ms-transform': 'scale(1)',
|
||||
'-o-transition': '0.2s opacity, 0.2s -o-transform',
|
||||
'-o-transform': 'scale(1)',
|
||||
'opacity': '1'
|
||||
});
|
||||
}, 1);
|
||||
|
||||
setTimeout(function () {
|
||||
me.$window.addClass('notransform');
|
||||
me.fireEvent('show', me);
|
||||
}, (this.initConfig.modal) ? 1000 : 350);
|
||||
} else {
|
||||
this.$window.css({opacity: 1});
|
||||
this.$window.addClass('notransform');
|
||||
this.fireEvent('show', this);
|
||||
}
|
||||
|
||||
Common.NotificationCenter.trigger('window:show');
|
||||
},
|
||||
|
||||
close: function(suppressevent) {
|
||||
$(document).off('keydown.' + this.cid);
|
||||
if ( this.initConfig.header ) {
|
||||
this.$window.find('.header').off('mousedown', this.binding.dragStart);
|
||||
}
|
||||
|
||||
if (this.initConfig.modal) {
|
||||
var mask = _getMask(),
|
||||
hide_mask = true;
|
||||
mask.attr('counter', parseInt(mask.attr('counter'))-1);
|
||||
|
||||
if (this.$lastmodal.size() > 0) {
|
||||
this.$lastmodal.removeClass('dethrone');
|
||||
hide_mask = !(this.$lastmodal.hasClass('modal') && this.$lastmodal.is(':visible'));
|
||||
}
|
||||
|
||||
if ( hide_mask ) {
|
||||
if (this.options.animate !== false) {
|
||||
var opacity = mask.css('opacity');
|
||||
mask.css(_getTransformation(0));
|
||||
|
||||
setTimeout(function () {
|
||||
mask.css('opacity', opacity);
|
||||
if (parseInt(mask.attr('counter'))<1) {
|
||||
mask.hide();
|
||||
mask.attr('counter', 0);
|
||||
}
|
||||
}, 300);
|
||||
} else {
|
||||
if (parseInt(mask.attr('counter'))<1) {
|
||||
mask.hide();
|
||||
mask.attr('counter', 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Common.NotificationCenter.trigger('modal:close', this);
|
||||
}
|
||||
|
||||
this.$window.remove();
|
||||
|
||||
suppressevent!==true && this.fireEvent('close', this);
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
$(document).off('keydown.' + this.cid);
|
||||
if (this.$window) {
|
||||
if (this.initConfig.modal) {
|
||||
var mask = _getMask(),
|
||||
hide_mask = true;
|
||||
mask.attr('counter', parseInt(mask.attr('counter'))-1);
|
||||
|
||||
if (this.$lastmodal.size() > 0) {
|
||||
this.$lastmodal.removeClass('dethrone');
|
||||
hide_mask = !(this.$lastmodal.hasClass('modal') && this.$lastmodal.is(':visible'));
|
||||
}
|
||||
|
||||
if ( hide_mask ) {
|
||||
if (this.options.animate !== false) {
|
||||
var opacity = mask.css('opacity');
|
||||
mask.css(_getTransformation(0));
|
||||
|
||||
setTimeout(function () {
|
||||
mask.css('opacity', opacity);
|
||||
if (parseInt(mask.attr('counter'))<1) {
|
||||
mask.hide();
|
||||
mask.attr('counter', 0);
|
||||
}
|
||||
}, 300);
|
||||
} else {
|
||||
if (parseInt(mask.attr('counter'))<1) {
|
||||
mask.hide();
|
||||
mask.attr('counter', 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
Common.NotificationCenter.trigger('modal:hide', this);
|
||||
}
|
||||
this.$window.hide();
|
||||
this.$window.removeClass('notransform');
|
||||
this.fireEvent('hide', this);
|
||||
}
|
||||
},
|
||||
|
||||
isLocked: function() {
|
||||
return this.$window.hasClass('dethrone') ||
|
||||
(!this.options.modal && this.$window.parent().find('.asc-window.modal:visible').length);
|
||||
},
|
||||
|
||||
getChild: function(selector) {
|
||||
return selector ? this.$window.find(selector) : this.$window;
|
||||
},
|
||||
|
||||
setWidth: function(width) {
|
||||
if (width >= 0) {
|
||||
var min = parseInt(this.$window.css('min-width'));
|
||||
width < min && (width = min);
|
||||
this.$window.width(width);
|
||||
}
|
||||
},
|
||||
|
||||
getWidth: function() {
|
||||
return parseInt(this.$window.css('width'));
|
||||
},
|
||||
|
||||
setHeight: function(height) {
|
||||
if (height >= 0) {
|
||||
var min = parseInt(this.$window.css('min-height'));
|
||||
height < min && (height = min);
|
||||
this.$window.height(height);
|
||||
|
||||
if (this.initConfig.header)
|
||||
height -= parseInt(this.$window.find('> .header').css('height'));
|
||||
|
||||
this.$window.find('> .body').css('height', height);
|
||||
}
|
||||
},
|
||||
|
||||
getHeight: function() {
|
||||
return parseInt(this.$window.css('height'));
|
||||
},
|
||||
|
||||
setSize: function(w, h) {
|
||||
this.setWidth(w);
|
||||
this.setHeight(h);
|
||||
},
|
||||
|
||||
getSize: function() {
|
||||
return [this.getWidth(), this.getHeight()];
|
||||
},
|
||||
|
||||
setTitle: function(title) {
|
||||
this.$window.find('> .header > .title').text(title);
|
||||
},
|
||||
|
||||
getTitle: function() {
|
||||
return this.$window.find('> .header > .title').text();
|
||||
},
|
||||
|
||||
isVisible: function() {
|
||||
return this.$window && this.$window.is(':visible');
|
||||
},
|
||||
|
||||
onPrimary: function() {},
|
||||
|
||||
cancelButtonText: 'Cancel',
|
||||
okButtonText: 'OK',
|
||||
yesButtonText: 'Yes',
|
||||
noButtonText: 'No',
|
||||
closeButtonText: 'Close',
|
||||
textWarning: 'Warning',
|
||||
textError: 'Error',
|
||||
textConfirmation: 'Confirmation',
|
||||
textInformation: 'Information',
|
||||
textDontShow: 'Don\'t show this message again'
|
||||
};
|
||||
|
||||
})(), Common.UI.Window || {}));
|
||||
});
|
183
apps/common/main/lib/controller/Chat.js
Normal file
183
apps/common/main/lib/controller/Chat.js
Normal file
|
@ -0,0 +1,183 @@
|
|||
/**
|
||||
* Chat.js
|
||||
*
|
||||
* Controller
|
||||
*
|
||||
* Created by Maxim Kadushkin on 27 February 2014
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
define([
|
||||
'core',
|
||||
'common/main/lib/collection/Users',
|
||||
'common/main/lib/collection/ChatMessages',
|
||||
'common/main/lib/view/Chat'
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
Common.Controllers.Chat = Backbone.Controller.extend(_.extend({
|
||||
models: [],
|
||||
collections: [
|
||||
'Common.Collections.Users',
|
||||
'Common.Collections.ChatMessages'
|
||||
],
|
||||
views: [
|
||||
'Common.Views.Chat'
|
||||
],
|
||||
|
||||
initialize: function() {
|
||||
this.addListeners({
|
||||
'Common.Views.Chat': {
|
||||
'message:add': _.bind(this.onSendMessage, this)
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
events: {
|
||||
},
|
||||
|
||||
|
||||
onLaunch: function() {
|
||||
this.panelChat = this.createView('Common.Views.Chat', {
|
||||
storeUsers: this.getApplication().getCollection('Common.Collections.Users'),
|
||||
storeMessages: this.getApplication().getCollection('Common.Collections.ChatMessages')
|
||||
});
|
||||
},
|
||||
|
||||
setMode: function(mode) {
|
||||
this.mode = mode;
|
||||
|
||||
if (this.api && this.mode.canCoAuthoring) {
|
||||
if (this.mode.canChat)
|
||||
this.api.asc_registerCallback('asc_onCoAuthoringChatReceiveMessage', _.bind(this.onReceiveMessage, this));
|
||||
this.api.asc_registerCallback('asc_onAuthParticipantsChanged', _.bind(this.onUsersChanged, this));
|
||||
this.api.asc_registerCallback('asc_onConnectionStateChanged', _.bind(this.onUserConnection, this));
|
||||
|
||||
this.api.asc_coAuthoringGetUsers();
|
||||
if (this.mode.canChat)
|
||||
this.api.asc_coAuthoringChatGetMessages();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
setApi: function(api) {
|
||||
this.api = api;
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
onUsersChanged: function(users){
|
||||
if (!this.mode.canLicense) {
|
||||
var len = 0;
|
||||
for (name in users) {
|
||||
if (undefined !== name) len++;
|
||||
}
|
||||
if (len>1 && this._isCoAuthoringStopped==undefined) {
|
||||
this._isCoAuthoringStopped = true;
|
||||
this.api.asc_coAuthoringDisconnect();
|
||||
Common.NotificationCenter.trigger('api:disconnect');
|
||||
/*
|
||||
setTimeout(_.bind(function(){
|
||||
Common.UI.alert({
|
||||
closable: false,
|
||||
title: this.notcriticalErrorTitle,
|
||||
msg: this.textUserLimit,
|
||||
iconCls: 'warn',
|
||||
buttons: ['ok']
|
||||
});
|
||||
}, this), 100);
|
||||
*/
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var usersStore = this.getApplication().getCollection('Common.Collections.Users');
|
||||
|
||||
if (usersStore) {
|
||||
var arrUsers = [], name, user;
|
||||
|
||||
for (name in users) {
|
||||
if (undefined !== name) {
|
||||
user = users[name];
|
||||
if (user) {
|
||||
arrUsers.push(new Common.Models.User({
|
||||
id : user.asc_getId(),
|
||||
username : user.asc_getUserName(),
|
||||
online : true,
|
||||
color : user.asc_getColor(),
|
||||
view : user.asc_getView()
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
usersStore[usersStore.size() > 0 ? 'add' : 'reset'](arrUsers);
|
||||
}
|
||||
},
|
||||
|
||||
onUserConnection: function(change){
|
||||
var usersStore = this.getApplication().getCollection('Common.Collections.Users');
|
||||
|
||||
if (usersStore){
|
||||
var user = usersStore.findUser(change.asc_getId());
|
||||
if (!user) {
|
||||
usersStore.add(new Common.Models.User({
|
||||
id : change.asc_getId(),
|
||||
username : change.asc_getUserName(),
|
||||
online : change.asc_getState(),
|
||||
color : change.asc_getColor(),
|
||||
view : change.asc_getView()
|
||||
}));
|
||||
} else {
|
||||
user.set({online: change.asc_getState()});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onReceiveMessage: function(messages, clear){
|
||||
var msgStore = this.getApplication().getCollection('Common.Collections.ChatMessages');
|
||||
|
||||
if ( msgStore ) {
|
||||
var array = [];
|
||||
messages.forEach(function(msg) {
|
||||
array.push(new Common.Models.ChatMessage({
|
||||
userid : msg.user,
|
||||
message : msg.message,
|
||||
username : msg.username
|
||||
}));
|
||||
});
|
||||
|
||||
msgStore[(msgStore.size() < 1 || clear) ? 'reset' : 'add'](array);
|
||||
}
|
||||
},
|
||||
|
||||
onSendMessage: function(panel, text){
|
||||
if (text.length > 0){
|
||||
var splitString = function(string, chunkSize) {
|
||||
var chunks = [];
|
||||
|
||||
while (string) {
|
||||
if (string.length < chunkSize) {
|
||||
chunks.push(string);
|
||||
break;
|
||||
} else {
|
||||
chunks.push(string.substr(0, chunkSize));
|
||||
string = string.substr(chunkSize);
|
||||
}
|
||||
}
|
||||
|
||||
return chunks;
|
||||
};
|
||||
|
||||
var me = this;
|
||||
splitString(text, 2048).forEach(function(message) {
|
||||
me.api.asc_coAuthoringChatSendMessage(message);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
notcriticalErrorTitle: 'Warning',
|
||||
textUserLimit: 'You are using ONLYOFFICE Editors free version.<br>Only two users can co-edit the document simultaneously.<br>Want more? Consider buying ONLYOFFICE Editors Pro version.<br><a href=\"http:\/\/www.onlyoffice.com\" target=\"_blank\">Read more</a>'
|
||||
}, Common.Controllers.Chat || {}));
|
||||
});
|
1257
apps/common/main/lib/controller/Comments.js
Normal file
1257
apps/common/main/lib/controller/Comments.js
Normal file
File diff suppressed because it is too large
Load diff
198
apps/common/main/lib/controller/ExternalDiagramEditor.js
Normal file
198
apps/common/main/lib/controller/ExternalDiagramEditor.js
Normal file
|
@ -0,0 +1,198 @@
|
|||
/**
|
||||
* ExternalDiagramEditor.js
|
||||
*
|
||||
* Created by Julia Radzhabova on 4/08/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
Common.Controllers = Common.Controllers || {};
|
||||
|
||||
define([
|
||||
'core',
|
||||
'common/main/lib/view/ExternalDiagramEditor'
|
||||
], function () { 'use strict';
|
||||
Common.Controllers.ExternalDiagramEditor = Backbone.Controller.extend(_.extend((function() {
|
||||
var appLang = 'en',
|
||||
customization = undefined,
|
||||
externalEditor = null;
|
||||
|
||||
|
||||
var createExternalEditor = function() {
|
||||
externalEditor = new DocsAPI.DocEditor('id-diagram-editor-placeholder', {
|
||||
width : '100%',
|
||||
height : '100%',
|
||||
documentType: 'spreadsheet',
|
||||
document : {
|
||||
url : '_offline_',
|
||||
permissions : {
|
||||
edit : true,
|
||||
download: false
|
||||
}
|
||||
},
|
||||
editorConfig: {
|
||||
mode : 'editdiagram',
|
||||
lang : appLang,
|
||||
canCoAuthoring : false,
|
||||
canBackToFolder : false,
|
||||
canCreateNew : false,
|
||||
customization : customization,
|
||||
user : {id: ('uid-'+Date.now())}
|
||||
},
|
||||
events: {
|
||||
'onReady' : function() {},
|
||||
'onDocumentStateChange' : function() {},
|
||||
'onError' : function() {},
|
||||
'onInternalMessage' : _.bind(this.onInternalMessage, this)
|
||||
}
|
||||
});
|
||||
Common.Gateway.on('processmouse', _.bind(this.onProcessMouse, this));
|
||||
};
|
||||
|
||||
return {
|
||||
views: ['Common.Views.ExternalDiagramEditor'],
|
||||
|
||||
initialize: function() {
|
||||
this.addListeners({
|
||||
'Common.Views.ExternalDiagramEditor': {
|
||||
'setchartdata': _.bind(this.setChartData, this),
|
||||
'drag': _.bind(function(o, state){
|
||||
externalEditor.serviceCommand('window:drag', state == 'start');
|
||||
},this),
|
||||
'show': _.bind(function(cmp){
|
||||
var h = this.diagramEditorView.getHeight();
|
||||
if (window.innerHeight>h && h<700 || window.innerHeight<h) {
|
||||
h = Math.min(window.innerHeight, 700);
|
||||
this.diagramEditorView.setHeight(h);
|
||||
}
|
||||
|
||||
if (externalEditor) {
|
||||
externalEditor.serviceCommand('setAppDisabled',false);
|
||||
if (this.needDisableEditing && this.diagramEditorView._isExternalDocReady) {
|
||||
this.onDiagrammEditingDisabled();
|
||||
}
|
||||
externalEditor.attachMouseEvents();
|
||||
} else {
|
||||
createExternalEditor.apply(this);
|
||||
}
|
||||
this.isExternalEditorVisible = true;
|
||||
}, this),
|
||||
'hide': _.bind(function(cmp){
|
||||
if (externalEditor) {
|
||||
externalEditor.detachMouseEvents();
|
||||
this.isExternalEditorVisible = false;
|
||||
}
|
||||
}, this)
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
},
|
||||
|
||||
onLaunch: function() {
|
||||
this.diagramEditorView = this.createView('Common.Views.ExternalDiagramEditor', {handler: _.bind(this.handler, this)});
|
||||
},
|
||||
|
||||
setApi: function(api) {
|
||||
this.api = api;
|
||||
this.api.asc_registerCallback('asc_onCloseChartEditor', _.bind(this.onDiagrammEditingDisabled, this));
|
||||
return this;
|
||||
},
|
||||
|
||||
handler: function(result, value) {
|
||||
externalEditor.serviceCommand('queryClose',{mr:result});
|
||||
return true;
|
||||
},
|
||||
|
||||
setChartData: function() {
|
||||
externalEditor && externalEditor.serviceCommand('setChartData', this.diagramEditorView._chartData);
|
||||
this.diagramEditorView._chartData = null;
|
||||
},
|
||||
|
||||
loadConfig: function(data) {
|
||||
if (data && data.config) {
|
||||
if (data.config.lang) appLang = data.config.lang;
|
||||
if (data.config.customization) customization = data.config.customization;
|
||||
}
|
||||
},
|
||||
|
||||
onDiagrammEditingDisabled: function() {
|
||||
if ( !this.diagramEditorView.isVisible() || !this.diagramEditorView._isExternalDocReady ) {
|
||||
this.needDisableEditing = true;
|
||||
return;
|
||||
}
|
||||
|
||||
this.diagramEditorView.setControlsDisabled(true);
|
||||
|
||||
Common.UI.alert({
|
||||
title: this.warningTitle,
|
||||
msg : this.warningText,
|
||||
iconCls: 'warn',
|
||||
buttons: ['ok'],
|
||||
callback: _.bind(function(btn){
|
||||
this.setControlsDisabled(false);
|
||||
this.diagramEditorView.hide();
|
||||
}, this)
|
||||
});
|
||||
|
||||
this.needDisableEditing = false;
|
||||
},
|
||||
|
||||
onInternalMessage: function(data) {
|
||||
var eventData = data.data;
|
||||
|
||||
if (this.diagramEditorView) {
|
||||
if (eventData.type == 'documentReady') {
|
||||
this.diagramEditorView._isExternalDocReady = true;
|
||||
this.diagramEditorView.setControlsDisabled(false);
|
||||
if (this.diagramEditorView._chartData) {
|
||||
externalEditor && externalEditor.serviceCommand('setChartData', this.diagramEditorView._chartData);
|
||||
this.diagramEditorView._chartData = null;
|
||||
}
|
||||
if (this.needDisableEditing) {
|
||||
this.onDiagrammEditingDisabled();
|
||||
}
|
||||
} else
|
||||
if (eventData.type == "shortcut") {
|
||||
if (eventData.data.key == 'escape')
|
||||
this.diagramEditorView.hide();
|
||||
} else
|
||||
if (eventData.type == "canClose") {
|
||||
if (eventData.data.answer === true) {
|
||||
if (externalEditor) {
|
||||
externalEditor.serviceCommand('setAppDisabled',true);
|
||||
externalEditor.serviceCommand((eventData.data.mr == 'ok') ? 'getChartData' : 'clearChartData');
|
||||
}
|
||||
this.diagramEditorView.hide();
|
||||
}
|
||||
} else
|
||||
if (eventData.type == "processMouse") {
|
||||
if (eventData.data.event == 'mouse:up') {
|
||||
this.diagramEditorView.binding.dragStop();
|
||||
} else
|
||||
if (eventData.data.event == 'mouse:move') {
|
||||
var x = parseInt(this.diagramEditorView.$window.css('left')) + eventData.data.pagex,
|
||||
y = parseInt(this.diagramEditorView.$window.css('top')) + eventData.data.pagey + 34;
|
||||
this.diagramEditorView.binding.drag({pageX:x, pageY:y});
|
||||
}
|
||||
} else
|
||||
this.diagramEditorView.fireEvent('internalmessage', this.diagramEditorView, eventData);
|
||||
}
|
||||
} ,
|
||||
|
||||
onProcessMouse: function(data) {
|
||||
if (data.type == 'mouseup' && this.isExternalEditorVisible) {
|
||||
externalEditor && externalEditor.serviceCommand('processmouse', data);
|
||||
}
|
||||
},
|
||||
|
||||
warningTitle: 'Warning',
|
||||
warningText: 'The object is disabled because of editing by another user.',
|
||||
textClose: 'Close',
|
||||
textAnonymous: 'Anonymous'
|
||||
}
|
||||
})(), Common.Controllers.ExternalDiagramEditor || {}));
|
||||
});
|
200
apps/common/main/lib/controller/ExternalMergeEditor.js
Normal file
200
apps/common/main/lib/controller/ExternalMergeEditor.js
Normal file
|
@ -0,0 +1,200 @@
|
|||
/**
|
||||
* ExternalDiagramEditor.js
|
||||
*
|
||||
* Created by Julia Radzhabova on 4/08/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
Common.Controllers = Common.Controllers || {};
|
||||
|
||||
define([
|
||||
'core',
|
||||
'common/main/lib/view/ExternalMergeEditor'
|
||||
], function () { 'use strict';
|
||||
Common.Controllers.ExternalMergeEditor = Backbone.Controller.extend(_.extend((function() {
|
||||
var appLang = 'en',
|
||||
customization = undefined,
|
||||
externalEditor = null;
|
||||
|
||||
|
||||
var createExternalEditor = function() {
|
||||
externalEditor = new DocsAPI.DocEditor('id-merge-editor-placeholder', {
|
||||
width : '100%',
|
||||
height : '100%',
|
||||
documentType: 'spreadsheet',
|
||||
document : {
|
||||
url : '_offline_',
|
||||
permissions : {
|
||||
edit : true,
|
||||
download: false
|
||||
}
|
||||
},
|
||||
editorConfig: {
|
||||
mode : 'editmerge',
|
||||
lang : appLang,
|
||||
canCoAuthoring : false,
|
||||
canBackToFolder : false,
|
||||
canCreateNew : false,
|
||||
customization : customization,
|
||||
user : {id: ('uid-'+Date.now())}
|
||||
},
|
||||
events: {
|
||||
'onReady' : function() {},
|
||||
'onDocumentStateChange' : function() {},
|
||||
'onError' : function() {},
|
||||
'onInternalMessage' : _.bind(this.onInternalMessage, this)
|
||||
}
|
||||
});
|
||||
Common.Gateway.on('processmouse', _.bind(this.onProcessMouse, this));
|
||||
};
|
||||
|
||||
return {
|
||||
views: ['Common.Views.ExternalMergeEditor'],
|
||||
|
||||
initialize: function() {
|
||||
this.addListeners({
|
||||
'Common.Views.ExternalMergeEditor': {
|
||||
'setmergedata': _.bind(this.setMergeData, this),
|
||||
'drag': _.bind(function(o, state){
|
||||
externalEditor.serviceCommand('window:drag', state == 'start');
|
||||
},this),
|
||||
'show': _.bind(function(cmp){
|
||||
var h = this.mergeEditorView.getHeight();
|
||||
if (window.innerHeight>h && h<700 || window.innerHeight<h) {
|
||||
h = Math.min(window.innerHeight, 700);
|
||||
this.mergeEditorView.setHeight(h);
|
||||
}
|
||||
|
||||
if (externalEditor) {
|
||||
externalEditor.serviceCommand('setAppDisabled',false);
|
||||
if (this.needDisableEditing && this.mergeEditorView._isExternalDocReady) {
|
||||
this.onMergeEditingDisabled();
|
||||
}
|
||||
externalEditor.attachMouseEvents();
|
||||
} else {
|
||||
createExternalEditor.apply(this);
|
||||
}
|
||||
this.isExternalEditorVisible = true;
|
||||
}, this),
|
||||
'hide': _.bind(function(cmp){
|
||||
if (externalEditor) {
|
||||
externalEditor.detachMouseEvents();
|
||||
this.isExternalEditorVisible = false;
|
||||
}
|
||||
}, this)
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
},
|
||||
|
||||
onLaunch: function() {
|
||||
this.mergeEditorView = this.createView('Common.Views.ExternalMergeEditor', {handler: _.bind(this.handler, this)});
|
||||
},
|
||||
|
||||
setApi: function(api) {
|
||||
this.api = api;
|
||||
this.api.asc_registerCallback('asc_onCloseMergeEditor', _.bind(this.onMergeEditingDisabled, this));
|
||||
return this;
|
||||
},
|
||||
|
||||
handler: function(result, value) {
|
||||
externalEditor.serviceCommand('queryClose',{mr:result});
|
||||
return true;
|
||||
},
|
||||
|
||||
setMergeData: function() {
|
||||
externalEditor && externalEditor.serviceCommand('setMergeData', this.mergeEditorView._mergeData);
|
||||
this.mergeEditorView.setEditMode(true);
|
||||
this.mergeEditorView._mergeData = null;
|
||||
},
|
||||
|
||||
loadConfig: function(data) {
|
||||
if (data && data.config) {
|
||||
if (data.config.lang) appLang = data.config.lang;
|
||||
if (data.config.customization) customization = data.config.customization;
|
||||
}
|
||||
},
|
||||
|
||||
onMergeEditingDisabled: function() {
|
||||
if ( !this.mergeEditorView.isVisible() || !this.mergeEditorView._isExternalDocReady ) {
|
||||
this.needDisableEditing = true;
|
||||
return;
|
||||
}
|
||||
|
||||
this.mergeEditorView.setControlsDisabled(true);
|
||||
|
||||
Common.UI.alert({
|
||||
title: this.warningTitle,
|
||||
msg : this.warningText,
|
||||
iconCls: 'warn',
|
||||
buttons: ['ok'],
|
||||
callback: _.bind(function(btn){
|
||||
this.setControlsDisabled(false);
|
||||
this.mergeEditorView.hide();
|
||||
}, this)
|
||||
});
|
||||
|
||||
this.needDisableEditing = false;
|
||||
},
|
||||
|
||||
onInternalMessage: function(data) {
|
||||
var eventData = data.data;
|
||||
|
||||
if (this.mergeEditorView) {
|
||||
if (eventData.type == 'documentReady') {
|
||||
this.mergeEditorView._isExternalDocReady = true;
|
||||
this.mergeEditorView.setControlsDisabled(false);
|
||||
if (this.mergeEditorView._mergeData) {
|
||||
externalEditor && externalEditor.serviceCommand('setMergeData', this.mergeEditorView._mergeData);
|
||||
this.mergeEditorView._mergeData = null;
|
||||
}
|
||||
if (this.needDisableEditing) {
|
||||
this.onMergeEditingDisabled();
|
||||
}
|
||||
} else
|
||||
if (eventData.type == "shortcut") {
|
||||
if (eventData.data.key == 'escape')
|
||||
this.mergeEditorView.hide();
|
||||
} else
|
||||
if (eventData.type == "canClose") {
|
||||
if (eventData.data.answer === true) {
|
||||
if (externalEditor) {
|
||||
externalEditor.serviceCommand('setAppDisabled',true);
|
||||
if (eventData.data.mr == 'ok')
|
||||
externalEditor.serviceCommand('getMergeData');
|
||||
}
|
||||
this.mergeEditorView.hide();
|
||||
}
|
||||
} else
|
||||
if (eventData.type == "processMouse") {
|
||||
if (eventData.data.event == 'mouse:up') {
|
||||
this.mergeEditorView.binding.dragStop();
|
||||
} else
|
||||
if (eventData.data.event == 'mouse:move') {
|
||||
var x = parseInt(this.mergeEditorView.$window.css('left')) + eventData.data.pagex,
|
||||
y = parseInt(this.mergeEditorView.$window.css('top')) + eventData.data.pagey + 34;
|
||||
this.mergeEditorView.binding.drag({pageX:x, pageY:y});
|
||||
}
|
||||
} else
|
||||
this.mergeEditorView.fireEvent('internalmessage', this.mergeEditorView, eventData);
|
||||
}
|
||||
} ,
|
||||
|
||||
onProcessMouse: function(data) {
|
||||
if (data.type == 'mouseup' && this.isExternalEditorVisible) {
|
||||
externalEditor && externalEditor.serviceCommand('processmouse', data);
|
||||
}
|
||||
},
|
||||
|
||||
warningTitle: 'Warning',
|
||||
warningText: 'The object is disabled because of editing by another user.',
|
||||
textClose: 'Close',
|
||||
textAnonymous: 'Anonymous'
|
||||
}
|
||||
})(), Common.Controllers.ExternalMergeEditor || {}));
|
||||
});
|
124
apps/common/main/lib/controller/Fonts.js
Normal file
124
apps/common/main/lib/controller/Fonts.js
Normal file
|
@ -0,0 +1,124 @@
|
|||
/**
|
||||
* Fonts.js
|
||||
*
|
||||
* Created by Alexander Yuzhin on 2/11/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
Common.Controllers = Common.Controllers || {};
|
||||
|
||||
define([
|
||||
'core',
|
||||
'common/main/lib/collection/Fonts'
|
||||
], function () { 'use strict';
|
||||
Common.Controllers.Fonts = Backbone.Controller.extend((function() {
|
||||
var FONT_TYPE_USERUSED = 4;
|
||||
|
||||
function isFontSaved(store, rec) {
|
||||
var out = rec.get('type') == FONT_TYPE_USERUSED,
|
||||
i = -1,
|
||||
c = store.length,
|
||||
su,
|
||||
n = rec.get('name');
|
||||
while (!out && ++i < c) {
|
||||
su = store.at(i);
|
||||
|
||||
if (su.get('type') != FONT_TYPE_USERUSED)
|
||||
break;
|
||||
|
||||
out = su.get('name') == n;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
function onSelectFont(combo, record) {
|
||||
if (combo.showlastused && !isFontSaved(combo.store, record)) {
|
||||
// var node = combo.picker.getNode(records[0]);
|
||||
//
|
||||
// var data = records[0].data;
|
||||
// var font = {
|
||||
// id: data.id,
|
||||
// name: data.name,
|
||||
// imgidx: data.imgidx,
|
||||
// cloneid: node.querySelector('img').id,
|
||||
// type: FONT_TYPE_USERUSED
|
||||
// };
|
||||
// combo.getStore().insert(0,[font]);
|
||||
//
|
||||
// var separator = combo.picker.getEl().down('.used-fonts-separator');
|
||||
// if (!separator) {
|
||||
// separator = document.createElement('div');
|
||||
// separator.setAttribute('class', 'x-menu-item-separator used-fonts-separator');
|
||||
// separator.setAttribute('style', 'padding:0 10px;margin-left: 10px;');
|
||||
//
|
||||
// node = combo.picker.getNode(combo.getStore().getAt(1));
|
||||
// node.parentNode.insertBefore(separator,node);
|
||||
// }
|
||||
//
|
||||
// font = combo.getStore().getAt(5);
|
||||
// if (font.data.type==FONT_TYPE_USERUSED) {
|
||||
// combo.getStore().remove(font);
|
||||
// } else {
|
||||
// var plugin = combo.getPlugin('scrollpane');
|
||||
// if (plugin){plugin.updateScrollPane();}
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
function onApiFontChange(fontobj) {
|
||||
Common.NotificationCenter.trigger('fonts:change', fontobj)
|
||||
}
|
||||
|
||||
function onApiLoadFonts(fonts, select) {
|
||||
var fontsArray = [];
|
||||
_.each(fonts, function(font){
|
||||
var fontId = font.asc_getFontId();
|
||||
fontsArray.push({
|
||||
id :_.isEmpty(fontId) ? Common.UI.getId() : fontId,
|
||||
name : font.asc_getFontName(),
|
||||
// displayValue: font.asc_getFontName(),
|
||||
imgidx : font.asc_getFontThumbnail(),
|
||||
type : font.asc_getFontType()
|
||||
});
|
||||
});
|
||||
|
||||
var store = this.getCollection('Common.Collections.Fonts');
|
||||
|
||||
if (store) {
|
||||
store.add(fontsArray);
|
||||
store.sort();
|
||||
}
|
||||
|
||||
Common.NotificationCenter.trigger('fonts:load', store, select);
|
||||
}
|
||||
|
||||
return {
|
||||
models: [
|
||||
'Common.Models.Fonts'
|
||||
],
|
||||
collections: [
|
||||
'Common.Collections.Fonts'
|
||||
],
|
||||
views: [],
|
||||
|
||||
initialize: function() {
|
||||
Common.NotificationCenter.on('fonts:select', _.bind(onSelectFont, this))
|
||||
},
|
||||
|
||||
onLaunch: function() {
|
||||
//
|
||||
},
|
||||
|
||||
setApi: function(api) {
|
||||
this.api = api;
|
||||
this.api.asc_registerCallback('asc_onInitEditorFonts', _.bind(onApiLoadFonts, this));
|
||||
this.api.asc_registerCallback('asc_onFontFamily', _.bind(onApiFontChange, this));
|
||||
}
|
||||
}
|
||||
})());
|
||||
});
|
133
apps/common/main/lib/controller/History.js
Normal file
133
apps/common/main/lib/controller/History.js
Normal file
|
@ -0,0 +1,133 @@
|
|||
/**
|
||||
* User: Julia.Radzhabova
|
||||
* Date: 06.03.15
|
||||
* Time: 12:13
|
||||
*/
|
||||
|
||||
define([
|
||||
'core',
|
||||
'common/main/lib/collection/HistoryVersions',
|
||||
'common/main/lib/view/History'
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
Common.Controllers.History = Backbone.Controller.extend(_.extend({
|
||||
models: [],
|
||||
collections: [
|
||||
'Common.Collections.HistoryVersions'
|
||||
],
|
||||
views: [
|
||||
'Common.Views.History'
|
||||
],
|
||||
|
||||
initialize: function() {
|
||||
this.currentChangeId = -1;
|
||||
this.currentArrColors = [];
|
||||
this.currentDocId = '';
|
||||
this.currentDocIdPrev = '';
|
||||
},
|
||||
|
||||
events: {
|
||||
},
|
||||
|
||||
onLaunch: function() {
|
||||
this.panelHistory= this.createView('Common.Views.History', {
|
||||
storeHistory: this.getApplication().getCollection('Common.Collections.HistoryVersions')
|
||||
});
|
||||
this.panelHistory.on('render:after', _.bind(this.onAfterRender, this));
|
||||
Common.Gateway.on('sethistorydata', _.bind(this.onSetHistoryData, this));
|
||||
},
|
||||
|
||||
setApi: function(api) {
|
||||
this.api = api;
|
||||
return this;
|
||||
},
|
||||
|
||||
setMode: function(mode) {
|
||||
if (!mode.canHistoryClose) {
|
||||
this.panelHistory.$el.find('#history-header').hide();
|
||||
this.panelHistory.$el.find('#history-list').css('padding-top', 0);
|
||||
}
|
||||
},
|
||||
|
||||
onAfterRender: function(historyView) {
|
||||
historyView.viewHistoryList.on('item:click', _.bind(this.onSelectRevision, this));
|
||||
historyView.btnBackToDocument.on('click', _.bind(this.onClickBackToDocument, this));
|
||||
},
|
||||
|
||||
onSelectRevision: function(picker, item, record) {
|
||||
var url = record.get('url'),
|
||||
rev = record.get('revision'),
|
||||
urlGetTime = new Date();
|
||||
|
||||
this.currentChangeId = record.get('changeid');
|
||||
this.currentArrColors = record.get('arrColors');
|
||||
this.currentDocId = record.get('docId');
|
||||
this.currentDocIdPrev = record.get('docIdPrev');
|
||||
|
||||
if ( _.isEmpty(url) || (urlGetTime - record.get('urlGetTime') > 5 * 60000)) {
|
||||
_.delay(function() {
|
||||
Common.Gateway.requestHistoryData(rev); // получаем url-ы для ревизий
|
||||
}, 10);
|
||||
} else {
|
||||
var urlDiff = record.get('urlDiff'),
|
||||
hist = new Asc.asc_CVersionHistory();
|
||||
hist.asc_setDocId(_.isEmpty(urlDiff) ? this.currentDocId : this.currentDocIdPrev);
|
||||
hist.asc_setUrl(url);
|
||||
hist.asc_setUrlChanges(urlDiff);
|
||||
hist.asc_setCurrentChangeId(this.currentChangeId);
|
||||
hist.asc_setArrColors(this.currentArrColors);
|
||||
this.api.asc_showRevision(hist);
|
||||
|
||||
var commentsController = this.getApplication().getController('Common.Controllers.Comments');
|
||||
if (commentsController) commentsController.onApiHideComment();
|
||||
}
|
||||
},
|
||||
|
||||
onSetHistoryData: function(opts) {
|
||||
if (opts.data.error) {
|
||||
var config = {
|
||||
closable: false,
|
||||
title: this.notcriticalErrorTitle,
|
||||
msg: opts.data.error,
|
||||
iconCls: 'warn',
|
||||
buttons: ['ok']
|
||||
};
|
||||
Common.UI.alert(config);
|
||||
} else {
|
||||
var data = opts.data;
|
||||
var historyStore = this.getApplication().getCollection('Common.Collections.HistoryVersions');
|
||||
if (historyStore && data!==null) {
|
||||
var rev, revisions = historyStore.findRevisions(data.version),
|
||||
urlGetTime = new Date();
|
||||
if (revisions && revisions.length>0) {
|
||||
for(var i=0; i<revisions.length; i++) {
|
||||
rev = revisions[i];
|
||||
rev.set('url', opts.data.url, {silent: true});
|
||||
rev.set('urlDiff', opts.data.urlDiff, {silent: true});
|
||||
rev.set('urlGetTime', urlGetTime, {silent: true});
|
||||
}
|
||||
}
|
||||
var hist = new Asc.asc_CVersionHistory();
|
||||
hist.asc_setUrl(opts.data.url);
|
||||
hist.asc_setUrlChanges(opts.data.urlDiff);
|
||||
hist.asc_setDocId(_.isEmpty(opts.data.urlDiff) ? this.currentDocId : this.currentDocIdPrev);
|
||||
hist.asc_setCurrentChangeId(this.currentChangeId);
|
||||
hist.asc_setArrColors(this.currentArrColors);
|
||||
this.api.asc_showRevision(hist);
|
||||
|
||||
var commentsController = this.getApplication().getController('Common.Controllers.Comments');
|
||||
if (commentsController) commentsController.onApiHideComment();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onClickBackToDocument: function () {
|
||||
// reload editor
|
||||
Common.Gateway.requestHistoryClose();
|
||||
},
|
||||
|
||||
notcriticalErrorTitle: 'Warning'
|
||||
|
||||
}, Common.Controllers.History || {}));
|
||||
});
|
488
apps/common/main/lib/controller/ReviewChanges.js
Normal file
488
apps/common/main/lib/controller/ReviewChanges.js
Normal file
|
@ -0,0 +1,488 @@
|
|||
/**
|
||||
* ReviewChanges.js
|
||||
*
|
||||
* Created by Julia.Radzhabova on 05.08.15
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
Common.Controllers = Common.Controllers || {};
|
||||
|
||||
define([
|
||||
'core',
|
||||
'common/main/lib/model/ReviewChange',
|
||||
'common/main/lib/collection/ReviewChanges',
|
||||
'common/main/lib/view/ReviewChanges'
|
||||
], function () {
|
||||
'use strict';
|
||||
|
||||
Common.Controllers.ReviewChanges = Backbone.Controller.extend(_.extend({
|
||||
models : [],
|
||||
collections : [
|
||||
'Common.Collections.ReviewChanges'
|
||||
],
|
||||
views : [
|
||||
'Common.Views.ReviewChanges',
|
||||
'Common.Views.ReviewChangesPopover'
|
||||
],
|
||||
sdkViewName : '#id_main',
|
||||
|
||||
initialize: function () {
|
||||
|
||||
this.addListeners({
|
||||
'Common.Views.ReviewChanges': {
|
||||
|
||||
// comments handlers
|
||||
'reviewchange:accept': _.bind(this.onAcceptClick, this),
|
||||
'reviewchange:reject': _.bind(this.onRejectClick, this),
|
||||
'reviewchange:delete': _.bind(this.onDeleteClick, this)
|
||||
}
|
||||
});
|
||||
},
|
||||
onLaunch: function () {
|
||||
this.collection = this.getApplication().getCollection('Common.Collections.ReviewChanges');
|
||||
this.popoverChanges = new Common.Collections.ReviewChanges();
|
||||
this.userCollection = this.getApplication().getCollection('Common.Collections.Users');
|
||||
|
||||
this.view = this.createView('Common.Views.ReviewChanges', {
|
||||
store : this.collection,
|
||||
popoverChanges : this.popoverChanges
|
||||
});
|
||||
this.view.render();
|
||||
this.bindViewEvents(this.view, this.events);
|
||||
|
||||
var me = this;
|
||||
this.view.btnPrev.on('click', _.bind(this.onBtnPreviewClick, this));
|
||||
this.view.btnNext.on('click', _.bind(this.onBtnPreviewClick, this));
|
||||
this.view.btnAccept.on('click', _.bind(this.onAcceptClick, this));
|
||||
this.view.btnAccept.menu.on('item:click', _.bind(this.onAcceptClick, this));
|
||||
this.view.btnReject.on('click', _.bind(this.onRejectClick, this));
|
||||
this.view.btnReject.menu.on('item:click', _.bind(this.onRejectClick, this));
|
||||
|
||||
this._state = {posx: -1000, posy: -1000, popoverVisible: false};
|
||||
},
|
||||
setConfig: function (data, api) {
|
||||
this.setApi(api);
|
||||
|
||||
if (data) {
|
||||
this.currentUserId = data.config.user.id;
|
||||
this.currentUserName = data.config.user.name;
|
||||
this.sdkViewName = data['sdkviewname'] || this.sdkViewName;
|
||||
}
|
||||
},
|
||||
setApi: function (api) {
|
||||
if (api) {
|
||||
this.api = api;
|
||||
|
||||
this.api.asc_registerCallback('asc_onShowRevisionsChange', _.bind(this.onApiShowChange, this));
|
||||
this.api.asc_registerCallback('asc_onUpdateRevisionsChangesPosition', _.bind(this.onApiUpdateChangePosition, this));
|
||||
}
|
||||
},
|
||||
|
||||
setMode: function(mode) {
|
||||
this.view.isReviewOnly = mode.isReviewOnly;
|
||||
this.view.btnAccept.setDisabled(mode.isReviewOnly);
|
||||
this.view.btnReject.setDisabled(mode.isReviewOnly);
|
||||
return this;
|
||||
},
|
||||
|
||||
onApiShowChange: function (sdkchange) {
|
||||
if (this.getPopover()) {
|
||||
if (sdkchange && sdkchange.length>0) {
|
||||
var i = 0,
|
||||
changes = this.readSDKChange(sdkchange),
|
||||
posX = sdkchange[0].get_X(),
|
||||
posY = sdkchange[0].get_Y(),
|
||||
animate = ( Math.abs(this._state.posx-posX)>0.001 || Math.abs(this._state.posy-posY)>0.001),
|
||||
lock = (sdkchange[0].get_LockUserId()!==null),
|
||||
lockUser = this.getUserName(sdkchange[0].get_LockUserId());
|
||||
|
||||
this.popoverChanges.reset(changes);
|
||||
|
||||
if (animate) {
|
||||
if ( this.getPopover().isVisible() ) this.getPopover().hide();
|
||||
this.getPopover().setLeftTop(posX+25, posY);
|
||||
}
|
||||
|
||||
this.getPopover().show(animate, lock, lockUser);
|
||||
|
||||
if (!this.view.isReviewOnly && this._state.lock !== lock) {
|
||||
this.view.btnAccept.setDisabled(lock==true);
|
||||
this.view.btnReject.setDisabled(lock==true);
|
||||
this._state.lock = lock;
|
||||
}
|
||||
this._state.posx = posX;
|
||||
this._state.posy = posY;
|
||||
this._state.popoverVisible = true;
|
||||
} else if (this._state.popoverVisible){
|
||||
this._state.posx = this._state.posy = -1000;
|
||||
this._state.popoverVisible = false;
|
||||
this.getPopover().hide();
|
||||
this.popoverChanges.reset();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onApiUpdateChangePosition: function (posX, posY) {
|
||||
var i, useAnimation = false,
|
||||
change = null,
|
||||
text = undefined,
|
||||
saveTxtId = '',
|
||||
saveTxtReplyId = '';
|
||||
|
||||
if (this.getPopover()) {
|
||||
if (posY < 0 || this.getPopover().sdkBounds.height < posY) {
|
||||
this.getPopover().hide();
|
||||
} else if (this.popoverChanges.length>0) {
|
||||
if (!this.getPopover().isVisible())
|
||||
this.getPopover().show(false);
|
||||
this.getPopover().setLeftTop(posX+25, posY);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
findChange: function (uid, id) {
|
||||
if (_.isUndefined(uid)) {
|
||||
return this.collection.findWhere({id: id});
|
||||
}
|
||||
|
||||
return this.collection.findWhere({uid: uid});
|
||||
},
|
||||
|
||||
getPopover: function () {
|
||||
return this.view.getPopover(this.sdkViewName);
|
||||
},
|
||||
|
||||
// helpers
|
||||
|
||||
readSDKChange: function (data) {
|
||||
var me = this, arr = [];
|
||||
_.each(data, function(item) {
|
||||
var changetext = '', proptext = '',
|
||||
value = item.get_Value(),
|
||||
settings = false;
|
||||
switch (item.get_Type()) {
|
||||
case c_oAscRevisionsChangeType.TextAdd:
|
||||
changetext = me.textInserted;
|
||||
if (typeof value == 'object') {
|
||||
_.each(value, function(obj) {
|
||||
if (typeof obj === 'string')
|
||||
changetext += (' ' + obj);
|
||||
else {
|
||||
switch (obj) {
|
||||
case 0:
|
||||
changetext += (' <' + me.textImage + '>');
|
||||
break;
|
||||
case 1:
|
||||
changetext += (' <' + me.textShape + '>');
|
||||
break;
|
||||
case 2:
|
||||
changetext += (' <' + me.textChart + '>');
|
||||
break;
|
||||
case 3:
|
||||
changetext += (' <' + me.textEquation + '>');
|
||||
break;
|
||||
}
|
||||
}
|
||||
})
|
||||
} else if (typeof value === 'string') {
|
||||
changetext += (' ' + value);
|
||||
}
|
||||
break;
|
||||
case c_oAscRevisionsChangeType.TextRem:
|
||||
changetext = me.textDeleted;
|
||||
if (typeof value == 'object') {
|
||||
_.each(value, function(obj) {
|
||||
if (typeof obj === 'string')
|
||||
changetext += (' ' + obj);
|
||||
else {
|
||||
switch (obj) {
|
||||
case 0:
|
||||
changetext += (' <' + me.textImage + '>');
|
||||
break;
|
||||
case 1:
|
||||
changetext += (' <' + me.textShape + '>');
|
||||
break;
|
||||
case 2:
|
||||
changetext += (' <' + me.textChart + '>');
|
||||
break;
|
||||
case 3:
|
||||
changetext += (' <' + me.textEquation + '>');
|
||||
break;
|
||||
}
|
||||
}
|
||||
})
|
||||
} else if (typeof value === 'string') {
|
||||
changetext += (' ' + value);
|
||||
}
|
||||
break;
|
||||
case c_oAscRevisionsChangeType.ParaAdd:
|
||||
changetext = me.textParaInserted;
|
||||
break;
|
||||
case c_oAscRevisionsChangeType.ParaRem:
|
||||
changetext = me.textParaDeleted;
|
||||
break;
|
||||
case c_oAscRevisionsChangeType.TextPr:
|
||||
changetext = '<b>' + me.textFormatted;
|
||||
if (value.Get_Bold() !== undefined)
|
||||
proptext += ((value.Get_Bold() ? '' : me.textNot) + me.textBold + ', ');
|
||||
if (value.Get_Italic() !== undefined)
|
||||
proptext += ((value.Get_Italic() ? '' : me.textNot) + me.textItalic + ', ');
|
||||
if (value.Get_Underline() !== undefined)
|
||||
proptext += ((value.Get_Underline() ? '' : me.textNot) + me.textUnderline + ', ');
|
||||
if (value.Get_Strikeout() !== undefined)
|
||||
proptext += ((value.Get_Strikeout() ? '' : me.textNot) + me.textStrikeout + ', ');
|
||||
if (value.Get_DStrikeout() !== undefined)
|
||||
proptext += ((value.Get_DStrikeout() ? '' : me.textNot) + me.textDStrikeout + ', ');
|
||||
if (value.Get_Caps() !== undefined)
|
||||
proptext += ((value.Get_Caps() ? '' : me.textNot) + me.textCaps + ', ');
|
||||
if (value.Get_SmallCaps() !== undefined)
|
||||
proptext += ((value.Get_SmallCaps() ? '' : me.textNot) + me.textSmallCaps + ', ');
|
||||
if (value.Get_VertAlign() !== undefined)
|
||||
proptext += (((value.Get_VertAlign()==1) ? me.textSuperScript : ((value.Get_VertAlign()==2) ? me.textSubScript : me.textBaseline)) + ', ');
|
||||
if (value.Get_Color() !== undefined)
|
||||
proptext += (me.textColor + ', ');
|
||||
if (value.Get_Highlight() !== undefined)
|
||||
proptext += (me.textHighlight + ', ');
|
||||
if (value.Get_Shd() !== undefined)
|
||||
proptext += (me.textShd + ', ');
|
||||
if (value.Get_FontFamily() !== undefined)
|
||||
proptext += (value.Get_FontFamily() + ', ');
|
||||
if (value.Get_FontSize() !== undefined)
|
||||
proptext += (value.Get_FontSize() + ', ');
|
||||
if (value.Get_Spacing() !== undefined)
|
||||
proptext += (me.textSpacing + ' ' + Common.Utils.Metric.fnRecalcFromMM(value.Get_Spacing()).toFixed(2) + ' ' + Common.Utils.Metric.metricName[Common.Utils.Metric.getCurrentMetric()] + ', ');
|
||||
if (value.Get_Position() !== undefined)
|
||||
proptext += (me.textPosition + ' ' + Common.Utils.Metric.fnRecalcFromMM(value.Get_Position()).toFixed(2) + ' ' + Common.Utils.Metric.metricName[Common.Utils.Metric.getCurrentMetric()] + ', ');
|
||||
if (value.Get_Lang() !== undefined)
|
||||
proptext += (Common.util.LanguageInfo.getLocalLanguageName(value.Get_Lang())[1] + ', ');
|
||||
|
||||
if (!_.isEmpty(proptext)) {
|
||||
changetext += ': ';
|
||||
proptext = proptext.substring(0, proptext.length-2);
|
||||
}
|
||||
changetext += '</b>';
|
||||
changetext += proptext;
|
||||
break;
|
||||
case c_oAscRevisionsChangeType.ParaPr:
|
||||
changetext = '<b>' + me.textParaFormatted;
|
||||
if (value.Get_ContextualSpacing())
|
||||
proptext += ((value.Get_ContextualSpacing() ? me.textContextual : me.textNoContextual) + ', ');
|
||||
if (value.Get_IndLeft() !== undefined)
|
||||
proptext += (me.textIndentLeft + ' ' + Common.Utils.Metric.fnRecalcFromMM(value.Get_IndLeft()).toFixed(2) + ' ' + Common.Utils.Metric.metricName[Common.Utils.Metric.getCurrentMetric()] + ', ');
|
||||
if (value.Get_IndRight() !== undefined)
|
||||
proptext += (me.textIndentRight + ' ' + Common.Utils.Metric.fnRecalcFromMM(value.Get_IndRight()).toFixed(2) + ' ' + Common.Utils.Metric.metricName[Common.Utils.Metric.getCurrentMetric()] + ', ');
|
||||
if (value.Get_IndFirstLine() !== undefined)
|
||||
proptext += (me.textFirstLine + ' ' + Common.Utils.Metric.fnRecalcFromMM(value.Get_IndFirstLine()).toFixed(2) + ' ' + Common.Utils.Metric.metricName[Common.Utils.Metric.getCurrentMetric()] + ', ');
|
||||
if (value.Get_Jc() !== undefined) {
|
||||
switch (value.Get_Jc()) {
|
||||
case 0:
|
||||
proptext += (me.textRight + ', ');
|
||||
break;
|
||||
case 1:
|
||||
proptext += (me.textLeft + ', ');
|
||||
break;
|
||||
case 2:
|
||||
proptext += (me.textCenter + ', ');
|
||||
break;
|
||||
case 3:
|
||||
proptext += (me.textJustify + ', ');
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
if (value.Get_KeepLines() !== undefined)
|
||||
proptext += ((value.Get_KeepLines() ? me.textKeepLines : me.textNoKeepLines) + ', ');
|
||||
if (value.Get_KeepNext())
|
||||
proptext += ((value.Get_KeepNext() ? me.textKeepNext : me.textNoKeepNext) + ', ');
|
||||
if (value.Get_PageBreakBefore())
|
||||
proptext += ((value.Get_PageBreakBefore() ? me.textBreakBefore : me.textNoBreakBefore) + ', ');
|
||||
if (value.Get_SpacingLineRule() !== undefined && value.Get_SpacingLine() !== undefined) {
|
||||
proptext += me.textLineSpacing;
|
||||
proptext += (((value.Get_SpacingLineRule() == c_paragraphLinerule.LINERULE_LEAST) ? me.textAtLeast : ((value.Get_SpacingLineRule() == c_paragraphLinerule.LINERULE_AUTO) ? me.textMultiple : me.textExact)) + ' ');
|
||||
proptext += (((value.Get_SpacingLineRule()==c_paragraphLinerule.LINERULE_AUTO) ? value.Get_SpacingLine() : Common.Utils.Metric.fnRecalcFromMM(value.Get_SpacingLine()).toFixed(2) + ' ' + Common.Utils.Metric.metricName[Common.Utils.Metric.getCurrentMetric()]) + ', ');
|
||||
}
|
||||
if (value.Get_SpacingBeforeAutoSpacing())
|
||||
proptext += (me.textSpacingBefore + ' ' + me.textAuto +', ');
|
||||
else if (value.Get_SpacingBefore() !== undefined)
|
||||
proptext += (me.textSpacingBefore + ' ' + Common.Utils.Metric.fnRecalcFromMM(value.Get_SpacingBefore()).toFixed(2) + ' ' + Common.Utils.Metric.metricName[Common.Utils.Metric.getCurrentMetric()] + ', ');
|
||||
if (value.Get_SpacingAfterAutoSpacing())
|
||||
proptext += (me.textSpacingAfter + ' ' + me.textAuto +', ');
|
||||
else if (value.Get_SpacingAfter() !== undefined)
|
||||
proptext += (me.textSpacingAfter + ' ' + Common.Utils.Metric.fnRecalcFromMM(value.Get_SpacingAfter()).toFixed(2) + ' ' + Common.Utils.Metric.metricName[Common.Utils.Metric.getCurrentMetric()] + ', ');
|
||||
if (value.Get_WidowControl())
|
||||
proptext += ((value.Get_WidowControl() ? me.textWidow : me.textNoWidow) + ', ');
|
||||
if (value.Get_Tabs() !== undefined)
|
||||
proptext += proptext += (me.textTabs + ', ');
|
||||
if (value.Get_NumPr() !== undefined)
|
||||
proptext += proptext += (me.textNum + ', ');
|
||||
if (value.Get_PStyle() !== undefined) {
|
||||
var style = me.api.asc_GetStyleNameById(value.Get_PStyle());
|
||||
if (!_.isEmpty(style)) proptext += (style + ', ');
|
||||
}
|
||||
|
||||
if (!_.isEmpty(proptext)) {
|
||||
changetext += ': ';
|
||||
proptext = proptext.substring(0, proptext.length-2);
|
||||
}
|
||||
changetext += '</b>';
|
||||
changetext += proptext;
|
||||
break;
|
||||
|
||||
}
|
||||
var date = (item.get_DateTime() == '') ? new Date() : new Date(item.get_DateTime()),
|
||||
color = item.get_UserColor(),
|
||||
change = new Common.Models.ReviewChange({
|
||||
uid : Common.UI.getId(),
|
||||
userid : item.get_UserId(),
|
||||
username : item.get_UserName(),
|
||||
usercolor : '#'+Common.Utils.ThemeColor.getHexColor(color.get_r(), color.get_g(), color.get_b()),
|
||||
date : me.dateToLocaleTimeString(date),
|
||||
changetext : changetext,
|
||||
id : Common.UI.getId(),
|
||||
lock : (item.get_LockUserId()!==null),
|
||||
lockuser : item.get_LockUserId(),
|
||||
type : item.get_Type(),
|
||||
changedata : item,
|
||||
scope : me.view
|
||||
});
|
||||
|
||||
arr.push(change);
|
||||
});
|
||||
return arr;
|
||||
},
|
||||
|
||||
getUserName: function(id){
|
||||
if (this.userCollection && id!==null){
|
||||
var rec = this.userCollection.findUser(id);
|
||||
if (rec) return rec.get('username');
|
||||
}
|
||||
return '';
|
||||
},
|
||||
|
||||
dateToLocaleTimeString: function (date) {
|
||||
function format(date) {
|
||||
var strTime,
|
||||
hours = date.getHours(),
|
||||
minutes = date.getMinutes(),
|
||||
ampm = hours >= 12 ? 'pm' : 'am';
|
||||
|
||||
hours = hours % 12;
|
||||
hours = hours ? hours : 12; // the hour '0' should be '12'
|
||||
minutes = minutes < 10 ? '0'+minutes : minutes;
|
||||
strTime = hours + ':' + minutes + ' ' + ampm;
|
||||
|
||||
return strTime;
|
||||
}
|
||||
|
||||
// MM/dd/yyyy hh:mm AM
|
||||
return (date.getMonth() + 1) + '/' + (date.getDate()) + '/' + date.getFullYear() + ' ' + format(date);
|
||||
},
|
||||
|
||||
onBtnPreviewClick: function(btn, eOpts){
|
||||
switch (btn.options.value) {
|
||||
case 1:
|
||||
this.api.asc_GetPrevRevisionsChange();
|
||||
break;
|
||||
case 2:
|
||||
this.api.asc_GetNextRevisionsChange();
|
||||
break;
|
||||
}
|
||||
Common.NotificationCenter.trigger('edit:complete', this.view);
|
||||
},
|
||||
|
||||
onAcceptClick: function(menu, item, e) {
|
||||
if (this.api) {
|
||||
if (item) {
|
||||
if (item.value === 'all') {
|
||||
this.api.asc_AcceptAllChanges();
|
||||
} else {
|
||||
this.api.asc_AcceptChanges();
|
||||
}
|
||||
} else {
|
||||
this.api.asc_AcceptChanges(menu);
|
||||
}
|
||||
}
|
||||
Common.NotificationCenter.trigger('edit:complete', this.view);
|
||||
},
|
||||
|
||||
onRejectClick: function(menu, item, e) {
|
||||
if (this.api) {
|
||||
if (item) {
|
||||
if (item.value === 'all') {
|
||||
this.api.asc_RejectAllChanges();
|
||||
} else {
|
||||
this.api.asc_RejectChanges();
|
||||
}
|
||||
} else {
|
||||
this.api.asc_RejectChanges(menu);
|
||||
}
|
||||
}
|
||||
Common.NotificationCenter.trigger('edit:complete', this.view);
|
||||
},
|
||||
|
||||
onDeleteClick: function(change) {
|
||||
if (this.api) {
|
||||
this.api.asc_RejectChanges(change);
|
||||
}
|
||||
Common.NotificationCenter.trigger('edit:complete', this.view);
|
||||
},
|
||||
|
||||
textInserted: '<b>Inserted:</b>',
|
||||
textDeleted: '<b>Deleted:</b>',
|
||||
textParaInserted: '<b>Paragraph Inserted</b> ',
|
||||
textParaDeleted: '<b>Paragraph Deleted</b> ',
|
||||
textFormatted: 'Formatted',
|
||||
textParaFormatted: 'Paragraph Formatted',
|
||||
textNot: 'Not ',
|
||||
textBold: 'Bold',
|
||||
textItalic: 'Italic',
|
||||
textStrikeout: 'Strikeout',
|
||||
textUnderline: 'Underline',
|
||||
textColor: 'Font color',
|
||||
textBaseline: 'Baseline',
|
||||
textSuperScript: 'Superscript',
|
||||
textSubScript: 'Subscript',
|
||||
textHighlight: 'Highlight color',
|
||||
textSpacing: 'Spacing',
|
||||
textDStrikeout: 'Double strikeout',
|
||||
textCaps: 'All caps',
|
||||
textSmallCaps: 'Small caps',
|
||||
textPosition: 'Position',
|
||||
textFontSize: 'Font size',
|
||||
textShd: 'Background color',
|
||||
textContextual: 'Don\'t add interval between paragraphs of the same style',
|
||||
textNoContextual: 'Add interval between paragraphs of the same style',
|
||||
textIndentLeft: 'Indent left',
|
||||
textIndentRight: 'Indent right',
|
||||
textFirstLine: 'First line',
|
||||
textRight: 'Align right',
|
||||
textLeft: 'Align left',
|
||||
textCenter: 'Align center',
|
||||
textJustify: 'Align justify',
|
||||
textBreakBefore: 'Page break before',
|
||||
textKeepNext: 'Keep with next',
|
||||
textKeepLines: 'Keep lines together',
|
||||
textNoBreakBefore: 'No page break before',
|
||||
textNoKeepNext: 'Don\'t keep with next',
|
||||
textNoKeepLines: 'Don\'t keep lines together',
|
||||
textLineSpacing: 'Line Spacing: ',
|
||||
textMultiple: 'multiple',
|
||||
textAtLeast: 'at least',
|
||||
textExact: 'exactly',
|
||||
textSpacingBefore: 'Spacing before',
|
||||
textSpacingAfter: 'Spacing after',
|
||||
textAuto: 'auto',
|
||||
textWidow: 'Widow control',
|
||||
textNoWidow: 'No widow control',
|
||||
textTabs: 'Change tabs',
|
||||
textNum: 'Change numbering',
|
||||
textEquation: 'Equation',
|
||||
textImage: 'Image',
|
||||
textChart: 'Chart',
|
||||
textShape: 'Shape'
|
||||
|
||||
}, Common.Controllers.ReviewChanges || {}));
|
||||
});
|
46
apps/common/main/lib/core/NotificationCenter.js
Normal file
46
apps/common/main/lib/core/NotificationCenter.js
Normal file
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* 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) 2014 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 = {};
|
||||
|
||||
define([
|
||||
'backbone'
|
||||
], 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.')
|
||||
}
|
||||
});
|
565
apps/common/main/lib/core/application.js
Normal file
565
apps/common/main/lib/core/application.js
Normal file
|
@ -0,0 +1,565 @@
|
|||
(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.')
|
||||
}
|
||||
})();
|
337
apps/common/main/lib/core/keymaster.js
Normal file
337
apps/common/main/lib/core/keymaster.js
Normal file
|
@ -0,0 +1,337 @@
|
|||
// 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
|
||||
},
|
||||
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 (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);
|
184
apps/common/main/lib/extend/Bootstrap.js
Normal file
184
apps/common/main/lib/extend/Bootstrap.js
Normal file
|
@ -0,0 +1,184 @@
|
|||
/**
|
||||
* Bootstrap.js
|
||||
*
|
||||
* Created by Alexander Yuzhin on 5/27/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
function onDropDownKeyDown(e) {
|
||||
var $this = $(this),
|
||||
$parent = $this.parent(),
|
||||
beforeEvent = jQuery.Event('keydown.before.bs.dropdown'),
|
||||
afterEvent = jQuery.Event('keydown.after.bs.dropdown');
|
||||
|
||||
$parent.trigger(beforeEvent);
|
||||
|
||||
if ($parent.hasClass('no-stop-propagate') && arguments.length>1 && arguments[1] instanceof jQuery.Event) {
|
||||
e = arguments[1];
|
||||
if ( /^(38|40|27|13|9)$/.test(e.keyCode)) {
|
||||
patchDropDownKeyDownAdditional.call(this, e);
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
} else if ( !$parent.hasClass('no-stop-propagate') || /^(38|40|27|13|9)$/.test(e.keyCode)) {
|
||||
patchDropDownKeyDown.call(this, e);
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
$parent.trigger(afterEvent);
|
||||
}
|
||||
|
||||
function patchDropDownKeyDown(e) {
|
||||
if (!/(38|40|27|37|39)/.test(e.keyCode)) return;
|
||||
|
||||
var $this = $(this);
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if ($this.is('.disabled, :disabled')) return;
|
||||
|
||||
var $parent = getParent($this);
|
||||
var isActive = $parent.hasClass('open') || $parent.hasClass('over');
|
||||
|
||||
if (!isActive || (isActive && e.keyCode == 27)) {
|
||||
if (e.which == 27) {
|
||||
$items = $('[role=menu] li.dropdown-submenu.over:visible', $parent);
|
||||
if ($items.size()) {
|
||||
$items.eq($items.size()-1).removeClass('over');
|
||||
return false;
|
||||
} else if ($parent.hasClass('dropdown-submenu') && $parent.hasClass('over')) {
|
||||
$parent.removeClass('over');
|
||||
$parent.find('> a').focus();
|
||||
} else {
|
||||
$parent.find('[data-toggle=dropdown]').focus();
|
||||
}
|
||||
}
|
||||
return (isActive) ? $this.click() : undefined;
|
||||
}
|
||||
|
||||
// var $items = $('[role=menu] li:not(.divider):visible a', $parent) - original search function
|
||||
var $items = $('> [role=menu] > li:not(.divider):not(.disabled):visible', $parent).find('> a');
|
||||
|
||||
if (!$items.length) return;
|
||||
|
||||
var index = $items.index($items.filter(':focus'));
|
||||
if (e.keyCode == 39) { // right
|
||||
if (index<0) return;
|
||||
|
||||
var li = $items.eq(index).parent();
|
||||
if (li.hasClass('dropdown-submenu') && !li.hasClass('over')) {// open submenu and select first <li> item
|
||||
li.mouseenter();
|
||||
li.addClass('focused-submenu');
|
||||
_.delay(function() {
|
||||
var mnu = $('> [role=menu]', li),
|
||||
$subitems = mnu.find('> li:not(.divider):not(.disabled):visible > a'),
|
||||
focusIdx = 0;
|
||||
if (mnu.find('> .menu-scroll').length>0) {
|
||||
var offset = mnu.scrollTop();
|
||||
for (var i=0; i<$subitems.length; i++) {
|
||||
if ($subitems[i].offsetTop > offset) {
|
||||
focusIdx = i; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($subitems.length>0)
|
||||
$subitems.eq(focusIdx).focus();
|
||||
}, 250);
|
||||
}
|
||||
} else if (e.keyCode == 37) { // left
|
||||
if ($parent.hasClass('dropdown-submenu') && $parent.hasClass('over')) { // close submenu
|
||||
$parent.removeClass('over');
|
||||
$parent.find('> a').focus();
|
||||
}
|
||||
} else {
|
||||
if (e.keyCode == 38) { index > 0 ? index-- : ($this.hasClass('no-cyclic') ? (index = 0) : (index = $items.length - 1));} else // up
|
||||
if (e.keyCode == 40) { index < $items.length - 1 ? index++ : ($this.hasClass('no-cyclic') ? (index = $items.length - 1) : (index = 0));} // down
|
||||
if (!~index) index=0;
|
||||
if ($parent.hasClass('dropdown-submenu') && $parent.hasClass('over'))
|
||||
$parent.addClass('focused-submenu'); // for Safari. When focus go from parent menuItem to it's submenu don't hide this submenu
|
||||
|
||||
$items.eq(index).focus();
|
||||
}
|
||||
}
|
||||
|
||||
function patchDropDownKeyDownAdditional(e) { // only for formula menu when typing in cell editor
|
||||
if (!/(38|40|27|37|39)/.test(e.keyCode)) return;
|
||||
|
||||
var $this = $(this);
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if ($this.is('.disabled, :disabled')) return;
|
||||
|
||||
var $parent = getParent($this);
|
||||
var isActive = $parent.hasClass('open') || $parent.hasClass('over');
|
||||
|
||||
if (!isActive || (isActive && e.keyCode == 27)) {
|
||||
if (e.which == 27)
|
||||
$parent.find('[data-toggle=dropdown]').focus();
|
||||
return (isActive) ? $this.click() : undefined;
|
||||
}
|
||||
|
||||
var $items = $('> [role=menu] > li:not(.divider):not(.disabled):visible', $parent).find('> a');
|
||||
|
||||
if (!$items.length) return;
|
||||
|
||||
var index = $items.index($items.filter('.focus'));
|
||||
if (e.keyCode == 38) { index > 0 ? index-- : ($this.hasClass('no-cyclic') ? (index = 0) : (index = $items.length - 1));} else // up
|
||||
if (e.keyCode == 40) { index < $items.length - 1 ? index++ : ($this.hasClass('no-cyclic') ? (index = $items.length - 1) : (index = 0));} // down
|
||||
if (!~index) index=0;
|
||||
|
||||
$items.removeClass('focus');
|
||||
$items.eq(index).addClass('focus');
|
||||
}
|
||||
|
||||
function getParent($this) {
|
||||
var selector = $this.attr('data-target');
|
||||
|
||||
if (!selector) {
|
||||
selector = $this.attr('href');
|
||||
selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, ''); //strip for ie7
|
||||
}
|
||||
|
||||
var $parent = selector && $(selector);
|
||||
|
||||
return $parent && $parent.length ? $parent : $this.parent();
|
||||
}
|
||||
|
||||
$(document)
|
||||
.off('keydown.bs.dropdown.data-api')
|
||||
.on('keydown.bs.dropdown.data-api', '[data-toggle=dropdown], [role=menu]' , onDropDownKeyDown);
|
||||
|
||||
/*
|
||||
* workaround closing menu by right click
|
||||
* */
|
||||
(function () {
|
||||
var eventsObj = $._data($(document).get(0), "events"), clickDefHandler;
|
||||
if (eventsObj && eventsObj.click) {
|
||||
eventsObj.click.every(function(e, i, a){
|
||||
if (/click/.test(e.type) && !e.selector && /bs\..+\.dropdown/.test(e.namespace)) {
|
||||
clickDefHandler = e.handler;
|
||||
}
|
||||
|
||||
return !clickDefHandler;
|
||||
});
|
||||
}
|
||||
|
||||
function onDropDownClick(e) {
|
||||
if ((e.which == 1 || e.which == undefined) && !!clickDefHandler) {
|
||||
clickDefHandler(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (!!clickDefHandler) {
|
||||
$(document)
|
||||
.off('click.bs.dropdown.data-api', clickDefHandler)
|
||||
.on('click.bs.dropdown.data-api', onDropDownClick);
|
||||
}
|
||||
})();
|
||||
/*
|
||||
* */
|
26
apps/common/main/lib/model/ChatMessage.js
Normal file
26
apps/common/main/lib/model/ChatMessage.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* ChatMessage.js
|
||||
*
|
||||
* Model
|
||||
*
|
||||
* Created by Maxim Kadushkin on 01 March 2014
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
define([
|
||||
'backbone'
|
||||
], function(Backbone){
|
||||
'use strict';
|
||||
|
||||
Common.Models = Common.Models || {};
|
||||
|
||||
Common.Models.ChatMessage = Backbone.Model.extend({
|
||||
defaults: {
|
||||
type : 0,
|
||||
userid : null,
|
||||
username : '',
|
||||
message : ''
|
||||
}
|
||||
});
|
||||
});
|
63
apps/common/main/lib/model/Comment.js
Normal file
63
apps/common/main/lib/model/Comment.js
Normal file
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* Comments.js
|
||||
*
|
||||
* Created by Alexey Musinov on 16.01.14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
Common.Models = Common.Models || {};
|
||||
|
||||
define([
|
||||
'underscore',
|
||||
'backbone',
|
||||
'common/main/lib/component/BaseView'
|
||||
], function(_, Backbone){
|
||||
'use strict';
|
||||
|
||||
Common.Models.Comment = Backbone.Model.extend({
|
||||
defaults: {
|
||||
uid : 0, // asc
|
||||
userid : 0,
|
||||
username : 'Guest',
|
||||
date : undefined,
|
||||
quote : '',
|
||||
comment : '',
|
||||
resolved : false,
|
||||
lock : false,
|
||||
lockuserid : '',
|
||||
unattached : false,
|
||||
|
||||
id : Common.UI.getId(), // internal
|
||||
time : 0,
|
||||
showReply : false,
|
||||
showReplyInPopover : false,
|
||||
editText : false,
|
||||
editTextInPopover : false,
|
||||
last : undefined,
|
||||
replys : [],
|
||||
hideAddReply : false,
|
||||
scope : null,
|
||||
hide : false,
|
||||
hint : false,
|
||||
dummy : undefined
|
||||
}
|
||||
});
|
||||
Common.Models.Reply = Backbone.Model.extend({
|
||||
defaults: {
|
||||
time : 0, // acs
|
||||
userid : 0,
|
||||
username : 'Guest',
|
||||
reply : '',
|
||||
date : undefined,
|
||||
|
||||
id : Common.UI.getId(), // internal
|
||||
editText : false,
|
||||
editTextInPopover : false,
|
||||
scope : null
|
||||
}
|
||||
});
|
||||
});
|
29
apps/common/main/lib/model/Font.js
Normal file
29
apps/common/main/lib/model/Font.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* Font.js
|
||||
*
|
||||
* Created by Alexander Yuzhin on 2/11/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
Common.Models = Common.Models || {};
|
||||
|
||||
define([
|
||||
'backbone'
|
||||
], function(Backbone){ 'use strict';
|
||||
|
||||
Common.Models.Font = Backbone.Model.extend({
|
||||
defaults: function() {
|
||||
return {
|
||||
id : Common.UI.getId(),
|
||||
name : null,
|
||||
cloneid : null,
|
||||
imgidx : 0,
|
||||
type : 0
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
40
apps/common/main/lib/model/HistoryVersion.js
Normal file
40
apps/common/main/lib/model/HistoryVersion.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* User: Julia.Radzhabova
|
||||
* Date: 05.03.15
|
||||
* Time: 16:42
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
Common.Models = Common.Models || {};
|
||||
|
||||
define([
|
||||
'underscore',
|
||||
'backbone',
|
||||
'common/main/lib/component/BaseView'
|
||||
], function(_, Backbone){
|
||||
'use strict';
|
||||
|
||||
Common.Models.HistoryVersion = Backbone.Model.extend({
|
||||
defaults: function() {
|
||||
return {
|
||||
version : 0,
|
||||
revision: 0,
|
||||
changeid : undefined,
|
||||
userid : undefined,
|
||||
username: 'Guest',
|
||||
usercolor: '#ff0000',
|
||||
created : undefined,
|
||||
id : Common.UI.getId(), // internal
|
||||
url : '',
|
||||
urlDiff : '',
|
||||
urlGetTime : '',
|
||||
docId: '',
|
||||
docIdPrev: '',
|
||||
arrColors: [], // array of user colors for all changes of current version
|
||||
markedAsVersion: false
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
38
apps/common/main/lib/model/ReviewChange.js
Normal file
38
apps/common/main/lib/model/ReviewChange.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* ReviewChange.js
|
||||
*
|
||||
* Created by Julia.Radzhabova on 05.08.15
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
Common.Models = Common.Models || {};
|
||||
|
||||
define([
|
||||
'underscore',
|
||||
'backbone',
|
||||
'common/main/lib/component/BaseView'
|
||||
], function(_, Backbone){
|
||||
'use strict';
|
||||
|
||||
Common.Models.ReviewChange = Backbone.Model.extend({
|
||||
defaults: {
|
||||
uid : 0, // asc
|
||||
userid : 0,
|
||||
username : 'Guest',
|
||||
usercolor : '#ee3525',
|
||||
date : undefined,
|
||||
changetext : '',
|
||||
lock : false,
|
||||
lockuser : '',
|
||||
type : 0,
|
||||
changedata : null,
|
||||
|
||||
id : Common.UI.getId(), // internal
|
||||
scope : null
|
||||
}
|
||||
});
|
||||
});
|
28
apps/common/main/lib/model/User.js
Normal file
28
apps/common/main/lib/model/User.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* User.js
|
||||
*
|
||||
* Model
|
||||
*
|
||||
* Created by Maxim Kadushkin on 27 February 2014
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
define([
|
||||
'backbone'
|
||||
], function(Backbone){
|
||||
'use strict';
|
||||
|
||||
Common.Models = Common.Models || {};
|
||||
|
||||
Common.Models.User = Backbone.Model.extend({
|
||||
defaults: {
|
||||
id : undefined,
|
||||
username : 'Guest',
|
||||
color : '#fff',
|
||||
colorval : null,
|
||||
online : false,
|
||||
view : false
|
||||
}
|
||||
});
|
||||
});
|
|
@ -0,0 +1,34 @@
|
|||
# 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
|
|
@ -0,0 +1,48 @@
|
|||
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();
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
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 () {
|
103
apps/common/main/lib/mods/perfect-scrollbar-patch-margins.diff
Normal file
103
apps/common/main/lib/mods/perfect-scrollbar-patch-margins.diff
Normal file
|
@ -0,0 +1,103 @@
|
|||
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) {
|
655
apps/common/main/lib/mods/perfect-scrollbar.js
Normal file
655
apps/common/main/lib/mods/perfect-scrollbar.js
Normal file
|
@ -0,0 +1,655 @@
|
|||
/* 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');
|
||||
|
||||
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),
|
||||
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 = containerWidth - scrollbarXWidth;
|
||||
|
||||
if (newLeft < 0) {
|
||||
scrollbarXLeft = 0;
|
||||
}
|
||||
else if (newLeft > maxLeft) {
|
||||
scrollbarXLeft = maxLeft;
|
||||
}
|
||||
else {
|
||||
scrollbarXLeft = newLeft;
|
||||
}
|
||||
|
||||
var scrollLeft = parseInt(scrollbarXLeft * (contentWidth - containerWidth) / (containerWidth - 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: containerWidth, 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.css({left: scrollbarXLeft, width: scrollbarXWidth});
|
||||
$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);
|
||||
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);
|
||||
}
|
||||
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 >= containerWidth - scrollbarXWidth) {
|
||||
scrollbarXLeft = containerWidth - 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) {
|
||||
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 = containerWidth - 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;
|
||||
});
|
||||
};
|
||||
}));
|
14
apps/common/main/lib/template/Chat.template
Normal file
14
apps/common/main/lib/template/Chat.template
Normal file
|
@ -0,0 +1,14 @@
|
|||
<div id="chat-box" class="layout-ct vbox">
|
||||
<div id="chat-users" class="layout-item area">
|
||||
<div id="chat-user-ct"></div>
|
||||
</div>
|
||||
<div id="chat-messages" class="layout-item area">
|
||||
<div id="chat-message-ct"></div>
|
||||
</div>
|
||||
<div id="chat-options" class="layout-item">
|
||||
<div id="chat-options-ct">
|
||||
<textarea id="chat-msg-text" class="user-select" maxlength="<%=maxMsgLength%>"></textarea>
|
||||
<button id="chat-msg-btn-add" class="btn normal dlg-btn primary"><%=scope.textSend%></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
87
apps/common/main/lib/template/Comments.template
Normal file
87
apps/common/main/lib/template/Comments.template
Normal file
|
@ -0,0 +1,87 @@
|
|||
<% if (!hide) { %>
|
||||
<div id="<%= id %>" class="user-comment-item">
|
||||
|
||||
<!-- comment block -->
|
||||
|
||||
<div class="user-name"><%=scope.getUserName(username)%></div>
|
||||
<div class="user-date"><%=date%></div>
|
||||
<% if (quote!==null) { %>
|
||||
<div class="user-quote"><%=scope.getFixedQuote(quote)%></div>
|
||||
<% } %>
|
||||
<% if (!editText) { %>
|
||||
<div class="user-message user-select" data-can-copy="true"><%=scope.pickLink(comment)%></div>
|
||||
<% } else { %>
|
||||
<div class="inner-edit-ct">
|
||||
<textarea class="msg-reply user-select" maxlength="maxCommLength"><%=comment%></textarea>
|
||||
<button class="btn normal dlg-btn primary btn-inner-edit" id="id-comments-change">textEdit</button>
|
||||
<button class="btn normal dlg-btn btn-inner-close">textCancel</button>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- replys elements -->
|
||||
|
||||
<% if (replys.length) { %>
|
||||
<div class="reply-arrow img-commonctrl"></div>
|
||||
<% _.each(replys, function (item) { %>
|
||||
<div class="reply-item-ct">
|
||||
<div class="user-name"><%=scope.getUserName(item.get("username"))%></div>
|
||||
<div class="user-date"><%=item.get("date")%></div>
|
||||
<% if (!item.get("editText")) { %>
|
||||
<div class="user-message user-select" data-can-copy="true"><%=scope.pickLink(item.get("reply"))%></div>
|
||||
<div class="btns-reply-ct">
|
||||
<div class="btn-edit img-commonctrl" data-value="<%=item.get("id")%>"></div>
|
||||
<div class="btn-delete img-commonctrl" data-value="<%=item.get("id")%>"></div>
|
||||
</div>
|
||||
<% } else { %>
|
||||
<div class="inner-edit-ct">
|
||||
<textarea class="msg-reply textarea-fix user-select" maxlength="maxCommLength"><%=item.get("reply")%></textarea>
|
||||
<button class="btn normal dlg-btn primary btn-inner-edit btn-fix" id="id-comments-change">textEdit</button>
|
||||
<button class="btn normal dlg-btn btn-inner-close">textClose</button>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
<% }); %>
|
||||
<% } %>
|
||||
|
||||
<!-- add reply button -->
|
||||
|
||||
<% if (!showReply) { %>
|
||||
<% if (replys.length) { %>
|
||||
<label class="user-reply" style="margin-left: 20px; margin-top: 5px;" role="presentation" tabindex="-1">textAddReply</label>
|
||||
<% } else { %>
|
||||
<label class="user-reply" role="presentation" tabindex="-1">textAddReply</label>
|
||||
<% } %>
|
||||
<% } %>
|
||||
|
||||
<!-- edit buttons -->
|
||||
|
||||
<% if (!editText && !lock) { %>
|
||||
<div class="edit-ct">
|
||||
<div class="btn-edit img-commonctrl"></div>
|
||||
<div class="btn-delete img-commonctrl"></div>
|
||||
<% if (resolved) { %>
|
||||
<div class="btn-resolve-check img-commonctrl" data-toggle="tooltip"></div>
|
||||
<% } else { %>
|
||||
<div class="btn-resolve img-commonctrl" data-toggle="tooltip"></div>
|
||||
<% } %>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- reply -->
|
||||
|
||||
<% if (showReply) { %>
|
||||
<div class="reply-ct">
|
||||
<textarea class="msg-reply user-select" placeholder="textAddReply" maxlength="maxCommLength"></textarea>
|
||||
<button class="btn normal dlg-btn primary btn-reply" id="id-comments-change">textReply</button>
|
||||
<button class="btn normal dlg-btn btn-close">textClose</button>
|
||||
</div>
|
||||
<% } %>
|
||||
<% if (lock) { %>
|
||||
<div class="lock-area"></div>
|
||||
<div class="lock-author"><%=lockuserid%></div>
|
||||
<% } %>
|
||||
<% if (!last) { %>
|
||||
<div class="separator-cmt"></div>
|
||||
<% } %>
|
||||
</div>
|
||||
<% } %>
|
13
apps/common/main/lib/template/CommentsPanel.template
Normal file
13
apps/common/main/lib/template/CommentsPanel.template
Normal file
|
@ -0,0 +1,13 @@
|
|||
<div id="comments-box" class="layout-ct vbox">
|
||||
<div class="layout-item messages-ct"/>
|
||||
<div class="layout-item add-link-ct">
|
||||
<label class="btn new"><%=textAddCommentToDoc%></label>
|
||||
</div>
|
||||
<div style="display: none;" class="layout-item new-comment-ct">
|
||||
<div class="inner-ct">
|
||||
<textarea id="comment-msg-new" class="user-select" placeholder="<%=textEnterCommentHint%>" maxlength="<%=maxCommLength%>"/>
|
||||
</div>
|
||||
<button class="btn add normal dlg-btn primary"><%=textAddComment%></button>
|
||||
<button class="btn cancel normal dlg-btn"><%=textCancel%></button>
|
||||
</div>
|
||||
</div>
|
90
apps/common/main/lib/template/CommentsPopover.template
Normal file
90
apps/common/main/lib/template/CommentsPopover.template
Normal file
|
@ -0,0 +1,90 @@
|
|||
<div id="<%=id%>" class="user-comment-item">
|
||||
|
||||
<!-- comment block -->
|
||||
|
||||
<div class="user-name"><%=scope.getUserName(username)%></div>
|
||||
<div class="user-date"><%=date%></div>
|
||||
<% if (!editTextInPopover || hint) { %>
|
||||
<div class="user-message user-select"><%=scope.pickLink(comment)%></div>
|
||||
<% } else { %>
|
||||
<div class="inner-edit-ct">
|
||||
<textarea class="msg-reply user-select" maxlength="maxCommLength"><%=comment%></textarea>
|
||||
<% if (hideAddReply) { %>
|
||||
<button class="btn normal dlg-btn primary btn-inner-edit" id="id-comments-change-popover">textAdd</button>
|
||||
<% } else { %>
|
||||
<button class="btn normal dlg-btn primary btn-inner-edit" id="id-comments-change-popover">textEdit</button>
|
||||
<% } %>
|
||||
<button class="btn normal dlg-btn btn-inner-close">textCancel</button>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- replys elements -->
|
||||
|
||||
<% if (replys.length) { %>
|
||||
<div class="reply-arrow img-commonctrl"></div>
|
||||
<% _.each(replys, function (item) { %>
|
||||
<div class="reply-item-ct">
|
||||
<div class="user-name"><%=scope.getUserName(item.get("username"))%></div>
|
||||
<div class="user-date"><%=item.get("date")%></div>
|
||||
<% if (!item.get("editTextInPopover")) { %>
|
||||
<div class="user-message user-select"><%=scope.pickLink(item.get("reply"))%></div>
|
||||
<% if (!hint) { %>
|
||||
<div class="btns-reply-ct">
|
||||
<div class="btn-edit img-commonctrl" data-value="<%=item.get("id")%>"></div>
|
||||
<div class="btn-delete img-commonctrl" data-value="<%=item.get("id")%>"></div>
|
||||
</div>
|
||||
<%}%>
|
||||
<% } else { %>
|
||||
<div class="inner-edit-ct">
|
||||
<textarea class="msg-reply textarea-fix user-select" maxlength="maxCommLength"><%=item.get("reply")%></textarea>
|
||||
<button class="btn normal dlg-btn primary btn-inner-edit btn-fix" id="id-comments-change-popover">textEdit</button>
|
||||
<button class="btn normal dlg-btn btn-inner-close">textClose</button>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
<% }); %>
|
||||
|
||||
<% } %>
|
||||
|
||||
<!-- add reply button -->
|
||||
|
||||
<% if (!showReplyInPopover && !hideAddReply && !hint) { %>
|
||||
<% if (replys.length) { %>
|
||||
<label class="user-reply" style="margin-left: 20px; margin-top: 5px;" role="presentation" tabindex="-1">textAddReply</label>
|
||||
<% } else { %>
|
||||
<label class="user-reply" role="presentation" tabindex="-1">textAddReply</label>
|
||||
<% } %>
|
||||
<% } %>
|
||||
|
||||
<!-- edit buttons -->
|
||||
|
||||
<% if (!editTextInPopover && !lock && !hint) { %>
|
||||
<div class="edit-ct">
|
||||
<div class="btn-edit img-commonctrl"></div>
|
||||
<div class="btn-delete img-commonctrl"></div>
|
||||
<% if (resolved) { %>
|
||||
<div class="btn-resolve-check img-commonctrl" data-toggle="tooltip"></div>
|
||||
<% } else { %>
|
||||
<div class="btn-resolve img-commonctrl" data-toggle="tooltip"></div>
|
||||
<% } %>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- reply -->
|
||||
|
||||
<% if (showReplyInPopover) { %>
|
||||
<div class="reply-ct">
|
||||
<textarea class="msg-reply user-select" placeholder="textAddReply" maxlength="maxCommLength"></textarea>
|
||||
<button class="btn normal dlg-btn primary btn-reply" id="id-comments-change-popover">textReply</button>
|
||||
<button class="btn normal dlg-btn btn-close">textClose</button>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<!-- locked user -->
|
||||
|
||||
<% if (lock) { %>
|
||||
<div class="lock-area" style="cursor: default;"></div>
|
||||
<div class="lock-author" style="cursor: default;"><%=lockuserid%></div>
|
||||
<% } %>
|
||||
|
||||
</div>
|
32
apps/common/main/lib/template/ExtendedColorDialog.template
Normal file
32
apps/common/main/lib/template/ExtendedColorDialog.template
Normal file
|
@ -0,0 +1,32 @@
|
|||
<div class="color-box">
|
||||
<div id="id-hsb-colorpicker" style="vertical-align:top;">
|
||||
</div>
|
||||
<div class="color-info" style="">
|
||||
<div style="margin-left:15px;">
|
||||
<label class="color-label"><%= txtNew %></label>
|
||||
<div id="field-new-color" class="color-cnt top"></div>
|
||||
<div id="field-start-color" class="color-cnt bottom"></div>
|
||||
<label class="color-label"><%= txtCurrent %></label>
|
||||
</div>
|
||||
<div style="padding:13px 0 2px 0;">
|
||||
<label class="input-label">R:</label>
|
||||
<div id="extended-spin-r" class="color-spin"></div>
|
||||
</div>
|
||||
<div style="padding:2px 0;">
|
||||
<label class="input-label">G:</label>
|
||||
<div id="extended-spin-g" class="color-spin"></div>
|
||||
</div>
|
||||
<div style="padding:2px 0;">
|
||||
<label class="input-label">B:</label>
|
||||
<div id="extended-spin-b" class="color-spin"></div>
|
||||
</div>
|
||||
<div style="padding:11px 0 0 0;">
|
||||
<label class="input-label" style="width:12px;">#:</label>
|
||||
<input id="extended-text-color" type="text" role="textbox" style="width:62px; height: 22px;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer center">
|
||||
<button class="btn normal dlg-btn primary" result="1"><%= txtAdd %></button>
|
||||
<button class="btn normal dlg-btn" result="0"><%= txtCancel %></button>
|
||||
</div>
|
6
apps/common/main/lib/template/Header.template
Normal file
6
apps/common/main/lib/template/Header.template
Normal file
|
@ -0,0 +1,6 @@
|
|||
<div id="header-container">
|
||||
<div id="header-logo"></div>
|
||||
<div id="header-caption"><div><%= headerCaption %></div></div>
|
||||
<div id="header-documentcaption"><%= documentCaption %></div>
|
||||
<div id="header-back" style="display: <%= canBack ? 'table-cell' : 'none' %>;"><div><%= textBack %></div></div>
|
||||
</div>
|
13
apps/common/main/lib/template/ReviewChangesPopover.template
Normal file
13
apps/common/main/lib/template/ReviewChangesPopover.template
Normal file
|
@ -0,0 +1,13 @@
|
|||
<div id="<%=id%>" class="user-comment-item">
|
||||
<div class="user-name-colored"><span style="background-color:<%=usercolor%>;"><%=scope.getUserName(username)%></span></div>
|
||||
<div class="user-date"><%=date%></div>
|
||||
<div class="user-message user-select limit-height"><%=changetext%></div>
|
||||
<div class="edit-ct">
|
||||
<% if (scope.isReviewOnly) { %>
|
||||
<div class="btn-delete img-commonctrl"></div>
|
||||
<% } else { %>
|
||||
<div class="btn-accept img-commonctrl"></div>
|
||||
<div class="btn-reject img-commonctrl"></div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
423
apps/common/main/lib/util/LanguageInfo.js
Normal file
423
apps/common/main/lib/util/LanguageInfo.js
Normal file
|
@ -0,0 +1,423 @@
|
|||
/**
|
||||
* LanguageInfo.js
|
||||
*
|
||||
* Created by Maxim Kadushkin on 31 January 2014
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined) {
|
||||
var Common = {};
|
||||
}
|
||||
|
||||
Common.util = Common.util||{};
|
||||
|
||||
Common.util.LanguageInfo = new(function() {
|
||||
var localLanguageName = {
|
||||
0x0036 : ["af", "Afrikaans"],
|
||||
0x0436 : ["af-ZA", "Afrikaans (Suid Afrika)"],
|
||||
0x001C : ["sq", "Shqipe"],
|
||||
0x041C : ["sq-AL", "Shqipe (Shqipëria)"],
|
||||
0x0084 : ["gsw", "Elsässisch"],
|
||||
0x0484 : ["gsw-FR", "Elsässisch (Frànkrisch)"],
|
||||
0x005E : ["am", "አማርኛ"],
|
||||
0x045E : ["am-ET", "አማርኛ (ኢትዮጵያ)"],
|
||||
0x0001 : ["ar", "العربية"],
|
||||
0x1401 : ["ar-DZ", "العربية (الجزائر)"],
|
||||
0x3C01 : ["ar-BH", "العربية (البحرين)"],
|
||||
0x0C01 : ["ar-EG", "العربية (مصر)"],
|
||||
0x0801 : ["ar-IQ", "العربية (العراق)"],
|
||||
0x2C01 : ["ar-JO", "العربية (الأردن)"],
|
||||
0x3401 : ["ar-KW", "العربية (الكويت)"],
|
||||
0x3001 : ["ar-LB", "العربية (لبنان)"],
|
||||
0x1001 : ["ar-LY", "العربية (ليبيا)"],
|
||||
0x1801 : ["ar-MA", "العربية (المملكة المغربية)"],
|
||||
0x2001 : ["ar-OM", "العربية (عمان)"],
|
||||
0x4001 : ["ar-QA", "العربية (قطر)"],
|
||||
0x0401 : ["ar-SA", "العربية (المملكة العربية السعودية)"],
|
||||
0x2801 : ["ar-SY", "العربية (سوريا)"],
|
||||
0x1C01 : ["ar-TN", "العربية (تونس)"],
|
||||
0x3801 : ["ar-AE", "العربية (الإمارات العربية المتحدة)"],
|
||||
0x2401 : ["ar-YE", "العربية (اليمن)"],
|
||||
0x002B : ["hy", "Հայերեն"],
|
||||
0x042B : ["hy-AM", "Հայերեն (Հայաստան)"],
|
||||
0x004D : ["as", "অসমীয়া"],
|
||||
0x044D : ["as-IN", "অসমীয়া (ভাৰত)"],
|
||||
0x002C : ["az", "Azərbaycanılı"],
|
||||
0x742C : ["az-Cyrl", "Азәрбајҹан дили"],
|
||||
0x082C : ["az-Cyrl-AZ", "Азәрбајҹан (Азәрбајҹан)"],
|
||||
0x782C : ["az-Latn", "Azərbaycanılı"],
|
||||
0x042C : ["az-Latn-AZ", "Azərbaycanılı (Azərbaycan)"],
|
||||
0x006D : ["ba", "Башҡорт"],
|
||||
0x046D : ["ba-RU", "Башҡорт (Россия)"],
|
||||
0x002D : ["eu", "Euskara"],
|
||||
0x042D : ["eu-ES", "Euskara (Euskara)"],
|
||||
0x0023 : ["be", "Беларускі"],
|
||||
0x0423 : ["be-BY", "Беларускі (Беларусь)"],
|
||||
0x0045 : ["bn", "বাংলা"],
|
||||
0x0845 : ["bn-BD", "বাংলা (বাংলাদেশ)"],
|
||||
0x0445 : ["bn-IN", "বাংলা (ভারত)"],
|
||||
0x781A : ["bs", "bosanski"],
|
||||
0x641A : ["bs-Cyrl", "Босански (Ћирилица)"],
|
||||
0x201A : ["bs-Cyrl-BA", "Босански (Босна и Херцеговина)"],
|
||||
0x681A : ["bs-Latn", "Bosanski (Latinica)"],
|
||||
0x141A : ["bs-Latn-BA", "Bosanski (Bosna i Hercegovina)"],
|
||||
0x007E : ["br", "Brezhoneg"],
|
||||
0x047E : ["br-FR", "Brezhoneg (Frañs)"],
|
||||
0x0002 : ["bg", "Български"],
|
||||
0x0402 : ["bg-BG", "Български (България)"],
|
||||
0x0003 : ["ca", "Català"],
|
||||
0x0403 : ["ca-ES", "Català (Català)"],
|
||||
0x7804 : ["zh", "中文"],
|
||||
0x0004 : ["zh-Hans", "中文(简体)"],
|
||||
0x0804 : ["zh-CN", "中文(中华人民共和国)"],
|
||||
0x1004 : ["zh-SG", "中文(新加坡)"],
|
||||
0x7C04 : ["zh-Hant", "中文(繁體)"],
|
||||
0x0C04 : ["zh-HK", "中文(香港特別行政區)"],
|
||||
0x1404 : ["zh-MO", "中文(澳門特別行政區)"],
|
||||
0x0404 : ["zh-TW", "中文(台灣)"],
|
||||
0x0083 : ["co", "Corsu"],
|
||||
0x0483 : ["co-FR", "Corsu (France)"],
|
||||
0x001A : ["hr", "Hrvatski"],
|
||||
0x041A : ["hr-HR", "Hrvatski (Hrvatska)"],
|
||||
0x101A : ["hr-BA", "Hrvatski (Bosna i Hercegovina)"],
|
||||
0x0005 : ["cs", "Čeština"],
|
||||
0x0405 : ["cs-CZ", "Čeština (Česká republika)"],
|
||||
0x0006 : ["da", "Dansk"],
|
||||
0x0406 : ["da-DK", "Dansk (Danmark)"],
|
||||
0x008C : ["prs", "درى"],
|
||||
0x048C : ["prs-AF", "درى (افغانستان)"],
|
||||
0x0065 : ["dv", "ދިވެހިބަސް"],
|
||||
0x0465 : ["dv-MV", "ދިވެހިބަސް (ދިވެހި ރާއްޖެ)"],
|
||||
0x0013 : ["nl", "Nederlands"],
|
||||
0x0813 : ["nl-BE", "Nederlands (België)"],
|
||||
0x0413 : ["nl-NL", "Nederlands (Nederland)"],
|
||||
0x0009 : ["en", "English"],
|
||||
0x0C09 : ["en-AU", "English (Australia)"],
|
||||
0x2809 : ["en-BZ", "English (Belize)"],
|
||||
0x1009 : ["en-CA", "English (Canada)"],
|
||||
0x2409 : ["en-029", "English (Caribbean)"],
|
||||
0x4009 : ["en-IN", "English (India)"],
|
||||
0x1809 : ["en-IE", "English (Ireland)"],
|
||||
0x2009 : ["en-JM", "English (Jamaica)"],
|
||||
0x4409 : ["en-MY", "English (Malaysia)"],
|
||||
0x1409 : ["en-NZ", "English (New Zealand)"],
|
||||
0x3409 : ["en-PH", "English (Philippines)"],
|
||||
0x4809 : ["en-SG", "English (Singapore)"],
|
||||
0x1C09 : ["en-ZA", "English (South Africa)"],
|
||||
0x2C09 : ["en-TT", "English (Trinidad y Tobago)"],
|
||||
0x0809 : ["en-GB", "English (United Kingdom)"],
|
||||
0x0409 : ["en-US", "English (United States)"],
|
||||
0x3009 : ["en-ZW", "English (Zimbabwe)"],
|
||||
0x0025 : ["et", "Eesti"],
|
||||
0x0425 : ["et-EE", "Eesti (Eesti)"],
|
||||
0x0038 : ["fo", "Føroyskt"],
|
||||
0x0438 : ["fo-FO", "Føroyskt (Føroyar)"],
|
||||
0x0064 : ["fil", "Filipino"],
|
||||
0x0464 : ["fil-PH", "Filipino (Pilipinas)"],
|
||||
0x000B : ["fi", "Suomi"],
|
||||
0x040B : ["fi-FI", "Suomi (Suomi)"],
|
||||
0x000C : ["fr", "Français"],
|
||||
0x080C : ["fr-BE", "Français (Belgique)"],
|
||||
0x0C0C : ["fr-CA", "Français (Canada)"],
|
||||
0x040C : ["fr-FR", "Français (France)"],
|
||||
0x140C : ["fr-LU", "Français (Luxembourg)"],
|
||||
0x180C : ["fr-MC", "Français (Principauté de Monaco)"],
|
||||
0x100C : ["fr-CH", "Français (Suisse)"],
|
||||
0x0062 : ["fy", "Frysk"],
|
||||
0x0462 : ["fy-NL", "Frysk (Nederlân)"],
|
||||
0x0056 : ["gl", "Galego"],
|
||||
0x0456 : ["gl-ES", "Galego (Galego)"],
|
||||
0x0037 : ["ka", "ქართული"],
|
||||
0x0437 : ["ka-GE", "ქართული (საქართველო)"],
|
||||
0x0007 : ["de", "Deutsch"],
|
||||
0x0C07 : ["de-AT", "Deutsch (Österreich)"],
|
||||
0x0407 : ["de-DE", "Deutsch (Deutschland)"],
|
||||
0x1407 : ["de-LI", "Deutsch (Liechtenstein)"],
|
||||
0x1007 : ["de-LU", "Deutsch (Luxemburg)"],
|
||||
0x0807 : ["de-CH", "Deutsch (Schweiz)"],
|
||||
0x0008 : ["el", "Ελληνικά"],
|
||||
0x0408 : ["el-GR", "Ελληνικά (Ελλάδα)"],
|
||||
0x006F : ["kl", "Kalaallisut"],
|
||||
0x046F : ["kl-GL", "Kalaallisut (Kalaallit Nunaat)"],
|
||||
0x0047 : ["gu", "ગુજરાતી"],
|
||||
0x0447 : ["gu-IN", "ગુજરાતી (ભારત)"],
|
||||
0x0068 : ["ha", "Hausa"],
|
||||
0x7C68 : ["ha-Latn", "Hausa (Latin)"],
|
||||
0x0468 : ["ha-Latn-NG", "Hausa (Nigeria)"],
|
||||
0x000D : ["he", "עברית"],
|
||||
0x040D : ["he-IL", "עברית (ישראל)"],
|
||||
0x0039 : ["hi", "हिंदी"],
|
||||
0x0439 : ["hi-IN", "हिंदी (भारत)"],
|
||||
0x000E : ["hu", "Magyar"],
|
||||
0x040E : ["hu-HU", "Magyar (Magyarország)"],
|
||||
0x000F : ["is", "Íslenska"],
|
||||
0x040F : ["is-IS", "Íslenska (Ísland)"],
|
||||
0x0070 : ["ig", "Igbo"],
|
||||
0x0470 : ["ig-NG", "Igbo (Nigeria)"],
|
||||
0x0021 : ["id", "Bahasa Indonesia"],
|
||||
0x0421 : ["id-ID", "Bahasa Indonesia (Indonesia)"],
|
||||
0x005D : ["iu", "Inuktitut"],
|
||||
0x7C5D : ["iu-Latn", "Inuktitut (Qaliujaaqpait)"],
|
||||
0x085D : ["iu-Latn-CA", "Inuktitut"],
|
||||
0x785D : ["iu-Cans", "ᐃᓄᒃᑎᑐᑦ (ᖃᓂᐅᔮᖅᐸᐃᑦ)"],
|
||||
0x045D : ["iu-Cans-CA", "ᐃᓄᒃᑎᑐᑦ (ᑲᓇᑕᒥ)"],
|
||||
0x003C : ["ga", "Gaeilge"],
|
||||
0x083C : ["ga-IE", "Gaeilge (Éire)"],
|
||||
0x0034 : ["xh", "isiXhosa"],
|
||||
0x0434 : ["xh-ZA", "isiXhosa (uMzantsi Afrika)"],
|
||||
0x0035 : ["zu", "isiZulu"],
|
||||
0x0435 : ["zu-ZA", "isiZulu (iNingizimu Afrika)"],
|
||||
0x0010 : ["it", "Italiano"],
|
||||
0x0410 : ["it-IT", "Italiano (Italia)"],
|
||||
0x0810 : ["it-CH", "Italiano (Svizzera)"],
|
||||
0x0011 : ["ja", "日本語"],
|
||||
0x0411 : ["ja-JP", "日本語 (日本)"],
|
||||
0x004B : ["kn", "ಕನ್ನಡ"],
|
||||
0x044B : ["kn-IN", "ಕನ್ನಡ (ಭಾರತ)"],
|
||||
0x003F : ["kk", "Қазақ"],
|
||||
0x043F : ["kk-KZ", "Қазақ (Қазақстан)"],
|
||||
0x0053 : ["km", "ខ្មែរ"],
|
||||
0x0453 : ["km-KH", "ខ្មែរ (កម្ពុជា)"],
|
||||
0x0086 : ["qut", "K'iche"],
|
||||
0x0486 : ["qut-GT", "K'iche (Guatemala)"],
|
||||
0x0087 : ["rw", "Kinyarwanda"],
|
||||
0x0487 : ["rw-RW", "Kinyarwanda (Rwanda)"],
|
||||
0x0041 : ["sw", "Kiswahili"],
|
||||
0x0441 : ["sw-KE", "Kiswahili (Kenya)"],
|
||||
0x0057 : ["kok", "कोंकणी"],
|
||||
0x0457 : ["kok-IN", "कोंकणी (भारत)"],
|
||||
0x0012 : ["ko", "한국어"],
|
||||
0x0412 : ["ko-KR", "한국어 (대한민국)"],
|
||||
0x0040 : ["ky", "Кыргыз"],
|
||||
0x0440 : ["ky-KG", "Кыргыз (Кыргызстан)"],
|
||||
0x0054 : ["lo", "ລາວ"],
|
||||
0x0454 : ["lo-LA", "ລາວ (ສ.ປ.ປ. ລາວ)"],
|
||||
0x0026 : ["lv", "Latviešu"],
|
||||
0x0426 : ["lv-LV", "Latviešu (Latvija)"],
|
||||
0x0027 : ["lt", "Lietuvių"],
|
||||
0x0427 : ["lt-LT", "Lietuvių (Lietuva)"],
|
||||
0x7C2E : ["dsb", "Dolnoserbšćina"],
|
||||
0x082E : ["dsb-DE", "Dolnoserbšćina (Nimska)"],
|
||||
0x006E : ["lb", "Lëtzebuergesch"],
|
||||
0x046E : ["lb-LU", "Lëtzebuergesch (Luxembourg)"],
|
||||
0x042F : ["mk-MK", "Македонски јазик (Македонија)"],
|
||||
0x002F : ["mk", "Македонски јазик"],
|
||||
0x003E : ["ms", "Bahasa Melayu"],
|
||||
0x083E : ["ms-BN", "Bahasa Melayu (Brunei Darussalam)"],
|
||||
0x043E : ["ms-MY", "Bahasa Melayu (Malaysia)"],
|
||||
0x004C : ["ml", "മലയാളം"],
|
||||
0x044C : ["ml-IN", "മലയാളം (ഭാരതം)"],
|
||||
0x003A : ["mt", "Malti"],
|
||||
0x043A : ["mt-MT", "Malti (Malta)"],
|
||||
0x0081 : ["mi", "Reo Māori"],
|
||||
0x0481 : ["mi-NZ", "Reo Māori (Aotearoa)"],
|
||||
0x007A : ["arn", "Mapudungun"],
|
||||
0x047A : ["arn-CL", "Mapudungun (Chile)"],
|
||||
0x004E : ["mr", "मराठी"],
|
||||
0x044E : ["mr-IN", "मराठी (भारत)"],
|
||||
0x007C : ["moh", "Kanien'kéha"],
|
||||
0x047C : ["moh-CA", "Kanien'kéha"],
|
||||
0x0050 : ["mn", "Монгол хэл"],
|
||||
0x7850 : ["mn-Cyrl", "Монгол хэл"],
|
||||
0x0450 : ["mn-MN", "Монгол хэл (Монгол улс)"],
|
||||
0x7C50 : ["mn-Mong", "ᠮᠤᠨᠭᠭᠤᠯ ᠬᠡᠯᠡ"],
|
||||
0x0850 : ["mn-Mong-CN", "ᠮᠤᠨᠭᠭᠤᠯ ᠬᠡᠯᠡ (ᠪᠦᠭᠦᠳᠡ ᠨᠠᠢᠷᠠᠮᠳᠠᠬᠤ ᠳᠤᠮᠳᠠᠳᠤ ᠠᠷᠠᠳ ᠣᠯᠣᠰ)"],
|
||||
0x0061 : ["ne", "नेपाली"],
|
||||
0x0461 : ["ne-NP", "नेपाली (नेपाल)"],
|
||||
0x0014 : ["no", "Norsk"],
|
||||
0x7C14 : ["nb", "Norsk (bokmål)"],
|
||||
0x7814 : ["nn", "Norsk (Nynorsk)"],
|
||||
0x0414 : ["nb-NO", "Norsk, bokmål (Norge)"],
|
||||
0x0814 : ["nn-NO", "Norsk, nynorsk (Noreg)"],
|
||||
0x0082 : ["oc", "Occitan"],
|
||||
0x0482 : ["oc-FR", "Occitan (França)"],
|
||||
0x0048 : ["or", "ଓଡ଼ିଆ"],
|
||||
0x0448 : ["or-IN", "ଓଡ଼ିଆ (ଭାରତ)"],
|
||||
0x0063 : ["ps", "پښتو"],
|
||||
0x0463 : ["ps-AF", "پښتو (افغانستان)"],
|
||||
0x0029 : ["fa", "فارسى"],
|
||||
0x0429 : ["fa-IR", "فارسى (ایران)"],
|
||||
0x0015 : ["pl", "Polski"],
|
||||
0x0415 : ["pl-PL", "Polski (Polska)"],
|
||||
0x0016 : ["pt", "Português"],
|
||||
0x0416 : ["pt-BR", "Português (Brasil)"],
|
||||
0x0816 : ["pt-PT", "Português (Portugal)"],
|
||||
0x0046 : ["pa", "ਪੰਜਾਬੀ"],
|
||||
0x0446 : ["pa-IN", "ਪੰਜਾਬੀ (ਭਾਰਤ)"],
|
||||
0x006B : ["quz", "Runasimi"],
|
||||
0x046B : ["quz-BO", "Runasimi (Qullasuyu)"],
|
||||
0x086B : ["quz-EC", "Runasimi (Ecuador)"],
|
||||
0x0C6B : ["quz-PE", "Runasimi (Piruw)"],
|
||||
0x0018 : ["ro", "Română"],
|
||||
0x0418 : ["ro-RO", "Română (România)"],
|
||||
0x0017 : ["rm", "Rumantsch"],
|
||||
0x0417 : ["rm-CH", "Rumantsch (Svizra)"],
|
||||
0x0019 : ["ru", "Русский"],
|
||||
0x0419 : ["ru-RU", "Русский (Россия)"],
|
||||
0x703B : ["smn", "Sämikielâ"],
|
||||
0x7C3B : ["smj", "Julevusámegiella"],
|
||||
0x003B : ["se", "Davvisámegiella"],
|
||||
0x743B : ["sms", "Sääm´ǩiõll"],
|
||||
0x783B : ["sma", "åarjelsaemiengiele"],
|
||||
0x243B : ["smn-FI", "Sämikielâ (Suomâ)"],
|
||||
0x103B : ["smj-NO", "Julevusámegiella (Vuodna)"],
|
||||
0x143B : ["smj-SE", "Julevusámegiella (Svierik)"],
|
||||
0x0C3B : ["se-FI", "Davvisámegiella (Suopma)"],
|
||||
0x043B : ["se-NO", "Davvisámegiella (Norga)"],
|
||||
0x083B : ["se-SE", "Davvisámegiella (Ruoŧŧa)"],
|
||||
0x203B : ["sms-FI", "Sääm´ǩiõll (Lää´ddjânnam)"],
|
||||
0x183B : ["sma-NO", "åarjelsaemiengiele (Nöörje)"],
|
||||
0x1C3B : ["sma-SE", "åarjelsaemiengiele (Sveerje)"],
|
||||
0x004F : ["sa", "संस्कृत"],
|
||||
0x044F : ["sa-IN", "संस्कृत (भारतम्)"],
|
||||
0x0091 : ["gd", "Gàidhlig"],
|
||||
0x0491 : ["gd-GB", "Gàidhlig (An Rìoghachd Aonaichte)"],
|
||||
0x7C1A : ["sr", "Srpski"],
|
||||
0x6C1A : ["sr-Cyrl", "Српски (Ћирилица)"],
|
||||
0x1C1A : ["sr-Cyrl-BA", "Српски (Босна и Херцеговина)"],
|
||||
0x301A : ["sr-Cyrl-ME", "Српски (Црна Гора)"],
|
||||
0x0C1A : ["sr-Cyrl-CS", "Српски (Србија и Црна Гора (Претходно))"],
|
||||
0x281A : ["sr-Cyrl-RS", "Српски (Србија)"],
|
||||
0x701A : ["sr-Latn", "Srpski (Latinica)"],
|
||||
0x181A : ["sr-Latn-BA", "Srpski (Bosna i Hercegovina)"],
|
||||
0x2C1A : ["sr-Latn-ME", "Srpski (Crna Gora)"],
|
||||
0x081A : ["sr-Latn-CS", "Srpski (Srbija i Crna Gora (Prethodno))"],
|
||||
0x241A : ["sr-Latn-RS", "Srpski (Srbija)"],
|
||||
0x006C : ["nso", "Sesotho sa Leboa"],
|
||||
0x046C : ["nso-ZA", "Sesotho sa Leboa (Afrika Borwa)"],
|
||||
0x0032 : ["tn", "Setswana"],
|
||||
0x0432 : ["tn-ZA", "Setswana (Aforika Borwa)"],
|
||||
0x005B : ["si", "සිංහ"],
|
||||
0x045B : ["si-LK", "සිංහ (ශ්රී ලංකා)"],
|
||||
0x001B : ["sk", "Slovenčina"],
|
||||
0x041B : ["sk-SK", "Slovenčina (Slovenská republika)"],
|
||||
0x0024 : ["sl", "Slovenski"],
|
||||
0x0424 : ["sl-SI", "Slovenski (Slovenija)"],
|
||||
0x000A : ["es", "Español"],
|
||||
0x2C0A : ["es-AR", "Español (Argentina)"],
|
||||
0x400A : ["es-BO", "Español (Bolivia)"],
|
||||
0x340A : ["es-CL", "Español (Chile)"],
|
||||
0x240A : ["es-CO", "Español (Colombia)"],
|
||||
0x140A : ["es-CR", "Español (Costa Rica)"],
|
||||
0x1C0A : ["es-DO", "Español (República Dominicana)"],
|
||||
0x300A : ["es-EC", "Español (Ecuador)"],
|
||||
0x440A : ["es-SV", "Español (El Salvador)"],
|
||||
0x100A : ["es-GT", "Español (Guatemala)"],
|
||||
0x480A : ["es-HN", "Español (Honduras)"],
|
||||
0x080A : ["es-MX", "Español (México)"],
|
||||
0x4C0A : ["es-NI", "Español (Nicaragua)"],
|
||||
0x180A : ["es-PA", "Español (Panamá)"],
|
||||
0x3C0A : ["es-PY", "Español (Paraguay)"],
|
||||
0x280A : ["es-PE", "Español (Perú)"],
|
||||
0x500A : ["es-PR", "Español (Puerto Rico)"],
|
||||
0x0C0A : ["es-ES", "Español (España, alfabetización internacional)"],
|
||||
0x540A : ["es-US", "Español (Estados Unidos)"],
|
||||
0x380A : ["es-UY", "Español (Uruguay)"],
|
||||
0x200A : ["es-VE", "Español (Republica Bolivariana de Venezuela)"],
|
||||
0x001D : ["sv", "Svenska"],
|
||||
0x081D : ["sv-FI", "Svenska (Finland)"],
|
||||
0x041D : ["sv-SE", "Svenska (Sverige)"],
|
||||
0x005A : ["syr", "ܣܘܪܝܝܐ"],
|
||||
0x045A : ["syr-SY", "ܣܘܪܝܝܐ (سوريا)"],
|
||||
0x0028 : ["tg", "Тоҷикӣ"],
|
||||
0x7C28 : ["tg-Cyrl", "Тоҷикӣ"],
|
||||
0x0428 : ["tg-Cyrl-TJ", "Тоҷикӣ (Тоҷикистон)"],
|
||||
0x005F : ["tzm", "Tamazight"],
|
||||
0x7C5F : ["tzm-Latn", "Tamazight (Latin)"],
|
||||
0x085F : ["tzm-Latn-DZ", "Tamazight (Djazaïr)"],
|
||||
0x0049 : ["ta", "தமிழ்"],
|
||||
0x0449 : ["ta-IN", "தமிழ் (இந்தியா)"],
|
||||
0x0044 : ["tt", "Татар"],
|
||||
0x0444 : ["tt-RU", "Татар (Россия)"],
|
||||
0x004A : ["te", "తెలుగు"],
|
||||
0x044A : ["te-IN", "తెలుగు (భారత దేశం)"],
|
||||
0x001E : ["th", "ไทย"],
|
||||
0x041E : ["th-TH", "ไทย (ไทย)"],
|
||||
0x0051 : ["bo", "བོད་ཡིག"],
|
||||
0x0451 : ["bo-CN", "བོད་ཡིག (ཀྲུང་ཧྭ་མི་དམངས་སྤྱི་མཐུན་རྒྱལ་ཁབ།)"],
|
||||
0x001F : ["tr", "Türkçe"],
|
||||
0x041F : ["tr-TR", "Türkçe (Türkiye)"],
|
||||
0x0042 : ["tk", "Türkmençe"],
|
||||
0x0442 : ["tk-TM", "Türkmençe (Türkmenistan)"],
|
||||
0x0022 : ["uk", "Українська"],
|
||||
0x0422 : ["uk-UA", "Українська (Україна)"],
|
||||
0x002E : ["hsb", "Hornjoserbšćina"],
|
||||
0x042E : ["hsb-DE", "Hornjoserbšćina (Němska)"],
|
||||
0x0020 : ["ur", "اُردو"],
|
||||
0x0420 : ["ur-PK", "اُردو (پاکستان)"],
|
||||
0x0080 : ["ug", "ئۇيغۇر يېزىقى"],
|
||||
0x0480 : ["ug-CN", "(ئۇيغۇر يېزىقى (جۇڭخۇا خەلق جۇمھۇرىيىتى"],
|
||||
0x7843 : ["uz-Cyrl", "Ўзбек"],
|
||||
0x0843 : ["uz-Cyrl-UZ", "Ўзбек (Ўзбекистон)"],
|
||||
0x0043 : ["uz", "U'zbek"],
|
||||
0x7C43 : ["uz-Latn", "U'zbek"],
|
||||
0x0443 : ["uz-Latn-UZ", "U'zbek (U'zbekiston Respublikasi)"],
|
||||
0x002A : ["vi", "Tiếng Việt"],
|
||||
0x042A : ["vi-VN", "Tiếng Việt (Việt Nam)"],
|
||||
0x0052 : ["cy", "Cymraeg"],
|
||||
0x0452 : ["cy-GB", "Cymraeg (y Deyrnas Unedig)"],
|
||||
0x0088 : ["wo", "Wolof"],
|
||||
0x0488 : ["wo-SN", "Wolof (Sénégal)"],
|
||||
0x0085 : ["sah", "Саха"],
|
||||
0x0485 : ["sah-RU", "Саха (Россия)"],
|
||||
0x0078 : ["ii", "ꆈꌠꁱꂷ"],
|
||||
0x0478 : ["ii-CN", "ꆈꌠꁱꂷ (ꍏꉸꏓꂱꇭꉼꇩ)"],
|
||||
0x006A : ["yo", "Yoruba"],
|
||||
0x046A : ["yo-NG", "Yoruba (Nigeria)"],
|
||||
0x0851 : ["bo-BT", "Tibetan, Bhutan"],
|
||||
0x0466 : ["bin-NG", "Bini, Nigeria"],
|
||||
0x045c : ["chr-US", "Cherokee, United States"],
|
||||
0x3c09 : ["en-HK", "English, Hong Kong"],
|
||||
0x3809 : ["en-ID", "English, Indonesia"],
|
||||
0x040a : ["es-ES_tradnl", "Spanish"],
|
||||
0x3c0c : ["fr-HT", "French, Haiti"],
|
||||
0x240c : ["fr-CG", "French, Congo"],
|
||||
0x300c : ["fr-CI", "French, Cote d'Ivoire"],
|
||||
0x2c0c : ["fr-CM", "French, Cameroon"],
|
||||
0x380c : ["fr-MA", "French, Morocco"],
|
||||
0x340c : ["fr-ML", "French, Mali"],
|
||||
0x200c : ["fr-RE", "French, Reunion"],
|
||||
0x280c : ["fr-SN", "French, Senegal"],
|
||||
0x1c0c : ["fr-West", "French"],
|
||||
0x0467 : ["fuv-NG", "Nigerian Fulfulde, Nigeria"],
|
||||
0x0472 : ["gaz-ET", "West Central Oromo, Ethiopia"],
|
||||
0x0474 : ["gn-PY", "Guarani, Paraguay"],
|
||||
0x0475 : ["haw-US", "Hawaiian, UnitedStates"],
|
||||
0x0469 : ["ibb-NG", "Ibibio, Nigeria"],
|
||||
0x0471 : ["kr-NG", "Kanuri, Nigeria"],
|
||||
0x0458 : ["mni", "Manipuri"],
|
||||
0x0455 : ["my-MM", "Burmese, Myanmar"],
|
||||
0x0861 : ["ne-IN", "Nepali, India"],
|
||||
0x0479 : ["pap-AN", "Papiamento, Netherlands Antilles"],
|
||||
0x0846 : ["pa-PK", "Panjabi, Pakistan"],
|
||||
0x048d : ["plt-MG", "Plateau Malagasy, Madagascar"],
|
||||
0x0818 : ["ro-MO", "Romanian, Macao"],
|
||||
0x0819 : ["ru-MO", "Russian, Macao"],
|
||||
0x0459 : ["sd-IN", "Sindhi, India"],
|
||||
0x0859 : ["sd-PK", "Sindhi, Pakistan"],
|
||||
0x0477 : ["so-SO", "Somali, Somalia"],
|
||||
0x0430 : ["st-ZA", "Southern Sotho, South Africa"],
|
||||
0x0473 : ["ti-ER", "Tigrinya, Eritrea"],
|
||||
0x0873 : ["ti-ET", "Tigrinya, Ethiopia"],
|
||||
0x045f : ["tmz", "Tamanaku"],
|
||||
0x0c5f : ["tmz-MA", "Tamanaku, Morocco"],
|
||||
0x0431 : ["ts-ZA", "Tsonga, South Africa"],
|
||||
0x0820 : ["ur-IN", "Urdu, India"],
|
||||
0x0433 : ["ven-ZA", "South Africa"]
|
||||
};
|
||||
|
||||
return {
|
||||
getLocalLanguageName: function(code) {
|
||||
return localLanguageName[code] || ['', code];
|
||||
},
|
||||
|
||||
getLocalLanguageCode: function(name) {
|
||||
for (var code in localLanguageName) {
|
||||
if (localLanguageName[code][0].toLowerCase()===name.toLowerCase())
|
||||
return code;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
})();
|
76
apps/common/main/lib/util/LocalStorage.js
Normal file
76
apps/common/main/lib/util/LocalStorage.js
Normal file
|
@ -0,0 +1,76 @@
|
|||
/**
|
||||
* LocalStorage.js
|
||||
*
|
||||
* Created by Maxim Kadushkin on 31 July 2015
|
||||
* Copyright (c) 2015 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
Common.localStorage = new (function() {
|
||||
var _storeName, _filter;
|
||||
var _store = {};
|
||||
|
||||
var ongetstore = function(data) {
|
||||
if (data.type == 'localstorage') {
|
||||
_store = data.keys;
|
||||
}
|
||||
};
|
||||
|
||||
Common.Gateway.on('internalcommand', ongetstore);
|
||||
|
||||
var _refresh = function() {
|
||||
if (!_lsAllowed)
|
||||
Common.Gateway.internalMessage('localstorage', {cmd:'get', keys:_filter});
|
||||
};
|
||||
|
||||
var _save = function() {
|
||||
if (!_lsAllowed)
|
||||
Common.Gateway.internalMessage('localstorage', {cmd:'set', keys:_store});
|
||||
};
|
||||
|
||||
var _setItem = function(name, value, just) {
|
||||
if (_lsAllowed) {
|
||||
localStorage.setItem(name, value);
|
||||
} else {
|
||||
_store[name] = value;
|
||||
|
||||
if (just===true) {
|
||||
Common.Gateway.internalMessage('localstorage', {
|
||||
cmd:'set',
|
||||
keys: {
|
||||
name: value
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var _getItem = function(name) {
|
||||
if (_lsAllowed)
|
||||
return localStorage.getItem(name);
|
||||
else
|
||||
return _store[name]===undefined ? null : _store[name];
|
||||
};
|
||||
|
||||
try {
|
||||
var _lsAllowed = !!window.localStorage;
|
||||
} catch (e) {
|
||||
_lsAllowed = false;
|
||||
}
|
||||
|
||||
return {
|
||||
getId: function() {
|
||||
return _storeName;
|
||||
},
|
||||
setId: function(name) {
|
||||
_storeName = name;
|
||||
},
|
||||
getItem: _getItem,
|
||||
setItem: _setItem,
|
||||
setKeysFilter: function(value) {
|
||||
_filter = value;
|
||||
},
|
||||
sync: _refresh,
|
||||
save: _save
|
||||
};
|
||||
})();
|
131
apps/common/main/lib/util/Shortcuts.js
Normal file
131
apps/common/main/lib/util/Shortcuts.js
Normal file
|
@ -0,0 +1,131 @@
|
|||
/**
|
||||
* Shortcuts.js
|
||||
*
|
||||
* Created by Maxim Kadushkin on 05 March 2014
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Methods
|
||||
* -------
|
||||
*
|
||||
* @method delegateShortcuts
|
||||
* Accepts named array of shortcuts and callbacks
|
||||
*
|
||||
* @method suspendEvents
|
||||
*
|
||||
* @method resetEvents
|
||||
*
|
||||
*
|
||||
* Examples of usage
|
||||
* ----------------
|
||||
*
|
||||
* Common.util.Shortcuts.delegateShortcuts({
|
||||
* shortcuts: {
|
||||
* "ctrl+f": this.onShortcutSearch
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* Common.util.Shortcuts.delegateShortcuts({
|
||||
* shortcuts: {
|
||||
* "ctrl+f": "shortcutSearch"
|
||||
* },
|
||||
* shortcutSearch: function(event) {
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* Common.util.Shortcuts.suspendEvents('ctrl+f')
|
||||
* Common.util.Shortcuts.resumeEvents('ctrl+f')
|
||||
* */
|
||||
|
||||
if (Common === undefined) {
|
||||
var Common = {};
|
||||
}
|
||||
|
||||
Common.util = Common.util||{};
|
||||
|
||||
define([
|
||||
'backbone',
|
||||
'keymaster'
|
||||
], function (Backbone) {
|
||||
'use strict';
|
||||
|
||||
var Shortcuts = function(options) {
|
||||
this.cid = _.uniqueId("shortcuts");
|
||||
this.initialize.apply(this, arguments);
|
||||
// return this.delegateShortcuts(options);
|
||||
return this;
|
||||
};
|
||||
|
||||
_.extend(Shortcuts.prototype, Backbone.Events, {
|
||||
initialize: function() {
|
||||
window.key.filter = function(event) {
|
||||
return true;
|
||||
};
|
||||
|
||||
Common.NotificationCenter.on({
|
||||
'modal:show': function(e){
|
||||
window.key.suspend();
|
||||
},
|
||||
'modal:close': function(e) {
|
||||
window.key.resume();
|
||||
},
|
||||
'modal:hide': function(e) {
|
||||
window.key.resume();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
delegateShortcuts: function(options) {
|
||||
if (!options || !options.shortcuts) return;
|
||||
|
||||
this.removeShortcuts(options);
|
||||
|
||||
var callback, match, method, scope, shortcut, shortcutKey;
|
||||
var _results = [];
|
||||
for (shortcut in options.shortcuts) {
|
||||
callback = options.shortcuts[shortcut];
|
||||
|
||||
if (!_.isFunction(callback)){
|
||||
method = options[callback];
|
||||
if (!method) throw new Error("Method " + callback + " does not exist");
|
||||
} else {
|
||||
method = callback;
|
||||
}
|
||||
|
||||
match = shortcut.match(/^(\S+)\s*(.*)$/);
|
||||
shortcutKey = match[1];
|
||||
scope = match[2].length ? match[2] : 'all';
|
||||
method = _.bind(method, this);
|
||||
_results.push(window.key(shortcutKey, scope, method));
|
||||
}
|
||||
// return _results;
|
||||
},
|
||||
|
||||
removeShortcuts: function(options) {
|
||||
if (!options || !options.shortcuts) return;
|
||||
|
||||
var match, scope, shortcut, shortcutKey;
|
||||
var _results = [];
|
||||
for (shortcut in options.shortcuts) {
|
||||
match = shortcut.match(/^(\S+)\s*(.*)$/);
|
||||
shortcutKey = match[1];
|
||||
scope = match[2].length ? match[2] : 'all';
|
||||
|
||||
window.key.unbind(shortcutKey, scope);
|
||||
}
|
||||
},
|
||||
|
||||
suspendEvents: function(key,scope) {
|
||||
window.key.suspend(key,scope);
|
||||
},
|
||||
|
||||
resumeEvents: function(key,scope) {
|
||||
window.key.resume(key,scope);
|
||||
}
|
||||
});
|
||||
|
||||
Shortcuts.extend = Backbone.View.extend;
|
||||
|
||||
Common.util.Shortcuts = new Shortcuts;
|
||||
});
|
258
apps/common/main/lib/util/Tip.js
Normal file
258
apps/common/main/lib/util/Tip.js
Normal file
|
@ -0,0 +1,258 @@
|
|||
/* ===========================================================
|
||||
*
|
||||
* Extends bootstrap-tooltip.js
|
||||
*
|
||||
* =========================================================== */
|
||||
/*
|
||||
* Configuration
|
||||
* =============
|
||||
*
|
||||
* @cfg {String} trigger
|
||||
* Default value is 'hover focus'.
|
||||
* Describes how tooltip is triggered - click | hover | focus | manual.
|
||||
* You may pass multiple triggers; separate them with a space
|
||||
*
|
||||
* @cfg {String} title
|
||||
*
|
||||
* @cfg {Boolean} arrow
|
||||
* Default value is 'false'.
|
||||
* If 'true', shows an arrow that point to the parent component.
|
||||
*
|
||||
* @cfg {String} placement
|
||||
* Default value is 'top'.
|
||||
* Describes tooltips position relatively of the parent component
|
||||
* acceptable values: 'top', 'bottom', 'right', 'left',
|
||||
* 'top-right/left', 'bottom-right/left', 'cursor'
|
||||
* If placement = 'cursor', tooltip doesn't arrange position relatively
|
||||
* of the parent and shows relatively of the cursor position.
|
||||
*
|
||||
* @cfg {String} cls
|
||||
* An extra CSS class that will be added to tooltip dom-element.
|
||||
*
|
||||
* @cfg {Boolean} html
|
||||
* Default value is 'false'.
|
||||
* Insert HTML into the tooltip. If false, jQuery's text method will be used
|
||||
* to insert content into the DOM
|
||||
*
|
||||
*
|
||||
* Events
|
||||
* ======
|
||||
*
|
||||
* @event show.bs.tooltip
|
||||
* @event shown.bs.tooltip
|
||||
* @event hide.bs.tooltip
|
||||
* @event hidden.bs.tooltip
|
||||
*
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
var _superclass = $.fn.tooltip;
|
||||
_superclass.prototype = $.fn.tooltip.Constructor.prototype;
|
||||
|
||||
$.extend($.fn.tooltip.Constructor.DEFAULTS, {
|
||||
container: 'body',
|
||||
delay: {show:500},
|
||||
arrow: false
|
||||
});
|
||||
|
||||
var Tip = function (element, options) {
|
||||
this.init('tooltip', element, options);
|
||||
};
|
||||
|
||||
Tip.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {
|
||||
constructor: Tip,
|
||||
|
||||
init: function() {
|
||||
_superclass.prototype.init.apply(this, arguments);
|
||||
|
||||
if (this.options.placement == 'cursor') {
|
||||
if (/hover/.exec(this.options.trigger)) {
|
||||
this.$element.on('mousemove.tooltip', this.options.selector, $.proxy(this.mousemove, this))
|
||||
}
|
||||
}
|
||||
|
||||
if (this.options.zIndex) {
|
||||
this.tip().css('z-index', this.options.zIndex);
|
||||
}
|
||||
|
||||
var me = this;
|
||||
Common.NotificationCenter.on({'layout:changed': function(e){
|
||||
if (!me.options.hideonclick && me.tip().is(':visible'))
|
||||
me.hide();
|
||||
}});
|
||||
},
|
||||
|
||||
mousemove: function (e) {
|
||||
this.targetXY = [e.clientX, e.clientY];
|
||||
},
|
||||
|
||||
leave: function(obj) {
|
||||
_superclass.prototype.leave.apply(this, arguments);
|
||||
this.dontShow = undefined;
|
||||
},
|
||||
|
||||
show: function(at) {
|
||||
if (this.hasContent() && this.enabled && !this.dontShow) {
|
||||
if (!this.$element.is(":visible") && this.$element.closest('[role=menu]').length>0) return;
|
||||
var $tip = this.tip();
|
||||
var placement = typeof this.options.placement === 'function' ?
|
||||
this.options.placement.call(this, $tip[0], this.$element[0]) : this.options.placement;
|
||||
|
||||
if (this.options.arrow === false) $tip.addClass('arrow-free');
|
||||
if (this.options.cls) $tip.addClass(this.options.cls);
|
||||
|
||||
var placementEx = /^([a-zA-Z]+)-?([a-zA-Z]*)$/.exec(placement);
|
||||
|
||||
if (!at && !placementEx[2].length) {
|
||||
_superclass.prototype.show.apply(this, arguments);
|
||||
} else {
|
||||
var e = $.Event('show.bs.tooltip');
|
||||
this.$element.trigger(e);
|
||||
if (e.isDefaultPrevented()) { return; }
|
||||
|
||||
this.setContent();
|
||||
|
||||
if (this.options.animation) $tip.addClass('fade');
|
||||
|
||||
$tip.detach()
|
||||
.css({top: 0, left: 0, display: 'block'});
|
||||
|
||||
this.options.container ?
|
||||
$tip.appendTo(this.options.container) : $tip.insertAfter(this.$element);
|
||||
|
||||
if (typeof at == 'object') {
|
||||
var tp = {top: at[1] + 15, left: at[0] + 18};
|
||||
|
||||
if (tp.left + $tip.width() > window.innerWidth) {
|
||||
tp.left = window.innerWidth - $tip.width() - 30;
|
||||
}
|
||||
|
||||
$tip.offset(tp).addClass('in');
|
||||
} else {
|
||||
var pos = this.getPosition();
|
||||
|
||||
var actualWidth = $tip[0].offsetWidth,
|
||||
actualHeight = $tip[0].offsetHeight;
|
||||
|
||||
switch (placementEx[1]) {
|
||||
case 'bottom': tp = {top: pos.top + pos.height + 10}; break;
|
||||
case 'top': tp = {top: pos.top - actualHeight - 10}; break;
|
||||
}
|
||||
|
||||
switch (placementEx[2]) {
|
||||
case 'left':
|
||||
tp.left = pos.left;
|
||||
if (this.$element.outerWidth() <= 18) {tp.left -= 4;} // if button is small move tooltip left
|
||||
break;
|
||||
case 'right':
|
||||
tp.left = pos.left + pos.width - actualWidth;
|
||||
if (this.$element.outerWidth() <= 18) { tp.left += 4;}
|
||||
break;
|
||||
}
|
||||
|
||||
this.applyPlacement(tp, placementEx[1]);
|
||||
this.moveArrow();
|
||||
|
||||
$tip/*.removeClass(orgPlacement)*/
|
||||
.addClass(placementEx[1])
|
||||
.addClass(placementEx[0]);
|
||||
|
||||
}
|
||||
|
||||
this.$element.trigger('shown.bs.tooltip');
|
||||
}
|
||||
|
||||
var self = this;
|
||||
clearTimeout(self.timeout);
|
||||
self.timeout = setTimeout(function () {
|
||||
if (self.hoverState == 'in') self.hide();
|
||||
self.dontShow = false;
|
||||
}, 5000);
|
||||
}
|
||||
},
|
||||
|
||||
moveArrow: function () {
|
||||
var $arrow = this.tip().find(".tooltip-arrow, .arrow");
|
||||
var new_arrow_position = 10;
|
||||
switch (this.options.placement) {
|
||||
case 'top-left':
|
||||
case 'bottom-left':
|
||||
$arrow.css("left", new_arrow_position);
|
||||
break;
|
||||
case 'top-right':
|
||||
case 'bottom-right':
|
||||
$arrow.css("right", new_arrow_position);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
enter: function(obj) {
|
||||
if (obj.type !== 'mouseenter') return;
|
||||
var $target = $(obj.target);
|
||||
if ($target.is('[role=menu]') || $target.parentsUntil(obj.currentTarget,'[role=menu]').length && obj.target !== obj.currentTarget || this.tip().is(':visible') ) {return;}
|
||||
|
||||
var self = obj instanceof this.constructor ?
|
||||
obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.tooltip');
|
||||
|
||||
clearTimeout(self.timeout);
|
||||
self.hoverState = 'in';
|
||||
|
||||
if (!self.options.delay || !self.options.delay.show) {
|
||||
self.show();
|
||||
} else {
|
||||
self.timeout = setTimeout(function () {
|
||||
if (self.hoverState == 'in') {
|
||||
self.show(self.options.placement == 'cursor' ? self.targetXY : undefined);
|
||||
}
|
||||
}, self.options.delay.show);
|
||||
}
|
||||
},
|
||||
|
||||
replaceArrow: function(delta, dimension, position) {
|
||||
this.options.arrow === false ?
|
||||
this.arrow().hide() : _superclass.prototype.replaceArrow.apply(this, arguments);
|
||||
},
|
||||
|
||||
getCalculatedOffset: function (placement, pos, actualWidth, actualHeight) {
|
||||
var out = _superclass.prototype.getCalculatedOffset.apply(this, arguments);
|
||||
|
||||
if (this.options.offset > 0 || this.options.offset < 0) {
|
||||
switch (/(bottom|top)/.exec(placement)[1]) {
|
||||
case 'bottom': out.top += this.options.offset; break;
|
||||
case 'top': out.top -= this.options.offset; break;
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
/* TOOLTIP EXTRA PLUGIN DEFINITION
|
||||
* ========================= */
|
||||
|
||||
var old = $.fn.tooltip;
|
||||
|
||||
$.fn.tooltip = function (option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
, data = $this.data('bs.tooltip')
|
||||
, options = typeof option === 'object' && option;
|
||||
if (!data) { $this.data('bs.tooltip', (data = new Tip(this, options))); }
|
||||
if (typeof option === 'string') { data[option](); }
|
||||
});
|
||||
};
|
||||
|
||||
$.fn.tooltip.Constructor = Tip;
|
||||
|
||||
|
||||
/* TOOLTIP EXTRA NO CONFLICT
|
||||
* =================== */
|
||||
|
||||
$.fn.tooltip.noConflict = function () {
|
||||
$.fn.tooltip = old;
|
||||
return this;
|
||||
};
|
||||
|
||||
})(window.jQuery);
|
553
apps/common/main/lib/util/utils.js
Normal file
553
apps/common/main/lib/util/utils.js
Normal file
|
@ -0,0 +1,553 @@
|
|||
if (Common === undefined) {
|
||||
var Common = {};
|
||||
}
|
||||
|
||||
if (Common.Utils === undefined) {
|
||||
Common.Utils = {};
|
||||
}
|
||||
|
||||
Common.Utils = new(function() {
|
||||
var userAgent = navigator.userAgent.toLowerCase(),
|
||||
check = function(regex){
|
||||
return regex.test(userAgent);
|
||||
},
|
||||
isStrict = document.compatMode == "CSS1Compat",
|
||||
version = function (is, regex) {
|
||||
var m;
|
||||
return (is && (m = regex.exec(userAgent))) ? parseFloat(m[1]) : 0;
|
||||
},
|
||||
docMode = document.documentMode,
|
||||
isOpera = check(/opera/),
|
||||
isOpera10_5 = isOpera && check(/version\/10\.5/),
|
||||
isChrome = check(/\bchrome\b/),
|
||||
isWebKit = check(/webkit/),
|
||||
isSafari = !isChrome && check(/safari/),
|
||||
isSafari2 = isSafari && check(/applewebkit\/4/), // unique to Safari 2
|
||||
isSafari3 = isSafari && check(/version\/3/),
|
||||
isSafari4 = isSafari && check(/version\/4/),
|
||||
isSafari5_0 = isSafari && check(/version\/5\.0/),
|
||||
isSafari5 = isSafari && check(/version\/5/),
|
||||
isIE = !isOpera && (check(/msie/) || check(/trident/)),
|
||||
isIE7 = isIE && ((check(/msie 7/) && docMode != 8 && docMode != 9 && docMode != 10) || docMode == 7),
|
||||
isIE8 = isIE && ((check(/msie 8/) && docMode != 7 && docMode != 9 && docMode != 10) || docMode == 8),
|
||||
isIE9 = isIE && ((check(/msie 9/) && docMode != 7 && docMode != 8 && docMode != 10) || docMode == 9),
|
||||
isIE10 = isIE && ((check(/msie 10/) && docMode != 7 && docMode != 8 && docMode != 9) || docMode == 10),
|
||||
isIE11 = isIE && ((check(/trident\/7\.0/) && docMode != 7 && docMode != 8 && docMode != 9 && docMode != 10) || docMode == 11),
|
||||
isIE6 = isIE && check(/msie 6/),
|
||||
isGecko = !isWebKit && !isIE && check(/gecko/), // IE11 adds "like gecko" into the user agent string
|
||||
isGecko3 = isGecko && check(/rv:1\.9/),
|
||||
isGecko4 = isGecko && check(/rv:2\.0/),
|
||||
isGecko5 = isGecko && check(/rv:5\./),
|
||||
isGecko10 = isGecko && check(/rv:10\./),
|
||||
isFF3_0 = isGecko3 && check(/rv:1\.9\.0/),
|
||||
isFF3_5 = isGecko3 && check(/rv:1\.9\.1/),
|
||||
isFF3_6 = isGecko3 && check(/rv:1\.9\.2/),
|
||||
isWindows = check(/windows|win32/),
|
||||
isMac = check(/macintosh|mac os x/),
|
||||
isLinux = check(/linux/),
|
||||
chromeVersion = version(true, /\bchrome\/(\d+\.\d+)/),
|
||||
firefoxVersion = version(true, /\bfirefox\/(\d+\.\d+)/),
|
||||
ieVersion = version(isIE, /msie (\d+\.\d+)/),
|
||||
operaVersion = version(isOpera, /version\/(\d+\.\d+)/),
|
||||
safariVersion = version(isSafari, /version\/(\d+\.\d+)/),
|
||||
webKitVersion = version(isWebKit, /webkit\/(\d+\.\d+)/),
|
||||
isSecure = /^https/i.test(window.location.protocol),
|
||||
emailRe = /^(mailto:)?([a-z0-9'\._-]+@[a-z0-9\.-]+\.[a-z0-9]{2,4})([a-яё0-9\._%+-=\? :&]*)/i,
|
||||
ipRe = /^(((https?)|(ftps?)):\/\/)?([\-\wа-яё]*:?[\-\wа-яё]*@)?(((1[0-9]{2}|2[0-4][0-9]|25[0-5]|[1-9][0-9]|[0-9])\.){3}(1[0-9]{2}|2[0-4][0-9]|25[0-5]|[1-9][0-9]|[0-9]))(:\d+)?(\/[%\-\wа-яё]*(\.[\wа-яё]{2,})?(([\wа-яё\-\.\?\\\/+@&#;:`~=%!,\(\)]*)(\.[\wа-яё]{2,})?)*)*\/?/i,
|
||||
hostnameRe = /^(((https?)|(ftps?)):\/\/)?([\-\wа-яё]*:?[\-\wа-яё]*@)?(([\-\wа-яё]+\.)+[\wа-яё\-]{2,}(:\d+)?(\/[%\-\wа-яё]*(\.[\wа-яё]{2,})?(([\wа-яё\-\.\?\\\/+@&#;:`~=%!,\(\)]*)(\.[\wа-яё]{2,})?)*)*\/?)/i,
|
||||
localRe = /^(((https?)|(ftps?)):\/\/)([\-\wа-яё]*:?[\-\wа-яё]*@)?(([\-\wа-яё]+)(:\d+)?(\/[%\-\wа-яё]*(\.[\wа-яё]{2,})?(([\wа-яё\-\.\?\\\/+@&#;:`~=%!,\(\)]*)(\.[\wа-яё]{2,})?)*)*\/?)/i,
|
||||
emailStrongRe = /(mailto:)([a-z0-9'\._-]+@[a-z0-9\.-]+\.[a-z0-9]{2,4})([a-яё0-9\._%+-=\? :&]*)/ig,
|
||||
ipStrongRe = /(((https?)|(ftps?)):\/\/([\-\wа-яё]*:?[\-\wа-яё]*@)?)(((1[0-9]{2}|2[0-4][0-9]|25[0-5]|[1-9][0-9]|[0-9])\.){3}(1[0-9]{2}|2[0-4][0-9]|25[0-5]|[1-9][0-9]|[0-9]))(:\d+)?(\/[%\-\wа-яё]*(\.[\wа-яё]{2,})?(([\wа-яё\-\.\?\\\/+@&#;:`~=%!,\(\)]*)(\.[\wа-яё]{2,})?)*)*\/?/ig,
|
||||
hostnameStrongRe = /((((https?)|(ftps?)):\/\/([\-\wа-яё]*:?[\-\wа-яё]*@)?)|(([\-\wа-яё]*:?[\-\wа-яё]*@)?www\.))((([\-\wа-яё]+\.)+[\wа-яё\-]{2,}|([\-\wа-яё]+))(:\d+)?(\/[%\-\wа-яё]*(\.[\wа-яё]{2,})?(([\wа-яё\-\.\?\\\/+@&#;:`~=%!,\(\)]*)(\.[\wа-яё]{2,})?)*)*\/?)/ig,
|
||||
documentSettingsType = {
|
||||
Paragraph : 0,
|
||||
Table : 1,
|
||||
Image : 2,
|
||||
Header : 3,
|
||||
Shape : 4,
|
||||
Slide : 5,
|
||||
Chart : 6,
|
||||
MailMerge : 7,
|
||||
TextArt : 8
|
||||
};
|
||||
|
||||
return {
|
||||
userAgent: userAgent,
|
||||
isStrict: isStrict,
|
||||
isIEQuirks: isIE && (!isStrict && (isIE6 || isIE7 || isIE8 || isIE9)),
|
||||
isOpera : isOpera,
|
||||
isOpera10_5 : isOpera10_5,
|
||||
isWebKit : isWebKit,
|
||||
isChrome : isChrome,
|
||||
isSafari : isSafari,
|
||||
isSafari3 : isSafari3,
|
||||
isSafari4 : isSafari4,
|
||||
isSafari5 : isSafari5,
|
||||
isSafari5_0 : isSafari5_0,
|
||||
isSafari2 : isSafari2,
|
||||
isIE : isIE,
|
||||
isIE6 : isIE6,
|
||||
isIE7 : isIE7,
|
||||
isIE7m : isIE6 || isIE7,
|
||||
isIE7p : isIE && !isIE6,
|
||||
isIE8 : isIE8,
|
||||
isIE8m : isIE6 || isIE7 || isIE8,
|
||||
isIE8p : isIE && !(isIE6 || isIE7),
|
||||
isIE9 : isIE9,
|
||||
isIE9m : isIE6 || isIE7 || isIE8 || isIE9,
|
||||
isIE9p : isIE && !(isIE6 || isIE7 || isIE8),
|
||||
isIE10 : isIE10,
|
||||
isIE10m : isIE6 || isIE7 || isIE8 || isIE9 || isIE10,
|
||||
isIE10p : isIE && !(isIE6 || isIE7 || isIE8 || isIE9),
|
||||
isIE11: isIE11,
|
||||
isIE11m : isIE6 || isIE7 || isIE8 || isIE9 || isIE10 || isIE11,
|
||||
isIE11p : isIE && !(isIE6 || isIE7 || isIE8 || isIE9 || isIE10),
|
||||
isGecko : isGecko,
|
||||
isGecko3 : isGecko3,
|
||||
isGecko4 : isGecko4,
|
||||
isGecko5 : isGecko5,
|
||||
isGecko10 : isGecko10,
|
||||
isFF3_0 : isFF3_0,
|
||||
isFF3_5 : isFF3_5,
|
||||
isFF3_6 : isFF3_6,
|
||||
isFF4 : 4 <= firefoxVersion && firefoxVersion < 5,
|
||||
isFF5 : 5 <= firefoxVersion && firefoxVersion < 6,
|
||||
isFF10 : 10 <= firefoxVersion && firefoxVersion < 11,
|
||||
isLinux : isLinux,
|
||||
isWindows : isWindows,
|
||||
isMac : isMac,
|
||||
chromeVersion: chromeVersion,
|
||||
firefoxVersion: firefoxVersion,
|
||||
ieVersion: ieVersion,
|
||||
operaVersion: operaVersion,
|
||||
safariVersion: safariVersion,
|
||||
webKitVersion: webKitVersion,
|
||||
isSecure: isSecure,
|
||||
emailRe: emailRe,
|
||||
ipRe: ipRe,
|
||||
hostnameRe: hostnameRe,
|
||||
localRe: localRe,
|
||||
emailStrongRe: emailStrongRe,
|
||||
ipStrongRe: ipStrongRe,
|
||||
hostnameStrongRe: hostnameStrongRe,
|
||||
documentSettingsType: documentSettingsType
|
||||
}
|
||||
})();
|
||||
|
||||
Common.Utils.ThemeColor = new(function() {
|
||||
return {
|
||||
ThemeValues: [6, 15, 7, 16, 0, 1, 2, 3, 4, 5],
|
||||
|
||||
setColors: function(colors, standart_colors) {
|
||||
var i, j, item;
|
||||
|
||||
if (standart_colors && standart_colors.length > 0) {
|
||||
var standartcolors = [];
|
||||
|
||||
for (i = 0; i < standart_colors.length; i++) {
|
||||
item = this.getHexColor(standart_colors[i].get_r(), standart_colors[i].get_g(), standart_colors[i].get_b());
|
||||
standartcolors.push(item);
|
||||
}
|
||||
|
||||
this.standartcolors = standartcolors;
|
||||
}
|
||||
|
||||
var effectСolors= [];
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
for (j = 0; j < 10; j++) {
|
||||
var idx = i + j * 6;
|
||||
item = {
|
||||
color: this.getHexColor(colors[idx].get_r(), colors[idx].get_g(), colors[idx].get_b()),
|
||||
effectId: idx,
|
||||
effectValue: this.ThemeValues[j]
|
||||
};
|
||||
effectСolors.push(item);
|
||||
}
|
||||
}
|
||||
this.effectcolors = effectСolors;
|
||||
},
|
||||
|
||||
getEffectColors: function() {
|
||||
return this.effectcolors;
|
||||
},
|
||||
|
||||
getStandartColors: function() {
|
||||
return this.standartcolors;
|
||||
},
|
||||
|
||||
getHexColor: function(r, g, b){
|
||||
r = r.toString(16);
|
||||
g = g.toString(16);
|
||||
b = b.toString(16);
|
||||
if (r.length == 1) r = '0' + r;
|
||||
if (g.length == 1) g = '0' + g;
|
||||
if (b.length == 1) b = '0' + b;
|
||||
return r + g + b;
|
||||
},
|
||||
|
||||
getRgbColor: function(clr){
|
||||
var color = (typeof(clr) == 'object') ? clr.color : clr;
|
||||
|
||||
color=color.replace(/#/,'');
|
||||
if(color.length==3) color=color.replace(/(.)/g,'$1$1');
|
||||
color=parseInt(color,16);
|
||||
var c = new CAscColor();
|
||||
c.put_type( (typeof(clr) == 'object' && clr.effectId !== undefined)? c_oAscColor.COLOR_TYPE_SCHEME : c_oAscColor.COLOR_TYPE_SRGB);
|
||||
c.put_r(color>>16);
|
||||
c.put_g((color&0xff00)>>8);
|
||||
c.put_b(color&0xff);
|
||||
c.put_a(0xff);
|
||||
if (clr.effectId !== undefined)
|
||||
c.put_value(clr.effectId);
|
||||
return c;
|
||||
},
|
||||
|
||||
colorValue2EffectId: function(clr){
|
||||
if (typeof(clr) == 'object' && clr.effectValue !== undefined && this.effectcolors) {
|
||||
for (var i = 0; i < this.effectcolors.length; i++) {
|
||||
if (this.effectcolors[i].effectValue===clr.effectValue && clr.color.toUpperCase()===this.effectcolors[i].color.toUpperCase()) {
|
||||
clr.effectId = this.effectcolors[i].effectId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return clr;
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
Common.Utils.Metric = new(function() {
|
||||
var me = this;
|
||||
|
||||
me.c_MetricUnits = {
|
||||
cm: 0,
|
||||
pt: 1
|
||||
};
|
||||
me.currentMetric = me.c_MetricUnits.pt;
|
||||
me.metricName = ['cm', 'pt'];
|
||||
|
||||
return {
|
||||
c_MetricUnits: me.c_MetricUnits,
|
||||
metricName : me.metricName,
|
||||
|
||||
setCurrentMetric: function(value) {
|
||||
me.currentMetric = value;
|
||||
},
|
||||
|
||||
getCurrentMetric: function() {
|
||||
return me.currentMetric;
|
||||
},
|
||||
|
||||
fnRecalcToMM: function(value) {
|
||||
// value in pt/cm. need to convert to mm
|
||||
if (value!==null && value!==undefined) {
|
||||
switch (me.currentMetric) {
|
||||
case me.c_MetricUnits.cm:
|
||||
return value * 10;
|
||||
case me.c_MetricUnits.pt:
|
||||
return value * 25.4 / 72.0;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
},
|
||||
|
||||
fnRecalcFromMM: function(value) {
|
||||
// value in mm. need to convert to pt/cm
|
||||
switch (me.currentMetric) {
|
||||
case me.c_MetricUnits.cm:
|
||||
return parseFloat((value/10.).toFixed(4));
|
||||
case me.c_MetricUnits.pt:
|
||||
return parseFloat((value * 72.0 / 25.4).toFixed(3));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
Common.Utils.RGBColor = function(colorString) {
|
||||
var r, g, b;
|
||||
|
||||
if (colorString.charAt(0) == '#') {
|
||||
colorString = colorString.substr(1,6);
|
||||
}
|
||||
|
||||
colorString = colorString.replace(/ /g,'');
|
||||
colorString = colorString.toLowerCase();
|
||||
|
||||
var colorDefinitions = [
|
||||
{
|
||||
re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
|
||||
// example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'],
|
||||
process: function (bits){
|
||||
return [
|
||||
parseInt(bits[1]),
|
||||
parseInt(bits[2]),
|
||||
parseInt(bits[3])
|
||||
];
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^hsb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
|
||||
// example: ['hsb(123, 34, 100)'],
|
||||
process: function (bits){
|
||||
var rgb = {};
|
||||
var h = Math.round(bits[1]);
|
||||
var s = Math.round(bits[2] * 255 / 100);
|
||||
var v = Math.round(bits[3] * 255 / 100);
|
||||
if(s == 0) {
|
||||
rgb.r = rgb.g = rgb.b = v;
|
||||
} else {
|
||||
var t1 = v;
|
||||
var t2 = (255 - s) * v / 255;
|
||||
var t3 = (t1 - t2) * (h % 60) / 60;
|
||||
|
||||
if (h == 360) h = 0;
|
||||
if (h < 60) {rgb.r = t1; rgb.b = t2; rgb.g = t2 + t3}
|
||||
else if (h < 120) {rgb.g = t1; rgb.b = t2; rgb.r = t1 - t3}
|
||||
else if (h < 180) {rgb.g = t1; rgb.r = t2; rgb.b = t2 + t3}
|
||||
else if (h < 240) {rgb.b = t1; rgb.r = t2; rgb.g = t1 - t3}
|
||||
else if (h < 300) {rgb.b = t1; rgb.g = t2; rgb.r = t2 + t3}
|
||||
else if (h < 360) {rgb.r = t1; rgb.g = t2; rgb.b = t1 - t3}
|
||||
else {rgb.r = 0; rgb.g = 0; rgb.b = 0}
|
||||
}
|
||||
return [
|
||||
Math.round(rgb.r),
|
||||
Math.round(rgb.g),
|
||||
Math.round(rgb.b)
|
||||
];
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^(\w{2})(\w{2})(\w{2})$/,
|
||||
// example: ['#00ff00', '336699'],
|
||||
process: function (bits){
|
||||
return [
|
||||
parseInt(bits[1], 16),
|
||||
parseInt(bits[2], 16),
|
||||
parseInt(bits[3], 16)
|
||||
];
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^(\w{1})(\w{1})(\w{1})$/,
|
||||
// example: ['#fb0', 'f0f'],
|
||||
process: function (bits){
|
||||
return [
|
||||
parseInt(bits[1] + bits[1], 16),
|
||||
parseInt(bits[2] + bits[2], 16),
|
||||
parseInt(bits[3] + bits[3], 16)
|
||||
];
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
for (var i = 0; i < colorDefinitions.length; i++) {
|
||||
var re = colorDefinitions[i].re;
|
||||
var processor = colorDefinitions[i].process;
|
||||
var bits = re.exec(colorString);
|
||||
if (bits) {
|
||||
var channels = processor(bits);
|
||||
r = channels[0];
|
||||
g = channels[1];
|
||||
b = channels[2];
|
||||
}
|
||||
}
|
||||
|
||||
r = (r < 0 || isNaN(r)) ? 0 : ((r > 255) ? 255 : r);
|
||||
g = (g < 0 || isNaN(g)) ? 0 : ((g > 255) ? 255 : g);
|
||||
b = (b < 0 || isNaN(b)) ? 0 : ((b > 255) ? 255 : b);
|
||||
|
||||
var isEqual = function(color){
|
||||
return ((r == color.r) && (g == color.g) && (b == color.b));
|
||||
};
|
||||
|
||||
var toRGB = function() {
|
||||
return 'rgb(' + r + ', ' + g + ', ' + b + ')';
|
||||
};
|
||||
|
||||
var toRGBA = function(alfa) {
|
||||
if (alfa===undefined) alfa = 1;
|
||||
return 'rgba(' + r + ', ' + g + ', ' + b + ', ' + alfa + ')';
|
||||
};
|
||||
|
||||
var toHex = function() {
|
||||
var _r = r.toString(16);
|
||||
var _g = g.toString(16);
|
||||
var _b = b.toString(16);
|
||||
if (_r.length == 1) _r = '0' + _r;
|
||||
if (_g.length == 1) _g = '0' + _g;
|
||||
if (_b.length == 1) _b = '0' + _b;
|
||||
return '#' + _r + _g + _b;
|
||||
};
|
||||
|
||||
var toHSB = function() {
|
||||
var hsb = {
|
||||
h: 0,
|
||||
s: 0,
|
||||
b: 0
|
||||
};
|
||||
|
||||
var min = Math.min(r, g, b);
|
||||
var max = Math.max(r, g, b);
|
||||
var delta = max - min;
|
||||
hsb.b = max;
|
||||
hsb.s = max != 0 ? 255 * delta / max : 0;
|
||||
if (hsb.s != 0) {
|
||||
if (r == max) {
|
||||
hsb.h = 0 + (g - b) / delta;
|
||||
} else if (g == max) {
|
||||
hsb.h = 2 + (b - r) / delta;
|
||||
} else {
|
||||
hsb.h = 4 + (r - g) / delta;
|
||||
}
|
||||
} else {
|
||||
hsb.h = 0;
|
||||
}
|
||||
hsb.h *= 60;
|
||||
if (hsb.h < 0) {
|
||||
hsb.h += 360;
|
||||
}
|
||||
hsb.s *= 100 / 255;
|
||||
hsb.b *= 100 / 255;
|
||||
|
||||
hsb.h = parseInt(hsb.h);
|
||||
hsb.s = parseInt(hsb.s);
|
||||
hsb.b = parseInt(hsb.b);
|
||||
|
||||
return hsb;
|
||||
};
|
||||
|
||||
return {
|
||||
r : r,
|
||||
g : g,
|
||||
b : b,
|
||||
isEqual : isEqual,
|
||||
toRGB : toRGB,
|
||||
toRGBA : toRGBA,
|
||||
toHex : toHex,
|
||||
toHSB : toHSB
|
||||
}
|
||||
};
|
||||
|
||||
Common.Utils.String = new (function() {
|
||||
return {
|
||||
format: function(format) {
|
||||
var args = _.toArray(arguments).slice(1);
|
||||
return format.replace(/\{(\d+)\}/g, function(s, i) {
|
||||
return args[i];
|
||||
});
|
||||
},
|
||||
|
||||
htmlEncode: function(string) {
|
||||
return _.escape(string);
|
||||
},
|
||||
|
||||
htmlDecode: function(string) {
|
||||
return _.unescape(string);
|
||||
},
|
||||
|
||||
ellipsis: function(value, len, word) {
|
||||
if (value && value.length > len) {
|
||||
if (word) {
|
||||
var vs = value.substr(0, len - 2),
|
||||
index = Math.max(vs.lastIndexOf(' '), vs.lastIndexOf('.'), vs.lastIndexOf('!'), vs.lastIndexOf('?'));
|
||||
if (index !== -1 && index >= (len - 15)) {
|
||||
return vs.substr(0, index) + "...";
|
||||
}
|
||||
}
|
||||
return value.substr(0, len - 3) + "...";
|
||||
}
|
||||
return value;
|
||||
},
|
||||
|
||||
platformKey: function(string, template, hookFn) {
|
||||
if (_.isEmpty(template))
|
||||
template = ' ({0})';
|
||||
|
||||
if (Common.Utils.isMac) {
|
||||
if (_.isFunction(hookFn)) {
|
||||
string = hookFn.call(this, string);
|
||||
}
|
||||
return Common.Utils.String.format(template, string.replace(/\+(?=\S)/g, '').replace(/Ctrl|ctrl/g, '⌘').replace(/Alt|alt/g, '⌥').replace(/Shift|shift/g, '⇧'));
|
||||
}
|
||||
|
||||
return Common.Utils.String.format(template, string);
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
Common.Utils.isBrowserSupported = function() {
|
||||
return !((Common.Utils.ieVersion != 0 && Common.Utils.ieVersion < 9.0) ||
|
||||
(Common.Utils.safariVersion != 0 && Common.Utils.safariVersion < 5.0) ||
|
||||
(Common.Utils.firefoxVersion != 0 && Common.Utils.firefoxVersion < 4.0) ||
|
||||
(Common.Utils.chromeVersion != 0 && Common.Utils.chromeVersion < 7.0) ||
|
||||
(Common.Utils.operaVersion != 0 && Common.Utils.operaVersion < 10.5));
|
||||
};
|
||||
|
||||
Common.Utils.showBrowserRestriction = function() {
|
||||
var editor = (window.DE ? 'Document' : window.SSE ? 'Spreadsheet' : window.PE ? 'Presentation' : 'that');
|
||||
var newDiv = document.createElement("div");
|
||||
newDiv.innerHTML = '<div class="app-error-panel">' +
|
||||
'<div class="message-block">' +
|
||||
'<div class="message-inner">' +
|
||||
'<div class="title">Your browser is not supported.</div>' +
|
||||
'<div class="text">Sorry, ' + editor + ' Editor is currently only supported in the latest versions of the Chrome, Firefox, Safari or Internet Explorer web browsers.</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<div class="message-auxiliary"></div>' +
|
||||
'</div>';
|
||||
|
||||
document.body.appendChild(newDiv);
|
||||
|
||||
$('#loading-mask').hide().remove();
|
||||
$('#viewport').hide().remove();
|
||||
};
|
||||
|
||||
Common.Utils.applyCustomization = function(config, elmap) {
|
||||
for (var name in config) {
|
||||
var $el;
|
||||
if (!!elmap[name]) {
|
||||
$el = $(elmap[name]);
|
||||
|
||||
if ($el.length) {
|
||||
var item = config[name];
|
||||
if (item === false || item.visible === false) {
|
||||
$el.hide()
|
||||
} else {
|
||||
if (!!item.text) {
|
||||
$el.text(item.text);
|
||||
}
|
||||
|
||||
if (item.visible === false) {
|
||||
$el.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Common.Utils.fillUserInfo = function(info, lang, defname) {
|
||||
var _user = info || {};
|
||||
!_user.id && (_user.id = ('uid-' + Date.now()));
|
||||
_.isEmpty(_user.firstname) && _.isEmpty(_user.lastname) && (_user.firstname = defname);
|
||||
if (_.isEmpty(_user.firstname))
|
||||
_user.fullname = _user.lastname;
|
||||
else if (_.isEmpty(_user.lastname))
|
||||
_user.fullname = _user.firstname;
|
||||
else
|
||||
_user.fullname = /^ru/.test(lang) ? _user.lastname + ' ' + _user.firstname : _user.firstname + ' ' + _user.lastname;
|
||||
|
||||
return _user;
|
||||
};
|
||||
|
||||
// Extend javascript String type
|
||||
String.prototype.strongMatch = function(regExp){
|
||||
if (regExp && regExp instanceof RegExp) {
|
||||
var arr = this.toString().match(regExp);
|
||||
return !!(arr && arr.length > 0 && arr[0].length == this.length);
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
216
apps/common/main/lib/view/About.js
Normal file
216
apps/common/main/lib/view/About.js
Normal file
|
@ -0,0 +1,216 @@
|
|||
/**
|
||||
* About.js
|
||||
*
|
||||
* Created by Julia Radzhabova on 3/06/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
define([
|
||||
'common/main/lib/component/BaseView',
|
||||
'common/main/lib/component/Scroller'
|
||||
], function () { 'use strict';
|
||||
|
||||
Common.Views.About = Common.UI.BaseView.extend(_.extend({
|
||||
menu: undefined,
|
||||
options: {
|
||||
alias: 'Common.Views.About'
|
||||
},
|
||||
|
||||
initialize: function(options) {
|
||||
Common.UI.BaseView.prototype.initialize.call(this,arguments);
|
||||
|
||||
this.txtVersionNum = '3.7';
|
||||
this.txtAscMail = 'support@onlyoffice.com';
|
||||
this.txtAscTelNum = '+371 660-16425';
|
||||
this.txtAscUrl = 'www.onlyoffice.com';
|
||||
this.txtAscName = 'Ascensio System SIA';
|
||||
|
||||
this.template = _.template([
|
||||
'<table id="id-about-licensor-logo" cols="1" style="width: 100%; margin-top: 20px;">',
|
||||
'<tr>',
|
||||
'<td align="center"><div class="asc-about-office"/></td>',
|
||||
'</tr>',
|
||||
'<tr>',
|
||||
'<td align="center"><label class="asc-about-version">' + options.appName.toUpperCase() + '</label></td>',
|
||||
'</tr>',
|
||||
'<tr>',
|
||||
'<td align="center"><label class="asc-about-version">' + this.txtVersion + this.txtVersionNum + '</label></td>',
|
||||
'</tr>',
|
||||
'</table>',
|
||||
'<table id="id-about-licensor-info" cols="3" style="width: 100%;" class="margin-bottom">',
|
||||
'<tr>',
|
||||
'<td colspan="3" align="center" style="padding: 20px 0 10px 0;"><label class="asc-about-companyname">' + this.txtAscName + '</label></td>',
|
||||
'</tr>',
|
||||
'<tr>',
|
||||
'<td colspan="3" align="center" class="padding-small">',
|
||||
'<label class="asc-about-desc-name">' + this.txtAddress + '</label>',
|
||||
'<label class="asc-about-desc">' + this.txtAscAddress + '</label>',
|
||||
'</td>',
|
||||
'</tr>',
|
||||
'<tr>',
|
||||
'<td colspan="3" align="center" class="padding-small">',
|
||||
'<label class="asc-about-desc-name">' + this.txtMail + '</label>',
|
||||
'<a href="mailto:'+ this.txtAscMail +'">' + this.txtAscMail + '</a>',
|
||||
'</td>',
|
||||
'</tr>',
|
||||
'<tr>',
|
||||
'<td colspan="3" align="center" class="padding-small">',
|
||||
'<label class="asc-about-desc-name">' + this.txtTel + '</label>',
|
||||
'<label class="asc-about-desc">' + this.txtAscTelNum + '</label>',
|
||||
'</td>',
|
||||
'</tr>',
|
||||
'<tr>',
|
||||
'<td colspan="3" align="center">',
|
||||
'<a href="http:\/\/'+ this.txtAscUrl +'" target="_blank">' + this.txtAscUrl + '</a>',
|
||||
'</td>',
|
||||
'</tr>',
|
||||
'</table>',
|
||||
'<table id="id-about-licensee-info" cols="1" style="width: 100%; margin-top: 20px;" class="hidden margin-bottom"><tbody>',
|
||||
'<tr>',
|
||||
'<td align="center" class="padding-small"><div id="id-about-company-logo"/></td>',
|
||||
'</tr>',
|
||||
'<tr>',
|
||||
'<td align="center"><label class="asc-about-version">' + options.appName.toUpperCase() + '</label></td>',
|
||||
'</tr>',
|
||||
'<tr>',
|
||||
'<td align="center"><label style="padding-bottom: 29px;" class="asc-about-version">' + this.txtVersion + this.txtVersionNum + '</label></td>',
|
||||
'</tr>',
|
||||
'<tr>',
|
||||
'<td align="center" class="padding-small">',
|
||||
'<label class="asc-about-companyname" id="id-about-company-name"></label>',
|
||||
'</td>',
|
||||
'</tr>',
|
||||
'<tr>',
|
||||
'<td align="center" class="padding-small">',
|
||||
'<label class="asc-about-desc-name">' + this.txtAddress + '</label>',
|
||||
'<label class="asc-about-desc" id="id-about-company-address"></label>',
|
||||
'</td>',
|
||||
'</tr>',
|
||||
'<tr>',
|
||||
'<td align="center" class="padding-small">',
|
||||
'<label class="asc-about-desc-name">' + this.txtMail + '</label>',
|
||||
'<a href="mailto:" id="id-about-company-mail"></a>',
|
||||
'</td>',
|
||||
'</tr>',
|
||||
'<tr>',
|
||||
'<td align="center" class="padding-small">',
|
||||
'<a href="" target="_blank" id="id-about-company-url"></a>',
|
||||
'</td>',
|
||||
'</tr>',
|
||||
'<tr>',
|
||||
'<td align="center">',
|
||||
'<label class="asc-about-lic" id="id-about-company-lic"></label>',
|
||||
'</td>',
|
||||
'</tr>',
|
||||
'</table>',
|
||||
'<table id="id-about-licensor-short" cols="1" style="width: 100%; margin-top: 31px;" class="hidden"><tbody>',
|
||||
'<tr>',
|
||||
'<td style="width:50%;"><div class="separator horizontal short left"/></td>',
|
||||
'<td align="center"><label class="asc-about-header">' + this.txtPoweredBy + '</label></td>',
|
||||
'<td style="width:50%;"><div class="separator horizontal short"/></td>',
|
||||
'</tr>',
|
||||
'<tr>',
|
||||
'<td colspan="3" align="center" style="padding: 9px 0 10px;"><label class="asc-about-companyname">' + this.txtAscName + '</label></td>',
|
||||
'</tr>',
|
||||
'<tr>',
|
||||
'<td colspan="3" align="center">',
|
||||
'<a href="http:\/\/'+ this.txtAscUrl +'" target="_blank">' + this.txtAscUrl + '</a>',
|
||||
'</td>',
|
||||
'</tr>',
|
||||
'</table>'
|
||||
].join(''));
|
||||
this.menu = options.menu;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var el = $(this.el);
|
||||
el.html(this.template({
|
||||
scope: this
|
||||
}));
|
||||
|
||||
el.addClass('about-dlg');
|
||||
this.cntLicenseeInfo = $('#id-about-licensee-info');
|
||||
this.cntLicensorInfo = $('#id-about-licensor-info');
|
||||
this.divCompanyLogo = $('#id-about-company-logo');
|
||||
this.lblCompanyName = $('#id-about-company-name');
|
||||
this.lblCompanyAddress = $('#id-about-company-address');
|
||||
this.lblCompanyMail = $('#id-about-company-mail');
|
||||
this.lblCompanyUrl = $('#id-about-company-url');
|
||||
this.lblCompanyLic = $('#id-about-company-lic');
|
||||
|
||||
if (_.isUndefined(this.scroller)) {
|
||||
this.scroller = new Common.UI.Scroller({
|
||||
el: $(this.el),
|
||||
suppressScrollX: true
|
||||
});
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
setLicInfo: function(data){
|
||||
if (data && typeof data == 'object' && typeof(data.customer)=='object') {
|
||||
var customer = data.customer;
|
||||
|
||||
$('#id-about-licensor-logo').addClass('hidden');
|
||||
$('#id-about-licensor-short').removeClass('hidden');
|
||||
this.cntLicensorInfo.addClass('hidden');
|
||||
|
||||
this.cntLicenseeInfo.removeClass('hidden');
|
||||
this.cntLicensorInfo.removeClass('margin-bottom');
|
||||
|
||||
var value = customer.name;
|
||||
value && value.length ?
|
||||
this.lblCompanyName.text(value) :
|
||||
this.lblCompanyName.parents('tr').addClass('hidden');
|
||||
|
||||
value = customer.address;
|
||||
value && value.length ?
|
||||
this.lblCompanyAddress.text(value) :
|
||||
this.lblCompanyAddress.parents('tr').addClass('hidden');
|
||||
|
||||
(value = customer.mail) && value.length ?
|
||||
this.lblCompanyMail.attr('href', "mailto:"+value).text(value) :
|
||||
this.lblCompanyMail.parents('tr').addClass('hidden');
|
||||
|
||||
if ((value = customer.www) && value.length) {
|
||||
var http = !/^https?:\/{2}/i.test(value) ? "http:\/\/" : '';
|
||||
this.lblCompanyUrl.attr('href', http+value).text(value);
|
||||
} else
|
||||
this.lblCompanyUrl.parents('tr').addClass('hidden');
|
||||
|
||||
(value = customer.info) && value.length ?
|
||||
this.lblCompanyLic.text(value) :
|
||||
this.lblCompanyLic.parents('tr').addClass('hidden');
|
||||
|
||||
(value = customer.logo) && value.length ?
|
||||
this.divCompanyLogo.html('<img src="'+value+'" style="max-width:216px; max-height: 35px;" />') :
|
||||
this.divCompanyLogo.parents('tr').addClass('hidden');
|
||||
} else {
|
||||
this.cntLicenseeInfo.addClass('hidden');
|
||||
this.cntLicensorInfo.addClass('margin-bottom');
|
||||
}
|
||||
},
|
||||
|
||||
show: function () {
|
||||
Common.UI.BaseView.prototype.show.call(this,arguments);
|
||||
this.fireEvent('show', this );
|
||||
},
|
||||
|
||||
hide: function () {
|
||||
Common.UI.BaseView.prototype.hide.call(this,arguments);
|
||||
this.fireEvent('hide', this );
|
||||
},
|
||||
|
||||
txtPoweredBy: 'Powered by',
|
||||
txtVersion: 'Version ',
|
||||
txtLicensor: 'LICENSOR',
|
||||
txtLicensee: 'LICENSEE',
|
||||
txtAddress: 'address: ',
|
||||
txtAscAddress: 'Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021',
|
||||
txtMail: 'email: ',
|
||||
txtTel: 'tel.: '
|
||||
|
||||
}, Common.Views.About || {}));
|
||||
});
|
117
apps/common/main/lib/view/AdvancedSettingsWindow.js
Normal file
117
apps/common/main/lib/view/AdvancedSettingsWindow.js
Normal file
|
@ -0,0 +1,117 @@
|
|||
/**
|
||||
* AdvancedSettingsWindow.js
|
||||
*
|
||||
* Created by Julia Radzhabova on 2/21/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
define([
|
||||
'common/main/lib/component/Window'
|
||||
], function () { 'use strict';
|
||||
|
||||
Common.Views.AdvancedSettingsWindow = Common.UI.Window.extend(_.extend({
|
||||
initialize : function(options) {
|
||||
var _options = {};
|
||||
_.extend(_options, {
|
||||
height: 200,
|
||||
header: true,
|
||||
cls: 'advanced-settings-dlg',
|
||||
toggleGroup: 'advanced-settings-group',
|
||||
contentTemplate: '',
|
||||
items: []
|
||||
}, options);
|
||||
|
||||
this.template = options.template || [
|
||||
'<div class="box" style="height:' + (_options.height-85) + 'px;">',
|
||||
'<div class="menu-panel">',
|
||||
'<% _.each(items, function(item) { %>',
|
||||
'<button class="btn btn-category" style="margin-bottom: 2px;" content-target="<%= item.panelId %>"><span class=""><%= item.panelCaption %></span></button>',
|
||||
'<% }); %>',
|
||||
'</div>',
|
||||
'<div class="separator"/>',
|
||||
'<div class="content-panel" >' + _options.contentTemplate + '</div>',
|
||||
'</div>',
|
||||
'<div class="separator horizontal"/>',
|
||||
'<div class="footer center">',
|
||||
'<button class="btn normal dlg-btn primary" result="ok" style="margin-right: 10px;">' + this.okButtonText + '</button>',
|
||||
'<button class="btn normal dlg-btn" result="cancel">' + this.cancelButtonText + '</button>',
|
||||
'</div>'
|
||||
].join('');
|
||||
|
||||
_options.tpl = _.template(this.template, _options);
|
||||
|
||||
this.handler = _options.handler;
|
||||
this.toggleGroup = _options.toggleGroup;
|
||||
this.contentWidth = _options.contentWidth;
|
||||
|
||||
Common.UI.Window.prototype.initialize.call(this, _options);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
Common.UI.Window.prototype.render.call(this);
|
||||
|
||||
var me = this;
|
||||
|
||||
var $window = this.getChild();
|
||||
$window.find('.dlg-btn').on('click', _.bind(this.onDlgBtnClick, this));
|
||||
|
||||
this.btnsCategory = [];
|
||||
_.each($window.find('.btn-category'), function(item, index) {
|
||||
var btnEl = $(item);
|
||||
var btn = new Common.UI.Button({
|
||||
el: btnEl,
|
||||
enableToggle: true,
|
||||
toggleGroup: me.toggleGroup,
|
||||
allowDepress: false,
|
||||
contentTarget: btnEl.attr('content-target')
|
||||
});
|
||||
btn.on('click', _.bind(me.onCategoryClick, me));
|
||||
me.btnsCategory.push(btn);
|
||||
});
|
||||
var cnt_panel = $window.find('.content-panel');
|
||||
cnt_panel.width(this.contentWidth);
|
||||
$window.width($window.find('.menu-panel').width() + cnt_panel.outerWidth() + 1);
|
||||
|
||||
this.content_panels = $window.find('.settings-panel');
|
||||
if (this.btnsCategory.length>0)
|
||||
this.btnsCategory[0].toggle(true, true);
|
||||
},
|
||||
|
||||
setHeight: function(height) {
|
||||
Common.UI.Window.prototype.setHeight.call(this, height);
|
||||
|
||||
var $window = this.getChild();
|
||||
var boxEl = $window.find('.body > .box');
|
||||
|
||||
boxEl.css('height', height - 85);
|
||||
},
|
||||
|
||||
onDlgBtnClick: function(event) {
|
||||
var state = event.currentTarget.attributes['result'].value;
|
||||
if ( this.handler && this.handler.call(this, state, (state == 'ok') ? this.getSettings() : undefined) )
|
||||
return;
|
||||
this.close();
|
||||
},
|
||||
|
||||
onCategoryClick: function(btn, event) {
|
||||
this.content_panels.filter('.active').removeClass('active');
|
||||
$("#" + btn.options.contentTarget).addClass("active");
|
||||
},
|
||||
|
||||
getSettings: function() {
|
||||
return;
|
||||
},
|
||||
|
||||
onPrimary: function() {
|
||||
if ( this.handler && this.handler.call(this, 'ok', this.getSettings()) )
|
||||
return;
|
||||
|
||||
this.close();
|
||||
return false;
|
||||
},
|
||||
|
||||
cancelButtonText: 'Cancel',
|
||||
okButtonText : 'Ok'
|
||||
}, Common.Views.AdvancedSettingsWindow || {}));
|
||||
});
|
392
apps/common/main/lib/view/Chat.js
Normal file
392
apps/common/main/lib/view/Chat.js
Normal file
|
@ -0,0 +1,392 @@
|
|||
/**
|
||||
* Chat.js
|
||||
*
|
||||
* View
|
||||
*
|
||||
* Created by Maxim Kadushkin on 27 February 2014
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
Common.Views = Common.Views || {};
|
||||
|
||||
define([
|
||||
'text!common/main/lib/template/Chat.template',
|
||||
'common/main/lib/util/utils',
|
||||
'common/main/lib/component/BaseView',
|
||||
'common/main/lib/component/Layout'
|
||||
], function (template) {
|
||||
'use strict';
|
||||
|
||||
Common.Views.Chat = Common.UI.BaseView.extend(_.extend({
|
||||
el: '#left-panel-chat',
|
||||
template: _.template(template),
|
||||
storeUsers: undefined,
|
||||
storeMessages: undefined,
|
||||
|
||||
tplUser: ['<li id="chat-user-<%= user.get("id") %>"<% if (!user.get("online")) { %> class="offline"<% } %>>',
|
||||
'<div class="color" style="background-color: <%= user.get("color") %>;" >',
|
||||
'<label class="name"><%= scope.getUserName(user.get("username")) %></label>',
|
||||
'</div>',
|
||||
'</li>'].join(''),
|
||||
|
||||
templateUserList: _.template('<ul>' +
|
||||
'<% _.each(users, function(item) { %>' +
|
||||
'<%= _.template(usertpl, {user: item, scope: scope}) %>' +
|
||||
'<% }); %>' +
|
||||
'</ul>'),
|
||||
|
||||
tplMsg: ['<li>',
|
||||
'<% if (msg.get("type")==1) { %>',
|
||||
'<div class="message service" data-can-copy="true"><%= msg.get("message") %></div>',
|
||||
'<% } else { %>',
|
||||
'<div class="user user-select" data-can-copy="true" style="color: <%= msg.get("usercolor") %>;"><%= scope.getUserName(msg.get("username")) %></div>',
|
||||
'<label class="message user-select" data-can-copy="true"><%= msg.get("message") %></label>',
|
||||
'<% } %>',
|
||||
'</li>'].join(''),
|
||||
|
||||
templateMsgList: _.template('<ul>' +
|
||||
'<% _.each(messages, function(item) { %>' +
|
||||
'<%= _.template(msgtpl, {msg: item, scope: scope}) %>' +
|
||||
'<% }); %>' +
|
||||
'</ul>'),
|
||||
|
||||
events: {
|
||||
},
|
||||
|
||||
usersBoxHeight: 72,
|
||||
messageBoxHeight: 70,
|
||||
addMessageBoxHeight: 110,
|
||||
|
||||
initialize: function(options) {
|
||||
_.extend(this, options);
|
||||
Common.UI.BaseView.prototype.initialize.call(this, arguments);
|
||||
|
||||
this.storeUsers.bind({
|
||||
add : _.bind(this._onAddUser, this),
|
||||
change : _.bind(this._onUsersChanged, this),
|
||||
reset : _.bind(this._onResetUsers, this)
|
||||
});
|
||||
|
||||
this.storeMessages.bind({
|
||||
add : _.bind(this._onAddMessage, this),
|
||||
reset : _.bind(this._onResetMessages, this)
|
||||
});
|
||||
},
|
||||
|
||||
render: function(el) {
|
||||
el = el || this.el;
|
||||
$(el).html(this.template({scope: this, maxMsgLength: c_oAscMaxCellOrCommentLength}));
|
||||
|
||||
this.panelBox = $('#chat-box', this.el);
|
||||
this.panelUsers = $('#chat-users', this.el);
|
||||
this.panelMessages = $('#chat-messages', this.el);
|
||||
this.txtMessage = $('#chat-msg-text', this.el);
|
||||
this.panelOptions = $('#chat-options', this.el);
|
||||
|
||||
this.panelUsers.scroller = new Common.UI.Scroller({
|
||||
el : $('#chat-users'),
|
||||
useKeyboard : true,
|
||||
minScrollbarLength : 25
|
||||
});
|
||||
this.panelMessages.scroller = new Common.UI.Scroller({
|
||||
el : $('#chat-messages'),
|
||||
includePadding : true,
|
||||
useKeyboard : true,
|
||||
minScrollbarLength : 40
|
||||
});
|
||||
|
||||
$('#chat-msg-btn-add', this.el).on('click', _.bind(this._onBtnAddMessage, this));
|
||||
this.txtMessage.on('keydown', _.bind(this._onKeyDown, this));
|
||||
|
||||
this.setupLayout();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
focus: function() {
|
||||
var me = this;
|
||||
_.defer(function(){
|
||||
me.txtMessage.focus();
|
||||
}, 100);
|
||||
|
||||
this.updateLayout(true);
|
||||
this.setupAutoSizingTextBox();
|
||||
},
|
||||
|
||||
_onKeyDown: function(event) {
|
||||
if (event.keyCode == Common.UI.Keys.RETURN) {
|
||||
if ((event.ctrlKey || event.metaKey) && !event.altKey) {
|
||||
this._onBtnAddMessage(event);
|
||||
}
|
||||
} else
|
||||
if (event.keyCode == Common.UI.Keys.ESC) {
|
||||
this.hide();
|
||||
}
|
||||
},
|
||||
|
||||
_onAddUser: function(m, c, opts) {
|
||||
if (this.panelUsers) {
|
||||
this.panelUsers.find('ul').append(_.template(this.tplUser, {user: m, scope: this}));
|
||||
this.panelUsers.scroller.update({minScrollbarLength : 25, alwaysVisibleY: true});
|
||||
}
|
||||
},
|
||||
|
||||
_onUsersChanged: function(m) {
|
||||
if (m.changed.online != undefined && this.panelUsers) {
|
||||
this.panelUsers.find('#chat-user-'+ m.get('id'))[m.changed.online?'removeClass':'addClass']('offline');
|
||||
this.panelUsers.scroller.update({minScrollbarLength : 25, alwaysVisibleY: true});
|
||||
}
|
||||
},
|
||||
|
||||
_onResetUsers: function(c, opts) {
|
||||
if (this.panelUsers) {
|
||||
this.panelUsers.html(this.templateUserList({users: c.models, usertpl: this.tplUser, scope: this}));
|
||||
this.panelUsers.scroller.update({minScrollbarLength : 25, alwaysVisibleY: true});
|
||||
}
|
||||
},
|
||||
|
||||
_onAddMessage: function(m, c, opts) {
|
||||
if (this.panelMessages) {
|
||||
var content = this.panelMessages.find('ul');
|
||||
if (content && content.length) {
|
||||
this._prepareMessage(m);
|
||||
content.append(_.template(this.tplMsg, {msg: m, scope: this}));
|
||||
|
||||
// scroll to end
|
||||
|
||||
this.panelMessages.scroller.update({minScrollbarLength : 40, alwaysVisibleY: true});
|
||||
this.panelMessages.scroller.scrollTop(content.get(0).getBoundingClientRect().height);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_onResetMessages: function(c, opts) {
|
||||
if (this.panelMessages) {
|
||||
var user, color;
|
||||
c.each(function(msg){
|
||||
this._prepareMessage(msg);
|
||||
}, this);
|
||||
|
||||
this.panelMessages.html(this.templateMsgList({messages: c.models, msgtpl: this.tplMsg, scope: this}));
|
||||
this.panelMessages.scroller.update({minScrollbarLength : 40, alwaysVisibleY: true});
|
||||
}
|
||||
},
|
||||
|
||||
_onBtnAddMessage: function(e) {
|
||||
if (this.txtMessage) {
|
||||
this.fireEvent('message:add', [this, this.txtMessage.val().trim()]);
|
||||
this.txtMessage.val('');
|
||||
this.focus();
|
||||
}
|
||||
},
|
||||
|
||||
_prepareMessage: function(m) {
|
||||
var user = this.storeUsers.findUser(m.get('userid'));
|
||||
m.set({
|
||||
usercolor : user ? user.get('color') : '#000',
|
||||
message : this._pickLink(Common.Utils.String.htmlEncode(m.get('message')))
|
||||
}, {silent:true});
|
||||
},
|
||||
|
||||
_pickLink: function(message) {
|
||||
var arr = [], offset, len;
|
||||
|
||||
message.replace(Common.Utils.emailStrongRe, function(subStr) {
|
||||
offset = arguments[arguments.length-2];
|
||||
arr.push({start: offset, end: subStr.length+offset, str: '<a href="' + subStr + '">' + subStr + '</a>'});
|
||||
return '';
|
||||
});
|
||||
|
||||
message.replace(Common.Utils.ipStrongRe, function(subStr) {
|
||||
offset = arguments[arguments.length-2];
|
||||
len = subStr.length;
|
||||
var elem = _.find(arr, function(item){
|
||||
return ( (offset>=item.start) && (offset<item.end) ||
|
||||
(offset<=item.start) && (offset+len>item.start));
|
||||
});
|
||||
if (!elem)
|
||||
arr.push({start: offset, end: len+offset, str: '<a href="' + subStr + '" target="_blank" data-can-copy="true">' + subStr + '</a>'});
|
||||
return '';
|
||||
});
|
||||
|
||||
if (message.length<1000 || message.search(/\S{255,}/)<0)
|
||||
message.replace(Common.Utils.hostnameStrongRe, function(subStr) {
|
||||
var ref = (! /(((^https?)|(^ftp)):\/\/)/i.test(subStr) ) ? ('http://' + subStr) : subStr;
|
||||
offset = arguments[arguments.length-2];
|
||||
len = subStr.length;
|
||||
var elem = _.find(arr, function(item){
|
||||
return ( (offset>=item.start) && (offset<item.end) ||
|
||||
(offset<=item.start) && (offset+len>item.start));
|
||||
});
|
||||
if (!elem)
|
||||
arr.push({start: offset, end: len+offset, str: '<a href="' + ref + '" target="_blank" data-can-copy="true">' + subStr + '</a>'});
|
||||
return '';
|
||||
});
|
||||
arr = _.sortBy(arr, function(item){ return item.start; });
|
||||
|
||||
var str_res = (arr.length>0) ? ( message.substring(0, arr[0].start) + arr[0].str) : message;
|
||||
for (var i=1; i<arr.length; i++) {
|
||||
str_res += (message.substring(arr[i-1].end, arr[i].start) + arr[i].str);
|
||||
}
|
||||
if (arr.length>0) {
|
||||
str_res += message.substring(arr[i-1].end, message.length);
|
||||
}
|
||||
|
||||
return str_res;
|
||||
},
|
||||
|
||||
getUserName: function (username) {
|
||||
return Common.Utils.String.htmlEncode(username);
|
||||
},
|
||||
|
||||
hide: function () {
|
||||
Common.UI.BaseView.prototype.hide.call(this,arguments);
|
||||
this.fireEvent('hide', this );
|
||||
},
|
||||
|
||||
setupLayout: function () {
|
||||
var me = this, parent = $(me.el), items = this.panelBox.find(' > .layout-item');
|
||||
|
||||
me.layout = new Common.UI.VBoxLayout({
|
||||
box: this.panelBox,
|
||||
items: [
|
||||
{el: items[0], rely: true, behaviour: 'splitter',
|
||||
resize: {
|
||||
hidden: false,
|
||||
autohide: false,
|
||||
fmin: (function () {
|
||||
return me.usersBoxHeight;
|
||||
}),
|
||||
fmax: (function () {
|
||||
return me.panelBox.height() * 0.5 - me.messageBoxHeight;
|
||||
})
|
||||
}},
|
||||
{el: items[1], rely: true, behaviour: 'splitter',
|
||||
resize: {
|
||||
hidden: false,
|
||||
autohide: false,
|
||||
fmin: (function () {
|
||||
return Math.max(me.messageBoxHeight + me.usersBoxHeight, me.panelBox.height() * 0.5);
|
||||
}),
|
||||
fmax: (function () {
|
||||
return me.panelBox.height() - me.addMessageBoxHeight;
|
||||
})
|
||||
}},
|
||||
{el: items[2], stretch: true}
|
||||
]
|
||||
});
|
||||
|
||||
me.layout.on('layout:resizedrag', function(resizer) {
|
||||
me.updateScrolls();
|
||||
me.usersCachedHeigt = me.panelUsers.height() + 8 + 1; // resizeHeight * 2 + 1
|
||||
if (!resizer.index) {
|
||||
me.textBoxAutoSizeLocked = true;
|
||||
}
|
||||
}, this);
|
||||
|
||||
$(window).on('resize', function() {
|
||||
if (parent.css('display') !== 'none') {
|
||||
me.updateLayout();
|
||||
}
|
||||
});
|
||||
|
||||
this.updateLayout();
|
||||
|
||||
// default sizes
|
||||
|
||||
var height = this.panelBox.height();
|
||||
|
||||
this.layout.setResizeValue(0, this.usersBoxHeight);
|
||||
this.layout.setResizeValue(1,
|
||||
Math.max (this.addMessageBoxHeight,
|
||||
Math.max (height * 0.5, height - me.panelOptions.height() - 4)));
|
||||
|
||||
// text box setup autosize input text
|
||||
|
||||
this.setupAutoSizingTextBox();
|
||||
},
|
||||
|
||||
updateLayout: function (applyUsersAutoSizig) {
|
||||
var me = this;
|
||||
var height = this.panelBox.height();
|
||||
|
||||
me.layout.setResizeValue(1,
|
||||
Math.max (me.addMessageBoxHeight,
|
||||
Math.max (height * 0.5, height - me.panelOptions.height() - 4)));
|
||||
|
||||
if (applyUsersAutoSizig) {
|
||||
|
||||
var oldHeight = this.panelUsers.css('height');
|
||||
this.panelUsers.css('height', '1px');
|
||||
var content = this.panelUsers.get(0).scrollHeight;
|
||||
|
||||
me.layout.setResizeValue(0, Math.max(me.usersBoxHeight,
|
||||
Math.min(content+2, Math.floor(height * 0.5) - me.messageBoxHeight)));
|
||||
} else {
|
||||
me.layout.setResizeValue(0, Math.max(me.usersBoxHeight,
|
||||
Math.min(me.usersCachedHeigt + 2, Math.floor(height * 0.5) - me.messageBoxHeight)));
|
||||
}
|
||||
|
||||
me.updateScrolls();
|
||||
me.updateHeightTextBox(null);
|
||||
},
|
||||
|
||||
setupAutoSizingTextBox: function () {
|
||||
this.lineHeight = 0;
|
||||
this.minHeight = 44;
|
||||
this.lineHeight = parseInt(this.txtMessage.css('lineHeight'), 10) * 1.25; // TODO: need fix
|
||||
|
||||
this.updateHeightTextBox(true);
|
||||
this.txtMessage.bind('input propertychange', _.bind(this.updateHeightTextBox, this));
|
||||
},
|
||||
|
||||
updateHeightTextBox: function (event) {
|
||||
var textBox, controlHeight, contentHeight, height,
|
||||
textBoxMinHeightIndent = 36 + 4; // 4px - autosize line height + big around border
|
||||
|
||||
textBox = $('#chat-msg-text', this.el);
|
||||
height = this.panelBox.height();
|
||||
|
||||
if (event && 0 == textBox.val().length) {
|
||||
this.layout.setResizeValue(1, Math.max(-this.addMessageBoxHeight, height - this.addMessageBoxHeight));
|
||||
this.textBoxAutoSizeLocked = undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_.isUndefined(this.textBoxAutoSizeLocked))
|
||||
return;
|
||||
|
||||
controlHeight = textBox.height();
|
||||
contentHeight = textBox.get(0).scrollHeight;
|
||||
|
||||
// calculate text content height
|
||||
|
||||
textBox.css({height: this.minHeight + 'px'});
|
||||
|
||||
controlHeight = textBox.height();
|
||||
contentHeight = Math.max(textBox.get(0).scrollHeight + this.lineHeight, 1);
|
||||
|
||||
textBox.css({height: '100%'});
|
||||
|
||||
height = this.panelBox.height();
|
||||
|
||||
this.layout.setResizeValue(1,
|
||||
Math.max(-this.addMessageBoxHeight,
|
||||
Math.min(height - contentHeight - textBoxMinHeightIndent, height - this.addMessageBoxHeight)));
|
||||
},
|
||||
|
||||
updateScrolls: function () {
|
||||
if (this.panelUsers && this.panelUsers.scroller && this.panelMessages && this.panelMessages.scroller) {
|
||||
this.panelUsers.scroller.update({minScrollbarLength: 25, alwaysVisibleY: true});
|
||||
this.panelMessages.scroller.update({minScrollbarLength: 40, alwaysVisibleY: true});
|
||||
}
|
||||
},
|
||||
|
||||
textSend: "Send"
|
||||
|
||||
}, Common.Views.Chat || {}))
|
||||
});
|
1386
apps/common/main/lib/view/Comments.js
Normal file
1386
apps/common/main/lib/view/Comments.js
Normal file
File diff suppressed because it is too large
Load diff
104
apps/common/main/lib/view/CopyWarningDialog.js
Normal file
104
apps/common/main/lib/view/CopyWarningDialog.js
Normal file
|
@ -0,0 +1,104 @@
|
|||
/**
|
||||
* CopyWarningDialog.js
|
||||
*
|
||||
* Created by Alexander Yuzhin on 4/15/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'common/main/lib/component/Window'
|
||||
], function () { 'use strict';
|
||||
|
||||
Common.Views.CopyWarningDialog = Common.UI.Window.extend(_.extend({
|
||||
options: {
|
||||
width : 500,
|
||||
height : 325,
|
||||
cls : 'modal-dlg copy-warning'
|
||||
},
|
||||
|
||||
initialize : function(options) {
|
||||
_.extend(this.options, {
|
||||
title: this.textTitle
|
||||
}, options || {});
|
||||
|
||||
this.template = [
|
||||
'<div class="box">',
|
||||
'<p class="message">' + this.textMsg + '</p>',
|
||||
'<div class="hotkeys">',
|
||||
'<div>',
|
||||
'<p class="hotkey">' + Common.Utils.String.platformKey('Ctrl+C', '{0}') + '</p>',
|
||||
'<p class="message">' + this.textToCopy + '</p>',
|
||||
'</div>',
|
||||
'<div>',
|
||||
'<p class="hotkey">' + Common.Utils.String.platformKey('Ctrl+X', '{0}') + '</p>',
|
||||
'<p class="message">' + this.textToCut + '</p>',
|
||||
'</div>',
|
||||
'<div>',
|
||||
'<p class="hotkey">' + Common.Utils.String.platformKey('Ctrl+V', '{0}') + '</p>',
|
||||
'<p class="message">' + this.textToPaste + '</p>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'<div id="copy-warning-checkbox" style="margin-top: 20px; text-align: left;"></div>',
|
||||
'</div>',
|
||||
'<div class="separator horizontal"/>',
|
||||
'<div class="footer center">',
|
||||
'<button class="btn normal dlg-btn primary">' + this.okButtonText + '</button>',
|
||||
'</div>'
|
||||
].join('');
|
||||
|
||||
this.options.tpl = _.template(this.template, this.options);
|
||||
|
||||
Common.UI.Window.prototype.initialize.call(this, this.options);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
Common.UI.Window.prototype.render.call(this);
|
||||
|
||||
this.chDontShow = new Common.UI.CheckBox({
|
||||
el: $('#copy-warning-checkbox'),
|
||||
labelText: this.textDontShow
|
||||
});
|
||||
|
||||
this.getChild().find('.btn').on('click', _.bind(this.onBtnClick, this));
|
||||
this.autoSize();
|
||||
},
|
||||
|
||||
autoSize: function() {
|
||||
var text_cnt = this.getChild('.box'),
|
||||
footer = this.getChild('.footer'),
|
||||
header = this.getChild('.header'),
|
||||
body = this.getChild('.body');
|
||||
|
||||
body.height(parseInt(text_cnt.height()) + parseInt(footer.css('height')));
|
||||
this.setHeight(parseInt(body.css('height')) + parseInt(header.css('height')));
|
||||
},
|
||||
|
||||
onBtnClick: function(event) {
|
||||
if (this.options.handler) this.options.handler.call(this, this.chDontShow.getValue() == 'checked');
|
||||
this.close();
|
||||
},
|
||||
|
||||
onKeyPress: function(event) {
|
||||
if (event.keyCode == Common.UI.Keys.RETURN) {
|
||||
if (this.options.handler) this.options.handler.call(this, this.chDontShow.getValue() == 'checked');
|
||||
this.close();
|
||||
}
|
||||
},
|
||||
|
||||
getSettings: function() {
|
||||
return (this.chDontShow.getValue() == 'checked');
|
||||
},
|
||||
|
||||
textTitle : 'Copy, Cut and Paste Actions',
|
||||
textMsg : 'Copy, cut and paste actions using the editor toolbar buttons and context menu actions will be performed within this editor tab only.<br><br>.To copy or paste to or from applications outside the editor tab use the following keyboard combinations:',
|
||||
textToCopy : 'for Copy',
|
||||
textToPaste : 'for Paste',
|
||||
textToCut: 'for Cut',
|
||||
textDontShow: 'Don\'t show this message again'
|
||||
}, Common.Views.CopyWarningDialog || {}))
|
||||
});
|
104
apps/common/main/lib/view/DocumentAccessDialog.js
Normal file
104
apps/common/main/lib/view/DocumentAccessDialog.js
Normal file
|
@ -0,0 +1,104 @@
|
|||
/**
|
||||
* DocumentAccessDialog.js
|
||||
*
|
||||
* Created by Julia Radzhabova on 3/14/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
define([
|
||||
'common/main/lib/component/Window',
|
||||
'common/main/lib/component/LoadMask'
|
||||
], function () { 'use strict';
|
||||
|
||||
Common.Views.DocumentAccessDialog = Common.UI.Window.extend(_.extend({
|
||||
initialize : function(options) {
|
||||
var _options = {};
|
||||
_.extend(_options, {
|
||||
title: this.textTitle,
|
||||
width: 850,
|
||||
height: 536,
|
||||
header: true
|
||||
}, options);
|
||||
|
||||
this.template = [
|
||||
'<div id="id-sharing-placeholder"></div>'
|
||||
].join('');
|
||||
|
||||
_options.tpl = _.template(this.template, _options);
|
||||
|
||||
this.settingsurl = options.settingsurl || '';
|
||||
Common.UI.Window.prototype.initialize.call(this, _options);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
Common.UI.Window.prototype.render.call(this);
|
||||
this.$window.find('> .body').css({height: 'auto', overflow: 'hidden'});
|
||||
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.width = '100%';
|
||||
iframe.height = 500;
|
||||
iframe.align = "top";
|
||||
iframe.frameBorder = 0;
|
||||
iframe.scrolling = "no";
|
||||
iframe.onload = _.bind(this._onLoad,this);
|
||||
$('#id-sharing-placeholder').append(iframe);
|
||||
|
||||
this.loadMask = new Common.UI.LoadMask({owner: $('#id-sharing-placeholder')});
|
||||
this.loadMask.setTitle(this.textLoading);
|
||||
this.loadMask.show();
|
||||
|
||||
iframe.src = this.settingsurl;
|
||||
|
||||
var me = this;
|
||||
this._eventfunc = function(msg) {
|
||||
me._onWindowMessage(msg);
|
||||
};
|
||||
this._bindWindowEvents.call(this);
|
||||
|
||||
this.on('close', function(obj){
|
||||
me._unbindWindowEvents();
|
||||
});
|
||||
},
|
||||
|
||||
_bindWindowEvents: function() {
|
||||
if (window.addEventListener) {
|
||||
window.addEventListener("message", this._eventfunc, false)
|
||||
} else if (window.attachEvent) {
|
||||
window.attachEvent("onmessage", this._eventfunc);
|
||||
}
|
||||
},
|
||||
|
||||
_unbindWindowEvents: function() {
|
||||
if (window.removeEventListener) {
|
||||
window.removeEventListener("message", this._eventfunc)
|
||||
} else if (window.detachEvent) {
|
||||
window.detachEvent("onmessage", this._eventfunc);
|
||||
}
|
||||
},
|
||||
|
||||
_onWindowMessage: function(msg) {
|
||||
// TODO: check message origin
|
||||
if (msg && window.JSON) {
|
||||
try {
|
||||
this._onMessage.call(this, window.JSON.parse(msg.data));
|
||||
} catch(e) {}
|
||||
}
|
||||
},
|
||||
|
||||
_onMessage: function(msg) {
|
||||
if (msg && msg.needUpdate) {
|
||||
this.trigger('accessrights', this, msg.sharingSettings);
|
||||
}
|
||||
Common.NotificationCenter.trigger('window:close', this);
|
||||
},
|
||||
|
||||
_onLoad: function() {
|
||||
if (this.loadMask)
|
||||
this.loadMask.hide();
|
||||
},
|
||||
|
||||
textTitle : 'Sharing Settings',
|
||||
textLoading : 'Loading'
|
||||
}, Common.Views.DocumentAccessDialog || {}));
|
||||
});
|
258
apps/common/main/lib/view/ExtendedColorDialog.js
Normal file
258
apps/common/main/lib/view/ExtendedColorDialog.js
Normal file
|
@ -0,0 +1,258 @@
|
|||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
define([
|
||||
'text!common/main/lib/template/ExtendedColorDialog.template',
|
||||
'common/main/lib/component/HSBColorPicker',
|
||||
'common/main/lib/component/MetricSpinner',
|
||||
'common/main/lib/component/MaskedField',
|
||||
'common/main/lib/component/Window'
|
||||
], function (dlgTemplate) {
|
||||
'use strict';
|
||||
|
||||
Common.UI.ExtendedColorDialog = Common.UI.Window.extend(_.extend({
|
||||
tpl: _.template(dlgTemplate),
|
||||
options: {},
|
||||
rendered: false,
|
||||
|
||||
initialize : function(options) {
|
||||
Common.UI.Window.prototype.initialize.call(this, {
|
||||
cls: 'extended-color-dlg',
|
||||
tpl: this.tpl({
|
||||
txtNew: this.textNew,
|
||||
txtCurrent: this.textCurrent,
|
||||
txtAdd: this.addButtonText,
|
||||
txtCancel: this.cancelButtonText
|
||||
}),
|
||||
header: false,
|
||||
width: 340,
|
||||
height: 272
|
||||
});
|
||||
|
||||
this.hexRe = /\s*#?([0-9a-fA-F][0-9a-fA-F]?)([0-9a-fA-F][0-9a-fA-F]?)([0-9a-fA-F][0-9a-fA-F]?)\s*/;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var me = this;
|
||||
Common.UI.Window.prototype.render.call(this);
|
||||
|
||||
this.colorsPicker = new Common.UI.HSBColorPicker({
|
||||
el: $('#id-hsb-colorpicker'),
|
||||
showCurrentColor: false
|
||||
});
|
||||
this.colorsPicker.on('changecolor', _.bind(this.onChangeColor, this));
|
||||
|
||||
this.colorNew = $('#field-new-color');
|
||||
this.colorSaved = $('#field-start-color');
|
||||
|
||||
this.spinR = new Common.UI.MetricSpinner({
|
||||
el: $('#extended-spin-r'),
|
||||
step: 1,
|
||||
width: 63,
|
||||
value: '0',
|
||||
defaultUnit : "",
|
||||
maxValue: 255,
|
||||
minValue: 0,
|
||||
tabindex: 1,
|
||||
maskExp: /[0-9]/,
|
||||
allowDecimal: false
|
||||
});
|
||||
|
||||
this.spinG = new Common.UI.MetricSpinner({
|
||||
el: $('#extended-spin-g'),
|
||||
step: 1,
|
||||
width: 63,
|
||||
value: '0',
|
||||
defaultUnit : "",
|
||||
maxValue: 255,
|
||||
minValue: 0,
|
||||
tabindex: 2,
|
||||
maskExp: /[0-9]/,
|
||||
allowDecimal: false
|
||||
});
|
||||
|
||||
this.spinB = new Common.UI.MetricSpinner({
|
||||
el: $('#extended-spin-b'),
|
||||
step: 1,
|
||||
width: 63,
|
||||
value: '0',
|
||||
defaultUnit : "",
|
||||
maxValue: 255,
|
||||
minValue: 0,
|
||||
tabindex: 3,
|
||||
maskExp: /[0-9]/,
|
||||
allowDecimal: false
|
||||
});
|
||||
|
||||
this.textColor = new Common.UI.MaskedField({
|
||||
el: $('#extended-text-color'),
|
||||
width: 55,
|
||||
maskExp: /[a-fA-F0-9]/,
|
||||
maxLength: 6
|
||||
});
|
||||
|
||||
this.spinR.on('change', _.bind(this.showColor, this, null, true)).on('changing', _.bind(this.onChangingRGB, this, 1));
|
||||
this.spinG.on('change', _.bind(this.showColor, this, null, true)).on('changing', _.bind(this.onChangingRGB, this, 2));
|
||||
this.spinB.on('change', _.bind(this.showColor, this, null, true)).on('changing', _.bind(this.onChangingRGB, this, 3));
|
||||
this.textColor.on('change', _.bind(this.onChangeMaskedField, this));
|
||||
this.textColor.on('changed', _.bind(this.onChangedMaskedField, this));
|
||||
this.textColor.$el.attr('tabindex', 4);
|
||||
this.spinR.$el.find('input').attr('maxlength', 3);
|
||||
this.spinG.$el.find('input').attr('maxlength', 3);
|
||||
this.spinB.$el.find('input').attr('maxlength', 3);
|
||||
|
||||
this.on('close', function() {
|
||||
me.trigger('onmodalresult', 0);
|
||||
});
|
||||
|
||||
function onBtnClick(event) {
|
||||
me.trigger('onmodalresult', parseInt(event.currentTarget.attributes['result'].value));
|
||||
me.close(true);
|
||||
}
|
||||
$(this)[0].getChild('.footer .dlg-btn').on('click', onBtnClick);
|
||||
|
||||
this.rendered = true;
|
||||
if (this.color!==undefined)
|
||||
this.setColor(this.color);
|
||||
return this;
|
||||
},
|
||||
|
||||
onChangeColor: function(o, color) {
|
||||
this.colorNew.css({'background-color' : color});
|
||||
|
||||
this.stopevents = true;
|
||||
var values = color.match(this.hexRe);
|
||||
this.spinR.setValue(parseInt(values[1], 16));
|
||||
this.spinG.setValue(parseInt(values[2], 16));
|
||||
this.spinB.setValue(parseInt(values[3], 16));
|
||||
this.textColor.setValue((values[1]+values[2]+values[3]).toUpperCase());
|
||||
this.stopevents = false;
|
||||
},
|
||||
|
||||
showColor: function (exlude, validate) {
|
||||
if (!this.stopevents) {
|
||||
var val = this.spinR.getNumberValue();
|
||||
var r = (val==null||val<0) ? 0 : (val>255 ? 255 : val);
|
||||
if (validate) this.spinR.setValue(r, true); r = r.toString(16);
|
||||
val = this.spinG.getNumberValue();
|
||||
var g = (val==null||val<0) ? 0 : (val>255 ? 255 : val);
|
||||
if (validate) this.spinG.setValue(g, true); g = g.toString(16);
|
||||
val = this.spinB.getNumberValue();
|
||||
var b = ((val==null||val<0) ? 0 : (val>255 ? 255 : val));
|
||||
if (validate) this.spinB.setValue(b, true); b = b.toString(16);
|
||||
var color = (r.length==1?'0'+r:r)+(g.length==1?'0'+g:g)+(b.length==1?'0'+b:b);
|
||||
this.colorsPicker.setColor('#'+color);
|
||||
if (exlude!='hex') this.textColor.setValue(color.toUpperCase());
|
||||
this.colorNew.css('background-color','#'+color);
|
||||
}
|
||||
},
|
||||
|
||||
onChangingRGB: function (type, cmp, newValue, e) {
|
||||
if (!this.stopevents) {
|
||||
var r, g, b, val;
|
||||
newValue = (_.isEmpty(newValue) ||isNaN(parseInt(newValue))) ? parseInt(cmp.getValue()) : parseInt(newValue);
|
||||
switch (type) {
|
||||
case 1:
|
||||
r = ((newValue==null || isNaN(newValue) || newValue<0) ? 0 : (newValue>255 ? 255 : newValue)).toString(16);
|
||||
val = this.spinG.getNumberValue();
|
||||
g = ((val==null||val<0) ? 0 : (val>255 ? 255 : val)).toString(16);
|
||||
val = this.spinB.getNumberValue();
|
||||
b = ((val==null||val<0) ? 0 : (val>255 ? 255 : val)).toString(16);
|
||||
break;
|
||||
case 2:
|
||||
val = this.spinR.getNumberValue();
|
||||
r = ((val==null||val<0) ? 0 : (val>255 ? 255 : val)).toString(16);
|
||||
g = ((newValue==null || isNaN(newValue) || newValue<0) ? 0 : (newValue>255 ? 255 : newValue)).toString(16);
|
||||
val = this.spinB.getNumberValue();
|
||||
b = ((val==null||val<0) ? 0 : (val>255 ? 255 : val)).toString(16);
|
||||
break;
|
||||
case 3:
|
||||
val = this.spinR.getNumberValue();
|
||||
r = ((val==null||val<0) ? 0 : (val>255 ? 255 : val)).toString(16);
|
||||
val = this.spinG.getNumberValue();
|
||||
g = ((val==null||val<0) ? 0 : (val>255 ? 255 : val)).toString(16);
|
||||
b = ((newValue==null || isNaN(newValue) || newValue<0) ? 0 : (newValue>255 ? 255 : newValue)).toString(16);
|
||||
break;
|
||||
}
|
||||
var color = (r.length==1?'0'+r:r)+(g.length==1?'0'+g:g)+(b.length==1?'0'+b:b);
|
||||
this.colorsPicker.setColor('#'+color);
|
||||
this.textColor.setValue(color.toUpperCase());
|
||||
this.colorNew.css('background-color','#'+color);
|
||||
}
|
||||
},
|
||||
|
||||
onChangeMaskedField: function(field, newValue) {
|
||||
newValue = ((/^[a-fA-F0-9]{0,6}$/.test(newValue))) ? newValue : '000000';
|
||||
newValue = '000000' + newValue;
|
||||
var colors = newValue.match(/([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})$/i);
|
||||
this.stopevents = true;
|
||||
this.spinR.setValue(parseInt(colors[1], 16));
|
||||
this.spinG.setValue(parseInt(colors[2], 16));
|
||||
this.spinB.setValue(parseInt(colors[3], 16));
|
||||
this.stopevents = false;
|
||||
if (this.rendered) this.showColor('hex');
|
||||
},
|
||||
|
||||
onChangedMaskedField: function(field, newValue) {
|
||||
var me = this;
|
||||
if (!/^[a-fA-F0-9]{0,6}$/.test(newValue) || _.isEmpty(newValue)) {
|
||||
field.setValue('000000');
|
||||
}
|
||||
if (this.rendered) this.showColor('', true);
|
||||
},
|
||||
|
||||
getColor: function() {
|
||||
var color = /#?([a-fA-F0-9]{6})/.exec(this.colorsPicker.getColor());
|
||||
return color ? color[1] : null;
|
||||
},
|
||||
|
||||
setColor: function(cl) {
|
||||
var me = this;
|
||||
|
||||
if (this.rendered!==true) {
|
||||
this.color = cl;
|
||||
return;
|
||||
}
|
||||
|
||||
var color = /#?([a-fA-F0-9]{6})/.test(cl) ? cl : 'ff0000';
|
||||
me.colorsPicker.setColor('#'+color);
|
||||
|
||||
function keepcolor() {
|
||||
if (cl == 'transparent') {
|
||||
me.colorSaved.addClass('color-transparent');
|
||||
} else {
|
||||
me.colorSaved.removeClass('color-transparent');
|
||||
me.colorSaved.css('background-color','#'+cl);
|
||||
}
|
||||
|
||||
me.colorNew.css('background-color','#'+color);
|
||||
}
|
||||
|
||||
keepcolor();
|
||||
|
||||
me.stopevents = true;
|
||||
var values = me.hexRe.exec(color);
|
||||
me.spinR.setValue(parseInt(values[1], 16));
|
||||
me.spinG.setValue(parseInt(values[2], 16));
|
||||
me.spinB.setValue(parseInt(values[3], 16));
|
||||
me.textColor.setValue((values[1]+values[2]+values[3]).toUpperCase());
|
||||
me.stopevents = false;
|
||||
},
|
||||
|
||||
show: function() {
|
||||
Common.UI.Window.prototype.show.apply(this, arguments);
|
||||
|
||||
var me = this;
|
||||
_.delay(function(){
|
||||
me.getChild('#extended-text-color').focus();
|
||||
},50);
|
||||
},
|
||||
|
||||
cancelButtonText: 'Cancel',
|
||||
addButtonText: 'Add',
|
||||
textNew: 'New',
|
||||
textCurrent: 'Current',
|
||||
textRGBErr: 'The entered value is incorrect.<br>Please enter a numeric value between 0 and 255.',
|
||||
textHexErr: 'The entered value is incorrect.<br>Please enter a value between 000000 and FFFFFF.'
|
||||
}, Common.UI.ExtendedColorDialog || {}));
|
||||
});
|
117
apps/common/main/lib/view/ExternalDiagramEditor.js
Normal file
117
apps/common/main/lib/view/ExternalDiagramEditor.js
Normal file
|
@ -0,0 +1,117 @@
|
|||
/**
|
||||
* ExternalDiagramEditor.js
|
||||
*
|
||||
* Created by Julia Radzhabova on 4/08/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
define([
|
||||
'common/main/lib/component/Window'
|
||||
], function () { 'use strict';
|
||||
|
||||
Common.Views.ExternalDiagramEditor = Common.UI.Window.extend(_.extend({
|
||||
initialize : function(options) {
|
||||
var _options = {};
|
||||
_.extend(_options, {
|
||||
title: this.textTitle,
|
||||
width: 910,
|
||||
height: (window.innerHeight-700)<0 ? window.innerHeight: 700,
|
||||
cls: 'advanced-settings-dlg',
|
||||
header: true,
|
||||
toolclose: 'hide',
|
||||
toolcallback: _.bind(this.onToolClose, this)
|
||||
}, options);
|
||||
|
||||
this.template = [
|
||||
'<div id="id-diagram-editor-container" class="box" style="height:' + (_options.height-85) + 'px;">',
|
||||
'<div id="id-diagram-editor-placeholder" style="width: 100%;height: 100%;"></div>',
|
||||
'</div>',
|
||||
'<div class="separator horizontal"/>',
|
||||
'<div class="footer" style="text-align: center;">',
|
||||
'<button id="id-btn-diagram-editor-apply" class="btn normal dlg-btn primary custom" result="ok" style="margin-right: 10px;">' + this.textSave + '</button>',
|
||||
'<button id="id-btn-diagram-editor-cancel" class="btn normal dlg-btn disabled" result="cancel">' + this.textClose + '</button>',
|
||||
'</div>'
|
||||
].join('');
|
||||
|
||||
_options.tpl = _.template(this.template, _options);
|
||||
|
||||
this.handler = _options.handler;
|
||||
this._chartData = null;
|
||||
this._isNewChart = true;
|
||||
Common.UI.Window.prototype.initialize.call(this, _options);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
Common.UI.Window.prototype.render.call(this);
|
||||
|
||||
this.btnSave = new Common.UI.Button({
|
||||
el: $('#id-btn-diagram-editor-apply'),
|
||||
disabled: true
|
||||
});
|
||||
this.btnCancel = new Common.UI.Button({
|
||||
el: $('#id-btn-diagram-editor-cancel'),
|
||||
disabled: true
|
||||
});
|
||||
|
||||
this.$window.find('.tool.close').addClass('disabled');
|
||||
this.$window.find('.dlg-btn').on('click', _.bind(this.onDlgBtnClick, this));
|
||||
},
|
||||
|
||||
setChartData: function(data) {
|
||||
this._chartData = data;
|
||||
if (this._isExternalDocReady)
|
||||
this.fireEvent('setchartdata', this);
|
||||
},
|
||||
|
||||
setEditMode: function(mode) {
|
||||
this._isNewChart = !mode;
|
||||
},
|
||||
|
||||
isEditMode: function() {
|
||||
return !this._isNewChart;
|
||||
},
|
||||
|
||||
setControlsDisabled: function(disable) {
|
||||
this.btnSave.setDisabled(disable);
|
||||
this.btnCancel.setDisabled(disable);
|
||||
(disable) ? this.$window.find('.tool.close').addClass('disabled') : this.$window.find('.tool.close').removeClass('disabled');
|
||||
},
|
||||
|
||||
onDlgBtnClick: function(event) {
|
||||
var state = event.currentTarget.attributes['result'].value;
|
||||
if ( this.handler && this.handler.call(this, state) )
|
||||
return;
|
||||
this.hide();
|
||||
},
|
||||
|
||||
onToolClose: function() {
|
||||
if ( this.handler && this.handler.call(this, 'cancel') )
|
||||
return;
|
||||
this.hide();
|
||||
},
|
||||
|
||||
setHeight: function(height) {
|
||||
if (height >= 0) {
|
||||
var min = parseInt(this.$window.css('min-height'));
|
||||
height < min && (height = min);
|
||||
this.$window.height(height);
|
||||
|
||||
var header_height = (this.initConfig.header) ? parseInt(this.$window.find('> .header').css('height')) : 0;
|
||||
|
||||
this.$window.find('> .body').css('height', height-header_height);
|
||||
this.$window.find('> .body > .box').css('height', height-85);
|
||||
|
||||
var top = ((parseInt(window.innerHeight) - parseInt(height)) / 2) * 0.9;
|
||||
var left = (parseInt(window.innerWidth) - parseInt(this.initConfig.width)) / 2;
|
||||
|
||||
this.$window.css('left',left);
|
||||
this.$window.css('top',top);
|
||||
}
|
||||
},
|
||||
|
||||
textSave: 'Save & Exit',
|
||||
textClose: 'Close',
|
||||
textTitle: 'Chart Editor'
|
||||
}, Common.Views.ExternalDiagramEditor || {}));
|
||||
});
|
117
apps/common/main/lib/view/ExternalMergeEditor.js
Normal file
117
apps/common/main/lib/view/ExternalMergeEditor.js
Normal file
|
@ -0,0 +1,117 @@
|
|||
/**
|
||||
* ExternalDiagramEditor.js
|
||||
*
|
||||
* Created by Julia Radzhabova on 4/08/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
define([
|
||||
'common/main/lib/component/Window'
|
||||
], function () { 'use strict';
|
||||
|
||||
Common.Views.ExternalMergeEditor = Common.UI.Window.extend(_.extend({
|
||||
initialize : function(options) {
|
||||
var _options = {};
|
||||
_.extend(_options, {
|
||||
title: this.textTitle,
|
||||
width: 910,
|
||||
height: (window.innerHeight-700)<0 ? window.innerHeight: 700,
|
||||
cls: 'advanced-settings-dlg',
|
||||
header: true,
|
||||
toolclose: 'hide',
|
||||
toolcallback: _.bind(this.onToolClose, this)
|
||||
}, options);
|
||||
|
||||
this.template = [
|
||||
'<div id="id-merge-editor-container" class="box" style="height:' + (_options.height-85) + 'px;">',
|
||||
'<div id="id-merge-editor-placeholder" style="width: 100%;height: 100%;"></div>',
|
||||
'</div>',
|
||||
'<div class="separator horizontal"/>',
|
||||
'<div class="footer" style="text-align: center;">',
|
||||
'<button id="id-btn-merge-editor-apply" class="btn normal dlg-btn primary custom" result="ok" style="margin-right: 10px;">' + this.textSave + '</button>',
|
||||
'<button id="id-btn-merge-editor-cancel" class="btn normal dlg-btn disabled" result="cancel">' + this.textClose + '</button>',
|
||||
'</div>'
|
||||
].join('');
|
||||
|
||||
_options.tpl = _.template(this.template, _options);
|
||||
|
||||
this.handler = _options.handler;
|
||||
this._mergeData = null;
|
||||
this._isNewMerge = true;
|
||||
Common.UI.Window.prototype.initialize.call(this, _options);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
Common.UI.Window.prototype.render.call(this);
|
||||
|
||||
this.btnSave = new Common.UI.Button({
|
||||
el: $('#id-btn-merge-editor-apply'),
|
||||
disabled: true
|
||||
});
|
||||
this.btnCancel = new Common.UI.Button({
|
||||
el: $('#id-btn-merge-editor-cancel'),
|
||||
disabled: true
|
||||
});
|
||||
|
||||
this.$window.find('.tool.close').addClass('disabled');
|
||||
this.$window.find('.dlg-btn').on('click', _.bind(this.onDlgBtnClick, this));
|
||||
},
|
||||
|
||||
setMergeData: function(data) {
|
||||
this._mergeData = data;
|
||||
if (this._isExternalDocReady)
|
||||
this.fireEvent('setmergedata', this);
|
||||
},
|
||||
|
||||
setEditMode: function(mode) {
|
||||
this._isNewMerge = !mode;
|
||||
},
|
||||
|
||||
isEditMode: function() {
|
||||
return !this._isNewMerge;
|
||||
},
|
||||
|
||||
setControlsDisabled: function(disable) {
|
||||
this.btnSave.setDisabled(disable);
|
||||
this.btnCancel.setDisabled(disable);
|
||||
(disable) ? this.$window.find('.tool.close').addClass('disabled') : this.$window.find('.tool.close').removeClass('disabled');
|
||||
},
|
||||
|
||||
onDlgBtnClick: function(event) {
|
||||
var state = event.currentTarget.attributes['result'].value;
|
||||
if ( this.handler && this.handler.call(this, state) )
|
||||
return;
|
||||
this.hide();
|
||||
},
|
||||
|
||||
onToolClose: function() {
|
||||
if ( this.handler && this.handler.call(this, 'cancel') )
|
||||
return;
|
||||
this.hide();
|
||||
},
|
||||
|
||||
setHeight: function(height) {
|
||||
if (height >= 0) {
|
||||
var min = parseInt(this.$window.css('min-height'));
|
||||
height < min && (height = min);
|
||||
this.$window.height(height);
|
||||
|
||||
var header_height = (this.initConfig.header) ? parseInt(this.$window.find('> .header').css('height')) : 0;
|
||||
|
||||
this.$window.find('> .body').css('height', height-header_height);
|
||||
this.$window.find('> .body > .box').css('height', height-85);
|
||||
|
||||
var top = ((parseInt(window.innerHeight) - parseInt(height)) / 2) * 0.9;
|
||||
var left = (parseInt(window.innerWidth) - parseInt(this.initConfig.width)) / 2;
|
||||
|
||||
this.$window.css('left',left);
|
||||
this.$window.css('top',top);
|
||||
}
|
||||
},
|
||||
|
||||
textSave: 'Save & Exit',
|
||||
textClose: 'Close',
|
||||
textTitle: 'Mail Merge Recipients'
|
||||
}, Common.Views.ExternalMergeEditor || {}));
|
||||
});
|
193
apps/common/main/lib/view/Header.js
Normal file
193
apps/common/main/lib/view/Header.js
Normal file
|
@ -0,0 +1,193 @@
|
|||
/**
|
||||
* Header.js
|
||||
*
|
||||
* Created by Alexander Yuzhin on 2/14/14
|
||||
* Copyright (c) 2014 Ascensio System SIA. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
Common.Views = Common.Views || {};
|
||||
|
||||
define([
|
||||
'backbone',
|
||||
'text!common/main/lib/template/Header.template',
|
||||
'core'
|
||||
], function (Backbone, headerTemplate) { 'use strict';
|
||||
|
||||
Common.Views.Header = Backbone.View.extend(_.extend({
|
||||
options : {
|
||||
branding: {},
|
||||
headerCaption: 'Default Caption',
|
||||
documentCaption: '',
|
||||
canBack: false
|
||||
},
|
||||
|
||||
el: '#header',
|
||||
|
||||
// Compile our stats template
|
||||
template: _.template(headerTemplate),
|
||||
|
||||
// Delegated events for creating new items, and clearing completed ones.
|
||||
events: {
|
||||
'click #header-logo': function(e) {
|
||||
var _url = !!this.branding && !!this.branding.logo && !!this.branding.logo.url ?
|
||||
this.branding.logo.url : 'http://www.onlyoffice.com';
|
||||
|
||||
var newDocumentPage = window.open(_url);
|
||||
newDocumentPage && newDocumentPage.focus();
|
||||
}
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
this.options = this.options ? _({}).extend(this.options, options) : options;
|
||||
|
||||
this.headerCaption = this.options.headerCaption;
|
||||
this.documentCaption = this.options.documentCaption;
|
||||
this.canBack = this.options.canBack;
|
||||
this.branding = this.options.customization;
|
||||
},
|
||||
|
||||
render: function () {
|
||||
$(this.el).html(this.template({
|
||||
headerCaption : this.headerCaption,
|
||||
documentCaption : Common.Utils.String.htmlEncode(this.documentCaption),
|
||||
canBack : this.canBack,
|
||||
textBack : this.textBack
|
||||
}));
|
||||
|
||||
var menuNewTab = new Common.UI.MenuItem({
|
||||
caption : this.openNewTabText
|
||||
}).on('click', function(item, e) {
|
||||
Common.NotificationCenter.trigger('goback', true);
|
||||
Common.component.Analytics.trackEvent('Back to Folder');
|
||||
});
|
||||
this.gotoDocsMenu = new Common.UI.Menu({
|
||||
style: 'min-width: 100px;',
|
||||
items: [
|
||||
menuNewTab
|
||||
]
|
||||
});
|
||||
},
|
||||
|
||||
setVisible: function(visible) {
|
||||
visible
|
||||
? this.show()
|
||||
: this.hide();
|
||||
},
|
||||
|
||||
setBranding: function(value) {
|
||||
var element;
|
||||
|
||||
this.branding = value;
|
||||
|
||||
if (value && value.logo && value.logo.image) {
|
||||
element = $('#header-logo');
|
||||
if (element) {
|
||||
element.html('<img src="'+value.logo.image+'" style="max-width:86px; max-height:20px; margin: 0 8px 0 15px;"/>');
|
||||
element.css({'background-image': 'none', width: 'auto'});
|
||||
}
|
||||
}
|
||||
|
||||
// if (value && value.backgroundColor) {
|
||||
// element = Ext.select(".common-header");
|
||||
// if (element) {
|
||||
// element.setStyle("background-image", "none");
|
||||
// element.setStyle("background-color", value.backgroundColor);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (value && value.textColor) {
|
||||
// var allSpanEl = element.select('span');
|
||||
// allSpanEl.each(function(el){
|
||||
// el.setStyle("color", value.textColor);
|
||||
// });
|
||||
// }
|
||||
},
|
||||
|
||||
setHeaderCaption: function(value) {
|
||||
this.headerCaption = value;
|
||||
|
||||
var caption = $('#header-caption > div');
|
||||
|
||||
if (caption)
|
||||
caption.html(value);
|
||||
|
||||
return value;
|
||||
},
|
||||
|
||||
getHeaderCaption: function() {
|
||||
return this.headerCaption;
|
||||
},
|
||||
|
||||
setDocumentCaption: function(value, applyOnly) {
|
||||
if (_.isUndefined(applyOnly)) {
|
||||
this.documentCaption = value;
|
||||
}
|
||||
|
||||
if (!value)
|
||||
value = '';
|
||||
|
||||
var dc = $('#header-documentcaption');
|
||||
if (dc)
|
||||
dc.html(Common.Utils.String.htmlEncode(value));
|
||||
|
||||
return value;
|
||||
},
|
||||
|
||||
getDocumentCaption: function() {
|
||||
return this.documentCaption;
|
||||
},
|
||||
|
||||
setCanBack: function(value) {
|
||||
this.canBack = value;
|
||||
var back = $('#header-back');
|
||||
|
||||
if (back) {
|
||||
back.off('mouseup');
|
||||
back.css('display', value ? 'table-cell' : 'none');
|
||||
|
||||
if (value)
|
||||
back.on('mouseup', _.bind(this.onBackClick, this));
|
||||
}
|
||||
},
|
||||
|
||||
getCanBack: function() {
|
||||
return this.canBack;
|
||||
},
|
||||
|
||||
onBackClick: function(e) {
|
||||
if (e.which == 3) { // right button click
|
||||
Common.UI.Menu.Manager.hideAll();
|
||||
var me = this,
|
||||
showPoint = [e.pageX, e.pageY],
|
||||
menuContainer = $(this.el).find(Common.Utils.String.format('#menu-container-{0}', this.gotoDocsMenu.id));
|
||||
if (!this.gotoDocsMenu.rendered) {
|
||||
// Prepare menu container
|
||||
if (menuContainer.length < 1) {
|
||||
menuContainer = $(Common.Utils.String.format('<div id="menu-container-{0}" style="position: absolute; z-index: 10000;"><div class="dropdown-toggle" data-toggle="dropdown"></div></div>', this.gotoDocsMenu.id));
|
||||
$(this.el).append(menuContainer);
|
||||
}
|
||||
|
||||
this.gotoDocsMenu.render(menuContainer);
|
||||
this.gotoDocsMenu.cmpEl.attr({tabindex: "-1"});
|
||||
}
|
||||
_.delay(function(){
|
||||
menuContainer.css({
|
||||
left: showPoint[0] - me.gotoDocsMenu.cmpEl.width(),
|
||||
top : showPoint[1] + 3
|
||||
});
|
||||
me.gotoDocsMenu.show();
|
||||
},10);
|
||||
} else {
|
||||
Common.NotificationCenter.trigger('goback', e.which == 2);
|
||||
Common.component.Analytics.trackEvent('Back to Folder');
|
||||
}
|
||||
},
|
||||
|
||||
textBack: 'Go to Documents',
|
||||
openNewTabText: 'Open in New Tab'
|
||||
}, Common.Views.Header || {}))
|
||||
});
|
72
apps/common/main/lib/view/History.js
Normal file
72
apps/common/main/lib/view/History.js
Normal file
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
* User: Julia.Radzhabova
|
||||
* Date: 06.03.15
|
||||
* Time: 11:46
|
||||
*/
|
||||
|
||||
if (Common === undefined)
|
||||
var Common = {};
|
||||
|
||||
Common.Views = Common.Views || {};
|
||||
|
||||
define([
|
||||
'common/main/lib/util/utils',
|
||||
'common/main/lib/component/BaseView',
|
||||
'common/main/lib/component/Layout'
|
||||
], function (template) {
|
||||
'use strict';
|
||||
|
||||
Common.Views.History = Common.UI.BaseView.extend(_.extend({
|
||||
el: '#left-panel-history',
|
||||
|
||||
storeHistory: undefined,
|
||||
template: _.template([
|
||||
'<div id="history-box" class="layout-ct vbox">',
|
||||
'<div id="history-header" class="">',
|
||||
'<div id="history-btn-back"><%=scope.textHistoryHeader%></div>',
|
||||
'</div>',
|
||||
'<div id="history-list" class="">',
|
||||
'</div>',
|
||||
'</div>'
|
||||
].join('')),
|
||||
|
||||
initialize: function(options) {
|
||||
_.extend(this, options);
|
||||
Common.UI.BaseView.prototype.initialize.call(this, arguments);
|
||||
},
|
||||
|
||||
render: function(el) {
|
||||
el = el || this.el;
|
||||
$(el).html(this.template({scope: this})).width( (parseInt(Common.localStorage.getItem('de-mainmenu-width')) || MENU_SCALE_PART) - SCALE_MIN);
|
||||
|
||||
this.viewHistoryList = new Common.UI.DataView({
|
||||
el: $('#history-list'),
|
||||
store: this.storeHistory,
|
||||
enableKeyEvents: false,
|
||||
itemTemplate: _.template([
|
||||
'<div id="<%= id %>" class="history-item-wrap" style="display: block;">',
|
||||
'<div class="user-date"><%= created %></div>',
|
||||
'<% if (markedAsVersion) { %>',
|
||||
'<div class="user-version">ver.<%=version%></div>',
|
||||
'<% } %>',
|
||||
'<div class="user-name">',
|
||||
'<div class="color" style="display: inline-block; background-color:' + '<%=usercolor%>;' + '" >',
|
||||
'</div><%= Common.Utils.String.htmlEncode(username) %>',
|
||||
'</div>',
|
||||
'</div>'
|
||||
].join(''))
|
||||
});
|
||||
|
||||
this.btnBackToDocument = new Common.UI.Button({
|
||||
el: $('#history-btn-back'),
|
||||
enableToggle: false
|
||||
});
|
||||
|
||||
this.trigger('render:after', this);
|
||||
return this;
|
||||
},
|
||||
|
||||
textHistoryHeader: 'Back to Document'
|
||||
|
||||
}, Common.Views.History || {}))
|
||||
});
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue