diff --git a/static/css/global.css b/static/css/global.css
index 64360ae1..b80fe0f7 100644
--- a/static/css/global.css
+++ b/static/css/global.css
@@ -802,3 +802,24 @@ div.screenshotviewer-caption {
.options-menu-widget.open {
color:#fff;
}
+
+.click-to-copy {
+ cursor: pointer;
+}
+
+.fade-out {
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity 1s;
+ transition-timing-function: ease-in;
+}
+
+.hidden-element {
+ height: 0;
+ left: 0;
+ opacity: 0;
+ padding: 0;
+ pointer-events: none;
+ position: fixed;
+ top: 1px;
+}
diff --git a/static/js/basic.js b/static/js/basic.js
index 4163d42a..05d30daf 100644
--- a/static/js/basic.js
+++ b/static/js/basic.js
@@ -2077,6 +2077,12 @@ $WH.Tooltip = {
$WH.Tooltip.move(x, y, 0, 0, paddX, paddY);
},
+ showFadingTooltipAtCursor: function (text, ev, className, noWrap, maxWidth) {
+ text = $WH.Tooltip.prepareTooltipHtml(text, noWrap, maxWidth, ev);
+ $WH.Tooltip.showAtCursor(ev, text, undefined, undefined, className);
+ requestAnimationFrame(function () { $WH.Tooltip.tooltip.classList.add('fade-out'); });
+ },
+
cursorUpdate: function(e, x, y) { // Used along with showAtCursor
if ($WH.Tooltip.disabled || !$WH.Tooltip.tooltip) {
return;
@@ -2126,12 +2132,42 @@ $WH.Tooltip = {
$WH.Tooltip.iconVisible = icon ? 1 : 0;
},
- simple: function(element, text, className, fixed) {
+ prepareTooltipHtml: function (textOrFn, noWrap, maxWidth, ev) {
+ textOrFn = typeof textOrFn === "function" ? textOrFn.call(ev.target, ev) : textOrFn;
+ if (typeof textOrFn === "string") {
+ if (noWrap === undefined && textOrFn.length < 30)
+ noWrap = true;
+
+ let attr = [];
+ if (noWrap)
+ attr.push(' class="no-wrap"');
+
+ if (maxWidth && !isNaN(maxWidth))
+ attr.push(' style="max-width:' + maxWidth + 'px"');
+
+ if (attr.length)
+ textOrFn = "
" + textOrFn + "
";
+ }
+
+ return textOrFn;
+ },
+
+ simple: function(element, textOrFn, className, fixed) {
if (fixed)
- element.onmouseover = function(x) { $WH.Tooltip.show(element, text, false, false, className) };
+ {
+ element.onmouseover = function(ev)
+ {
+ let text = $WH.Tooltip.prepareTooltipHtml(textOrFn, null, null, ev);
+ $WH.Tooltip.show(element, text, false, false, className);
+ };
+ }
else
{
- element.onmouseover = function(x) { $WH.Tooltip.showAtCursor(x, text, false, false, className) };
+ element.onmouseover = function(ev)
+ {
+ let text = $WH.Tooltip.prepareTooltipHtml(textOrFn, null, null, ev);
+ $WH.Tooltip.showAtCursor(ev, text, false, false, className);
+ };
element.onmousemove = $WH.Tooltip.cursorUpdate;
}
diff --git a/static/js/global.js b/static/js/global.js
index 574eaa0b..cead8fe9 100644
--- a/static/js/global.js
+++ b/static/js/global.js
@@ -5346,32 +5346,23 @@ function Listview(opt) {
id: 'debug-id',
compute: function(data, td) {
if (data.id) {
- $WH.ae(td, $WH.ct(data.id));
+ let pre = $WH.ce('pre', { style: { display: 'inline', margin: '0' }}, $WH.ct(data.id));
+ $WH.clickToCopy(pre);
+ $WH.ae(td, pre);
}
},
getVisibleText: function(data) {
- if (data.id) {
- return data.id;
- }
- else {
- return '';
- }
+ return data.id || '';
},
getValue: function(data) {
- if (data.id) {
- return data.id;
- }
- else {
- return 0;
- }
+ return data.id || 0;
},
sortFunc: function(a, b, col) {
- if (a.id == null) {
+ if (a.id == null)
return -1;
- }
- else if (b.id == null) {
+
+ if (b.id == null)
return 1;
- }
return $WH.strcmp(a.id, b.id);
},
@@ -5379,19 +5370,17 @@ function Listview(opt) {
width: '5%',
tooltip: 'ID'
});
+
this.visibility.splice(0, 0, -1);
- for (var i = 0, len = this.visibility.length; i < len; ++i) {
+ for (var i = 0, len = this.visibility.length; i < len; ++i)
this.visibility[i] = this.visibility[i] + 1;
- }
for (var i = 0, len = this.sort.length; i < len; ++i) {
- if (this.sort[i] < 0) {
+ if (this.sort[i] < 0)
this.sort[i] = this.sort[i] - 1;
- }
- else {
+ else
this.sort[i] = this.sort[i] + 1;
- }
}
}
@@ -22637,6 +22626,114 @@ function CreateAjaxLoader() {
}
+$WH.clickToCopy = function (el, textOrFn, opt) {
+ opt = opt || {};
+
+ $WH.aE(el, 'click', $WH.clickToCopy.copy.bind(null, el, textOrFn, opt));
+ // $WH.preventSelectStart(el);
+
+ el.classList.add('click-to-copy');
+
+ if (opt.modifyTooltip) {
+ el._fixTooltip = function (e) {
+ return e + '
' + $WH.ce('span', { className: 'q2', innerHTML: $WH.clickToCopy.getTooltip(false, opt) }).outerHTML;
+ };
+
+ opt.overrideOtherTooltips = false;
+ }
+
+ // Aowow - fitted to old system
+ // $WH.Tooltips.attach(
+ $WH.Tooltip.simple(
+ el,
+ $WH.clickToCopy.getTooltip.bind(null, false, opt),
+ undefined,
+ // {
+ /* byCursor: */ !opt.attachToElement,
+ // stopPropagation: opt.overrideOtherTooltips
+ // }
+ );
+};
+$WH.clickToCopy.copy = function (el, textOrFn, opt, ev) {
+ ev.preventDefault();
+ ev.stopPropagation();
+
+ if (textOrFn === undefined) {
+ if (!el.childNodes[0] || !el.childNodes[0].textContent) {
+ let text = 'Could not find text to copy.';
+ // $WH.error(text, el);
+
+ if (opt.attachToElement)
+ $WH.Tooltip.show(el, text, 'q10');
+ else
+ $WH.Tooltip.showAtCursor(ev, text, 'q10');
+
+ return;
+ }
+
+ textOrFn = el.childNodes[0].textContent;
+ }
+ else if (typeof textOrFn === 'function')
+ textOrFn = textOrFn();
+
+ $WH.copyToClipboard(textOrFn);
+
+ if (opt.attachToElement)
+ $WH.Tooltip.show(el, $WH.clickToCopy.getTooltip(true, opt));
+ else
+ $WH.Tooltip.showAtCursor(ev, $WH.clickToCopy.getTooltip(true, opt));
+};
+$WH.clickToCopy.getTooltip = function (clicked, opt) {
+ let txt = '';
+ let attr = undefined;
+ if (clicked) {
+ txt = ' ' + LANG.copied;
+ attr = { className: 'q1 icon-tick' };
+ }
+ else
+ txt = LANG.clickToCopy;
+
+ let tt = $WH.ce('div', attr, $WH.ct(txt));
+
+ if (opt.prefix) {
+ tt.style.marginTop = '10px';
+ let prefix = typeof opt.prefix === 'function' ? opt.prefix() : opt.prefix;
+ return prefix + tt.outerHTML;
+ }
+
+ return tt.outerHTML;
+};
+$WH.copyToClipboard = function (text, t) {
+ if (!$WH.copyToClipboard.hiddenInput) {
+ $WH.copyToClipboard.hiddenInput = $WH.ce('textarea', { className: 'hidden-element' });
+ $WH.ae(document.body, $WH.copyToClipboard.hiddenInput);
+ }
+
+ $WH.copyToClipboard.hiddenInput.value = text;
+
+ let isEmpty = $WH.copyToClipboard.hiddenInput.value === '';
+ if (isEmpty)
+ $WH.copyToClipboard.hiddenInput.value = LANG.nothingToCopy_tip;
+
+ $WH.copyToClipboard.hiddenInput.focus();
+ $WH.copyToClipboard.hiddenInput.select();
+
+ if (!document.execCommand('copy'))
+ prompt(null, text);
+
+ $WH.copyToClipboard.hiddenInput.blur();
+
+ if (t) {
+ if (isEmpty)
+ $WH.Tooltips.showFadingTooltipAtCursor(LANG.nothingToCopy_tip, t, 'q10');
+ else {
+ let e = $WH.ce('span', { className: 'q1 icon-tick' }, $WH.ct(' ' + LANG.copied));
+ $WH.Tooltips.showFadingTooltipAtCursor(e.outerHTML, t)
+ }
+ }
+};
+
+
/*
Global utility functions related to arrays, format validation, regular expressions, and strings
*/
diff --git a/static/js/locale_dede.js b/static/js/locale_dede.js
index 83692e30..1564acb3 100644
--- a/static/js/locale_dede.js
+++ b/static/js/locale_dede.js
@@ -4896,6 +4896,12 @@ var LANG = {
/* AoWoW: start custom */
+ // click to copy fn
+ copied: 'Kopiert',
+ clickToCopy: 'Klicke zum Kopieren',
+ nothingToCopy_tip: 'Nichts zu kopieren!',
+
+ // TC conditions display
tab_conditions: 'Konditionen',
tab_condition_for: 'Kondition für',
cnd_either: 'Entweder',
diff --git a/static/js/locale_enus.js b/static/js/locale_enus.js
index eda14775..012bb207 100644
--- a/static/js/locale_enus.js
+++ b/static/js/locale_enus.js
@@ -4944,6 +4944,12 @@ var LANG = {
/* AoWoW: start custom */
+ // click to copy fn
+ copied: 'Copied',
+ clickToCopy: 'Click to Copy',
+ nothingToCopy_tip: 'Nothing to copy!',
+
+ // TC conditions display
tab_conditions: 'Conditions',
tab_condition_for: 'Condition for',
cnd_either: 'Either',
diff --git a/static/js/locale_eses.js b/static/js/locale_eses.js
index da7e06bc..d9f78932 100644
--- a/static/js/locale_eses.js
+++ b/static/js/locale_eses.js
@@ -4898,6 +4898,12 @@ var LANG = {
/* AoWoW: start custom */
+ // click to copy fn
+ copied: 'Copiado',
+ clickToCopy: 'Click para copiar',
+ nothingToCopy_tip: '[Nothing to copy!]',
+
+ // TC conditions display
tab_conditions: 'Condiciones',
tab_condition_for: 'Condición para',
cnd_either: 'Cualquiera',
diff --git a/static/js/locale_frfr.js b/static/js/locale_frfr.js
index fa562af5..a27b4eae 100644
--- a/static/js/locale_frfr.js
+++ b/static/js/locale_frfr.js
@@ -4898,6 +4898,12 @@ var LANG = {
/* AoWoW: start custom */
+ // click to copy fn
+ copied: 'Copié',
+ clickToCopy: 'Cliquer pour Copier',
+ nothingToCopy_tip: 'Rien à copier !',
+
+ // TC conditions display
tab_conditions: '[Conditions]',
tab_condition_for: '[Condition for]',
cnd_either: '[Either]',
diff --git a/static/js/locale_ruru.js b/static/js/locale_ruru.js
index b2aea8e5..6825f61d 100644
--- a/static/js/locale_ruru.js
+++ b/static/js/locale_ruru.js
@@ -4900,6 +4900,12 @@ var LANG = {
/* AoWoW: start custom */
+ // click to copy fn
+ copied: 'Скопировано',
+ clickToCopy: 'Нажмите, чтобы скопировать',
+ nothingToCopy_tip: 'Нет данных для копирования!',
+
+ // TC conditions display
tab_conditions: '[Conditions]',
tab_condition_for: '[Condition for]',
cnd_either: '[Either]',
diff --git a/static/js/locale_zhcn.js b/static/js/locale_zhcn.js
index d6a21db6..b5bce119 100644
--- a/static/js/locale_zhcn.js
+++ b/static/js/locale_zhcn.js
@@ -4923,6 +4923,12 @@ var LANG = {
/* AoWoW: start custom */
+ // click to copy fn
+ copied: '已复制',
+ clickToCopy: '点击复制',
+ nothingToCopy_tip: '[Nothing to copy!]',
+
+ // TC conditions display
tab_conditions: '[Conditions]',
tab_condition_for: '[Condition for]',
cnd_either: '[Either]',