This commit is contained in:
Alexander Trofimov
2015-06-25 11:27:08 +03:00
parent dbf21ee32f
commit a10605c91f
174 changed files with 24121 additions and 8908 deletions

View File

@@ -0,0 +1,50 @@
/*
* (c) Copyright Ascensio System SIA 2010-2015
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia,
* EU, LV-1021.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
if (Common === undefined) {
var Common = {};
}
Common.Collections = Common.Collections || {};
define(["underscore", "backbone", "common/main/lib/model/HistoryVersion"], function (_, Backbone) {
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
});
}
});
});

View File

@@ -46,4 +46,12 @@
});
}
});
Common.Collections.HistoryUsers = Backbone.Collection.extend({
model: Common.Models.User,
findUser: function (id) {
return this.find(function (model) {
return model.get("id") == id;
});
}
});
});

View File

@@ -41,16 +41,22 @@ define(["common/main/lib/component/ComboBox"], function () {
thumbCanvas = document.createElement("canvas"),
thumbContext = thumbCanvas.getContext("2d"),
thumbPath = "../../../sdk/Common/Images/fonts_thumbnail.png",
thumbPath2x = "../../../sdk/Common/Images/fonts_thumbnail@2x.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"></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="display: block;">', '<img src="<%= scope.getImageUri(item) %>" width="<%= scope.getImageWidth() %>" height="<%= scope.getImageHeight() %>" style="vertical-align: middle;margin: 0 0 0 -10px;">', "</a>", "</li>", "<% }); %>", "</ul>", "</div>"].join("")),
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"></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));
},
@@ -64,20 +70,86 @@ define(["common/main/lib/component/ComboBox"], function () {
this._input.on("keyup", _.bind(this.onInputKeyUp, this));
this._input.on("keydown", _.bind(this.onInputKeyDown, this));
this.scroller.update({
alwaysVisibleY: true
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) {
if (this.lastValue !== this._input.val()) {
this._input.trigger("change");
}
} else {
$(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) {
this.selectCandidate();
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) {
document.selection.createRange().text = text;
} else {
if (input.selectionStart || input.selectionStart == "0") {
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.closeMenu();
this.onAfterHideMenu(e);
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()) {
@@ -87,10 +159,11 @@ define(["common/main/lib/component/ComboBox"], function () {
_.delay(function () {
var selected = me.cmpEl.find("ul li.selected a");
if (selected.length <= 0) {
selected = me.cmpEl.find("ul li:first a");
selected = me.cmpEl.find("ul li:not(.divider):first a");
}
me._skipInputChange = true;
selected.focus();
me.updateVisibleFontsTiles();
},
10);
} else {
@@ -120,6 +193,7 @@ define(["common/main/lib/component/ComboBox"], function () {
return;
}
record[this.valueField] = val;
record[this.displayField] = val;
this.trigger("changed:before", this, record, e);
if (e.isDefaultPrevented()) {
return;
@@ -129,6 +203,12 @@ define(["common/main/lib/component/ComboBox"], function () {
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();
}
this.trigger("changed:after", this, record, e);
@@ -153,6 +233,9 @@ define(["common/main/lib/component/ComboBox"], function () {
getImageHeight: function () {
return iconHeight;
},
getListItemHeight: function () {
return listItemHeight;
},
loadSprite: function (callback) {
if (callback) {
this.spriteThumbs = new Image();
@@ -200,28 +283,11 @@ define(["common/main/lib/component/ComboBox"], function () {
var record = this.store.findWhere({
id: el.attr("id")
});
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[0]);
}
var new_record = record.clone();
new_record.set({
"type": FONT_TYPE_RECENT,
"id": Common.UI.getId(),
cloneid: record.id
});
this.store.add(new_record);
}
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="display: block;">', '<img src="<%= scope.getImageUri(item) %>" width="<%= scope.getImageWidth() %>" height="<%= scope.getImageHeight() %>" style="vertical-align: middle;margin: 0 0 0 -10px;">', "</a>", "</li>"].join(""), {
$(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
}));
@@ -229,6 +295,17 @@ define(["common/main/lib/component/ComboBox"], function () {
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) {
@@ -240,20 +317,52 @@ define(["common/main/lib/component/ComboBox"], function () {
} else {
Common.UI.ComboBox.prototype.onAfterShowMenu.apply(this, arguments);
}
this.updateVisibleFontsTiles(null, 0);
},
selectCandidate: function () {
onAfterHideMenu: function (e) {
if (this.lastValue !== this._input.val()) {
this._input.val(this.lastValue);
}
this.flushVisibleFontsTiles();
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 (font[me.displayField].toLowerCase().indexOf(inputVal) == 0);
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) {
@@ -268,6 +377,63 @@ define(["common/main/lib/component/ComboBox"], function () {
}
}
}
},
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;
}
}
}
};
})());

View File

@@ -51,13 +51,13 @@
setMode: function (mode) {
this.mode = mode;
if (this.api) {
if (this.mode.canCoAuthoring) {
if (this.mode.canCoAuthoring && 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.canCoAuthoring) {
if (this.mode.canCoAuthoring && this.mode.canChat) {
this.api.asc_coAuthoringChatGetMessages();
}
}

View File

@@ -616,6 +616,9 @@ define(["core", "common/main/lib/model/Comment", "common/main/lib/collection/Com
if (hint && this.isSelectedComment && (0 === _.difference(this.uids, uids).length)) {
return;
}
if (this.mode && !this.mode.canComments) {
hint = true;
}
if (this.getPopover()) {
this.clearDummyComment();
if (this.isSelectedComment && (0 === _.difference(this.uids, uids).length)) {
@@ -817,7 +820,7 @@ define(["core", "common/main/lib/model/Comment", "common/main/lib/collection/Com
this.view.update();
},
disableHint: function (comment) {
if (comment) {
if (comment && this.mode.canComments) {
comment.set("hint", false);
this.isSelectedComment = true;
}

View File

@@ -0,0 +1,119 @@
/*
* (c) Copyright Ascensio System SIA 2010-2015
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia,
* EU, LV-1021.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
define(["core", "common/main/lib/collection/HistoryVersions", "common/main/lib/view/History"], function () {
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;
},
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");
this.currentChangeId = record.get("changeid");
this.currentArrColors = record.get("arrColors");
this.currentDocId = record.get("docId");
this.currentDocIdPrev = record.get("docIdPrev");
if (_.isEmpty(url)) {
_.delay(function () {
Common.Gateway.requestHistoryData(rev);
},
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);
}
},
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);
if (revisions && revisions.length > 0) {
for (var i = 0; i < revisions.length; i++) {
rev = revisions[i];
rev.set("url", opts.data.url);
rev.set("urlDiff", opts.data.urlDiff);
}
}
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);
}
}
},
onClickBackToDocument: function () {
Common.Gateway.requestHistoryClose();
},
notcriticalErrorTitle: "Warning"
},
Common.Controllers.History || {}));
});

View File

@@ -0,0 +1,57 @@
/*
* (c) Copyright Ascensio System SIA 2010-2015
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia,
* EU, LV-1021.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
if (Common === undefined) {
var Common = {};
}
Common.Models = Common.Models || {};
define(["underscore", "backbone", "common/main/lib/component/BaseView"], function (_, Backbone) {
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(),
url: "",
urlDiff: "",
docId: "",
docIdPrev: "",
arrColors: [],
markedAsVersion: false
};
}
});
});

View File

@@ -36,6 +36,7 @@
id: undefined,
username: "Guest",
color: "#fff",
colorval: null,
online: false
}
});

View File

@@ -211,6 +211,9 @@
scrollbarXLeft = containerWidth - scrollbarXWidth;
}
updateScrollbarCss();
if (settings.onChange) {
settings.onChange(this);
}
};
var bindMouseScrollXHandler = function () {
var currentLeft, currentPageX;

View File

@@ -490,6 +490,27 @@ Common.Utils.showBrowserRestriction = function () {
$("#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();
}
}
}
}
}
};
String.prototype.strongMatch = function (regExp) {
if (regExp && regExp instanceof RegExp) {
var arr = this.toString().match(regExp);

View File

@@ -68,20 +68,21 @@
return this;
},
setLicInfo: function (data) {
if (data && typeof(data) == "object") {
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 = data.customer;
var value = customer.name;
value && value.length ? this.lblCompanyName.text(value) : this.lblCompanyName.parents("tr").addClass("hidden");
value = data.customerAddr;
value = customer.address;
value && value.length ? this.lblCompanyAddress.text(value) : this.lblCompanyAddress.parents("tr").addClass("hidden");
(value = data.customerMail) && value.length ? this.lblCompanyMail.attr("href", "mailto:" + value).text(value) : this.lblCompanyMail.parents("tr").addClass("hidden");
(value = data.customerWww) && value.length ? this.lblCompanyUrl.attr("href", "http://" + value).text(value) : this.lblCompanyUrl.parents("tr").addClass("hidden");
(value = data.customerInfo) && value.length ? this.lblCompanyLic.text(value) : this.lblCompanyLic.parents("tr").addClass("hidden");
(value = data.customerLogo) && value.length ? this.divCompanyLogo.html('<img src="' + value + '" />') : this.divCompanyLogo.parents("tr").addClass("hidden");
(value = customer.mail) && value.length ? this.lblCompanyMail.attr("href", "mailto:" + value).text(value) : this.lblCompanyMail.parents("tr").addClass("hidden");
(value = customer.www) && value.length ? this.lblCompanyUrl.attr("href", "http://" + value).text(value) : 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 + '" />') : this.divCompanyLogo.parents("tr").addClass("hidden");
} else {
this.cntLicenseeInfo.addClass("hidden");
this.cntLicensorInfo.addClass("margin-bottom");

View File

@@ -54,7 +54,7 @@ define(["backbone", "text!common/main/lib/template/Header.template", "core"], fu
this.headerCaption = this.options.headerCaption;
this.documentCaption = this.options.documentCaption;
this.canBack = this.options.canBack;
this.branding = this.options.branding;
this.branding = this.options.customization;
},
render: function () {
$(this.el).html(this.template({

View File

@@ -0,0 +1,66 @@
/*
* (c) Copyright Ascensio System SIA 2010-2015
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia,
* EU, LV-1021.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
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) {
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="">', '<label id="history-btn-back" class="btn"><%=scope.textHistoryHeader%></label>', "</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(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 || {}));
});

View File

@@ -43,7 +43,6 @@
display: inline-block;
float: left;
margin-left: -18px;
background-image: ~"url('@{common-image-path}/@{common-controls}')";
background-repeat: no-repeat;
background-position: @menu-check-offset-x @menu-check-offset-y;
.background-ximage('@{common-image-path}/@{common-controls}', '@{common-image-path}/@{common-controls2x}', 100px);

View File

@@ -0,0 +1,129 @@
#history-box {
position: relative;
width: 100%;
height: 100%;
border-collapse: collapse;
background-color: #f4f4f4;
border-right: 1px solid #cbcbcb;
.layout-resizer {
border-bottom:none !important;
border-top:none !important;
&.move {
border-top: 1px solid @gray-dark !important;
border-bottom: 1px solid @gray-dark !important;
opacity: 0.4;
}
}
#history-header {
position: absolute;
height: 45px;
text-align: center;
left: 0;
top: 0;
right: 0;
overflow: hidden;
border-bottom: 1px solid @gray-dark;
label {
color: @black;
font-size: 12px;
font-family: arial;
line-height: normal;
border-bottom: 1px dotted @black;
padding-top: 12px;
outline: none;
height: 29px;
cursor: pointer;
}
}
#history-list {
height: 100%;
overflow: hidden;
padding-top: 45px;
.dataview {
& > div:not(.ps-scrollbar-x-rail):not(.ps-scrollbar-y-rail) {
display: block;
border: none;
width: 100%;
.box-shadow(none);
margin: 0;
font-size: 12px;
&:hover:not(.selected),
&.over {
background-color: #e5e5e5;
.user-version {
color: #fff;
background-color: #ababab;
}
}
&.selected {
background-color: @primary;
.user-date {
color: #fff;
}
.user-name {
color: #fff;
}
}
}
.history-item-wrap {
padding: 10px 2px 15px 20px;
.user-date {
display: inline-block;
color: @gray-deep;
font-size: 12px;
font-weight: bold;
min-width: 135px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.user-version {
display: inline-block;
width: 36px;
height: 18px;
color: @primary;
font-size: 10px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
background-color: #e6e6e6;
text-align: center;
padding: 1px 0;
border-radius: 2px;
}
.user-name {
width: 100%;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
color: @gray-deep;
font-size: 12px;
cursor: pointer;
}
.color {
width: 12px;
height: 12px;
border: 1px solid @gray-dark;
margin: 0 5px 3px 0;
vertical-align: middle;
}
}
}
}
}

View File

@@ -21,11 +21,6 @@
width: 9px;
background-color: @gray-light;
// background-image: ~"url('@{common-image-path}/controls/Scroll_center.png')";
// background-image: ~"-webkit-image-set(url('@{common-image-path}/controls/Scroll_center.png') 1x, url('@{common-image-path}/controls/Scroll_center@2x.png') 2x)";
/*background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAANCAYAAACZ3F9/AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RURFNzkyNkE0RTFGMTFFNDkyRUNFRUEwNkNERTY4N0QiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RURFNzkyNkI0RTFGMTFFNDkyRUNFRUEwNkNERTY4N0QiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFREU3OTI2ODRFMUYxMUU0OTJFQ0VFQTA2Q0RFNjg3RCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFREU3OTI2OTRFMUYxMUU0OTJFQ0VFQTA2Q0RFNjg3RCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PtLoUWcAAAA2SURBVHjaYvz//z8DCFy4cAHCgABGEGFoaAjmfPz4EUOOAaQRppkUwDhq46iNdLORGUQABBgA2y5vq3CS7yUAAAAASUVORK5CYII=');*/
/*background-image: -webkit-image-set(url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAANCAYAAACZ3F9/AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RURFNzkyNkE0RTFGMTFFNDkyRUNFRUEwNkNERTY4N0QiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RURFNzkyNkI0RTFGMTFFNDkyRUNFRUEwNkNERTY4N0QiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFREU3OTI2ODRFMUYxMUU0OTJFQ0VFQTA2Q0RFNjg3RCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFREU3OTI2OTRFMUYxMUU0OTJFQ0VFQTA2Q0RFNjg3RCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PtLoUWcAAAA2SURBVHjaYvz//z8DCFy4cAHCgABGEGFoaAjmfPz4EUOOAaQRppkUwDhq46iNdLORGUQABBgA2y5vq3CS7yUAAAAASUVORK5CYII=') 1x,*/
/*url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAaCAYAAACkVDyJAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RDlFQjdBRjE0RTFGMTFFNDk3Q0ZDOUVBNkQwRkFGNTYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RDlFQjdBRjI0RTFGMTFFNDk3Q0ZDOUVBNkQwRkFGNTYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpEOUVCN0FFRjRFMUYxMUU0OTdDRkM5RUE2RDBGQUY1NiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpEOUVCN0FGMDRFMUYxMUU0OTdDRkM5RUE2RDBGQUY1NiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PupPpWQAAABYSURBVHjaYvz//z8DMrhw4QKqABQYGBgwMuABnz59wqqPj48PRR8TA50BCxYxRjLNIkrfoPDhfzJ9QJS+0TgcjcPROByNw9E4HI3D0TgcjcPROCQDAAQYAPFLF1XTzO2YAAAAAElFTkSuQmCC') 2x);*/
.background-ximage('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAANCAYAAACZ3F9/AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RURFNzkyNkE0RTFGMTFFNDkyRUNFRUEwNkNERTY4N0QiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RURFNzkyNkI0RTFGMTFFNDkyRUNFRUEwNkNERTY4N0QiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFREU3OTI2ODRFMUYxMUU0OTJFQ0VFQTA2Q0RFNjg3RCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFREU3OTI2OTRFMUYxMUU0OTJFQ0VFQTA2Q0RFNjg3RCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PtLoUWcAAAA2SURBVHjaYvz//z8DCFy4cAHCgABGEGFoaAjmfPz4EUOOAaQRppkUwDhq46iNdLORGUQABBgA2y5vq3CS7yUAAAAASUVORK5CYII=',
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAaCAYAAACkVDyJAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RDlFQjdBRjE0RTFGMTFFNDk3Q0ZDOUVBNkQwRkFGNTYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RDlFQjdBRjI0RTFGMTFFNDk3Q0ZDOUVBNkQwRkFGNTYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpEOUVCN0FFRjRFMUYxMUU0OTdDRkM5RUE2RDBGQUY1NiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpEOUVCN0FGMDRFMUYxMUU0OTdDRkM5RUE2RDBGQUY1NiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PupPpWQAAABYSURBVHjaYvz//z8DMrhw4QKqABQYGBgwMuABnz59wqqPj48PRR8TA50BCxYxRjLNIkrfoPDhfzJ9QJS+0TgcjcPROByNw9E4HI3D0TgcjcPROCQDAAQYAPFLF1XTzO2YAAAAAElFTkSuQmCC', 14px);