mx pak1%V�mbackground.html������css\menu_icons.b64pngf�wI css\options.css=֚��def.jsonQ8
)�x
defaults.json[;9'x�Zicon-18.png�?��s �icon.pngyC�r&"icons\icon_16.png�]���#Jicons\icon_32.png�a'��Uicons\icon_48.png�h- �^�includes\app.js�q�ڃ
�includes\opener.jsZ��kz�includes\viewer.js
�����50js\app_bg.js�L�w�pjs\background.js�Q��c�js\frames.js:^�MJM�
js\options.js�./G�#locale\cs-cz.iniL��Ģ�locale\de-de.ini��^�Õ�locale\el-gr.iniJ�[
d|�
locale\en.ini�-ϖ�locale\es-mx.ini�>��Nlocale\fi-fi.ini�'5v�locale\fr-ca.ini-.
lYMlocale\hu-hu.ini081���locale\ko-kr.iniaI8
2�=locale\nl-nl.ini�Y��=plocale\pl-pl.iniE`�V��locale\pt-br.ini1p�K��locale\ru-ru.ini7w��dZlocale\sv-sv.iniK����QZlocale\tr-tr.ini��� ��locale\uk-ua.ini�[� )�locale\zh-cn.ini`��x4locale\zh-tw.inip�`n%olocales.jsonи�ƿ��options.htmlj��
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEoAAAKaCAMAAACurz9FAAAB3VBMVEVMaXH////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////9/f39/f3////////9/f39/f39/f39/f39/f39/f39/f3////////9/f39/f39/f39/f39/f3////////+/v7+/v7+/v7+/v7+/v7////////+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7////////+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7////////+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7////////+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7///////97uGncAAAAn3RSTlMAAQIDBAUGBwgJCgwODxARExQVFhgZGhscHR4fICEiJCYnKywvMDIzNDY4Ojw9P0BDRkdJSk9QUlVWWVxeX2BiZGhpa2xtb3BxdXZ7fH1/gIaJj5CRk5WWl5qbn6Cio6Wnqa+ws7e4vL2/wMHDxMXGx8jJysvNz8/Q0dLT1NXX2Nrb3N/f4OLj5OXm6Orr7u/v8PLz9PX2+Pn6/P3+/8woVNI3AAAMpUlEQVR42uycP3LqMBCH9wQ6gVq1cRW6uHzurBkoocKVfQE4gN3LB9BdHxmc/BCytfiJGfLe26/JRMFf/Ge1LJpF9EMR1LZ3R/0U08lfcOY5JrhyTXDlmuDKN8GVb4Ir3wRXvgmuXBPoFa0HpoATrab0C5S0FuuvjM31ZzNOA5bWUk0mYyeDmVwVrUUNVxN9qejqGhStxpy9PxuC6mvkT1CKCKppJAOoMshWfdS/FK9Sv+oPRqQ/Y7w3nMr0n3GvKIFxmBxLKkyq3nCmCyqtUsgTnIlXwcWYztwFnuFKm0b+to9w8aZYxbh4E1SsC6aJYx3SXofbOuTo513a+QycJtD4LBoCLk/lCAx5qoHALk+1I6DOOaazonlXY0O663BnQ5rIFLvcYyHqIhPngoo18S6oeFPs4rNo2gQXn/o4E1y8CibGxWdRmNKugb/tA0zLlLZ65C21suWPqhleWxSZk/cnAxVG1qLcdQ5BZRxTuDNlrUNZ65iyli223XF6T3Motl/zEQCTI+ZM61FnJo9nuFBQ5LlgynXBlOuCKdcFU64LplwXTPkumLJdu2FsND0HQRCEbe+/6WvKYAdRbonmQlWfofJ3POlw/yAERCWqvBDlGUPTkKGy+dMZrgGiwdJrEbbOf+P+35zvH4TXikpUDJLzBcnhUreLSup2yeEvRxAEQfiBCIJg6rat3zXlgt4Ld/EpykH7W/pj/ZbwvTFtKhH9fvYQtffeFfFw3fujoQuFn6NVCy3tTt2LHHomG65FMCyzy0iE16tZl4tbf+JK/QOfpLspGnZd7Fp60CVEvQcHQnCVXbp35us4TRCBURNUrQ84UMgGFxKL/FAguPb+joJC2tvx4hSKylgEBgoxGKcivICxCkRsw9LhazwSWXUbwjHjwuwa50UIsRib/hTIi7oCbedReMbsEiIqEQlsD9gBkRSLEIaGQvqUCCEGERUIw4AiISogQoghDDdzkQA6iMjMifDEh/R3b9oPE/4XiJbmPvAR7XbSdTMiBM+oEssUYK+wiogQC8/KJlcdwZEu6BEiAmpcaPJTuIwoeZhmHCDCgx0RwiHmMMSqilIUtIgqbBP6NPEkfd2IB52N3tius5r+bgRBEARBEARBEARB17dg34hNOP6OPSMCdGL1o8H6ZsBm/mv3fWJNpltYtbNYpwn4F1WiEpWohgeTTDGfZAYCurK3VN+pzwZMJlJ3L9f0dyMIgiAIgiBsWje1gVEuaNUwlIcKatosCqgqyqOCakd59FA5tfqR1Rq/2KWWtDdDLFts0RZ14pS3fUpbYtj7T7aaLug2auFQhO6sPSX5PvjUtr0HkNX1tEEF49r7VezzTXx8GL+agolsHn4GHNaaBsXuxMWDHZWec4mWQOZpKUpg15g6eprq8DxVQymauSPshWbt3s96ud9QlYMHfCfUMTojhT+qKIJbWqRmbmz16H50Oj4ndmZt49Ay73UkQqcdiO6X295lectOeyR7Znfx7uF5MXJh75gIZPJQT4CZ9+yt+CNV8QpV/gWOzG1nGi8HLhgcU9mALt4omZ9hxQOxbH6zd/c4bsNAFIDnBHMCtmrNatWZZdyZwLq0KruyLmAdQOrFA/CuAbILTBzaepyMsgkQvXJtfKD+zOF4JftTwY0VT61PXfRNxX44w53ece3DLQN8/WX6xXEdwTEGH8hjS5/xd3C94yl1Ph93u2/vo3bG6a3zvKSzU+uPirMmd/M8L/H4qfL2YbEccGu1ffgbFTJeuZ4MSwBjtd3VlGrT6Xl1loe+H7Ak4xo8yY1K5a0L7iQSsDpCS8smVT2MoPEP8PPZwEVPynAqZjscfEyDkYp/pPvBRqqRyZOs+bxhYepbWsyWLVv47f2jE3a33avL+1t+yGWvAxZvOBx/B2tf1A2jV0K80KI7qiR3XyyBGAKwvNJb/LPUH7xn9j4Oeov4/tiIkdkzLXROQFNUoKIZE2ukdqkXGFJZm+E6dHAkKdeeN8WPijkwHwZ89NAGhKLABm+MuBDxVNVnT4zXih3YPhkUHNZcdyYwqkTw+XDC7VdpqR3QMhC/ibqaM36sOjixZuy5imoVFINickXqizdwWG+393KYrSdDxFe9dE/bqgvH1awGnP1yvtStmq74O05fOVME/GF0A9tXNNID+vDv65+j0oC5zRPMtGi1s+wBxcIvLH3/sWfVevTsSFI8JePisDVkwRr58+6i/6FTHrJkPB/fdru341kqJaUForB6syWJK1rNi4F1QW9RGEqo98S5tHB8l3KWTFEeu1NYOM0h9j8SW0cfcUlhIf5Lrc3aLF7PirSaNdJ6Fq1n0WrWlVazApktUJHorZ7JHI5TztdA/222bHHnOY9H1vZQxzz/Wk8HmTzUbcY5FK2b0sJS+VPRXRZLJZWrlTmrLJHK5hGYbIFU3l4nllaainK9sLBUzs6cCkshTfzwosISSXqyyNJL2MIStvQStrCELSwpLSxhC0t6C0vYwpLewhK2gKSygKSygKSygKSxgKSxgIQsJNktLGFLJLslkt3CErawhKkZL7j1klh2SSy7hC0sYQtLwLJI2MJSSsCql5oGWJqqB1gKCVgKCVgKCVhKCVtY+idq36323WpfttW+TJJoq30jSUZb7TuSxFr7kiTZat9Eks5W+3YkcclS+yb35F+Zpu/s3OlP1FAUBfAziyCuKAIqrkgUFQ2Oxg0BFYgriSa4xjUBNXFBGSVREQQScdzIsDMzh7/VzNw3Zdrpa1/5yvw+Ns157WvvfU2TdiXPvsk22Ox6lKT8xTzg69rko11Y3UpKTrxfpE1m9GoYOeGroxnaLL4/Aa3TaRa7g5w7LJY+DY3QOF1k9gPA/gxdjIdMv/ISFwHgIl3pukI1XV3x+FanGhpLQaOWoHMwGSwqeRBau+8ODGYNe0cND2YN3N0NX83fvaO+N8NMeU/G7wQzPeUwsCNuMlfxHfDV8NNs2n82wEfjpOkVnGyEpwP/zG+GfwfgoWaClk/33aLuf6JlogZaZf3MW7gWaXOLaotcW2Befxl0bjPvRyPgHgU0/mDebWg0pal8qYY+CtVfqKSb4Co6ROVrJQBcoOgEgE6KCwBQ+ZXKUBRuOqkkapF1lCIGADGKo8iqTdAax0XFb4rFI6qpxuUQcwNH5UDiqm0eWaT4XYFiHVRuQtmezfq8Bzl7PmeTtkO5SaUDRUIjFENrkBduaj0egRI53toURt6aIYqREJyOUTkJIyepHIPTPYoBGBqguAeHUILiPAydp0iEnHVMkVwLQ2uTFM6qvkTxFMaeUlyC3QOKVhhrpXgAu7cU+2BsH8Vb2KlZnwvDWHhOzbtjc0qtcAhArZYp+/AbKF4jgNcUG1BoG0UfAuij2IZCWyleIIAXFFtRaD3FOwTwjmI9bFTvH0MAY2pFgd24antlMFam2t847F5RNMBYA8Ur2PVYTdFYB0UP7FooemGsl6IFdnUU85thaPM8RZ2mCtgFQ13U1dotirEojETHKG7BqZ5KO4y0U6nX37u/NsLAxl8e9XGWykMYeEjlLIpFvlE5B1/nqHyLwMUZKjOH4OPQDJUzcPWSyp96eKr/Q+Ul3O2dtbIOw8NhK2l2LzQu09qnBVots8y7DK1ntDyphKvKJ7Q8g966OC1/u8pRpLzrLy3xdfBQNcJliRu1sKm9keCykSp4qhlmgfSb7uYtyNnS3P0mzQLDNfBR9YEOU6ODg6NTdPhQBV8Vj2ngcYVZ0U/Tx3Q7DNX10lNvHczFPlLrYwyBhGJ9abpI98VCCGzn9f4UbVL913dihTad6n4en5hJpWYm4s+7T21CSUlJSckq+KfH/3bOGMdBGAqinMAncOt2XS1dKDddLIVyqTYVXGB9AKfHB8hdU4A0IR9rME7JFGmivPBRniMhe/6xabwIgwaIQgziSjFIKMYgn8D46TWD83VZwQzOzg0DzWZMv4rBaV1fikHVoS3E4Glwl4/x7dvX6xFNEzmYWiXOnTeFGNzzoRSD0hEjO2lGghFx6/qpQDAyOlHT3G3B2MUsfaJ/INCr0Zew+FyTOlc3c5JDnf4ej1iLjTVRJ0+Y93r1gq6j2MrR4p6nzu6LdVqdJs883iAat691m4j9HUWZMdXY3mcWplQ/IVHyxzR2cTHl92QYNOMaI/qGNqhrACjWORpjSploiMZkSsRrojGZEhkU0XjzlB3RmLFEHxTRmKPwi2Uac5T0Ehrno+Al0ZigMCXVmKMwJdWYozAl05ijMCXRmKJuNVYfojFBnYWXQ7ULFa300uxCeSW9dNUeVCtWH9CzUHLjH1qn81DeVCKCQ2PwZ1WcLp4/Azpy5MiRJ7p8llfzx3Q5AAAAAElFTkSuQmCC::-moz-selection {
background: #adf;
}
::selection {
background: #adf;
}
html {
min-height: 100%;
background-color: #f3f3f5;
cursor: default;
}
body {
display: none;
position: relative;
max-width: 700px;
min-height: 300px;
margin: 0 auto;
box-shadow: 0 0 4px #999;
border-top: 0;
padding: 6px 15px 15px;
background-color: #fff;
font: 13px "Lucida Grande", "Lucida Sans Unicode", Tahoma, sans-serif;
}
a {
text-decoration: none;
color: #1155ef;
}
a:hover {
color: #000;
}
:focus {
outline: none;
}
.fn {
float: none;
}
/* http://nicolasgallagher.com/micro-clearfix-hack/ */
.cf::after {
display: block;
clear: both;
content: "";
}
hr {
border: 1px solid #eee;
margin: 10px 0;
}
#right-panel {
position: absolute;
top: 0;
left: 100%;
}
#right-panel > aside {
z-index: -1;
overflow: hidden;
position: fixed;
box-shadow: 2px 2px 2px #ccc;
max-width: 145px;
padding: 0 5px 3px 8px;
background-color: #fff;
text-align: center;
}
#right-panel > aside, section {
box-sizing: border-box;
}
.logo {
display: block;
width: 128px;
height: 128px;
margin-top: 5px;
border-radius: 10px;
background: url(../icon.png) no-repeat center;
-webkit-transition: box-shadow .2s;
transition: box-shadow .2s;
}
.logo:hover {
box-shadow: 0 0 10px #bef;
}
aside > .app-info {
font-weight: bold;
}
#platform-info {
font: normal 8px sans-serif;
color: gray;
}
body > form > section,
.hidden,
body.opera .opera, body.firefox .firefox, body.chrome .chrome,
body.safari .safari, body.maxthon .maxthon {
display: none;
}
nav {
margin-bottom: 20px;
text-align: center;
}
nav > a {
display: inline-block;
border-bottom: 3px solid transparent;
padding: 5px 6px;
text-decoration: none;
color: #1155ef;
-webkit-transition: border-bottom-color .5s;
transition: border-bottom-color .5s;
}
nav > a:hover {
border-bottom: 3px solid #aaf;
color: #000;
-webkit-transition: border-bottom-color 0s;
transition: border-bottom-color 0s;
}
nav > .active {
border-bottom: 3px solid #000;
color: #000;
}
.prow {
clear: both;
padding-bottom: 3px;
}
.prow, .tiptop {
position: relative;
}
.tip {
z-index: 1;
visibility: hidden;
overflow: hidden;
position: absolute;
left: -48px;
top: -5px;
max-width: 100%;
width: 33px;
height: 25px;
border: 1px solid transparent;
padding: 5px 7px;
opacity: 0;
white-space: pre-wrap;
color: rgba(0, 0, 0, 0);
font: 12px/150% Verdana, sans-serif;
-webkit-transition: visibility 0s 0.5s, opacity 0.5s, color .7s;
transition: visibility 0s 0.5s, opacity 0.5s, color .7s;
}
.tiptop:hover > .tip:not(:empty) {
visibility: visible;
opacity: 1;
-webkit-transition-delay: 0s;
transition-delay: 0s;
}
.tip:hover {
overflow: visible;
left: -45px;
width: auto;
height: auto;
box-shadow: 0 0 10px #dedede;
border: 1px solid #ddd;
border-left: none;
border-radius: 6px;
padding: 10px;
padding-left: 40px;
background-color: #fff;
color: #000;
}
.tip::before {
display: inline-block;
margin-right: 20px;
border: 3px solid #aaa;
border-right: none;
border-radius: 10px 6px 6px 10px;
padding: 0 6px 2px;
text-align: center;
text-shadow: 0 0 3px #000, 0 0 3px #000;
font: 700 17px Verdana, sans-serif;
color: #fff;
content: "?";
}
.tip:hover::before {
position: absolute;
top: 5px;
left: 5px;
}
.prow > label, .prow > span:not(.clean) {
display: inline-block;
width: 49.6%;
box-sizing: border-box;
}
.prow > label {
padding-top: 8px;
}
.prow:hover label:not(.checkbox), label:not(.checkbox):hover {
color: #45f;
}
.prow > span:not(.clean) {
float: right;
max-width: 50%;
margin-top: 4px;
text-align: right;
}
.prow input[type="text"] {
width: 300px;
}
.prow select {
max-width: 308px;
}
.prow input[type="color"] + input[type="text"], .shorter-input {
width: 242px;
vertical-align: middle;
}
.prowone > label, .prowone > span {
width: auto !important;
padding: 2px 0;
}
.sub-opt {
padding-left: 20px;
}
input, textarea, select, code, .checkbox, .pager > a {
box-sizing: border-box;
margin: 2px;
border: 1px solid #ddd;
border-radius: 3px;
padding: 3px;
background-color: rgba(242, 242, 242, 0);
background-image: linear-gradient(to bottom, #fff, #f5f5f5);
font: 13px Verdana, sans-serif;
-webkit-transition: color .2s, border-color .2s;
transition: color .2s, border-color .2s;
}
pre, code, textarea {
font: 13px Consolas, Monaco, monospace;
transition: all 0s 0s;
}
code {
display: inline-block;
border: 1px solid silver;
padding: 3px 5px;
background-image: linear-gradient(to bottom, #fff, #f5f5f5);
}
select {
max-width: 100%;
}
textarea {
overflow-x: hidden;
box-sizing: border-box;
width: 100%;
resize: none;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
}
select:focus, textarea:focus,
input[type="text"]:focus,
input:hover, select:hover, textarea:hover,
.prow:hover input, .prow:hover select,
label:hover input, .pager > a:hover,
.prow:hover .checkbox, label:hover > .checkbox, .checkbox:hover,
.sub-shortcuts > li:hover > input:first-child {
border: 1px solid #888;
}
input[type="checkbox"] {
display: none;
}
.checkbox {
position: relative;
display: inline-block;
width: 20px;
height: 20px;
padding: 0;
color: transparent;
vertical-align: middle;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.checkbox::after {
position: absolute;
top: 0;
left: 3px;
font-weight: 700;
content: "✔";
}
input[type="checkbox"]:checked + .checkbox {
color: #616161;
}
input[type="number"], input[type="color"] {
width: 50px;
text-align: center;
}
input[type="color"] {
box-sizing: border-box;
padding: 2px;
background: none;
vertical-align: middle;
}
input[type="number"] {
width: 60px;
box-shadow: none; /* Firefox marks "invalid" inputs */
}
input[type="range"] {
height: 24px;
vertical-align: middle;
}
output {
display: inline-block;
min-width: 24px;
}
h3 {
clear: left;
}
.color-helper {
float: right;
opacity: 0.3;
transition: opacity .3s;
}
.color-helper:hover {
opacity: 1;
}
.color-helper > input[type="text"] {
width: 80px !important;
}
.shortcuts > label {
display: block;
}
.shortcuts > label:hover input {
border: 1px solid #aaa;
}
.shortcuts input, .sub-shortcuts input {
margin: 5px;
width: 35px;
text-align: center;
}
.sub-shortcuts input {
margin: 0;
}
.sub-shortcuts li {
line-height: 200%;
}
.op-buttons > button, .action-buttons > span {
position: relative;
border: 1px solid #ddd;
border-radius: 3px;
background-color: #fff;
background-image: linear-gradient(to bottom, #fff, #f5f5f5);
font-weight: 700;
font-size: 14px;
cursor: pointer;
color: #000;
}
.op-buttons > button {
width: 95%;
box-shadow: 0 1px 2px rgba(0, 0, 0, .5);
margin-bottom: 10px;
padding: 10px 0;
font: 700 14px Arial;
-webkit-transition: border-color .3s, color .3s;
transition: border-color .3s, color .3s;
}
.op-buttons > button:hover {
border: 1px solid #999;
}
.container-info {
text-align: center;
}
#info-sec > pre {
white-space: pre-line;
}
#locales-table {
border-collapse: separate;
padding: 0 40px;
font: 13px/1.4em Consolas, Monaco, monospace;
}
#locales-table > div > span:not(:empty)::before {
margin: 0 10px;
content: "\2014";
}
[{
"type": "extension",
"frameworkVersion": "1.0.1",
"guid": "{000008f5-8a32-4389-a7da-2daa0e9d7760}",
"version": "2016.1113.1700",
"title": {"en": "Viewhance"},
"description": {"_t": "appDescriptionShort"},
"author": {
"name": "Deathamns",
"email": "deathamns@gmail.com"
},
"permissions": {"httpRequest": ["*"]},
"config": "options.html",
"service": {
"main": "background.html#Viewhance,2016.1113.1700"
},
"actions": [
{
"type": "script",
"entryPoints": ["doc_start"],
"exclude": ["res"],
"js": [
"includes/app.js",
"includes/viewer.js"
],
"includeFrames": true
},
{
"type": "script",
"entryPoints": ["doc_end"],
"exclude": ["res"],
"js": [
"includes/opener.js"
],
"includeFrames": true
}
]
}]
{
"mode": 1,
"minUpscale": 0,
"mediaInfo": "%ow\u00d7%oh | %name (%perc%)",
"favicon": "",
"css": "body { background: silver; overflow: hidden; }\n#media { background: #fafafa; box-shadow: 0 0 5px grey; }",
"center": true,
"wheelZoom": false,
"mediaAttrs": "autoplay controls loop",
"lpLeft": 1,
"lpRight": 2,
"sendToHosts": [
"TinEye|https://www.tineye.com/search?sort=size&order=desc&url=%url",
"Google|https://www.google.com/searchbyimage?image_url=%url",
"Bing|https://www.bing.com/images/searchbyimage?cbir=sbi&imgurl=%url",
"Yandex|https://yandex.ru/images/search?rpt=imageview&img_url=%url",
"ZXing QRCode|https://zxing.org/w/decode?full=true&u=%url",
"ImgOps|https://imgops.com/%url",
"Pixlr|https://apps.pixlr.com/editor/?image=%url",
"PicMonkey|https://www.picmonkey.com/service?_import=%url"
],
"key_mOrig": "0",
"key_mFit": "1",
"key_mFitW": "2",
"key_mFitH": "3",
"key_rotL": "E",
"key_rotR": "R",
"key_flipH": "W",
"key_flipV": "Q",
"key_cycle": "C",
"key_wheelZoom": "Z",
"key_imgBg": "B",
"key_pixelate": "P",
"opener": 0
}
�PNG
IHDRVΎW�IDAT8��oTU����3�Ngj���
-!Z0�j��q>�\�r�^]����pm��A6��I�iJ��C;��;�y�9~>��n����%��R
%"ԍ���sx�y�w��y�������?�R�Rh�0Z���hE�V�_7�b]1�r�l�Xg)�Q���R��?�o�]k@����1es�˫K\���ѣ����/D�!��pe���j38Ȑ�o�}g�Nҡ�����Yzu�H70Q�184����XYhr��,.&�Y�O�,�ZE�����&�^���%��Ĭ�%��s'dU�1³�c��c�䝘�c��:1//���'���Z�Ok[zT�OxL�f����<�WJ+r�9HC�{k���/���Mnm�DŽZ]��#��BC�LYY��@�`��+P*/lw"���w�����<�P(��(-f�~}va�B@% "h`
����x<�y��g~<������Y�IEND�B`��PNG
IHDR������PLTE��������������������������������������������������������������������������������н�̿�߱���������������ᘾܗ�ڙ�ٔ�ۑ�ؒ�ӕ�ԕ�ڗ�ړ�ߎ�ڌ�Ռ�ԍ�ь�҉�Ո�ш�Є�Ђ�Є�҆�҇�ч�ԅ����~��x��m��r��q��s��w��w��w��w��s��p��m��m��g��e��[��N��R��J��H��A��?��8��7��:��3��/��1�2x�-s�2p�3j�;l�?m�9f�5`�0b�2Z�8X���IDATx^��}�\�y��{o�L�!�"a�B���C�J�f�M
;ة-Q�FF�&�6��
,�����J��Zv�x7�"�Ļ��|H`&�,�r�bhFf43=}ϻ�;��ۭA�V��ܹ�V?�yޏ��V�r�A��E�0�-�$ @9BNL�O%��2��P'��'�`�L(��}yD!8��A�o'^TU�4J��S@+Cy�Aބ.~'�{��U5TQ�*
hO0mʊ>��^���9���У����LV�9䑲�"�����N�Em��Y�;
����i�N_��?���+�A�%l� a��WB:�V01EK�1�>7�W� 8�YP�-2�W%��=Ɣ��d�WR����_�9����J>���b�'� �Z'�QP,��Ok��'���Ӭ���F#�SB��#�>�·�
��wA��B'VP
,��;_�M��&�� �����<��8�I�ޛ� �+��bi}y
p��ն�,LE��,�?I!%ar�r�Yc/�N^���R9(��XN��P��a��`�gl���o�V)y&��"�]fz�\����V�����L��?�
�!��,K��'�p"~����Y���;�YK��ؒ\^�H�����O�z��@Y�)X~�����f�.��{G�$�[@�j�$(81�I���!�]�/��J��o���!�Tq�NkTp�do��OSs�_Q�@8C0t.�л����ٯ���鍴uGV�T���C1>~�7�NhCR���>���|ƚ����@o p�e�� Y#,Ƒ �4k��.������'�=�Ol��OU���ƝyO�ؚ@�Qa
I����D�I���+��9�<�9]H�� < u[M�EXCJ�
8�%L�r�\�`9 �
pP��#l���O�2��pGDu�'���#h�I��bGNq�H�WT��p�1�������(�Fѫ!(VH^o��茂/E�3X�M��f���J�f�b���%�8�pD}Eq2{Ů�G�Y�N�Y�e��M�����v�u)`����y��ǂw�5$EZ�̒���P$@��mHiΤ�>���,�i; �F�~�������D�p�BOe(�Y9+E���1P~
{����m������>���&��
㰮V���vnd@� ¾�@�)#{����U( �?�B�f� >~���=��C��7���\�
�h����(�"{��z�t��'ɳ��nB��N����7���\D���ҳb�ƻ{��&�B���oO�VSč�k4sU�#��i�ǚX8����S��*#E`2�c�M�c����LM� ��Q�����mB�i,8fʖ��_�~�n߽{LdD�8��X�����a�`���S��$m��3�4�]λ~ �{��G�E��N��H�V�P�_p���M����H�7���j����^v��+u`h����;��lp�v�2VB�y�������&!`8@�rH��;�C�避��x��w���1�>?��% i����Ǐ�����v݀ˊNˉ �,7at���XI��$.x���k���Hnչ�W�u��Xpo�ٞ�m;���W��v\u0p9xL<+�Q�"W�Z�R�Icɲ1$!�/3ː=���#�+�/;�p��^��ᤁv@�T����5�X��pW:�f���w�9�2�(܀2��/��
�o3����"��,�F�,��qJG���[>8��{7T���Pg�R�2�?'���=9��K۹AR���E:�et���6�&��>yu]^D��%�1��$���=� ��gO<�aNz��K`�z�AX�,U8�y^}� �sqA=!�������?+OUebo����l8p~�;Aё^/������k��Ҁ��d��l���P��y�Pˁ���ݺ�8�g&���"Z�C���u,��+ �9B0�38~- ����㴂CN��x�x�
��.V�ގ��i;�]�x<`G[����Rъ�j)��椠 �C��I(��� ��kĕ{vYB�v(��v�xi?AQj�
d�9��ۂ�Aj��/\�n��oR(x;R�!�rCv�%��;l���ㅀy�����t��z`��f?�]>�vզ��}l��E��$\�_���c����Zp��,?@���$��p��֦�<��@�{�1��{��uG��ú�����)��Ǹ��Q�H��Q��c͉'�r�5C x
�c<����.���Q���7t#@�υ�7���@�[Ӑ~����\vٺuT��Lj@b]��pI�g��C\���24�fJo)g8.���v���˜*��+�OdX�%���,~El�]}я�ͳ�O��ѫH���'ޔ@���A�]>���)�tFv\�����^Qk��'��>x�st�N�9p@����M�P�E�����%�N`Ggϭ��Ɋ�.������R塆0J�^@8
L��Րe�Uh���U�V��}� <�^nW
5�3t�o&�˝+ \NZ�D�^��2!E~TIB�P�gk\�*�W�G����gPm:��)�_�2J�p��H�����_q�b��
1�����@v�Hr ���z��!�t,Z-��e&a����ΩQBx���ޓ�i�_KOD�s�Z�*(�)-�Sc:@]o��%?�6�7��w�a�L,��ZSO��ɫ�02�U~U�k��?����h�C�_RoB��H��J7��ح
ߕ�ӑ#i
�j���������O�������DHV�t��
I(l�a�S`D�t���V��h�/�挗����0��&I1/�������: 8###x�5��X�n{�E�?�ъUg<�3��S��Ӑ���>
\^^�����l=3�f��D�pI_A�ӿ�(N[�J�yH�`]�lh�3P�����i+R#SPձ���N���9����BvҾ��;I��b7(7��\M�XS�S�Y8����������[ٰ����[B��`t�$����\�c�B@�����&�p)*u�y|ݭ��'?��kS�����������+�3dž�9rJ���&r����*74~��]��@{��iZ�C���
F��T�Ɛ#p�>������B�G�z��Y?��Ҭ��QUS6�q���p2W&�зRj�d�Z�3G3)S��Oj:�G��,���xJP����o��2�Y
��[FD�g�����ϋ�{.���8 ��9�4R�͏����w�j~�D���b�mt~dՈ p%%ڋ��9:�S��q���倫4(�H_������I�:�!}چ���KN�����"���(o��=]u�G��N�\�G�"�mX��no X���;�-�ʃX�����Gj�|��BiL��Q��Y���m0�o�6γI�#��,_p���^��ܙ�OY�X0rDP_@VFK����̉S�q�p������\�8��xT�j�8�ʷL.��o�E��`�.���� �9��/9�u����?� �2�(����־��9�;)Vl�v{�ҥ�_$�\��2Ak.�T��j=��"=,?� y�ߨE��o���B<}A��蟟�8οs�����$P������`�����prMSC� ��A,�S�}3X����»���ܩ/8�;�p�Ash���%����k@�0�ȋ��8 ��n�|��c7́��I��3t�ǔ�4:�ہ`�R�၍3���Q�_>�>)�Li,}eb��l�V��ZkCz��@X[Ṕ��j(
�/��ŝȡ]�.>;��"��s��4���S䮸@��[��9Y���q���;��sG[?�g�;��ز|�0�#�_����ȁC?�5� �2^�p����>�������%�7�8��vk�����j��ǥ6>�{r�`LJ�+ �|�N��g,�]q������;���ՂA���D~��d�@�y;������G
�;pO?>Ef����a��s�q�7F1�P� 0�q��d3�̱���!��9c|v�ӓ�A��B2������_���6�|�{;+��>��q�>���q�X �L�d���!P8�h�C}��ɂDh��pO�N����:t��qgI�*���z�Ťzǐ�<'9�
�A�,.�-��A /��d���^�36w���u; �'#ä�~+�+s���&0"��zfQX��xKib|�X����AA�OG`Eꄽ�����fqHh�����
*�����J�(*��z\�
��2!w���^1����� ��y̿�� mT���^����� <��\O4�zt� R"���@8�@�'2pr��iE:�o8H`�~�U��@?��
��U���c[t�R�%qq/ZE3���S��S
@�GD�71%����[�1���h�肜J��~A�`pc��o�e�*b5RxQD��dP�*�$�Ah�
���Ϋ� eE߷&���]8q�L���;�=�F2D1��� lD���|h*Sj�?�:��L���!���n�� ���g0y����V~�y��[}nd�����lf�uJ�\� ]����(�����!�1'\��eJ_~��jH�n��qB�/���������.I�rԄn��IEND�B`��PNG
IHDR��asRGB���gAMA���a pHYs���o�dtEXtSoftwarepaint.net 4.0;��imIDAT8O-��O�g��g��-z�v�%[��n�D3��c��&u�
)Ȁ��ЁRhK-�W�GKK�����m)-��`2~{J<��;�s]����ܒ�T�y�[ǁx��#�P�Lm#�H��CI�O�|/���cQ�9��K^e�x)`U���xUJ&Dps�
��7�vr�������ᵋ̆"K��#ĥl��N���d��<����;�q�5��,]J�6�}/d&�'I��rB� ͨY�E�a�G.G[ G�+GS�5c�I�Qtk
�M��?!.����!O�C�R9*\<�`��i��S���b�M�Z�U�z���p���-@�S��G>@�f(��%7R4x�t�v)�e�|���]�
wpo���Z�� �x�@�#͗C>j�ܚKr�o]��t,���'(�L�I��F��W;Ẓ�^�'�< �qF�b1M�=E�X�j�w�t���yD�q�
������*�=����.b�k����[�vNi�Ԍop����J,:g#\j�RP?�9C��Bl����:�~��vɯl�n�3�F~���kf8U9Li�<:�*tV�����:3�� ��q
/7��Ňl�}��{{\���O�s����M�^��f?U�k��Ls�;3?�(y����N
>���R=J6���`r&�^I�����.?�n���(%-�xﺞ�_��aa+U���[LwYYiz3MJ�z���(}sa:���*�w������E�:�ߋ2O��M�i��LE��2
�~����эyh� 0��Q�4K{��]�9ߟ��4�nd
��KF���?�r﹋��uj��<�/�鵅����v�E���}��{f�2}"+Yܛ���%q�r��5�i��Dm\ ��yo>cqG��W+���aIEND�B`��PNG
IHDR D����PLTE��ֱ�ԭ�ԣ�ϝ�ԝ�ˍ�Њ�҇�ч�҇�Ӌ�Ս�Ԍ�Ґ�֔�Ք�ڙ�ڔ�֑�Շ����͂�Ђ�̅��}��u��r��r��k��|�ۄ�ޅ������}��u��r��u��v��z��r��n��p��s��w��x��~�������������������������������������������������������������������ܑ�ܛ�ޡ�ߠ���ݩ�ݮ���۳�����������������������������������������������������������������������������������������������������������������������������������������ڮ�֚�ڙ�����������������̍�Ѕ�Ȓ�Ìʷy��z��rĴs����q��f��g��c��^��T��N��I}�Bw�:t�>p�9f�2e�5_�;Z�8T�1W�3N�2I�1F�8B�@I�EM�CX�Hb�Jd�Po�Ww�Vv�bj�ku�kx�j|�l��o��r��|}�{��}�����j��p��h{�nj�[_�Q_�F~�E��B��<��B��E��M��F��M��T��Q��[��\��h��f��[��c��j��o��m��l�v|���ƍ�Δ��������������֝�Г��z��n��p��iܧ�༥�������������u�5��2��.}�&x�1r����������������������������}�^�tRNS���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������¿�$L���IDATx�E�]h�u������w�6���� o�4L�� ��DX!�A��Y���`�QEP��AZL�l�0,
5)�4l���y�����N����Sc!�����x�T���[�-�E3 6pұt$Ӗ&A��+w�זPTG�!6|�m�������Rf���x9;�p�����
��u[/-V+f�)�_}c�ޱ2��L��>�8ӌ��+�fH� D� �f�l�8�{��s����M����8�]#�r;������c�=����ht��!��Z��!��a�y|[u��߽�����7�ne[����o������f��_����-v�b�.@|�yҐ,�o�~�AX4��/ޓ��h�.8�?������є4*Kv�GC����,���F�o�?���װ�X�B�Se���z+QL��ő�
�#L'�֛፣C�N���ڪ?�E��C���,����e䋭����`nj�~�L&�k�������ӓBt���e��L�}08�!����$5����J(�'U~�^ja��4�(v���)�0~��@�T+��n�H� ���"h���%�@��K3 ��^��#U�Q�
MT�@9�����_ ���z��Ě^�'[IEND�B`��PNG
IHDR00`� ��PLTE�������������������������������������m�s�$v�(z�0�8��4��:��?��H~�Ez�Bw�?q�;k�3i�9c�3`�2Z�:[�:T�2S�9N�7J�0J�4C�;E�BL�CX�AS�NZ�Ha�Pf�Pn�^h�m`�TT�2;�1r�M��V��Q��X��\��d��b��l��l��u��q��k��o��x��~��}�ل�܇�҇�ы�ӑ��ԍ�ѐ�Ռ�ד�ٔ��ט�ܕ�ے�ݗ�ٛ�����������������������������������������������������������������������������������������ߵ����������������������������������������������������������ݦ���ו�Ӗ����������z��t��w��v��s��m��m��g��`��V��^��b��h��q��y��~������������������������������}��y��s��o��u��q�Ƀ�Ђ��~�̂�̇�φ�Ѝ�Ӊ�Ʌ�̝�ʤ�Η�٤�ܵ�٥�ɠ���q��l��x��Y��\��c��S��S��r��J��K��A��@��S��`��lz�eq�Z{�b}�j���������������������������������ϴ�֖���o��m�yq��i�������d��y�ъ�ޠ���������������ű�ǣܧ�ި�ץ�̟���������s����8��itRNS0>I�������������������������������������������������������������������������������������������������������|IDATx�]�ol�e���<�i��I�E�Nh�!�"!�l�3H4�����j
U1�2����i��15�?V�X� �I�cU��Fi���E��9�}��v}�y���<��/�u��o^
����b�L\�`��xF�B"��|�����P ̊m3��ͦ��4��S^� ����v��vng🢘��?�B���X�n��}��~�l�~�JLnSyk�#��S���w���ƙD�%�i��ϒ����ޛ~����/R
�^�]�/�:*"�����N�r�.���:n�f�qU��)����߂W����+ύ\E��M��?�43����TE�@�H1=}���̪H�����m��<�ˈ6�E��83a�v� v��r�G�R���y��WV�e[����HyY�F����%���|��:w|�b�j��Ei�~����Ŝ ��4 l<(F�J��,l�4�)+]��ɶa������x@D�*�N!��7�t����o img#img_elem:first-child, '
+ 'body > '
+ 'video[name=media][controls][autoplay]:first-child:not([src]) >'
+ 'source[src]:only-child'
);
this._mediaType = '';
if ( !media ) {
return this._mediaType;
}
if ( media.src !== location.href && media.currentSrc !== location.href ) {
return this._mediaType;
}
if ( media.parentNode !== document.body ) {
media = document.body.firstElementChild;
} else if ( media.localName === 'img' ) {
var stopPropagation = function(e) {
e.stopPropagation();
};
// Suppress event listeners added by Maxthon
document.documentElement.addEventListener('mousedown', stopPropagation);
document.documentElement.addEventListener('keydown', stopPropagation);
media.parentNode.replaceChild(media.cloneNode(false), media);
}
this._mediaType = media.localName;
return this._mediaType;
},
set: function(type) {
this._mediaType = type;
}
});
vAPI.contentScriptCount = 2;
vAPI.suicideAttempt = function() {
if ( --vAPI.contentScriptCount === 0 ) {
vAPI = null;
}
};
vAPI.buildNodes = function(host, items) {
if ( !host || !Array.isArray(items) ) {
return null;
}
if ( !items.length ) {
return host;
}
var doc = host.ownerDocument;
var fragment = doc.createDocumentFragment();
for ( var i = 0, l = items.length; i < l; ++i ) {
if ( !items[i] ) {
continue;
}
if ( typeof items[i] === 'string' ) {
fragment.appendChild(doc.createTextNode(items[i]));
continue;
}
var element = doc.createElement(items[i].tag);
if ( items[i].attrs ) {
for ( var attr in items[i].attrs ) {
// bypass CSP
if ( attr === 'style' ) {
element.style.cssText = items[i].attrs[attr];
} else {
element.setAttribute(attr, items[i].attrs[attr]);
}
}
}
if ( items[i].nodes ) {
this.buildNodes(element, items[i].nodes);
} else if ( items[i].text ) {
element.textContent = items[i].text;
}
fragment.appendChild(element);
}
if ( fragment.childNodes.length ) {
host.appendChild(fragment);
}
return host;
};
/* eslint indent:"off" */
'use strict';
// eslint-disable-next-line padded-blocks
(function() {
if ( document instanceof window.HTMLDocument === false ) {
vAPI.suicideAttempt();
return;
}
// Should not run on media documents
if ( vAPI.mediaType ) {
return;
}
if ( vAPI.safari && location.protocol === 'safari-extension:' ) {
vAPI.suicideAttempt();
return;
}
vAPI.messaging.send({cmd: 'loadPrefs', property: 'opener'}, function(response) {
var opener = response && response.prefs;
if ( !opener ) {
vAPI.suicideAttempt();
return;
}
var elementsFromPoint, lastMouseDownTime, lastMouseDownX, lastMouseDownY;
var checkBG = function(cs) {
// ("...\"") - Gecko
// (...) or ('...)') - WebKit
// ("..."") - Presto
// eslint-disable-next-line max-len
var rgxCssUrl = /\burl\(([^'"\)][^\)]*|"[^"\\]+(?:\\.[^"\\]*)*|'[^'\\]+(?:\\.[^'\\]*)*)(?=['"]?\))/g;
var imgs = cs.backgroundImage + cs.content + cs.listStyleImage;
imgs = imgs.match(rgxCssUrl);
if ( imgs === null ) {
return imgs;
}
for ( var i = 0, pos; i < imgs.length; ++i ) {
pos = imgs[i][4];
pos = pos === '"' || pos === "'" ? 5 : 4;
imgs[i] = imgs[i].slice(pos);
}
return imgs;
};
var checkIMG = function(node) {
var nname = node.localName;
if ( nname === 'img' || nname === 'embed' || node.type === 'image' ) {
return node.src || node.currentSrc;
} else if ( nname === 'canvas' ) {
return node.toDataURL();
} else if ( nname === 'object' ) {
if ( node.data ) {
return node.data;
}
} else if ( nname === 'area' ) {
var img = document.querySelector(
'img[usemap="#' + node.parentNode.name + '"]'
);
if ( img && img.src ) {
return img.src;
}
} else if ( nname === 'video' ) {
try {
var canvas = document.createElement('canvas');
canvas.width = node.clientWidth;
canvas.height = node.clientHeight;
canvas.getContext('2d').drawImage(
node, 0, 0, canvas.width, canvas.height
);
return canvas.toDataURL('image/jpeg');
} catch ( ex ) {
return node.poster || null;
}
} else if ( /^\[object SVG/.test(node.toString()) ) {
var svgString = (new window.XMLSerializer).serializeToString(
node.ownerSVGElement === null
? node
: node.ownerSVGElement
);
if ( typeof svgString === 'string' ) {
return 'data:image/svg+xml,' + encodeURIComponent(
svgString
);
}
} else if ( node.poster ) {
return node.poster;
}
return null;
};
if ( typeof document.elementsFromPoint === 'function' ) {
elementsFromPoint = function(x, y, target) {
var urls = [];
var rgxIgnore = /^(html|body)$/;
var elements = document.elementsFromPoint(x, y);
for ( var i = 0; i < elements.length; ++i ) {
var node = elements[i];
if ( rgxIgnore.test(node.localName) ) {
if ( !rgxIgnore.test(target.localName) ) {
continue;
}
}
var url = checkIMG(node);
if ( url ) {
urls.push(url);
}
if ( url = checkBG(window.getComputedStyle(node)) ) {
urls = urls.concat(url);
}
}
return urls;
};
} else {
// Not exactly what we want
elementsFromPoint = function(x, y, target) {
var node;
var urls = [];
var rgxIgnore = /^(html|body)$/;
var xpath = document.evaluate(
[
'.',
'./ancestor::*[position()<30]',
'./preceding::*[position()<30]'
+ '[not(head) and not(ancestor::head)]',
'./descendant::*[position()<30]',
'./following::*[position()<30]'
].join(' | '),
target,
null,
4,
null
);
while ( node = xpath.iterateNext() ) {
if ( rgxIgnore.test(node.localName) ) {
if ( !rgxIgnore.test(target.localName) ) {
continue;
}
}
var rect = node.getBoundingClientRect();
if ( !rect || x < rect.left || x > rect.left + rect.width
|| y < rect.top || y > rect.top + rect.height ) {
continue;
}
var url = checkIMG(node);
if ( url ) {
urls.push(url);
}
if ( url = checkBG(window.getComputedStyle(node)) ) {
urls = urls.concat(url);
}
}
return urls;
};
}
window.addEventListener('mousedown', function(e) {
if ( e.button !== 2 ) {
return;
}
lastMouseDownTime = e.timeStamp;
// context menu should work where the mousedown happened (Chrome...)
lastMouseDownX = e.clientX;
lastMouseDownY = e.clientY;
}, true);
document.addEventListener('contextmenu', function(e) {
if ( e.button !== 2 || !lastMouseDownTime ) {
return;
}
if ( lastMouseDownX !== e.clientX || lastMouseDownY !== e.clientY ) {
return;
}
var elapsed = e.timeStamp - lastMouseDownTime >= 300;
if ( !(e.ctrlKey && e.altKey && !e.shiftKey && !elapsed && opener > 1
|| elapsed && (opener === 1 || opener === 3)
&& !e.ctrlKey && !e.shiftKey && !e.altKey) ) {
return;
}
var urls = elementsFromPoint(e.clientX, e.clientY, e.target);
if ( !urls || !urls.length ) {
return;
}
e.stopImmediatePropagation();
e.preventDefault();
var filter = {};
for ( var i = 0; i < urls.length; ++i ) {
if ( urls[i] === 'about:blank' ) {
continue;
}
filter[urls[i]] = true;
}
vAPI.messaging.send({
cmd: 'openURL',
url: Object.keys(filter).reverse()
});
}, true);
});
// eslint-disable-next-line padded-blocks
})();
/* eslint indent:"off" */
'use strict';
// eslint-disable-next-line padded-blocks
var init = function(win, doc, response) {
if ( !doc || !doc.body || !response || !response.prefs ) {
init = null;
vAPI.suicideAttempt();
return;
}
var cfg = response.prefs;
var media = doc.body.querySelector('img, video, audio');
if ( !media ) {
init = null;
vAPI.suicideAttempt();
return;
}
var pdsp = function(e, d, p) {
if ( !e || !e.preventDefault || !e.stopPropagation ) {
return;
}
if ( d === void 0 || d === true ) {
e.preventDefault();
}
if ( p !== false ) {
e.stopImmediatePropagation();
}
};
var shortcut = {
specKeys: {
8: 'Backspace', 9: 'Tab', 13: 'Enter',
16: 'Shift', 17: 'Ctrl', 18: 'Alt',
27: 'Esc', 32: 'Space',
33: 'PgUp', 34: 'PgDn', 35: 'End', 36: 'Home',
37: 'Left', 38: 'Up', 39: 'Right', 40: 'Down',
45: 'Ins', 46: 'Del',
96: '0', 97: '1', 98: '2', 99: '3', 100: '4',
101: '5', 102: '6', 103: '7', 104: '8', 105: '9',
106: '*', 107: '+', 109: '-', 110: '.', 111: '/', 173: '-',
186: ';', 187: '=', 188: ',', 189: '-', 190: '.',
191: '/', 192: '`', 219: '[', 220: '\\', 221: ']', 222: "'",
112: 'F1', 113: 'F2', 114: 'F3', 115: 'F4', 116: 'F5', 117: 'F6',
118: 'F7', 119: 'F8', 120: 'F9', 121: 'F10', 122: 'F11', 123: 'F12'
},
isModifier: function(e) {
return e.which > 15 && e.which < 19;
},
key: function(e) {
return this.specKeys[e.which]
|| String.fromCharCode(e.which).toUpperCase();
}
};
[doc.documentElement, doc.body, media].forEach(function(node) {
var i = node.attributes.length;
while ( i-- ) {
var attrName = node.attributes[i].name;
if ( node !== media || attrName !== 'src' ) {
node.removeAttribute(attrName);
}
}
});
var root = doc.documentElement;
var progress = null;
var initPingsLeft = 600;
var head = doc.querySelector('head');
if ( head ) {
doc.documentElement.removeChild(head);
}
head = doc.createElement('head');
if ( cfg.favicon ) {
var faviconLink = doc.createElement('link');
faviconLink.rel = 'shortcut icon';
faviconLink.href = cfg.favicon === '%url' && vAPI.mediaType === 'img'
? win.location.href
: cfg.favicon.replace('%url', encodeURIComponent(win.location.href));
head.appendChild(faviconLink);
}
head.appendChild(doc.createElement('style')).textContent = [
'html, body {',
'width: 100%;',
'height: 100%;',
'margin: 0;',
'padding: 0;',
'font: 12px "Trebuchet MS", sans-serif;',
'cursor: default;',
'-webkit-user-select: none;',
'-moz-user-select: none;',
'-ms-user-select: none;',
'}',
'#media {',
'display: block;',
'box-sizing: border-box;',
'max-width: none;',
'max-height: none;',
'position: absolute;',
'margin: 0;',
'background-clip: padding-box;',
'image-orientation: from-image;',
'}',
'html.audio #media {',
'box-sizing: inherit;',
'width: 50%;',
'height: 40px !important;',
'min-width: 300px;',
'max-width: 1000px;',
'position: absolute;',
'top: 0;',
'right: 0;',
'bottom: 0;',
'left: 0;',
'margin: auto;',
'box-shadow: none;',
'background: transparent;',
'}',
'html.load-failed #media {',
'margin: auto;',
'box-shadow: 0 0 10px red;',
'}',
'html.fullscreen #media {',
'background: black !important;',
'}',
'#media:-moz-full-screen {',
'background: black !important;',
'}',
'a {',
'text-decoration: none;',
'}',
':focus {',
'outline: 0;',
'}',
':invalid {',
'box-shadow: none;',
'}',
'#menu {',
'width: 50px;',
'height: 33.33%;',
'position: fixed;',
'top: 0;',
'opacity: 0;',
vAPI.browser.transitionCSS, ': opacity .15s, left .2s;',
'}',
'ul {',
'display: inline-block;',
'margin: 0;',
'padding: 5px 15px;',
'background: rgba(0, 0, 0, .6); color: #fff;',
'font-size: 25px; font-weight: 700;',
'text-align: center;',
'list-style: none;',
'}',
'li {',
'position: relative;',
'display: block;',
'}',
'li[data-cmd] > div {',
'width: 25px;',
'height: 25px;',
'margin: 8px 0;',
'background-repeat: no-repeat;',
'background-size: 100%;',
'cursor: pointer;',
'}',
'li[data-cmd] > div:hover {',
'opacity: .6;',
'}',
'li[data-cmd="cycle"] > div {',
'background-position: 0 0;',
'}',
'li[data-cmd="zoom"] > div {',
'background-position: 0 -125px;',
'}',
'li[data-cmd="flip"] > div {',
'background-position: 0 -50px;',
'}',
'li[data-cmd="rotate"] > div {',
'background-position: 0 -175px;',
'}',
'li[data-cmd].filters > div {',
'background-position: 0 -25px;',
'}',
'li[data-cmd="reset"] > div {',
'background-position: 0 -150px;',
'}',
'li[data-cmd].send-hosts > div {',
'background-position: 0 -200px;',
'}',
'li[data-cmd="frames"] > div {',
'background-position: 0 -75px;',
'}',
'li[data-cmd="options"] > div {',
'background-position: 0 -100px;',
'}',
'li ul {',
'visibility: hidden;',
'position: absolute;',
'top: 0;',
'left: 100%;',
'text-align: left;',
'opacity: 0;',
'}',
'li:hover ul {',
'display: block;',
'visibility: visible;',
'opacity: 1;',
vAPI.browser.transitionCSS, ': visibility .4s, opacity .2s .3s;',
'}',
'li ul > li {',
'display: block !important;',
'padding: 3px 0;',
'font-size: 15px;',
'}',
'.send-hosts li > a {',
'padding-bottom: 3px;',
'padding-left: 25px;',
'background-size: 16px 16px;',
'background-repeat: no-repeat;',
'background-position: 0 3px;',
'color: #fff;',
'cursor: pointer;',
'}',
'#menu > ul > li:hover, .send-hosts li > a:hover {',
'color: silver;',
'}',
'input[type="range"] {',
'vertical-align: middle;',
'}',
'li ul > li {',
'white-space: nowrap;',
'}',
'.filters > ul {',
'font-size: 15px;',
'}',
'.filters > form {',
'margin: 0;',
'padding: 0;',
'}',
'body.frames {',
'overflow-y: scroll !important;',
'text-align: center;',
'}',
'body.frames * {',
'margin: 2px;',
'}',
'#frames > canvas, #frames > img {',
'display: none;',
'}',
'#current-frame + output {',
'display: inline-block;',
'width: 65px;',
'font-family: Conoslas, monospace;',
'text-align: right;',
'}',
'.back {',
'font-size: 150%;',
'text-decoration: none;',
'color: black;',
'}',
'#frames.showall > img, #frames.showall > canvas {',
'display: inline-block !important;',
'}',
// Custom CSS
cfg.css
].join('');
root.insertBefore(head, doc.body);
init = function() {
if ( vAPI.mediaType === 'img' && !media.naturalWidth ) {
if ( progress && --initPingsLeft < 1 ) {
initPingsLeft = null;
clearInterval(progress);
}
return;
}
if ( progress ) {
clearInterval(progress);
progress = null;
}
media.id = 'media';
root.classList.add(vAPI.mediaType);
if ( media.parentNode !== doc.body ) {
doc.body.replaceChild(media, doc.body.firstElementChild);
}
while ( media.previousSibling || media.nextSibling ) {
media.parentNode.removeChild(
media.previousSibling || media.nextSibling
);
}
if ( vAPI.mediaType === 'audio' ) {
return;
}
var winW, winH, panning, sX, sY, mWidth, mHeight, setTitleTimer, menu;
var mOrigWidth, mOrigHeight, mFullWidth, mFullHeight, lastMoveX, lastMoveY;
var mediaCss = Object.create(null);
var noFit = {cur: null, real: null};
var lastEvent = {};
var dragSlide = [];
var freeZoom = null;
var cancelAction = false;
// var MAX_SIZE = 0x7fff;
var MODE_CUSTOM = 0;
var MODE_ORIG = 1;
var MODE_FIT = 2;
var MODE_WIDTH = 3;
var MODE_HEIGHT = 4;
if ( vAPI.mediaType === 'img' ) {
mOrigWidth = media.naturalWidth;
mOrigHeight = media.naturalHeight;
if ( mOrigWidth !== mOrigHeight ) {
// image-orientation in Firefox doesn't flip natural sizes
if ( mOrigWidth / mOrigHeight === media.height / media.width ) {
mOrigWidth = media.naturalHeight;
mOrigHeight = media.naturalWidth;
}
}
} else {
mOrigWidth = media.videoWidth;
mOrigHeight = media.videoHeight;
}
if ( !cfg.mediaInfo ) {
cfg.mediaInfo = false;
}
cfg.hiddenScrollbars = win.getComputedStyle(root).overflow === 'hidden'
|| win.getComputedStyle(doc.body).overflow === 'hidden';
var setMediaStyle = function() {
var css = '';
for ( var p in mediaCss ) {
css += p + ':' + mediaCss[p] + ';';
}
media.style.cssText = css;
};
var setCursor = function() {
var m = media;
var s = m.style;
if ( (m.mode !== MODE_FIT || m.angle )
&& (m.box.width > winW || m.box.height > winH) ) {
s.cursor = 'move';
} else if ( mWidth < mOrigWidth
|| mHeight < mOrigHeight ) {
s.cursor = vAPI.browser.zoomIn;
} else {
s.cursor = '';
}
};
var calcViewportDimensions = function() {
winH = doc.compatMode === 'BackCompat' ? doc.body : root;
winW = winH.clientWidth;
winH = winH.clientHeight;
};
var calcFit = function() {
var m = media;
mWidth = m.clientWidth - (mFullWidth - mOrigWidth);
mHeight = m.clientHeight - (mFullHeight - mOrigHeight);
m.box = m.getBoundingClientRect();
noFit.cur = m.box.width <= winW && m.box.height <= winH;
var radians = m.angle * Math.PI / 180;
var sin = Math.abs(Math.sin(radians));
var cos = Math.abs(Math.cos(radians));
var boxW = mFullWidth * cos + mFullHeight * sin;
var boxH = mFullWidth * sin + mFullHeight * cos;
noFit.real = boxW <= winW && boxH <= winH;
setCursor();
};
var adjustPosition = function() {
var radians = media.angle * Math.PI / 180;
var sin = Math.abs(Math.sin(radians));
var cos = Math.abs(Math.cos(radians));
var w = parseFloat(mediaCss.width || mFullWidth);
var h = w * mFullHeight / mFullWidth;
var boxW = w * cos + h * sin;
var boxH = w * sin + h * cos;
if ( cfg.center ) {
mediaCss.left = Math.max(0, (winW - boxW) / 2);
mediaCss.top = Math.max(0, (winH - boxH) / 2);
} else {
mediaCss.left = 0;
mediaCss.top = 0;
}
if ( media.angle ) {
mediaCss.left += (boxW - w) / 2;
mediaCss.top += (boxH - h) / 2;
}
mediaCss.left += 'px';
mediaCss.top += 'px';
setMediaStyle();
calcFit();
};
var convertInfoParameter = function(a, param) {
var m = media;
switch ( param ) {
case 'w': return m.width;
case 'h': return m.height;
case 'ow': return mOrigWidth;
case 'oh': return mOrigHeight;
case 'url': return win.location.href;
case 'name': return m.alt;
case 'ratio':
return Math.round(m.width / m.height * 100) / 100;
case 'perc': return Math.round(m.width * 100 / mOrigWidth);
}
return '';
};
var setTitle = function() {
if ( !cfg.mediaInfo ) {
return;
}
doc.title = cfg.mediaInfo.replace(
/%(o?[wh]|url|name|ratio|perc)/g,
convertInfoParameter
);
};
var resizeMedia = function(mode, w) {
var boxW;
var newMode = mode === void 0 ? MODE_FIT : mode;
var boxRatio = media.box.width / media.box.height;
media.mode = newMode;
calcViewportDimensions();
if ( !w && mode === MODE_FIT && !noFit.real ) {
newMode = boxRatio > winW / winH ? MODE_WIDTH : MODE_HEIGHT;
}
if ( w ) {
boxW = w;
} else if ( newMode === MODE_WIDTH ) {
boxW = winW;
} else if ( newMode === MODE_HEIGHT ) {
boxW = boxRatio * winH;
} else if ( newMode === MODE_ORIG
|| newMode === MODE_FIT && noFit.real ) {
delete mediaCss.width;
}
if ( boxW ) {
if ( media.angle ) {
var radians = media.angle * Math.PI / 180;
var sin = Math.abs(Math.sin(radians));
var cos = Math.abs(Math.cos(radians));
mediaCss.width = boxW * cos - boxW / boxRatio * sin;
mediaCss.width /= cos * cos - sin * sin;
boxW = mediaCss.width;
} else {
mediaCss.width = boxW;
}
mediaCss.width += 'px';
}
/*if ( mediaCss.width ) {
var offsetWidth = boxW || parseInt(mediaCss.width, 10);
if ( offsetWidth > MAX_SIZE ) {
offsetWidth = MAX_SIZE;
mediaCss.width = MAX_SIZE + 'px';
}
if ( offsetWidth * mFullHeight / mFullWidth > MAX_SIZE ) {
mediaCss.width = MAX_SIZE * mFullWidth / mFullHeight;
mediaCss.width += 'px';
}
}*/
adjustPosition();
clearTimeout(setTitleTimer);
setTitleTimer = setTimeout(setTitle, 50);
};
var cycleModes = function(back) {
var mode = media.mode === MODE_FIT ? MODE_ORIG : media.mode;
var dir = back ? 1 : -1;
mode -= dir;
if ( mode === MODE_FIT ) {
mode -= dir;
} else if ( mode < MODE_ORIG ) {
mode = MODE_HEIGHT;
} else if ( mode > MODE_HEIGHT ) {
mode = MODE_ORIG;
}
resizeMedia(mode);
};
var flipMedia = function(el, direction) {
if ( !media.scale ) {
media.scale = {h: 1, v: 1};
}
media.scale[direction] *= -1;
var transformCss = media.scale.h !== 1 || media.scale.v !== 1
? 'scale(' + media.scale.h + ',' + media.scale.v + ')'
: '';
if ( media.angle ) {
transformCss += ' rotate(' + media.angle + 'deg)';
}
mediaCss[vAPI.browser.transformCSS] = transformCss;
setMediaStyle();
setCursor();
};
var rotateMedia = function(direction, fine) {
var rot = '';
if ( direction === 'right' ) {
media.angle += fine ? 5 : 90;
} else {
media.angle -= fine ? 5 : 90;
}
media.angle %= 360;
if ( media.angle ) {
rot += 'rotate(' + media.angle + 'deg)';
}
if ( media.scale ) {
rot += ' scale(' + media.scale.h + ', ' + media.scale.v + ')';
}
win.status = media.angle + '°';
mediaCss[vAPI.browser.transformCSS] = rot;
adjustPosition();
};
var stopScroll = function(e) {
if ( e ) {
this.removeEventListener(e.type, stopScroll);
}
if ( !dragSlide.length ) {
return;
}
cancelAnimationFrame(progress);
progress = null;
cancelAction = false;
dragSlide.length = 0;
media.dragSlideTime = false;
};
var startScroll = function() {
win.scrollBy(dragSlide[0], dragSlide[1]);
if ( dragSlide[0] ) {
if ( Math.abs(dragSlide[0]) < 1 ) {
dragSlide[0] = 0;
}
dragSlide[0] /= 1.11;
}
if ( dragSlide[1] ) {
if ( Math.abs(dragSlide[1]) < 1 ) {
dragSlide[1] = 0;
}
dragSlide[1] /= 1.11;
}
var box = media.box;
var atRight = Math.max(winW, box.width) - win.pageXOffset === winW;
var atBottom = Math.max(winH, box.height) - win.pageYOffset === winH;
if ( !(dragSlide[0] && dragSlide[1])
|| !win.pageYOffset && !win.pageXOffset
|| !win.pageYOffset && atRight
|| atBottom && !win.pageXOffset
|| atBottom && atRight ) {
stopScroll();
return;
}
progress = requestAnimationFrame(startScroll);
};
var isValidWheelTarget = function(t) {
var d = doc;
return t === media || t === d.body || t === d.documentElement;
};
var wheelZoom = function(e) {
if ( !isValidWheelTarget(e.target) ) {
return;
}
pdsp(e);
stopScroll();
media.box = media.getBoundingClientRect();
var x = e.clientX - media.box.left;
var y = e.clientY - media.box.top;
var w = media.box.width;
var h = media.box.height;
if ( (e.deltaY || -e.wheelDelta) > 0 ) {
resizeMedia(MODE_CUSTOM, Math.max(1, w * 0.75));
} else {
var nW = w * (4 / 3);
resizeMedia(MODE_CUSTOM, nW > 10 ? nW : nW + 3);
}
win.scrollTo(
x * media.box.width / w - e.clientX,
y * media.box.height / h - e.clientY
);
};
var zoomToCenter = function(e) {
wheelZoom({
target: media,
keypress: true,
deltaY: e.deltaY || -e.wheelDelta,
clientX: winW / 2,
clientY: winH / 2
});
};
var onWheel = function(e) {
if ( !isValidWheelTarget(e.target) ) {
return;
}
var w = Math.round(media.box.width);
var h = Math.round(media.box.height);
if ( w <= winW && h <= winH ) {
return;
}
stopScroll();
var x = 0;
var y = ((e.deltaX || e.deltaY || -e.wheelDelta) > 0 ? winH : -winH) / 5;
if ( w <= winW && h > winH ) {
if ( !cfg.hiddenScrollbars ) {
return;
}
} else if ( h <= winH && w > winW
|| e.clientX < winW / 2 && e.clientY > winH - 100
|| e.deltaX && !e.deltaY ) {
x = (y < 0 ? -winW : winW) / 5;
y = 0;
} else if ( !cfg.hiddenScrollbars ) {
return;
}
pdsp(e);
win.scrollBy(x, y);
};
var toggleWheelZoom = function() {
var evName = vAPI.browser.wheel;
var zoomMenuItem = menu && menu.querySelector('li[data-cmd="zoom"]');
if ( zoomMenuItem ) {
zoomMenuItem.style.display = cfg.wheelZoom ? 'none' : '';
}
if ( cfg.wheelZoom ) {
doc.removeEventListener(evName, onWheel, true);
doc.addEventListener(evName, wheelZoom, true);
} else {
doc.removeEventListener(evName, wheelZoom, true);
doc.addEventListener(evName, onWheel, true);
}
cfg.wheelZoom = !cfg.wheelZoom;
};
var onMoveFrame = function() {
win.scrollBy(sX - lastMoveX, sY - lastMoveY);
sX = lastMoveX;
sY = lastMoveY;
panning = null;
};
var onMove = function(e) {
lastMoveX = e.clientX;
lastMoveY = e.clientY;
if ( lastMoveX === lastEvent.clientX
&& lastMoveY === lastEvent.clientY ) {
return;
}
if ( progress ) {
clearTimeout(progress);
progress = lastEvent.button = null;
}
if ( sX === true || noFit.cur ) {
doc.removeEventListener('mousemove', onMove, true);
return;
}
if ( !panning ) {
// Smoother in Opera without setTimeout
if ( vAPI.opera ) {
onMoveFrame();
} else {
panning = requestAnimationFrame(onMoveFrame);
}
}
if ( dragSlide.length !== 3 ) {
dragSlide = [
[lastMoveX, lastMoveY],
[lastMoveX, lastMoveY],
[lastMoveX, lastMoveY]
];
return;
}
// Opera fires move event before mouseup
if ( dragSlide[2][0] === lastMoveX && dragSlide[2][1] === lastMoveY ) {
return;
}
dragSlide[0] = [dragSlide[1][0], dragSlide[1][1]];
dragSlide[1] = [dragSlide[2][0], dragSlide[2][1]];
dragSlide[2] = [lastMoveX, lastMoveY];
media.dragSlideTime = e.timeStamp;
pdsp(e);
};
var onContextMenu = function(e) {
doc.removeEventListener('mousemove', onMove, true);
if ( progress ) {
clearTimeout(progress);
progress = null;
}
if ( cancelAction ) {
cancelAction = false;
pdsp(e, true, false);
}
};
var drawMask = function(e) {
if ( ++freeZoom.counter % 3 ) {
return;
}
var x = e.clientX - freeZoom.left;
var y = e.clientY - freeZoom.top;
if ( e.ctrlKey ) {
var rx = freeZoom.prevX ? x - freeZoom.prevX : 0;
var ry = freeZoom.prevY ? y - freeZoom.prevY : 0;
freeZoom.prevX = x;
freeZoom.prevY = y;
freeZoom.x += rx;
freeZoom.y += ry;
freeZoom.startX += rx;
freeZoom.startY += ry;
} else {
if ( freeZoom.prevX !== void 0 ) {
delete freeZoom.prevX;
delete freeZoom.prevY;
}
freeZoom.w = Math.abs(freeZoom.startX - x);
freeZoom.h = Math.abs(freeZoom.startY - y);
freeZoom.x = freeZoom.startX < x
? freeZoom.startX
: freeZoom.startX - freeZoom.w;
freeZoom.y = freeZoom.startY < y
? freeZoom.startY
: freeZoom.startY - freeZoom.h;
}
media.mctx.clearRect(0, 0, media.mask.width, media.mask.height);
media.mctx.fillRect(0, 0, media.mask.width, media.mask.height);
media.mctx.clearRect(freeZoom.x, freeZoom.y, freeZoom.w, freeZoom.h);
pdsp(e);
};
var longpressHandler = function() {
progress = null;
cancelAction = true;
var action = cfg[lastEvent.button === 2 ? 'lpRight' : 'lpLeft'];
if ( action === 1 ) {
var m = media;
media.box = m.getBoundingClientRect();
var x = (lastEvent.clientX - m.box.left) / m.box.width;
var y = (lastEvent.clientY - m.box.top) / m.box.height;
if ( media.mode === MODE_WIDTH ) {
resizeMedia(MODE_HEIGHT);
} else if ( media.mode === MODE_HEIGHT ) {
resizeMedia(MODE_WIDTH);
} else {
resizeMedia(
media.box.width / media.box.height < winW / winH
? MODE_WIDTH
: MODE_HEIGHT
);
}
if ( m.mode === MODE_WIDTH ) {
x = 0;
y = y * m.box.height - winH / 2;
} else {
x = x * m.box.width - winW / 2;
y = 0;
}
win.scrollTo(x, y);
} else if ( action === 2 ) {
toggleWheelZoom();
}
};
var resetMedia = function() {
if ( freeZoom ) {
doc.removeEventListener('mousemove', drawMask);
doc.body.removeChild(media.mask);
freeZoom = null;
cancelAction = false;
return;
}
if ( vAPI.mediaType === 'img' && doc.readyState !== 'complete' ) {
return;
}
var filters = doc.querySelector('#menu li.filters > form');
if ( filters ) {
media.filters = {};
media.style[vAPI.browser.filter] = '';
filters.reset();
}
delete media.scale;
delete media.bgList;
delete media.bgListIndex;
mediaCss = {};
media.angle = 0;
resizeMedia(MODE_ORIG);
win.scrollTo(0, 0);
};
media.addEventListener('mousedown', function(e) {
pdsp(e, false);
if ( e.button === 1 || e.ctrlKey || e.altKey ) {
return;
}
if ( vAPI.fullScreenElement === media && vAPI.mediaType === 'video' ) {
return;
}
if ( menu && menu.style.display === 'block' ) {
menu.style.display = 'none';
}
if ( !e.shiftKey && vAPI.mediaType === 'video' ) {
var topPart = this.clientHeight;
topPart = Math.min(topPart - 40, topPart / 2);
if ( (e.offsetY || e.layerY || 0) > topPart ) {
return;
}
}
if ( e.button === 0 && this.mode <= MODE_HEIGHT || e.button === 2 ) {
if ( e.button === 2 ) {
sX = true;
} else {
if ( !e.shiftKey && noFit.cur && this.box.width >= 60 ) {
if ( this.box.left + this.box.width - e.clientX <= 30 ) {
lastEvent.clientX = e.clientX;
lastEvent.clientY = e.clientY;
return;
}
}
pdsp(e, true, false);
win.focus();
sX = e.clientX;
sY = e.clientY;
}
if ( !e.shiftKey ) {
doc.addEventListener('mousemove', onMove, true);
}
}
// For fine move and free zoom
if ( e.shiftKey ) {
cancelAction = true;
if ( e.button === 0 ) {
this.box = this.getBoundingClientRect();
freeZoom = {
counter: 0,
left: Math.max(0, this.box.left),
top: Math.max(0, this.box.top)
};
freeZoom.startX = e.clientX - freeZoom.left;
freeZoom.startY = e.clientY - freeZoom.top;
if ( !this.mask ) {
this.mask = doc.createElement('canvas');
this.mask.className = 'mask';
this.mask.style.cssText = [
'display: block',
'position: fixed'
].join(';');
this.mctx = this.mask.getContext('2d');
}
doc.addEventListener('mousemove', drawMask);
this.mask.width = Math.min(winW, this.box.width);
this.mask.height = Math.min(winH, this.box.height);
this.mask.style.left = freeZoom.left + 'px';
this.mask.style.top = freeZoom.top + 'px';
doc.body.appendChild(this.mask);
var maskColor = win.getComputedStyle(this.mask).color;
this.mctx.fillStyle = !maskColor || maskColor === 'rgb(0, 0, 0)'
? 'rgba(0, 0, 0, .4)'
: maskColor;
}
}
// Is dragSlideing
if ( progress ) {
if ( stopScroll ) {
stopScroll();
cancelAction = e.button === 0;
}
if ( e.button === 0 ) {
return;
}
}
if ( e.shiftKey ) {
return;
}
if ( e.button === 0 && !cfg.lpLeft ) {
return;
}
if ( e.button === 2 && !cfg.lpRight ) {
return;
}
lastEvent.clientX = e.clientX;
lastEvent.clientY = e.clientY;
lastEvent.button = e.button;
progress = setTimeout(longpressHandler, 300);
}, true);
doc.addEventListener('mouseup', function(e) {
if ( e.button !== 0 ) {
return;
}
if ( vAPI.fullScreenElement === media && vAPI.mediaType === 'video' ) {
return;
}
var x, y, w, h;
doc.removeEventListener('mousemove', onMove, true);
if ( freeZoom ) {
cancelAction = false;
doc.removeEventListener('mousemove', drawMask);
media.mctx.clearRect(0, 0, media.mask.width, media.mask.height);
doc.body.removeChild(media.mask);
if ( freeZoom.counter < 1 ) {
freeZoom = null;
return;
}
w = Math.min(
media.mask.width,
freeZoom.w + Math.min(freeZoom.x, 0)
+ (freeZoom.x + freeZoom.w > media.mask.width
? media.mask.width - freeZoom.x - freeZoom.w
: 0)
) || 1;
h = Math.min(
media.mask.height,
freeZoom.h + Math.min(freeZoom.y, 0)
+ (freeZoom.y + freeZoom.h > media.mask.height
? media.mask.height - freeZoom.y - freeZoom.h
: 0)
) || 1;
x = Math.max(0, freeZoom.x);
y = Math.max(0, freeZoom.y);
if ( x >= media.box.width || y >= media.box.height ) {
return;
}
var nimgw;
var fitW = winW < w * winH / h;
fitW = e.ctrlKey ? !fitW : fitW;
if ( fitW ) {
nimgw = media.box.width * winW / w;
} else {
nimgw = media.box.height * winH / h;
nimgw *= media.box.width / media.box.height;
}
x = freeZoom.left + x + w / 2 - media.box.left;
y = freeZoom.top + y + h / 2 - media.box.top;
w = media.box.width;
h = media.box.height;
freeZoom = null;
resizeMedia(MODE_CUSTOM, nimgw);
win.scrollTo(
x * media.box.width / w - winW / 2,
y * media.box.height / h - winH / 2
);
return;
}
if ( dragSlide.length === 3 ) {
x = dragSlide[0][0] - dragSlide[2][0];
y = dragSlide[0][1] - dragSlide[2][1];
if ( e.timeStamp - media.dragSlideTime > 100 ) {
cancelAction = false;
dragSlide.length = 0;
return;
}
if ( x || y ) {
dragSlide.length = 2;
dragSlide[0] = x * 1.5;
dragSlide[1] = y * 1.5;
startScroll();
win.addEventListener(vAPI.browser.wheel, stopScroll, true);
return;
}
}
if ( progress ) {
clearTimeout(progress);
progress = null;
}
if ( cancelAction ) {
cancelAction = false;
return;
}
if ( e.shiftKey || e.ctrlKey || e.altKey ) {
return;
}
if ( e.target !== media || lastEvent.button === null ) {
return;
}
if ( e.clientX !== lastEvent.clientX
|| e.clientY !== lastEvent.clientY ) {
return;
}
if ( media.mode < MODE_WIDTH && noFit.real ) {
if ( media.mode === MODE_CUSTOM && mWidth !== mOrigWidth ) {
resizeMedia(MODE_ORIG);
} else if ( (media.mode === MODE_FIT || media.mode === MODE_ORIG)
&& (media.box.width === winW || media.box.height === winH) ) {
resizeMedia(MODE_ORIG);
} else {
resizeMedia(
MODE_FIT,
mWidth === mOrigWidth
? media.box.width / media.box.height > winW / winH
? winW
: winH * media.box.width / media.box.height
: void 0
);
}
} else if ( media.mode === MODE_FIT || noFit.cur ) {
x = e.clientX - media.box.left;
y = e.clientY - media.box.top;
w = media.box.width;
h = media.box.height;
resizeMedia(MODE_ORIG);
win.scrollTo(
x * media.box.width / w - winW / 2,
y * media.box.height / h - winH / 2
);
} else {
resizeMedia(MODE_FIT);
}
}, true);
doc.addEventListener('keydown', function(e) {
if ( stopScroll ) {
stopScroll();
}
if ( shortcut.isModifier(e) ) {
return;
}
var key = shortcut.key(e);
if ( e.ctrlKey || freeZoom && key !== 'Esc' ) {
return;
}
if ( key === '+' || key === '-' ) {
pdsp(e);
zoomToCenter({deltaY: key === '+' ? -1 : 1});
return;
}
var x, y, z;
switch ( key ) {
case 'Esc':
resetMedia();
break;
case 'Left':
x = e.shiftKey ? -10 : -50;
y = 0;
break;
case 'Right':
x = e.shiftKey ? 10 : 50;
y = 0;
break;
case 'Up':
x = 0;
y = e.shiftKey ? -10 : -50;
break;
case 'Down':
x = 0;
y = e.shiftKey ? 10 : 50;
break;
case 'PgUp':
x = e.shiftKey ? -winW / 2 : 0;
y = e.shiftKey ? 0 : -winH / 2;
break;
case 'PgDn':
x = e.shiftKey ? winW / 2 : 0;
y = e.shiftKey ? 0 : winH / 2;
break;
case 'End':
x = e.shiftKey
? Math.max(winW, media.box.width)
: win.pageXOffset;
y = e.shiftKey
? win.pageYOffset
: Math.max(winH, media.box.height);
z = true;
break;
case 'Home':
x = e.shiftKey ? 0 : win.pageXOffset;
y = e.shiftKey ? win.pageYOffset : 0;
z = true;
break;
default: x = true;
}
if ( x !== true ) {
if ( x !== void 0 ) {
win[z ? 'scrollTo' : 'scrollBy'](x, y);
pdsp(e, true, false);
}
return;
}
switch ( key ) {
case cfg.key_mOrig:
resizeMedia(MODE_ORIG);
break;
case cfg.key_mFit:
resizeMedia(MODE_FIT);
break;
case cfg.key_mFitW:
resizeMedia(MODE_WIDTH);
break;
case cfg.key_mFitH:
resizeMedia(MODE_HEIGHT);
break;
case cfg.key_cycle:
cycleModes(e.shiftKey);
break;
case cfg.key_rotL:
rotateMedia('left', e.shiftKey);
break;
case cfg.key_rotR:
rotateMedia('right', e.shiftKey);
break;
case cfg.key_flipH:
flipMedia(media, 'h');
break;
case cfg.key_flipV:
flipMedia(media, 'v');
break;
case cfg.key_wheelZoom:
toggleWheelZoom();
break;
case cfg.key_pixelate:
if ( vAPI.mediaType !== 'img' ) {
break;
}
var ir = win.getComputedStyle(media).imageRendering;
if ( ir === vAPI.browser.irPixelated ) {
mediaCss['image-rendering'] = 'auto';
} else {
mediaCss['image-rendering'] = vAPI.browser.irPixelated;
}
setMediaStyle();
break;
case cfg.key_imgBg:
if ( vAPI.mediaType !== 'img' ) {
break;
}
// eslint-disable-next-line no-alert
var bgValue = e.shiftKey && prompt(
'background',
media.style.background
);
if ( bgValue === null ) {
break;
}
if ( bgValue !== false ) {
mediaCss.background = bgValue;
setMediaStyle();
break;
}
if ( !media.bgList ) {
bgValue = win.getComputedStyle(media);
bgValue = bgValue.background || bgValue.backgroundColor;
media.bgList = {};
media.bgList[bgValue] = true;
media.bgList['rgb(0, 0, 0)'] = true;
media.bgList['rgb(255, 255, 255)'] = true;
media.bgList['url(data:image/gif;base64,R0lGODlhFAAUAPABAO'
+ 'jo6P///yH5BAAKAAAALAAAAAAUABQAAAIohI+hy+jAYnhJLnrsx'
+ 'VBP7n1YyHVaSYKhh7Lq+VotPLo1TaW3HEtlAQA7)'] = true;
media.bgList = Object.keys(media.bgList).filter(Boolean);
media.bgListIndex = 0;
}
mediaCss.background = media.bgList[
++media.bgListIndex % media.bgList.length
];
setMediaStyle();
break;
default: x = true;
}
if ( vAPI.mediaType === 'video' ) {
x = null;
if ( key === 'Space' ) {
media.togglePlay();
} else if ( key === 'Up' || key === 'Down' ) {
key = media.volume + (key === 'Up' ? 0.1 : -0.1);
// Must check the range manually,
// otherwise browsers will throw an error
media.volume = key < 0
? 0
: key > 1 ? 1 : key;
} else {
x = true;
}
}
pdsp(e, x !== true, true);
}, true);
doc.addEventListener('contextmenu', onContextMenu, true);
win.addEventListener('resize', function() {
media.removeAttribute('width');
media.removeAttribute('height');
resizeMedia(media.mode);
});
toggleWheelZoom();
if ( vAPI.mediaType === 'video' ) {
media.addEventListener('click', function(e) {
if ( e.button !== 0 ) {
return;
}
var y = e.offsetY || e.layerY || 0;
if ( y > media.clientHeight - 40 ) {
return;
}
if ( vAPI.fullScreenElement === this
|| y > media.clientHeight / 2 ) {
media.togglePlay();
}
pdsp(e);
});
media.addEventListener('dblclick', function(e) {
if ( (e.offsetY || e.layerY || 0) < media.clientHeight / 2 ) {
pdsp(e);
}
});
}
progress = [];
media.angle = 0;
media.setAttribute('width', mOrigWidth);
media.setAttribute('height', mOrigHeight);
// Original dimensions with padding and border
mFullWidth = media.offsetWidth;
mFullHeight = media.offsetHeight;
calcViewportDimensions();
calcFit();
media.removeAttribute('width');
media.removeAttribute('height');
if ( vAPI.mediaType === 'img' && cfg.minUpscale && noFit.real ) {
if ( mOrigWidth >= winW * cfg.minUpscale / 100 ) {
progress[0] = true;
}
if ( mOrigHeight >= winH * cfg.minUpscale / 100 ) {
progress[1] = true;
}
}
// cfg.mode values: 0 - natural size; 1 - contain; 2 - best fit (fill)
if ( cfg.mode === 2 ) {
if ( noFit.real ) {
media.mode = MODE_FIT;
} else {
media.mode = mOrigWidth / mOrigHeight < winW / winH
? MODE_WIDTH
: MODE_HEIGHT;
}
} else {
media.mode = cfg.mode === 0 ? MODE_ORIG : MODE_FIT;
}
if ( media.mode === MODE_WIDTH && mOrigWidth < winW && !progress[0] ) {
media.mode = MODE_ORIG;
} else if ( !progress[1] ) {
if ( media.mode === MODE_HEIGHT && mOrigHeight < winH ) {
media.mode = MODE_ORIG;
}
}
resizeMedia(
media.mode,
media.mode <= MODE_FIT && progress.length
? mOrigWidth / mOrigHeight > winW / winH
? winW
: winH * mOrigWidth / mOrigHeight
: void 0
);
progress = null;
menu = root.appendChild(doc.createElement('div'));
menu.id = 'menu';
if ( win.getComputedStyle(menu).display === 'none' ) {
menu.parentNode.removeChild(menu);
menu = null;
return;
}
menu.style.cssText = '-webkit-filter: blur(0px); filter: blur(0px);';
if ( menu.style.filter || menu.style.webkitFilter ) {
vAPI.browser.filter = menu.style.filter
? 'filter'
: '-webkit-filter';
}
var onMenuChange = function(e) {
var filterName;
var filterCSS = '';
var t = e.target;
if ( !t.value ) {
media.style[vAPI.browser.filter] = filterCSS;
return;
}
if ( t.value === t.defaultValue ) {
delete media.filters[t.parentNode.textContent.trim()];
} else {
filterName = t.parentNode.textContent.trim();
media.filters[filterName] = t.value + t.getAttribute('unit');
}
for ( filterName in media.filters ) {
filterCSS += filterName;
filterCSS += '(' + media.filters[filterName] + ') ';
}
if ( filterCSS ) {
mediaCss[vAPI.browser.filter] = filterCSS;
} else {
delete mediaCss[vAPI.browser.filter];
}
media.style[vAPI.browser.filter] = filterCSS;
};
if ( vAPI.browser.filter ) {
media.filters = Object.create(null);
menu.addEventListener('change', onMenuChange);
} else {
onMenuChange = null;
}
vAPI.buildNodes(menu.appendChild(doc.createElement('ul')), [
{tag: 'li', attrs: {'data-cmd': 'cycle'}, nodes: [{tag: 'div'}]},
{tag: 'li', attrs: {'data-cmd': 'zoom'}, nodes: [{tag: 'div'}]},
{tag: 'li', attrs: {'data-cmd': 'flip'}, nodes: [{tag: 'div'}]},
{tag: 'li', attrs: {'data-cmd': 'rotate'}, nodes: [{tag: 'div'}]},
media.filters ? {tag: 'li', attrs: {class: 'filters', 'data-cmd': 'filters'}, nodes: [
{tag: 'div'},
{tag: 'form', nodes: [{tag: 'ul', nodes: [
{tag: 'li', nodes: [
{
tag: 'input',
attrs: {
type: 'range',
min: 0,
max: 250,
step: 10,
value: 100,
unit: '%'
}
},
' brightness'
]},
{tag: 'li', nodes: [
{
tag: 'input',
attrs: {
type: 'range',
min: 0,
max: 300,
step: 25,
value: 100,
unit: '%'
}
},
' contrast'
]},
{tag: 'li', nodes: [
{
tag: 'input',
attrs: {
type: 'range',
min: 0,
max: 1000,
step: 50,
value: 100,
unit: '%'
}
},
' saturate'
]},
{tag: 'li', nodes: [
{
tag: 'input',
attrs: {
type: 'range',
min: 0,
max: 100,
step: 25,
value: 0,
unit: '%'
}
},
' grayscale'
]},
{tag: 'li', nodes: [
{
tag: 'input',
attrs: {
type: 'range',
min: 0,
max: 100,
step: 100,
value: 0,
unit: '%'
}
},
' invert'
]},
{tag: 'li', nodes: [
{
tag: 'input',
attrs: {
type: 'range',
min: 0,
max: 100,
step: 20,
value: 0,
unit: '%'
}
},
' sepia'
]},
{tag: 'li', nodes: [
{
tag: 'input',
attrs: {
type: 'range',
min: 0,
max: 360,
step: 36,
value: 0,
unit: 'deg'
}
},
' hue-rotate'
]},
{tag: 'li', nodes: [
{
tag: 'input',
attrs: {
type: 'range',
min: 0,
max: 20,
step: 1,
value: 0,
unit: 'px'
}
},
' blur'
]}
]}]}
]} : '',
{tag: 'li', attrs: {'data-cmd': 'reset'}, nodes: [{tag: 'div'}]},
/^https?:$/.test(win.location.protocol) && cfg.sendToHosts.length
? {
tag: 'li',
attrs: {class: 'send-hosts', 'data-cmd': ''},
nodes: [{tag: 'div'}, {
tag: 'ul',
nodes: cfg.sendToHosts.map(function(item) {
var host = item.split('|');
return {
tag: 'li',
nodes: [{
tag: 'a',
attrs: {href: host.slice(1).join('|')},
text: host[0]
}]
};
})
}]
}
: null,
vAPI.mediaType === 'img'
? {
tag: 'li',
attrs: {'data-cmd': 'frames'},
nodes: [{tag: 'div'}]
}
: '',
{tag: 'li', attrs: {'data-cmd': 'options'}, nodes: [{tag: 'div'}]}
]);
menu.style.cssText = 'display: none; left: -' + menu.offsetWidth + 'px';
menu.addEventListener('mousedown', function(e) {
var t = e.target;
var href = t.getAttribute('href');
if ( href && href.indexOf('%') !== -1 ) {
t.href = href.replace('%url', encodeURIComponent(media.src));
}
pdsp(e, !!t.textContent);
});
// Load favicons only when the menu item is hovered for the first time
if ( cfg.sendToHosts.length && /^https?:$/.test(win.location.protocol) ) {
menu.onHostsHover = function(e) {
this.removeEventListener(e.type, menu.onHostsHover);
delete menu.onHostsHover;
var links = this.querySelectorAll('.send-hosts > ul > li > a');
[].forEach.call(links, function(a) {
var host = a.getAttribute('href');
host = host && host.match(/^[^\/]*(\/\/[^\/]+)/);
if ( !host ) {
return;
}
a.style.backgroundImage = 'url(' + host[1] + '/favicon.ico)';
});
};
menu.querySelector('.send-hosts > ul').addEventListener(
vAPI.browser.transitionend,
menu.onHostsHover
);
}
var handleCommand = function(cmd, e) {
if ( e.button === 1 ) {
return;
}
var p = e.button === 2
|| e.type === vAPI.browser.wheel
&& (e.deltaY || -e.wheelDelta) > 0;
if ( cmd === 'cycle' ) {
cycleModes(!p);
} else if ( cmd === 'flip' ) {
flipMedia(media, p ? 'v' : 'h');
} else if ( cmd === 'rotate' ) {
rotateMedia(p ? 'left' : 'right', e.ctrlKey);
} else if ( cmd === 'zoom' ) {
pdsp(e);
zoomToCenter({deltaY: p ? 1 : -1});
} else if ( cmd === 'reset' ) {
if ( e.button === 0 ) {
resetMedia();
}
} else if ( cmd === 'filters' ) {
if ( e.button === 2 ) {
media.filters = {};
delete mediaCss[vAPI.browser.filter];
media.style[vAPI.browser.filter] = '';
doc.querySelector('#menu li.filters > form').reset();
}
} else if ( cmd === 'frames' ) {
var message = {cmd: 'loadFile', path: 'js/frames.js'};
vAPI.messaging.send(message, function(data) {
var errorHandler = function(alertMessage) {
// Success
if ( alertMessage !== null ) {
// eslint-disable-next-line no-alert
alert(alertMessage);
menu.querySelector('li[data-cmd="frames"]')
.removeAttribute('data-cmd');
return;
}
if ( menu ) {
menu.parentNode.removeChild(menu);
}
};
// eslint-disable-next-line no-new-func
Function('win', 'drawFullFrame', 'errorHandler', data)(
win,
e.button === 0,
errorHandler
);
});
} else if ( cmd === 'options' && e.button !== 1 ) {
vAPI.messaging.send({
cmd: 'openURL',
url: 'options.html' + (e.button === 2 ? '#shortcuts' : '')
});
} else {
p = null;
}
if ( p !== null ) {
pdsp(e);
}
};
var onMenuClick = function(e) {
var cmd = e.target.parentNode.getAttribute('data-cmd');
if ( cmd ) {
handleCommand(cmd, e);
}
};
var menuTrigger = function(e) {
if ( panning || freeZoom || e.shiftKey ) {
return;
}
if ( e.clientX > 40 || e.clientX < 0 ) {
return;
}
if ( e.clientY > win.innerHeight / 3 || e.clientY < 0 ) {
return;
}
if ( menu.style.display === 'block' ) {
return;
}
if ( !menu.iconsLoaded ) {
var bgImage = win.getComputedStyle(menu).backgroundImage;
if ( bgImage && bgImage !== 'none' ) {
menu.iconsLoaded = true;
}
}
if ( !menu.iconsLoaded ) {
var message = {cmd: 'loadFile', path: 'css/menu_icons.b64png'};
vAPI.messaging.send(message, function(img) {
var sheet = doc.head.querySelector('style').sheet;
sheet.insertRule(
'li[data-cmd] > div {background-image: url(' + img + ');}',
sheet.cssRules.length
);
menu.iconsLoaded = true;
});
}
menu.style.display = 'block';
setTimeout(function() {
menu.style.left = '0';
menu.style.opacity = '1';
}, 50);
doc.removeEventListener('mousemove', menuTrigger);
};
menu.addEventListener(vAPI.browser.wheel, function(e) {
pdsp(e);
var t = e.target;
if ( t.nodeType === 3 ) {
t = t.parentNode;
}
if ( t.type === 'range' ) {
var delta = (e.deltaY || -e.wheelDelta) > 0 ? -1 : 1;
t.value = Math.max(
t.getAttribute('min'),
Math.min(
parseInt(t.value, 10) + t.getAttribute('step') * delta,
t.getAttribute('max')
)
);
onMenuChange(e);
} else if ( !/reset|frames|options/.test(t.getAttribute('data-cmd')
|| (t = t.parentNode) && t.getAttribute('data-cmd')) ) {
handleCommand(t.getAttribute('data-cmd'), e);
}
});
menu.addEventListener('click', onMenuClick);
menu.addEventListener('contextmenu', function(e) {
var target = e.target;
if ( target.type === 'range' ) {
target.value = target.defaultValue;
onMenuChange(e);
pdsp(e);
return;
}
onMenuClick(e);
});
menu.addEventListener(vAPI.browser.transitionend, function(e) {
if ( e.propertyName === 'left' && this.style.left[0] === '-' ) {
this.style.display = 'none';
}
});
menu.addEventListener('mouseenter', function() {
if ( !this.hideTimer ) {
return;
}
clearTimeout(this.hideTimer);
this.hideTimer = null;
this.style.left = '0';
this.style.opacity = '1';
});
menu.addEventListener('mouseleave', function() {
this.hideTimer = setTimeout(function() {
doc.addEventListener('mousemove', menuTrigger);
menu.hideTimer = null;
menu.style.left = '-' + menu.offsetWidth + 'px';
menu.style.opacity = '0';
}, 800);
});
// Safari showed the menu even if the cursor wasn't at the edge
setTimeout(function() {
doc.addEventListener('mousemove', menuTrigger);
}, 500);
};
root = doc.documentElement;
media.addEventListener('error', function() {
// Opera fires an error event on local video files
// when they're close to the end
// Firefox did it a few times too,
// even if there was nothing wrong with the video
if ( media.currentTime > 0.1 && win.location.protocol === 'file:' ) {
return;
}
clearInterval(progress);
root.classList.add('load-failed');
});
if ( win.location.protocol === 'data:' ) {
media.alt = vAPI.mediaType + ' (data:)';
if ( !cfg.mediaInfo ) {
doc.title = media.alt;
}
} else {
media.alt = (win.location.href
.replace(/#.*/, '')
.match(/(?:[^\/]+)?$/)[0] || vAPI.mediaType
).split('?')[0];
try {
// Some Unicode characters caused problems for decodeURIComponent
media.alt = decodeURIComponent(media.alt);
} catch ( ex ) {
//
}
}
if ( vAPI.mediaType === 'img' ) {
// Try to prevent default browser action
doc.body.addEventListener('click', function(e) {
e.stopImmediatePropagation();
}, true);
if ( media.naturalWidth ) {
initPingsLeft = 0;
init();
return;
}
progress = setInterval(init, 100);
return;
}
var attributeValues = {};
var mediaAttributes = ['autoplay', 'controls', 'loop', 'muted', 'volume'];
cfg.mediaAttrs.split(/\s+/).forEach(function(attribute) {
var attr = attribute.split('=');
if ( attr[0] === 'volume' ) {
attributeValues[attr[0]] = Math.min(
100,
Math.max(0, parseInt(attr[1], 10) / 100)
);
} else {
attributeValues[attr[0]] = true;
}
});
mediaAttributes.forEach(function(attr) {
if ( attr === 'volume' ) {
media[attr] = attributeValues[attr] === void 0
? 1
: attributeValues[attr];
} else {
media[attr] = attributeValues[attr] || false;
}
});
media.togglePlay = function() {
if ( this.paused || Math.abs(this.duration - this.currentTime) < 0.01 ) {
this.play();
} else {
this.pause();
}
};
media.addEventListener('loadedmetadata', function onLoadedMetadata(e) {
this.removeEventListener(e.type, onLoadedMetadata);
if ( this.videoHeight && (vAPI.opera || vAPI.chrome) ) {
doc.addEventListener('fullscreenchange', function() {
root.classList.toggle('fullscreen');
});
}
var playerStateSaver;
var monitoredAttrs = mediaAttributes.slice(1, -2);
var savePlayerState = function() {
var mediaAttrs = [];
mediaAttributes.forEach(function(attr) {
if ( attr === 'volume' ) {
if ( media.volume < 1 ) {
mediaAttrs.push(attr + '=' + (100 * media.volume | 0));
}
} else if ( media[attr] ) {
mediaAttrs.push(attr);
}
});
vAPI.messaging.send({cmd: 'savePrefs', prefs: {
mediaAttrs: mediaAttrs.join(' ')
}});
};
var onAttributeChange = function() {
if ( !media.controls && vAPI.mediaType === 'audio' ) {
media.controls = true;
}
clearTimeout(playerStateSaver);
playerStateSaver = setTimeout(savePlayerState, 500);
};
if ( win.MutationObserver ) {
new MutationObserver(onAttributeChange).observe(media, {
attributes: true,
attributeFilter: monitoredAttrs
});
} else {
// Legacy
media.addEventListener('DOMAttrModified', function(ev) {
if ( monitoredAttrs.indexOf(ev.attrName) > -1 ) {
onAttributeChange();
}
});
}
media.addEventListener('volumechange', onAttributeChange);
doc.addEventListener('keydown', function(ev) {
var key = shortcut.key(ev);
if ( key === 'Space' ) {
media.togglePlay();
} else if ( key === 'Up' || key === 'Down' ) {
key = media.volume + (key === 'Up' ? 0.1 : -0.1);
media.volume = key < 0
? 0
: key > 1 ? 1 : key;
} else {
return;
}
pdsp(ev);
});
media.addEventListener('dblclick', function(ev) {
pdsp(ev);
});
if ( media.autoplay ) {
setTimeout(media.play.bind(media), 50);
}
if ( this.videoHeight ) {
init();
return;
}
vAPI.mediaType = 'audio';
media.controls = true;
doc.title = media.alt;
init();
if ( vAPI.opera || vAPI.firefox ) {
return;
}
// To not show the black poster when audio restarts or if seek happens
media.addEventListener('playing', function() {
this.poster = 'data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=';
});
});
// eslint-disable-next-line padded-blocks
};
// eslint-disable-next-line padded-blocks
(function() {
if ( vAPI.safari && location.protocol === 'safari-extension:' ) {
init = null;
vAPI.suicideAttempt();
return;
}
var firstContact = function() {
if ( vAPI.opera || vAPI.firefox ) {
if ( !vAPI.mediaType ) {
init = null;
firstContact = null;
vAPI.suicideAttempt();
return;
}
vAPI.messaging.send({cmd: 'loadPrefs'}, function(response) {
firstContact = null;
init(window, document, response);
});
return;
}
vAPI.messaging.send({cmd: 'loadPrefs'}, function(response) {
firstContact = null;
if ( !vAPI.mediaType ) {
init = null;
vAPI.suicideAttempt();
return;
}
init(window, document, response);
});
};
firstContact();
var count = 0;
var pingBackground = setInterval(function() {
if ( firstContact === null || ++count > 4 ) {
clearInterval(pingBackground);
return;
}
firstContact();
}, 3000);
// eslint-disable-next-line padded-blocks
})();
'use strict';
var vAPI = Object.create(null);
vAPI.maxthon = true;
vAPI._runtime = external.mxGetRuntime();
vAPI.app = (function() {
var extInfo = location.hash.slice(1).split(',');
return {
name: extInfo[0],
version: extInfo[1],
platform: 'Maxthon ' + external.mxVersion
};
})();
vAPI.storage = {
_mxStorage: vAPI._runtime.storage,
get: function(key, callback) {
var value = this._mxStorage.getConfig(key);
callback(value === '' ? null : value);
},
set: function(key, value) {
return this._mxStorage.setConfig(key, value);
},
remove: function(key) {
this.set(key, '');
}
};
vAPI.tabs = {
_mxTabs: new mx.browser.tabs,
create: function(params) {
if ( /^[a-z-]{2,10}:/.test(params.url) === false ) {
params.url = vAPI._runtime.getPrivateUrl() + params.url;
}
this._mxTabs.newTab({
url: params.url,
activate: params.active
});
}
};
vAPI.messaging = {
listen: function(callback, name) {
vAPI._runtime.listen(name || 'service', function(request) {
var listenerId = request.listenerId;
callback(
JSON.parse(request.message),
{url: request.url},
function(response) {
vAPI._runtime.post(listenerId, JSON.stringify(response));
}
);
});
}
};
'use strict';
var cachedPrefs;
var onPrefsUpdatedCallbacks = [];
var xhr = function(url, onLoad) {
var req = new XMLHttpRequest;
req.overrideMimeType('application/json;charset=utf-8');
req.open('GET', url, true);
req.addEventListener('load', onLoad);
req.send();
};
var updatePrefs = function(newPrefs, storedPrefs) {
xhr('defaults.json', function() {
var key;
var defPrefs = JSON.parse(this.responseText);
cachedPrefs = {};
for ( key in defPrefs ) {
cachedPrefs[key] = storedPrefs[key] === void 0
? defPrefs[key]
: storedPrefs[key];
if ( newPrefs[key] === void 0 ) {
continue;
}
if ( typeof newPrefs[key] !== typeof defPrefs[key] ) {
continue;
}
if ( newPrefs[key] === defPrefs[key] ) {
cachedPrefs[key] = defPrefs[key];
continue;
}
if ( typeof defPrefs[key] === 'object'
&& JSON.stringify(newPrefs[key]) === JSON.stringify(defPrefs[key]) ) {
cachedPrefs[key] = defPrefs[key];
continue;
}
cachedPrefs[key] = newPrefs[key];
}
while ( onPrefsUpdatedCallbacks.length ) {
onPrefsUpdatedCallbacks.pop()();
}
// In order to initialize sooner on content side, Chrome reads the prefs
// there (to avoid messaging), so we have to save all prefs
if ( vAPI.chrome ) {
vAPI.storage.set('cfg', JSON.stringify(cachedPrefs));
return;
}
var prefsToStore = {};
for ( key in defPrefs ) {
if ( cachedPrefs[key] === defPrefs[key] ) {
continue;
}
if ( typeof defPrefs[key] === 'object' ) {
if ( JSON.stringify(cachedPrefs[key]) === JSON.stringify(defPrefs[key]) ) {
continue;
}
}
prefsToStore[key] = cachedPrefs[key];
}
prefsToStore = JSON.stringify(prefsToStore);
if ( prefsToStore === '{}' ) {
vAPI.storage.remove('cfg');
} else if ( prefsToStore !== JSON.stringify(storedPrefs) ) {
vAPI.storage.set('cfg', prefsToStore);
}
});
};
var onMessage = function(message, source, respond) {
var cmd = message.cmd;
if ( cmd === 'loadPrefs' ) {
if ( cachedPrefs === void 0 ) {
onPrefsUpdatedCallbacks.push(function() {
onMessage(message, source, respond);
});
return;
}
var response = {
prefs: message.property
? cachedPrefs[message.property]
: cachedPrefs
};
if ( !message.getAppInfo ) {
respond(response);
return;
}
xhr('defaults.json', function() {
response._app = vAPI.app;
response._defaultPrefs = this.responseText;
respond(response);
});
} else if ( cmd === 'savePrefs' ) {
vAPI.storage.get('cfg', function(cfg) {
updatePrefs(message.prefs, JSON.parse(cfg || '{}'));
});
} else if ( cmd === 'openURL' ) {
if ( !Array.isArray(message.url) ) {
message.url = [message.url];
}
message.url.forEach(function(url) {
if ( !url || typeof url !== 'string' ) {
return;
}
vAPI.tabs.create({url: url, active: !message.nf});
});
} else if ( cmd === 'loadFile' ) {
xhr(message.path, function() {
respond(this.responseText);
});
}
};
vAPI.storage.get('cfg', function(cfg) {
var storedPrefs;
try {
storedPrefs = JSON.parse(cfg || '{}');
} catch ( ex ) {
storedPrefs = {};
}
updatePrefs(storedPrefs, storedPrefs);
});
vAPI.messaging.listen(onMessage);
document.title = ':: ' + vAPI.app.name + ' ::';
/* global win, errorHandler, drawFullFrame */
'use strict';
var $ = function(id) {
return document.getElementById(id);
};
var crc32 = (function() {
var c, k;
var n = 0;
var crcTable = [];
for ( ; n < 256; ++n ) {
for ( c = n, k = 0; k < 8; ++k ) {
c = c & 1 ? 0xedb88320 ^ c >>> 1 : c >>> 1;
}
crcTable[n] = c;
}
return function(s) {
var i = 0;
var crc = -1;
var length = s.length;
while ( i < length ) {
crc = crcTable[(crc ^ s.charCodeAt(i++)) & 0xff] ^ crc >>> 8;
}
return crc ^ -1;
};
})();
var BinaryTools = function(data) {
this.pos = 0;
this.data = data;
this.length = data.length;
this.littleEndian = false;
this.zeropad = '00000000';
this.readByte = function(position) {
var pos = position === void 0 || position < 0 ? this.pos++ : position;
return this.data.charCodeAt(pos) & 0xff;
};
this.readString = function(length, position) {
var pos;
if ( position === void 0 || position < 0 ) {
pos = this.pos;
this.pos += length || 0;
} else {
pos = position;
}
return this.data.substr(pos, length || 0);
};
this.readBits = function(length, pos) {
var curbyte;
var bitarray = [];
var i = 0;
while ( i++ < length ) {
curbyte = this.readByte(pos).toString(2);
bitarray.push(
this.zeropad.substr(
0,
this.zeropad.length - curbyte.length
) + curbyte
);
}
return (this.littleEndian ? bitarray.reverse() : bitarray).join('');
};
this.readInt = function(bytes, position) {
if ( bytes < 1 ) {
return null;
}
var pos, i;
var integer = 0;
if ( position === void 0 || position < 0 ) {
pos = this.pos;
this.pos += bytes;
} else {
pos = position;
}
if ( this.littleEndian ) {
i = bytes - 1;
while ( i >= 0 ) {
integer += this.readByte(pos + i) << i-- * 8;
}
} else {
i = 0;
while ( i < bytes ) {
integer += this.readByte(pos + i++) << (bytes - i) * 8;
}
}
return integer >>> 0;
};
this.intToBytes = function(integer, numberOfBytes) {
var i = numberOfBytes || 4;
var bytes = [];
while ( i-- ) {
bytes.push(integer >> i * 8 & 0xff);
}
return String.fromCharCode.apply(
null,
this.littleEndian ? bytes.reverse() : bytes
);
};
};
if ( !win.opera ) {
// Solves utf8 problems
win.btoa = function(b64str) {
var c1, c2;
var b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
var mod = b64str.length % 3;
var l = b64str.length - mod;
var pos = 0;
var res = '';
while ( pos < l ) {
c1 = b64str.charCodeAt(pos++) & 0xff;
c2 = b64str.charCodeAt(pos++) & 0xff;
res += b64chars[c1 >> 2];
res += b64chars[(c1 & 3) << 4 | c2 >> 4];
c1 = b64str.charCodeAt(pos++) & 0xff;
res += b64chars[(c2 & 0x0f) << 2 | c1 >> 6];
res += b64chars[c1 & 0x3f];
}
if ( mod === 0 ) {
return res;
}
c1 = b64str.charCodeAt(pos++) & 0xff;
res += b64chars[c1 >> 2];
if ( mod === 1 ) {
res += b64chars[(c1 & 3) << 4];
res += '==';
} else {
c2 = b64str.charCodeAt(pos++) & 0xff;
res += b64chars[(c1 & 3) << 4 | c2 >> 4];
res += b64chars[(c2 & 0x0f) << 2];
res += '=';
}
return res;
};
}
var maxSize = 20 * 1024 * 1024;
var xhr = new win.XMLHttpRequest;
xhr.overrideMimeType('text/plain; charset=x-user-defined');
xhr.addEventListener('readystatechange', function() {
if ( this.readyState === 2 ) {
var contentLength = this.getResponseHeader('Content-Length');
if ( contentLength && contentLength > maxSize ) {
this.abort();
errorHandler('Image is too large...');
return;
}
}
if ( !this.responseText ) {
return;
}
var i, chunkSize, imgHead;
if ( !this.imgType ) {
// PNG or GIF or WEBP signature
imgHead = /^(?:\x89(PNG)\r\n\x1a\n|(GIF)8[79]a|RIFF....(WEBP)VP8X)/;
this.imgType = this.responseText.match(imgHead);
// Seems like in some cases a character encoding is applied anyway,
// however it's enough to check only the signature
if ( !this.imgType ) {
if ( this.responseText[1] === 'P' ) {
chunkSize = 8;
} else if ( this.responseText[0] === 'G' ) {
chunkSize = 6;
} else if ( this.responseText[0] === 'R' ) {
chunkSize = 1;
}
if ( chunkSize ) {
this.imgType = this.responseText.slice(0, chunkSize).split('');
for ( i = 0; i < this.imgType.length; ++i ) {
this.imgType[i] = this.imgType[i].charCodeAt(0) & 0xff;
}
this.imgType = String.fromCharCode
.apply(null, this.imgType)
.match(imgHead);
}
}
if ( !this.imgType ) {
this.abort();
errorHandler('Not animated...');
return;
}
this.imgType = this.imgType[2] || this.imgType[1] || this.imgType[3];
}
if ( this.readyState !== 4 ) {
/* || this.status !== 200*/
return;
}
if ( this.responseText.length > maxSize ) {
errorHandler('Image is too large...');
return;
}
var IHDR, chunkType;
var frames = [];
var bin = new BinaryTools(this.responseText);
var animation = {};
imgHead = '';
if ( this.imgType === 'PNG' ) {
// https://wiki.mozilla.org/APNG_Specification
// Skip signature
bin.pos = 8;
while ( bin.pos < bin.length ) {
// Read the chunk type
chunkType = bin.readString(4, bin.pos + 4);
// console.log(i, chunkType, bin.readInt(4, bin.pos));
if ( chunkType === 'IHDR' ) {
// Skip chunk length and name
bin.pos += 8;
animation.width = bin.readInt(4);
animation.height = bin.readInt(4);
IHDR = bin.readString(5);
// Skip crc
bin.pos += 4;
} else if ( chunkType === 'acTL' ) {
if ( frames.length ) {
continue;
}
animation.numFrames = bin.readInt(4, bin.pos + 8);
animation.numPlays = bin.readInt(4, bin.pos + 12);
bin.pos += 20;
} else if ( chunkType === 'fcTL' ) {
bin.pos += 12;
i = frames.length;
frames.push({
width: bin.readInt(4),
height: bin.readInt(4),
xOffset: bin.readInt(4),
yOffset: bin.readInt(4),
delay: 1000 * bin.readInt(2) / (bin.readInt(2) || 100),
disposeOp: bin.readInt(1),
blendOp: bin.readInt(1),
data: 'IDAT'
});
if ( i === 0 && frames[i].disposeOp === 2 ) {
frames[i].disposeOp = 1;
}
// Skip crc
bin.pos += 4;
// console.log(frames[frames.length - 1]);
} else if ( chunkType === 'IDAT' || chunkType === 'fdAT' ) {
if ( !animation.numFrames || animation.numFrames < 2 ) {
break;
// IDAT without acTL chunk should be ignored
} else if ( chunkType === 'IDAT' && !frames.length ) {
// console.log('PNG: ignoring IDAT from animation...');
bin.pos += bin.readInt(4, bin.pos) + 12;
continue;
}
i = chunkType === 'fdAT' ? 4 : 0;
// Read the length, also skip the sequence number from fdAT
chunkSize = bin.readInt(4) - i;
// Skip chunk type,
// also the sequence number in case of the fdAT chunk type
bin.pos += 4 + i;
frames[frames.length - 1].data += bin.readString(chunkSize);
// Skip crc
bin.pos += 4;
} else if ( frames.length ) {
bin.pos += bin.readInt(4, bin.pos) + 12;
} else {
// Read the full chunk (length + chunk type + chunkdate + crc)
imgHead += bin.readString(bin.readInt(4, bin.pos) + 12);
}
}
} else if ( this.imgType === 'GIF' ) {
// http://www.w3.org/Graphics/GIF/spec-gif89a.txt
bin.littleEndian = true;
bin.skipSubBlock = function() {
do {
this.pos += this.readInt(1, this.pos) + 1;
if ( bin.pos >= bin.length ) {
throw Error(this.imgType + ': end reached...');
}
} while ( this.readInt(1, this.pos) !== 0x00 );
++this.pos;
};
// Skip signature
bin.pos = 6;
// Logical Screen Descriptor
animation.width = bin.readInt(2);
animation.height = bin.readInt(2);
bin.packed = bin.readBits(1, 10);
bin.packed = bin.packed[0] === '1'
? 3 * 1 << parseInt(bin.packed.slice(-3), 2) + 1
: 0;
imgHead += bin.readString(3 + bin.packed);
// Frame index
i = 0;
while ( bin.pos < bin.length ) {
chunkType = bin.readString(1);
// console.log("sentinel: " + chunkType);
// Extension block (0x21, an exclamation point '!')
// optional
if ( chunkType === '!' ) {
chunkType = bin.readInt(1);
// console.log("ext_label: " + chunkType.toString(16));
// Plain Text Extension
if ( chunkType === 0x01 ) {
// No support for this, so skip
bin.pos += 13;
bin.skipSubBlock();
// Graphics Control Extension
} else if ( chunkType === 0xf9 ) {
bin.packed = bin.readBits(1, bin.pos + 1);
frames.push({
delay: bin.readInt(2, bin.pos + 2) * 10 || 100,
// -1 in order to match PNG's indexes, also treat 0 as 1
disposeOp: Math.max(
0,
parseInt(bin.packed.slice(3, -2), 2) - 1
),
// sentinel + ext_label
data: bin.readString(4, bin.pos - 2)
// with zero delay
+ bin.intToBytes(0, 2)
// transparent color index + block terminator
+ bin.readString(2, bin.pos + 4)
});
bin.pos += 6;
// Comment Block Extension
} else if ( chunkType === 0xfe ) {
bin.skipSubBlock();
// Application Block Extension
} else if ( chunkType === 0xff ) {
bin.pos += 12;
bin.skipSubBlock();
// Try to skip anything else
} else {
bin.pos = bin.data.indexOf('\x00', bin.pos);
if ( bin.pos === -1 ) {
bin.pos = bin.length;
} else {
++bin.pos;
}
}
// Image (0x2C, a comma ',')
} else if ( chunkType === ',' ) {
if ( !frames[i] ) {
frames.push({
delay: 100,
disposeOp: 0,
// sentinel, ext_label, block size, packed field, delay,
// transparent color index, terminator
data: '\x21\xf9\x04\x00\x00\x00\x00\x00'
});
}
frames[i].xOffset = bin.readInt(2);
frames[i].yOffset = bin.readInt(2);
bin._pos = bin.pos;
frames[i].width = bin.readInt(2);
frames[i].height = bin.readInt(2);
bin.packed = bin.readBits(1);
bin.pos += bin.packed[0] === '1'
? 3 * (1 << parseInt(bin.packed.slice(-3), 2) + 1)
: 0;
// LZW minimum code size
++bin.pos;
bin.skipSubBlock();
frames[i]._data = [bin.pos - bin._pos, bin._pos];
++i;
// Trailer (0x3B, a semi-colon ';') or something else
} else {
break;
}
}
} else if ( this.imgType === 'WEBP' ) {
// https://developers.google.com/speed/webp/docs/riff_container
bin.littleEndian = true;
// WebP file header + VP8X and its chunk size
bin.pos = 20;
// VP8X flags
bin.packed = bin.readBits(1);
// Animation flag
if ( bin.packed[6] === '0' ) {
errorHandler(this.imgType + ': not animated...');
return;
}
// Reserved 24 bits
bin.pos += 3;
// Canvas width
animation.width = bin.readInt(3) + 1;
// Canvas height
animation.height = bin.readInt(3) + 1;
while ( bin.pos < bin.length ) {
chunkType = bin.readString(4);
if ( chunkType === 'ANIM' ) {
// Skip Background Color: 32 bits + Loop Count: 16 bits
// chunk size + chunk payload
bin.pos += 4 + bin.readInt(4);
animation.ANIM = true;
continue;
}
if ( chunkType !== 'ANMF' ) {
// Skip chunk
bin.pos += 4 + bin.readInt(4);
continue;
}
if ( !animation.ANIM ) {
errorHandler(this.imgType + ': ANIM chunk not found!');
return;
}
i = frames.length;
// Size of the Frame Data
chunkSize = bin.readInt(4);
// If the chunk size is odd, then a padding byte is added
chunkSize += chunkSize & 1;
// Remove the size of the ANMF properties listed below
chunkSize -= 16;
frames.push({
xOffset: bin.readInt(3) * 2,
yOffset: bin.readInt(3) * 2,
width: bin.readInt(3) + 1,
height: bin.readInt(3) + 1,
delay: bin.readInt(3),
disposeOp: bin.readInt(1) & 1,
data: ''
});
bin._pos = bin.pos + chunkSize;
while ( bin.pos < bin._pos ) {
chunkType = bin.readString(4);
chunkSize = bin.readInt(4);
chunkSize += chunkSize & 1;
// Should exist before the 'VP8 ' chunk only
/* if ( chunkType === 'ALPH' ) {
if ( bin.readString(4, bin.pos + chunkSize) === 'VP8 ' ) {
// The whole ALPH chunk
frames[i].data += bin.readString(8, bin.pos - 8);
frames[i].data += bin.readString(chunkSize);
} else {
bin.pos += chunkSize;
}
} else */
if ( chunkType === 'VP8 ' || chunkType === 'VP8L' ) {
// chunk type + chunk size + VP8? bitstream;
frames[i].data += bin.readString(8, bin.pos - 8);
frames[i].data += bin.readString(chunkSize);
} else {
bin.pos += chunkSize;
}
}
// frames[i].data += bin.readString(chunkSize);
}
}
if ( frames.length < 1 ) {
errorHandler(this.imgType + ': not animated...');
return;
}
var generateImageSRC, wrap, speed, currentFrame;
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// "new Image" doesn't work in Maxthon
var img = document.createElement('img');
canvas.width = animation.width;
canvas.height = animation.height;
if ( this.imgType === 'PNG' ) {
chunkSize = bin.intToBytes(13);
var imgEnd = bin.readString(12, bin.length - 12);
generateImageSRC = function() {
var frm = frames[frames.idx];
var _IHDR = 'IHDR'
+ bin.intToBytes(frm.width)
+ bin.intToBytes(frm.height)
+ IHDR;
_IHDR += bin.intToBytes(crc32(_IHDR));
return 'data:image/png;base64,' + win.btoa(
'\x89PNG\r\n\x1a\n'
+ chunkSize + _IHDR
+ imgHead
+ bin.intToBytes(frm.data.length - 4) + frm.data
+ bin.intToBytes(crc32(frm.data))
+ imgEnd
);
};
} else if ( this.imgType === 'GIF' ) {
chunkSize = bin.intToBytes(0, 2);
chunkSize = ',' + chunkSize + chunkSize;
generateImageSRC = function() {
var frm = frames[frames.idx];
return 'data:image/gif;base64,' + win.btoa(
'GIF89a'
+ bin.intToBytes(frm.width, 2) + bin.intToBytes(frm.height, 2)
+ imgHead
+ frm.data + chunkSize
+ bin.readString(frm._data[0], frm._data[1])
+ ';'
);
};
} else if ( this.imgType === 'WEBP' ) {
generateImageSRC = function() {
var frm = frames[frames.idx];
return 'data:image/webp;base64,' + win.btoa(
'RIFF' + bin.intToBytes(frm.data.length + 4)
+ 'WEBP' + frm.data
);
};
}
var onImgLoad = function() {
if ( drawFullFrame ) {
var frame = frames[frames.idx];
var prev = frames[frames.idx - 1];
if ( prev ) {
if ( prev.disposeOp === 1 ) {
ctx.clearRect(
prev.xOffset, prev.yOffset,
prev.width, prev.height
);
} else if ( prev.disposeOp === 2 ) {
ctx.putImageData(
this.prevDisposeData,
prev.xOffset, prev.yOffset
);
}
}
if ( frame.disposeOp === 2 ) {
this.prevDisposeData = ctx.getImageData(
frame.xOffset, frame.yOffset,
frame.width, frame.height
);
}
// only for PNG
if ( frame.blendOp === 0 ) {
ctx.clearRect(
frame.xOffset, frame.yOffset,
frame.width, frame.height
);
}
ctx.drawImage(
this,
frame.xOffset, frame.yOffset
);
}
var c = canvas.cloneNode(false);
if ( drawFullFrame ) {
c.getContext('2d').putImageData(
ctx.getImageData(0, 0, canvas.width, canvas.height),
0, 0
);
} else {
c.width = this.width;
c.height = this.height;
c.getContext('2d').drawImage(this, 0, 0);
}
wrap.appendChild(c);
this.removeAttribute('src');
c.style.display = 'inline-block';
if ( c.previousElementSibling ) {
c.previousElementSibling.style.display = '';
}
++frames.idx;
currentFrame.value = frames.idx;
processNextFrame(); // eslint-disable-line
};
var done = function() {
wrap.current = 0;
wrap.children[wrap.children.length - 1].style.display = '';
wrap.children[wrap.current].style.display = 'inline-block';
currentFrame.value = 1;
var onWrapMouseUp = function(e) {
if ( e.button !== 0 ) {
return;
}
if ( e.ctrlKey ) {
if ( e.target.toDataURL && speed.value < 1 ) {
var canvasImg = document.createElement('img');
canvasImg.src = e.target.toDataURL();
this.replaceChild(canvasImg, e.target);
wrap.step(null);
}
return;
}
this.stop();
if ( this.classList.contains('showall') ) {
if ( e.target && e.target.parentNode === wrap ) {
currentFrame.value = [].indexOf.call(
wrap.childNodes,
e.target
) + 1;
wrap.step(null);
}
this.addEventListener(vAPI.browser.wheel, this.wheeler);
} else {
this.removeEventListener(vAPI.browser.wheel, this.wheeler);
}
this.classList.toggle('showall');
};
wrap.wheeler = function(e) {
wrap.step((e.deltaY || -e.wheelDelta) > 0);
wrap.stop();
e.preventDefault();
e.stopImmediatePropagation();
};
wrap.animate = function() {
clearTimeout(wrap.animationTimer);
wrap.step(wrap.speedValue < 0);
if ( wrap.speedValue ) {
wrap.animationTimer = setTimeout(
wrap.animate,
frames[wrap.current].delay / Math.abs(wrap.speedValue)
);
}
};
wrap.stop = function() {
clearTimeout(this.animationTimer);
speed.value = 0;
};
wrap.step = function(backward) {
wrap.children[wrap.current].style.display = '';
if ( backward === null ) {
wrap.current = Math.max(
1,
Math.min(
parseInt(currentFrame.value, 10) || 1,
currentFrame.max
)
) - 1;
} else if ( backward ) {
--wrap.current;
} else {
++wrap.current;
}
if ( wrap.current >= wrap.children.length ) {
wrap.current = 0;
} else if ( wrap.current < 0 ) {
wrap.current = wrap.children.length - 1;
}
wrap.children[wrap.current].style.display = 'inline-block';
currentFrame.value = wrap.current + 1;
currentFrame.nextElementSibling.value = currentFrame.value
+ ' / ' + frames.length;
};
wrap.addEventListener('mouseup', onWrapMouseUp);
wrap.addEventListener(vAPI.browser.wheel, wrap.wheeler);
currentFrame.addEventListener(vAPI.browser.wheel, wrap.wheeler);
currentFrame.addEventListener('input', function() {
if ( parseFloat(speed.value, 10) !== 0 ) {
wrap.stop();
}
if ( wrap.classList.contains('showall') ) {
onWrapMouseUp.call(wrap, {button: 0});
}
wrap.step(null);
});
speed.addEventListener('input', function() {
wrap.speedValue = parseFloat(speed.value) || 0;
if ( wrap.speedValue === 0 ) {
wrap.stop();
wrap.addEventListener(vAPI.browser.wheel, wrap.wheeler);
return;
}
wrap.classList.remove('showall');
wrap.removeEventListener(vAPI.browser.wheel, wrap.wheeler);
wrap.animate();
});
};
var processNextFrame = function() {
if ( frames.idx < frames.length ) {
img.src = generateImageSRC();
frames[frames.idx].data = null;
} else {
img.removeEventListener('load', onImgLoad);
img = null;
done();
errorHandler(null);
}
};
img.addEventListener('load', onImgLoad);
img.addEventListener('error', function() {
wrap.textContent = xhr.imgType
+ ': frame (' + (frames.idx + 1) + ") couldn't be parsed!";
wrap.appendChild(this);
});
wrap = document.body;
wrap.className = 'frames';
wrap.textContent = '';
vAPI.buildNodes(wrap, [
{tag: 'a', attrs: {
class: 'back',
href: win.location.href
}, text: '\u2190'},
' ',
{tag: 'input', attrs: {
type: 'number',
id: 'speed',
style: 'width: 55px; text-align: center;',
value: 0,
step: 0.5,
min: -10,
max: 10
}}, 'x ',
{tag: 'input', attrs: {
type: 'range',
id: 'current-frame',
style: 'width: 500px; vertical-align: middle;',
size: 6,
value: 1,
step: 1,
min: 1
}}, ' ',
{tag: 'output', attrs: {
for: 'currentFrame'
}, text: '1 / ' + frames.length}, ' ',
{tag: 'div', attrs: {id: 'frames'}}
]);
wrap = $('frames');
speed = $('speed');
currentFrame = $('current-frame');
currentFrame.max = frames.length;
frames.idx = 0;
processNextFrame();
});
xhr.addEventListener('error', function() {
errorHandler('Failed to load!');
});
xhr.open('GET', win.location.href, true);
xhr.send();
'use strict';
var defaultPrefs;
var inputChanges = Object.create(null);
var $ = function(id) {
return document.getElementById(id);
};
var localizeNodes = function(nodes) {
var i = nodes.length;
while ( i-- ) {
if ( nodes[i]._nodeLocalized ) {
continue;
}
var els = nodes[i].querySelectorAll('[data-l10n]');
var l = els.length;
while ( l-- ) {
var l10nString = vAPI.l10n(els[l].dataset.l10n);
var l10nAttr = els[l].dataset.l10nAttr;
els[l].removeAttribute('data-l10n');
if ( !l10nAttr ) {
vAPI.insertHTML(els[l], l10nString);
continue;
}
if ( /^(title|placeholder)$/i.test(l10nAttr) ) {
els[l][l10nAttr] = l10nString;
}
els[l].removeAttribute('data-l10n-attr');
}
nodes[i]._nodeLocalized = true;
}
};
var changeColor = function(node, color, time) {
clearTimeout(node.colorTransitionTimer);
if ( typeof color !== 'string' ) {
node.style.color = '';
delete node.colorTransitionTimer;
return;
}
node.style.color = color;
node.colorTransitionTimer = setTimeout(function() {
changeColor(node);
}, time || 2000);
};
var fillOutput = function(e) {
var node = e.target || e;
var op = node.previousElementSibling;
op.value = node.value;
op.defaultValue = defaultPrefs[node.name];
};
var colorOnInput = function(node) {
var target = node.type === 'input' ? this : node;
var c = /^#([\da-f]{3}){1,2}$/i.test(target.value)
? target.value
: '#ffffff';
if ( c.length === 4 ) {
c = '#' + c[1] + c[1] + c[2] + c[2] + c[3] + c[3];
}
target.previousElementSibling.value = c;
};
var colorOnChange = function() {
this.nextElementSibling.value = this.value;
};
var setDefault = function(selector) {
if ( !selector ) {
return;
}
var nodeList = typeof selector === 'string'
? document.querySelectorAll(selector)
: [selector];
[].forEach.call(nodeList, function(el) {
if ( el.type === 'checkbox' ) {
el.checked = el.defaultChecked;
} else if ( el.type.lastIndexOf('select', 0) === 0 ) {
var i = el.length;
while ( i-- ) {
if ( el[i].hasAttribute('selected') ) {
el.selectedIndex = i;
break;
}
}
} else {
el.value = el.defaultValue;
if ( el.type === 'range' ) {
fillOutput(el);
}
}
});
};
var load = function(prefs) {
var fields = document.querySelectorAll('form [name]');
var i = fields.length;
while ( i-- ) {
var field = fields[i];
var pref = field.name;
if ( field.disabled || field.readOnly ) {
continue;
}
if ( defaultPrefs[pref] === void 0 ) {
continue;
}
if ( field.type === 'checkbox' ) {
field.defaultChecked = defaultPrefs[pref];
pref = !!(prefs[pref] === void 0 ? defaultPrefs : prefs)[pref];
field.checked = field.defChecked = pref;
continue;
}
if ( pref === 'sendToHosts' ) {
if ( !Array.isArray(prefs[pref]) ) {
prefs[pref] = defaultPrefs[pref];
}
field.rows = prefs[pref].length || 2;
field.defaultValue = defaultPrefs[pref].join('\n');
prefs[pref] = prefs[pref].join('\n');
} else if ( field.type.lastIndexOf('select', 0) === 0 ) {
/* eslint-disable */
[].some.call(field, function(el) {
if ( el.value == defaultPrefs[pref] ) {
el.defaultSelected = true;
return true;
}
});
/* eslint-enable */
} else {
field.defaultValue = defaultPrefs[pref];
}
pref = (prefs[pref] === void 0 ? defaultPrefs : prefs)[pref];
field.value = field.defValue = pref;
if ( field.type === 'range' ) {
var m = field.previousElementSibling;
if ( m && m.localName === 'output' ) {
fillOutput(field);
}
m = m.previousElementSibling;
if ( m && m.getAttribute('type') === 'color' ) {
m.style.opacity = field.value;
}
field.addEventListener('change', fillOutput);
} else if ( field.type === 'text' ) {
if ( !field.previousElementSibling ) {
continue;
}
if ( field.previousElementSibling.getAttribute('type') === 'color' ) {
continue;
}
field.addEventListener('input', colorOnInput);
colorOnInput(field);
field.previousElementSibling.addEventListener('change', colorOnChange);
}
}
};
var save = function() {
var fields = document.querySelectorAll('form [name]');
var prefs = Object.create(null);
for ( var i = 0; i < fields.length; ++i ) {
var field = fields[i];
var pref = field.name;
if ( field.disabled || field.readOnly || defaultPrefs[pref] === void 0 ) {
continue;
}
if ( field.type === 'checkbox' ) {
prefs[pref] = field.checked;
} else if ( field.type === 'range'
|| field.type === 'number'
|| field.classList.contains('number') ) {
prefs[pref] = parseFloat(field.value);
if ( field.min ) {
prefs[pref] = Math.max(
field.min,
Math.min(field.max, prefs[pref])
);
}
if ( typeof prefs[pref] !== 'number' ) {
prefs[pref] = parseFloat(field.defaultValue);
}
field.value = prefs[pref];
} else {
// eslint-disable-next-line no-lonely-if
if ( pref === 'sendToHosts' ) {
prefs[pref] = field.value.trim().split(/[\r\n]+/).filter(Boolean);
field.rows = prefs[pref].length || 2;
} else {
prefs[pref] = field.value;
}
}
if ( prefs[pref] === void 0 ) {
prefs[pref] = defaultPrefs[pref];
}
}
vAPI.messaging.send({cmd: 'savePrefs', prefs: prefs});
};
var onHashChange = function() {
var args = [];
var menu = $('nav-menu');
var prevHash = menu.activeLink ? menu.activeLink.hash.slice(1) : 'general';
var hash = location.hash.slice(1) || 'general';
if ( hash.indexOf('/') > -1 ) {
args = hash.split('/');
hash = args.shift();
}
if ( prevHash !== hash && (prevHash = $(prevHash + '-sec')) ) {
prevHash.style.display = 'none';
}
if ( menu.activeLink ) {
menu.activeLink.classList.remove('active');
}
menu.activeLink = menu.querySelector('a[href="#' + hash + '"]');
if ( menu.activeLink ) {
menu.activeLink.classList.add('active');
}
var section = $(hash + '-sec') || $((hash = 'general') + '-sec');
if ( section._nodeLocalized ) {
section.style.display = 'block';
return;
}
localizeNodes([section]);
section.style.display = 'block';
if ( hash === 'info' ) {
vAPI.messaging.send({cmd: 'loadFile', path: 'locales.json'}, function(response) {
var translators;
var rows = [];
var locales = JSON.parse(response);
var lngMap = function(el, idx) {
el.name = [
el.name || el.realname || '',
el.realname && el.name ? ' (' + el.realname + ')' : ''
].join('');
if ( el.email ) {
el.email = el.email
.replace(/\(dot\)/g, '.')
.replace('(at)', '@');
}
if ( !el.name ) {
el.name = el.email || el.web;
}
if ( idx ) {
translators.nodes.push(', ');
}
translators.nodes.push(el.email || el.web
? {
tag: 'a',
attrs: {
href: el.email
? 'mailto:' + el.email
: el.web
},
text: el.name
}
: el.name
);
};
// _ is the default language
delete locales._;
for ( var alpha2 in locales ) {
var locale = locales[alpha2];
translators = {tag: 'span'};
if ( locale.translators ) {
translators.nodes = [];
locale.translators.forEach(lngMap);
} else {
translators.text = 'anonymous';
}
rows.push({tag: 'div', nodes: [
alpha2 + ', ' + locale.name,
translators
]});
}
vAPI.buildNodes($('locales-table'), rows);
});
}
};
window.addEventListener('hashchange', onHashChange);
window.addEventListener('load', function() {
['opera', 'firefox', 'chrome', 'safari', 'maxthon'].some(function(el) {
if ( vAPI[el] ) {
document.body.classList.add(el);
return true;
}
return false;
});
var menu = $('nav-menu');
var colorHelper = document.body.querySelector(
'.color-helper > input[type=text]'
);
if ( colorHelper ) {
colorHelper.addEventListener('input', colorOnInput);
colorOnInput(colorHelper);
colorHelper.previousElementSibling.addEventListener(
'change',
colorOnChange
);
}
localizeNodes([menu, $('right-panel').firstElementChild]);
menu.addEventListener('click', function(e) {
if ( e.button === 0 && e.target.hash ) {
e.preventDefault();
location.hash = e.target.hash;
}
});
var form = document.forms[0];
var onFormChange = function(e) {
if ( e.stopPropagation ) {
e.stopPropagation();
}
var defval;
var t = e.target;
if ( t.formSaved ) {
delete t.formSaved;
} else if ( t.parentNode.dataset.form
|| t.parentNode.parentNode.dataset.form ) {
defval = 'default';
} else if ( t.id.indexOf('_') > 0 ) {
defval = 'def';
}
if ( !defval ) {
return;
}
if ( t.type === 'checkbox' && t[defval + 'Checked'] !== t.checked ) {
inputChanges[t.name] = true;
// eslint-disable-next-line eqeqeq
} else if ( t.type !== 'checkbox' && t[defval + 'Value'] != t.value ) {
inputChanges[t.name] = true;
} else {
delete inputChanges[t.name];
}
$('button-save').style.color = Object.keys(inputChanges).length
? '#e03c00'
: '';
};
form.addEventListener('keydown', function(e) {
e.stopPropagation();
if ( e.which === 13 ) {
e.target.formSaved = true;
}
if ( e.repeat || !e.target.name ) {
return;
}
if ( e.target.name.indexOf('key_') !== 0 ) {
return;
}
if ( e.ctrlKey || e.altKey || e.metaKey || e.which < 47 ) {
return;
}
e.preventDefault();
changeColor(e.target);
var keys = {
96: '0', 97: '1', 98: '2', 99: '3', 100: '4',
101: '5', 102: '6', 103: '7', 104: '8', 105: '9',
106: '*', 107: '+', 109: '-', 110: '.', 111: '/', 173: '-',
186: ';', 187: '=', 188: ',', 189: '-', 190: '.',
191: '/', 192: '`', 219: '[', 220: '\\', 221: ']', 222: "'",
112: 'F1', 113: 'F2', 114: 'F3', 115: 'F4', 116: 'F5', 117: 'F6',
118: 'F7', 119: 'F8', 120: 'F9', 121: 'F10', 122: 'F11', 123: 'F12'
};
var key = keys[e.which] || String.fromCharCode(e.which).toUpperCase();
keys = document.body.querySelectorAll('input[name^="key_"]');
for ( var i = 0; i < keys.length; ++i ) {
if ( keys[i].value.toUpperCase() !== key ) {
continue;
}
if ( e.target !== keys[i] ) {
changeColor(e.target, 'red');
}
return;
}
e.target.value = key;
onFormChange(e);
});
form.addEventListener('contextmenu', function(e) {
e.stopPropagation();
var t = e.target;
if ( t.classList.contains('checkbox') ) {
t = t.previousElementSibling;
}
if ( !t.name ) {
return;
}
if ( e.ctrlKey ) {
e.preventDefault();
setDefault(t);
onFormChange({target: t});
}
});
form.addEventListener('change', onFormChange);
var resetButton = $('button-reset');
resetButton.reset = function() {
delete resetButton.pending;
resetButton.style.color = '#000';
};
resetButton.addEventListener('click', function(e) {
if ( e.button !== 0 ) {
return;
}
if ( this.pending ) {
clearTimeout(this.pending);
this.nextElementSibling.style.color = '#e03c00';
inputChanges.formReset = true;
if ( e.ctrlKey ) {
e.preventDefault();
var sec = (location.hash || '#general') + '-sec ';
setDefault(sec + 'input,' + sec + 'select,' + sec + 'textarea');
this.style.color = 'lime';
} else {
this.style.color = 'green';
}
this.pending = setTimeout(this.reset, 2000);
return;
}
this.style.color = 'orange';
this.pending = setTimeout(this.reset, 2000);
e.preventDefault();
});
$('button-save').addEventListener('click', function(e) {
e.preventDefault();
if ( e.button !== 0 ) {
return;
}
save();
changeColor(resetButton);
changeColor(this, 'green');
});
form.querySelector('.op-buttons').addEventListener('mousedown', function(e) {
e.preventDefault();
});
vAPI.messaging.send({cmd: 'loadPrefs', getAppInfo: true}, function(data) {
$('app-name').textContent = data._app.name;
$('app-version').textContent = data._app.version;
$('platform-info').textContent = data._app.platform;
document.title = ':: ' + data._app.name + ' ::';
defaultPrefs = JSON.parse(data._defaultPrefs);
load(data.prefs);
onHashChange();
document.body.style.display = 'block';
});
});
[lang]
appDescriptionShort=Vylepšuje práci s obrázky a videi ve vašem prohlížeči.
buttonReset=Výchozí nastavení
buttonSave=Uložit
centerContent=Zarovnat na střed
customCss=Vlastní styl (CSS)
customCssTextareaPh="Zde můžete změnit barvu pozadí stránky nebo obrázku, rám, stín, chování posuvníků, skrýt postranní panel...\nPro zobrazení příkladů přejeďte kurzorem přes otazník vlevo. Přesné kódy barev získáte pomocí tlačítka pro výběr barev výše."
customCssTip="body {\n background: #f3f3f5; /* Změní pozadí stránky a obrázku (je-li průhledný). Lze použít všechny platné CSS hodnoty (color, url(), gradient...). */\n overflow: hidden; /* Skryje posuvníky. */\n}\n\n#media {\n background: #eef; /* Pozadí obrázku, je-li průhledný. */\n border: 10px solid white; /* Rám obrázku. */\n box-shadow: 0 0 10px grey; /* Stín pod obrázkem. */\n cursor: default !important; /* Vynutí výchozí kurzor (tzn. nezmění se na ručičku či lupu). */\n}\n\n.mask {\n color: rgba(0, 0, 0, .4); /* Barva krytí v režimu ručního zvětšení. */\n}\n\n#menu {\n display: none; /* Vypne zobrazování postranního panelu v levém horní rohu. */\n}\n
"
defaultMode=Výchozí přiblížení
disabled=zakázáno
favicon=Vlastní ikona
faviconTip="Toto vám umožňuje nastavit vlastní ikonu, která se zobrazí vedle názvu panelu v prohlížeči.\nChcete-li jako ikonu použít obrázek samotný, použijte proměnnou %url."
infoTranslations=Překlady
longpressActionFitImage=roztáhnout na výšku/šířku
longpressLeft=Akce při dlouhém stisku levého tlačítka myši
longpressRight=Akce při dlouhém stisku pravého tlačítka myši
mediaAttributesTip="Lze použít tyto atributy:\nautoplay - přehrát video automaticky\nloop - přehrávat dokola\ncontrols - zobrazit ovládací prvky\nmuted - vypnout zvuk\nvolume=0-100 - výchozí hlasitost (v procentech)"
mediaInfo=Vlastnosti obrázku
mediaInfoTip="V titulku stránky (v panelu prohlížeče) lze zobrazit tyto vlastnosti obrázku:\n%ow - původní šířka obrázku\n%oh - původní výška obrázku\n%ratio - poměr stran (šířka / výška)\n%w - současná šířka\n%h - současná výška\n%perc - procento zvětšení\n%url - úplná URL adresa\n%name - název souboru"
minUpscale=Zvětšit malé obrázky
minUpscaleTip="Ve výchozím nastavení nebudou malé obrázky automaticky zvětšovány. Přeje-li si to, použijte tuto volbu.\nObrázky, které jsou větší než daný počet procent šířky nebo výšky okna prohlížeče (záleží na předchozí volbě) budou automaticky roztaženy."
modeAutoFit=přizpůsobit automaticky
modeBestFit=roztáhnout automaticky
modeNatural=původní velikost
navGeneral=Obecné
navInfo=O doplňku
opener=Otevřít obrázek ze stránky
openerBoth=obojí
openerCtrlAltClick=Ctrl + Alt + pravé tlačítko
openerRightLong=dlouhý stisk pravého tlačítka
phClickForExample=kliknutím zobrazíte příklady...
scCycleModes=Přepínat mezi režimy zvětšení: původní velikost, roztáhnout na šířku a roztáhnout na výšku
scDragndrop=Držte Ctrl nebo Alt nebo začněte v pravé části obrázku, chcete-li obrázek přetáhnout jinam (např. mimo okno prohlížeče)
scFitToHeight=Roztáhnout na výšku
scFitToWidth=Roztáhnout na šířku
scFlipHorizontal=Překlopit vodorovně
scFlipVertical=Překlopit svisle
scFloatMenu=Přesunutím kurzoru do levého horního rohu stránky vyvoláte postranní panel
scFreeZoom=Shift + výběr myší pro vyvolání režimu ručního zvětšení (pro posunutí výběru držte Ctrl)
scHorizontalScroll=Pro vodorovné posouvání obrázku kolečkem myši přesuňte kurzor do levé dolní části obrázku
scModeContain=Automaticky
scModeNatural=Skutečná velikost
scReset=Esc obnoví obrázek do původního stavu (pokud byl např. zvětšen, otočen nebo převrácen) nebo ukončí režim ručního zvětšení
scRotateLeft=Otočit vlevo
scRotateRight=Otočit vpravo
scZoom=Přiblížit / oddálit
sendTo=Odeslat obrázek do...
shortcuts=Klávesové zkratky
wheelZoom=Použít kolečko myši jako lupu
[lang]
appDescriptionShort=Erweiterte Funktionalität des eingebauten Bildbetrachters und Videoplayers.
buttonReset=Standard
buttonSave=Speichern
centerContent=Inhalt zentrieren
customCss=Angepasster Style (CSS)
customCssTextareaPh="Änderung der Hintergrundfarbe, Rahmen/Schatten, Verstecken der Scrollbalken oder des Menüs...\nFür Beispiele mit der Maus über das Fragezeichen fahren und den Color Picker für die Farbinformationen"
customCssTip="body {\n background: #f3f3f5; /* Jedes gültige Hintergrundmerkmal (color, url(), gradient...). */\n overflow: hidden; /* Verstecken der Scrollbalken. Zum sichtbarmachen \"hidden\" durch \"auto\" ersetzen. */\n}\n\n#media {\n background: #eef; /* Verschiedene Hintergründe für Bilder. */\n border: 10px solid white; /* Bildrahmen. */\n box-shadow: 0 0 10px grey; /* Bildschatten. */\n cursor: default !important; /* Unterdrücken der Änderung des Mauszeigers. */\n}\n\n.mask {\n color: rgba(0, 0, 0, .4); /* Farbe der stufenlosen Zoommaske. */\n}\n\n#menu {\n display: none; /* Dynamisches Menü abschalten. */\n}\n
"
defaultMode=Darstellungsmodus beim Aufruf
disabled=abgeschaltet
favicon=Angepasstes Favicon
faviconTip=Diese Einstellung erlaubt das setzen eines eigenen Icons für das Tab (Favicon) des geöffneten Bildes. Die Adresse des Bildes kann als Variable verwendet werden: %url
infoTranslations=Übersetzungen
longpressActionFitImage=an Höhe/Breite anpassen
longpressActionWheelZoom=Zoom mittels Mausrad
longpressLeft=Aktion bei langem Linkklick
longpressRight=Aktion bei langem Rechtsklick
mediaAttributes=Medienattribute
mediaAttributesTip="Mögliche Attribute\nautoplay - Video automatisch abspielen\nloop - In Schleife abspielen\ncontrols - Anzeige der Steuerungselemente\nmuted - Stummschaltung\nvolume=0-100 - Standardlautstärke (%)"
mediaInfo=Bildinformationen
mediaInfoTip="Display custom information in the title of the tab. It may contain the following variables:\n%ow - Originalbreite\n%oh - Originalhöhe\n%ratio - Aktuelle Breite : Aktuelle Höhe\n%w - Aktuelle Breite\n%h - Aktuelle Höhe\n%perc - Vergrößerung in Prozent\n%url - vollständige URL\n%name - Dateiname"
minUpscale=Kleine Bilder vergrößern
minUpscaleTip=Durch diese Einstellung werden kleine Bilder vergrößert. Jene Bilder welche größer als der Angegebene Prozentwert sind werden gemäß der vorigen Einstellung vergrößert.
modeAutoFit=eingepasst
modeBestFit=An Breite/Höhe angepasst
modeNatural=Originalgröße
navGeneral=Generelle Einstellungen
opener=Öffne Bilder von gewöhnlichen Webseiten
openerBoth=beides
openerCtrlAltClick=Strg + Alt + Rechtsklick
openerRightLong=langer Rechtsklick
phClickForExample=Für Beispiele drücken
scChangeVolume=Auf / Ab um Lautstärke anzupassen
scCycleModes=Durchwechseln der Darstellungsmodi: Original, An Breite angepasst, An Höhe angepasst
scDragndrop=Strg / Alt gedrückt halten für Drag 'n' Drop oder von der rechten Ecke des Bildes ziehen sollte es auf diese Weise ins Fenster passen
scFitToHeight=An Höhe anpassen
scFitToWidth=An Breite anpassen
scFlipHorizontal=Horizontales Spiegeln
scFlipVertical=Vertikales Spiegeln
scFloatMenu=Für Menü den Mauszeiger in die linke, obere Ecke bewegen
scFreeZoom=Umschalt + ziehen des Bildes für Freihandzoom, Strg gedrückt halten um die Auswahl zu bewegen
scHorizontalScroll=Zum horizontalen Scrollen den Mauszeiger in die linke, untere Ecke bewegen und das Mausrad verwenden
scImgBg=Durchwechseln der Hintergrundfarben: Standard, Schwarz, Weiß, Kariert oder Umschalt-Taste für eigene Farbe
scModeContain=Automatische Größenanpassung
scModeNatural=Originale Größe
scPixelate=Pixelinterpolation de-/aktivieren
scReset=Esc Zum zurücksetzen des Bildes auf seine Originaleinstellungen oder um den Freihandzoom zu verlassen
scRotateLeft=Drehen (entgegen Uhrzeigersinn)
scRotateRight=Drehen (im Uhrzeigersinn)
scTogglePlay=Space Wechsel Play/Pause
scWheelZoom=Wechsel Mausradzoom
scZoom=Rein- / Rauszoomen
sendTo=Bild senden an...
shortcuts=Tastaturkürzel
wheelZoom=Mausradzoom
[lang]
buttonReset=Επαναφορά
buttonSave=Αποθήκευση
customCss=Προσαρμοσμένο στυλ
defaultMode=Αρχικό μεγέθος
disabled=απενεργοποιημένο
favicon=Προσαρμοσμένο εικονίδιο
faviconTip="Η επιλογή αυτή ορίζει ένα εικονίδιο καρτέλας για την ανοιγμένη εικόνα.\nΗ διεύθυνση της εικόνας μπορεί να χρησιμοποιηθεί και ως μια μεταβλητή: %url"
infoTranslations=Μεταφράσεις
longpressActionFitImage=προσαρμογή στο πλάτος/ύψος
longpressLeft=Λειτουργία παρατετημένου πατήματος αριστερού κουμπιού
longpressRight=Λειτουργία παρατετημένου πατήματος δεξιού κουμπιού
mediaInfo=Πληροφορίες εικόνας
minUpscale=Μεγέθυνση μικρών εικόνων
minUpscaleTip="Μικρές εικόνες δεν μεγεθύνονται. Αυτή η επιλογή τις αναγκάζει να μεγεθυνθούν.\nΗ τιμή είναι σε ποσοστό και μεγεθύνει τις εικόνες που είναι μεγαλύτερες από το επιλεγμένο ποσοστό του ύψους ή του πλάτους της οθόνης."
modeAutoFit=αυτόματη προσαρμογή
modeBestFit=βέλτιστη προσαρμογή
modeNatural=φυσικό μέγεθος
navInfo=Πληροφορίες
scCycleModes=Εναλαγή μεταξύ μεγεθών: φυσικό, προσαρμογή στο πλάτος, προσαρμογή στο ύψος
scFitToHeight=Προσρμογή στο ύψος
scFitToWidth=Προσρμογή στο πλάτος
scFlipHorizontal=Οριζόντια αναστροφή
scFlipVertical=Κάθετη αναστροφή
scFreeZoom=Shift + μεταφορά στην εικόνα για ελεύθερη μεγέθυνση, κρατήστε το Ctrl για να μετακινήσετε την επιλογή
scModeContain=Αυτόματη προσαρμογή
scModeNatural=Φυσικό μέγεθος
scReset=To Esc θα επαναφέρει την εικόνα στην αρχική της μορφή ή θα κλείσει την ελεύθερη μεγέθυνση
scRotateLeft=Περιστροφή αριστερά
scRotateRight=Περιστροφή δεξιά
sendTo=Αποστολή εικόνας προς...
shortcuts=Συντομεύσεις
wheelZoom=Μεγεύθυνση με τη ροδέλα του ποντικιού
[lang]
appDescriptionShort=Additional functionality for the browser's default image and video viewer.
buttonReset=Default
buttonSave=Save
centerContent=Center content
customCss=Custom style (CSS)
customCssTextareaPh="Change the background color, image border/shadow, and hide the scrollbars or the floating menu... \nHover the question mark to see examples, use the color picker above for getting color codes."
customCssTip="body {\n background: #f3f3f5; /* Any valid background property (color, url(), gradient...). */\n overflow: hidden; /* Hides the scrollbars. To show them, change \"hidden\" to \"auto\". */\n}\n\n#media {\n background: #eef; /* Different background for the image. */\n border: 10px solid white; /* Image border. */\n box-shadow: 0 0 10px grey; /* Shadow of the image. */\n cursor: default !important; /* Don't allow the mouse cursor to change. */\n}\n\n.mask {\n color: rgba(0, 0, 0, .4); /* Color of the free-zoom mask. */\n}\n\n#menu {\n display: none; /* Disable the floating menu. */\n}\n
"
defaultMode=Initial sizing mode
disabled=disabled
favicon=Custom favicon
faviconTip="This option allows to set a custom tab-icon for the opened image.\nThe address of the image can be used as a variable: %url"
infoTranslations=Translations
longpressActionFitImage=fit to width/height
longpressActionWheelZoom=toggle wheel zooming
longpressLeft=Left long-press action
longpressRight=Right long-press action
mediaAttributes=Media attributes
mediaAttributesTip="Acceptable attributes\nautoplay - video starts automatically\nloop - repeat the play\ncontrols - show player controls\nmuted - mute sound\nvolume=0-100 - default volume (%)"
mediaInfo=Image informations
mediaInfoTip="Display custom information in the title of the tab. It may contain the following variables:\n%ow - original width\n%oh - original height\n%ratio - current width / current height\n%w - current width\n%h - current height\n%perc - percent of the original size\n%url - full URL\n%name - filename"
minUpscale=Enlarge small images
minUpscaleTip="Normally, smaller images won't be upscaled to the view-port. This option forces them to do so.\nThe value is given in percent, and tells the script to enlarge those images that are larger than the given percent of view-port's width or height (it depends on the previous option)."
modeAutoFit=contain
modeBestFit=best fit
modeNatural=natural size
navGeneral=General
navInfo=Info
opener=Open images from regular web-pages
openerBoth=both
openerCtrlAltClick=Ctrl + Alt + right click
openerRightLong=right long-press
phClickForExample=click for examples...
scChangeVolume=Up / Down Increase/decrease the volume
scCycleModes=Cycle through sizing modes: natural, fit to width, fit to height
scDragndrop=Hold Ctrl or Alt to allow drag-and-drop, or drag from the right edge of the image, if that fits into the window
scFitToHeight=Fit to height
scFitToWidth=Fit to width
scFlipHorizontal=Flip horizontal
scFlipVertical=Flip vertical
scFloatMenu=Move the cursor to the top left edge of the page to show the menu
scFreeZoom=Shift + drag on the image to use free-zoom, hold Ctrl to move the selection
scHorizontalScroll=To scroll the image horizontally, use the mouse wheel over the left bottom edge
scImgBg=Cycle through image backgrounds: default, black, white, check, or hold Shift for custom value
scModeContain=Auto fit
scModeNatural=Natural size
scPixelate=Pixelate image
scReset=Esc will reset the image to its original form, or quits from free-zoom
scRotateLeft=Rotate left
scRotateRight=Rotate right
scTogglePlay=Space Toggle play/pause
scWheelZoom=Toggle wheel zooming
scZoom=Zoom in / out
sendTo=Send image to...
shortcuts=Shortcuts
wheelZoom=Zoom with mouse wheel
[lang]
appDescriptionShort=Funciones adicionales para el visor de imágenes y vídeo del navegador.
buttonReset=Predeterminado
buttonSave=Guardar
centerContent=Centrar el contenido
customCss=Estilo personalizado (CSS)
customCssTextareaPh="Cambia el color de fondo, bordes/sombras de la imagen, y esconde las barras de desplazamiento o el menú flotante.\nColoca el cursor sobre el signo de interrogación a la izquierda para ver ejemplos. Utiliza el selector de color (arriba a la derecha) para obtener códigos de color."
customCssTip="body {\n background: #f3f3f5; /* Cualquier atributo válido para background (color, url(), gradient...). */\n overflow: hidden; /* Oculta las barras de desplazamiento. Para mostrarlas, cambia \"hidden\" por \"auto\". */\n}\n\n#media {\n background: #eef; /* Cambia el fondo de la imagen. */\n border: 10px solid white; /* Borde de la imagen. */\n box-shadow: 0 0 10px grey; /* Sombra de la imagen. */\n cursor: default !important; /* No permite que el puntero cambie. */\n}\n\n.mask {\n color: rgba(0, 0, 0, .4); /* Color para el modo de ampliación de selección. */\n}\n\n#menu {\n display: none; /* Deshabilita el menú flotante. */\n}\n
"
defaultMode=Modo inicial de escalado
disabled=deshabilitado
favicon=Icono personalizado
faviconTip="Esta opción permite establecer un favicono personalizado para las pestañas con imágenes abiertas.\nLa dirección de la imagen puede ser usada como variable: %url"
infoTranslations=Traducciones
longpressActionFitImage=ajustar a la anchura/altura
longpressLeft=Acción para una pulsación larga con el botón izquierdo
longpressRight=Acción para una pulsación larga con el botón derecho
mediaAttributes=Atributos multimedia
mediaAttributesTip="Atributos aceptados\nautoplay - comenzar reproducción automáticamente\nloop - repetir la reproducción\ncontrols - mostrar los controles del reproductor\nmuted - sin sonido\nvolume=0-100 - volumen por defecto (porcentaje)"
mediaInfo=Información de la imagen
mediaInfoTip="Muestra información sobre el contenido en el título de la pestaña. Puede contener las siguientes variables:\n%ow - anchura original\n%oh - altura original\n%ratio - anchura actual / altura actual\n%w - anchura actual\n%h - altura actual\n%perc - porcentaje del tamaño original\n%url - dirección URL\n%name - nombre del archivo"
minUpscale=Ampliar imágenes pequeñas
minUpscaleTip="Por defecto, las imágenes pequeñas no serán ampliadas para encajar en la ventana de visualización. Esta opción las fuerza a hacerlo.\nEl valor esta dado en porcentaje, e indica a la extensión que amplié las imágenes que sean mayores al porcentaje en anchura o altura de la ventana de visualización (esto depende de la opción anterior).\n Ejemplo: si el valor esta fijado en 20%, y una imagen ocupa el 30% de la ventana de visualización, será ampliada de acuerdo a la opción anterior (Modo inicial de escalado)."
modeAutoFit=ajustar
modeBestFit=mejor ajuste
modeNatural=tamaño original
navInfo=Información
opener=Abrir imágenes desde páginas web
openerBoth=ambas
openerCtrlAltClick=Ctrl + Alt + clic derecho
openerRightLong=una pulsación larga con el botón derecho
phClickForExample=haz clic para mostrar ejemplos...
scChangeVolume=Arriba / Abajo Aumentar/disminuir volumen
scCycleModes=Cambiar entre los modos de escalado: tamaño original, ajustar a la anchura, ajustar a la altura
scDragndrop=Mantén presionado Ctrl o Alt para permitir arrastrar y soltar, o arrastra desde el borde derecho de la imagen (si cabe en la ventana)
scFitToHeight=Ajustar a lo alto
scFitToWidth=Ajustar a lo ancho
scFlipHorizontal=Voltear horizontalmente
scFlipVertical=Voltear verticalmente
scFloatMenu=Mueve el cursor a la esquina superior izquierda de la pantalla para mostrar el menú
scFreeZoom=Shift + arrastrar sobre la imagen para usar el modo de ampliación de selección, mantén presionado Ctrl (sin soltar Shift) para mover la selección
scHorizontalScroll=Para desplazar la imagen horizontalmente, utiliza la rueda del ratón sobre el borde inferior izquierdo
scModeContain=Ajuste automático
scModeNatural=Tamaño original
scReset=Esc devolverá la imagen a su forma original, o saldrá del modo de ampliación de selección
scRotateLeft=Girar a la izquierda
scRotateRight=Girar a la derecha
scTogglePlay=Barra espaciadora Alterna entre reproducción/pausa
scZoom=Acercar/alejar la imagen
sendTo=Enviar imagen a...
shortcuts=Atajos
wheelZoom=Ampliar (zoom) con la rueda del ratón
[lang]
buttonReset=Palauta oletukset
buttonSave=Tallenna
defaultMode=Oletuskoko
disabled=poissa käytöstä
favicon=Oma kuvake
longpressActionFitImage=sovita leveyteen tai korkeuteen
longpressLeft=Ykköspainikkeen pitkän painalluksen toiminto
longpressRight=Kakkospainikkeen pitkän painalluksen toiminto
mediaInfo=Kuvan tiedot
minUpscale=Suurenna pieniä kuvia (%)
minUpscaleTip="Tavallisesti pieniä kuvia ei skaalata näkymäalueeseen, mutta tämä asetus pakottaa sen päälle.\nArvo annetaan prosentteina, ja se saa skriptin suurentamaan kuvia, jotka ovat suurempia kuin annettu prosenttiosuus näkymäalueen leveydestä tai korkeudesta (riippuen edellisestä asetuksesta)."
modeAutoFit=automaattinen sovitus
modeBestFit=paras sovitus
modeNatural=luonnollinen koko
navInfo=Tietoja
phClickForExample=klikkaa nähdäksesi esimerkkejä...
scCycleModes=Siirry suurennustilojen välillä: luonnollinen koko, sovita leveyteen, sovita korkeuteen
scFitToHeight=Sovita korkeuteen
scFitToWidth=Sovita leveyteen
scFlipHorizontal=Käännä pystysuunnassa
scFlipVertical=Käännä vaakasuunnassa
scFreeZoom=Pidä Vaihtoa pohjassa ja vedä kuvan päällä käyttääksesi FreeZoomia, pidä Ctrl:ia pohjassa siirtääksesi valittua aluetta
scModeContain=Automaattinen sovitus
scModeNatural=Luonnollinen koko
scReset=Esc palauttaa kuvan alkuperäiseen tilaan tai poistuu FreeZoom-tilasta
scRotateLeft=Kierrä vasemmalle
scRotateRight=Kierrä oikealle
scZoom=Suurenna / pienennä
sendTo=Lähetä kuvan osoite...
shortcuts=Näppäinoikotiet
wheelZoom=Suurennus hiiren rullalla
[lang]
appDescriptionShort=Des fonctionnalités additionnelles pour l’affichage des images et des vidéos de votre navigateur.
buttonReset=Par défaut
buttonSave=Sauvegarder
centerContent=Centrer le contenu
customCss=Style personnalisé (CSS)
defaultMode=Redimensionnement
disabled=désactivé
favicon=Favicon personnalisé
faviconTip="Cette option permet de choisir un icône personnalisé pour l'onglet de l'image ouverte.\nL'adresse de l'image peut être utilisée comme une variable : %url"
infoTranslations=Traductions
longpressActionFitImage=adapter à la largeur/hauteur
longpressLeft=Clic gauche prolongé
longpressRight=Clic droit prolongé
mediaAttributesTip="Options possibles\nautoplay - la vidéo se lance automatiquement\nloop - répéter la vidéo\ncontrols - montrer les boutons du lecteur\nmuted - rendre muet\nvolume=0-100 - volume par défaut (en pourcentage)"
mediaInfo=Détails de l'image
minUpscale=Agrandir les petites images
minUpscaleTip="En temps normal, les petites images ne sont pas élargies à la taille de la fenêtre. Cette option les y force.\nLa valeur est un pourcentage, et indique au script d'élargir les images plus grandes qu'un certain pourcentage de la hauteur ou de la largeur de la fenêtre (en fonction de l'option choisie précédemment)."
modeAutoFit=réduire
modeBestFit=taille optimale
modeNatural=taille initiale
navInfo=Infos
opener=Ouvre les images des pages web classiques
openerBoth=les deux
openerCtrlAltClick=Ctrl + Alt + clic droit
openerRightLong=clic droit prolongé
phClickForExample=cliquez pour avoir un exemple...
scCycleModes=Faire défiler les différents modes : taille initiale, adapter à la largeur, adapter à la hauteur
scFitToHeight=Adapter à la hauteur
scFitToWidth=Adapter à la largeur
scFlipHorizontal=Inverser horizontalement
scFlipVertical=Inverser verticalement
scFloatMenu=Déplacez le curseur en haut à gauche de la page pour afficher le menu
scFreeZoom=Maj + glisser sur l'image pour utiliser le zoom libre, maintenir Ctrl pour déplacer la sélection
scHorizontalScroll=Pour faire défiler l'image horizontalement, utilisez la molette de la souris en bas à gauche
scModeContain=Redimensionnement automatique
scModeNatural=Taille initiale
scReset=Échap ramènera l'image à sa taille initiale, ou sortira du zoom libre
scRotateLeft=Rotation vers la gauche
scRotateRight=Rotation vers la droite
scZoom=Zoom avant / arrière
sendTo=Envoyer l'image vers...
shortcuts=Raccourcis
wheelZoom=Zoomer avec la molette
[lang]
appDescriptionShort=A beépített kép- illetve videónéző funkcióit bővíti.
buttonReset=Alap
buttonSave=Mentés
centerContent=Tartalom középre helyezése
customCss=Egyedi stílus (CSS)
customCssTextareaPh="Itt lehetseéges a háttér színének, kép keretének/árnyékának, stb. beállítása, illetve a görgősávok és a lebegő menü elrejtése.\nPéldákért vidd az egérkurzort a kérdőjel fölé, a színkódokhoz pedig használd a fenti színválasztót."
customCssTip="body {\n background: #f3f3f5; /* Bármilyen elfogadott background érték (szín, url(), színátmenet...). */\n overflow: hidden; /* Elrejti a görgősávot. \"hidden\" változtatása \"auto\"-ra a megjelenítésükhöz. */\n}\n\n#media {\n background: #eef; /* Más háttér kizárólag a képnek. */\n border: 10px solid white; /* Egyéni képkeret. */\n box-shadow: 0 0 10px grey; /* Kép körüli árnyék. */\n cursor: default !important; /* Az egérkurzor változatlan marad ezzel az értékkel. */\n}\n\n.mask {\n color: rgba(0, 0, 0, .4); /* A szabad méretezés mask színe. */\n}\n\n#menu {\n display: none; /* A lebegő menü elrejtése. */\n}\n
"
defaultMode=Alap méretezés
disabled=kikapcsolva
favicon=Egyéni ikon a fülön
faviconTip=A kép címe használható változóként a megadott értékben: %url
infoTranslations=Fordítások
longpressActionFitImage=szélességhez/magassághoz méretez
longpressActionWheelZoom=egérgörgővel való nagyítás ki/bekapcsolása
longpressLeft=Bal hosszan-tartás funkciója
longpressRight=Jobb hosszan-tartás funkciója
mediaAttributes=Média attribútumok
mediaAttributesTip="Használható attribútumok\nautoplay - automatikus indítás\nloop - lejátszás ismétlése\ncontrols - lejátszógombok megjelenítése\nmuted - hang némítása\nvolume=0-100 - alapértelmezett hangerő (%)"
mediaInfo=Képinformációk
mediaInfoTip="Egyéni adatok megjelenítése a fül címében, a következő változók felhaszanálásával:\n%ow - eredeti szélesség\n%oh - eredeti magasság\n%ratio - jelenlegi szélesség és magasság aránya\n%w - jelenlegi szélesség\n%h - jelenlegi magasság\n%perc - átméretezés százalékban\n%url - teljes cím\n%name - fájl neve"
minUpscale=Kis képek nagyítása
minUpscaleTip="A kisebb képek alapból nem méreteződnek az ablakhoz. Ez a beállítás az ellenkezőjére kényszeríti őket.\nAzok a képek méreteződnek fel, amelyek méretei nagyobbak, mint a százalékban megadott ablak szélessége vagy magassága (az előző beállítástól függ)."
modeAutoFit=ablakhoz méretez
modeBestFit=illeszkedés az ablakhoz
modeNatural=eredeti méret
navGeneral=Beállítások
navInfo=Infó
opener=Képek megnyitása normál web-oldalkról
openerBoth=mindkettő
openerCtrlAltClick=Ctrl + Alt + jobb klikk
openerRightLong=jobb klikk hosszan-tartva
phClickForExample=kattints példákért...
scChangeVolume=Fel / Le Hangerő növelése/csökkentése
scCycleModes=Méretezések közti váltás: eredeti, szélességhez-, magassághoz méretez
scDragndrop=Ctrl vagy Alt nyomva-tartásával vonszolható a kép, vagy ha belefér a nézetablakba, akkor a jobb szélénél fogva
scFitToHeight=Magassághoz méretez
scFitToWidth=Szélességhez méretez
scFlipHorizontal=Vízszintes tükrözés
scFlipVertical=Függőleges tükrözés
scFloatMenu=A menü megjelenítéséhez mozgasd az egérkurzort az oldal bel felső szélére
scFreeZoom=Shift + vonszolás nagyít a kijelölt részre, Ctrl tartásával a kijelölés mozgatható
scHorizontalScroll=A kép vízszintes mozgatása az oldal bal also élén való görgetéssel lehetséges.
scImgBg=Kép hátterének váltogatása: alap, fekete, fehér, sakkminta, vagy a Shift lenyomásával egyéni érték megadása
scModeContain=Ablakhoz méretez
scModeNatural=Eredeti méret
scPixelate=Pixeles kép
scReset=Esc a képet az eredeti állapotára állítja, vagy kilép a szabad méretezésből
scRotateLeft=Forgatás jobbra
scRotateRight=Forgatás balra
scTogglePlay=Space Médiafájlok lejátszása/leállítása
scWheelZoom=Egérgörgővel való nagyítás ki/bekapcsolása
scZoom=Nagyítás / kicsinyítés
sendTo=Kép küldése...
shortcuts=Billentyűparancsok
wheelZoom=Nagyítás görgetéssel
[lang]
appDescriptionShort=브라우저의 기본 이미지와 비디오 뷰어에 여러 기능을 추가해줍니다.
buttonReset=기본
buttonSave=저장
centerContent=내용 가운데 정렬
customCss=커스텀 스타일 (CSS)
customCssTextareaPh="배경 색 바꾸기, 이미지 테두리 / 그림자, 스크롤바 숨기기와 떠 있는 메뉴 등...\n위 색상 선택기를 사용하여 색상 코드를 얻을 수 있습니다. 예시를 보려면 물음표에 커서를 올리세요."
customCssTip="body {\n background: #f3f3f5; /* 아무 유효한 배경 속성 (color, url(), gradient...) */\n overflow: hidden; /* 스크롤 바를 숨깁니다. 보이기 위해서는, \"hidden\"을 \"auto\"로 바꾸세요. */\n}\n\n#media {\n background: #eef; /* 이미지를 위한 배경 */\n border: 10px solid white; /* 이미지 테두리 */\n box-shadow: 0 0 10px grey; /* 이미지 그림자 */\n cursor: default !important; /* 마우스 커서의 모양이 변하지 않게 합니다. */\n}\n\n.mask {\n color: rgba(0, 0, 0, .4); /* 자유 확대 / 축소 마스크의 색상 */\n}\n\n#menu {\n display: none; /* 떠 있는 메뉴를 비활성화 */\n}\n
"
defaultMode=초기 크기 조절 모드
disabled=비활성화됨
favicon=커스텀 파비콘
faviconTip="이 옵션으로 이미지가 열린 탭의 아이콘을 바꿀 수 있습니다.\n이미지 주소가 변수로서 쓰일 수 있습니다:\n%url"
infoTranslations=번역
longpressActionFitImage=폭/높이에 맞춤
longpressLeft=왼쪽 길게 누르기 작동
longpressRight=오른쪽 길게 누르기 작동
mediaAttributesTip="사용 가능한 속성\n자동 재생 - 비디오가 자동으로 시작됨\n반복 재생 - 비디오를 반복하여 재생\n컨트롤 - 플레이어 컨트롤 표시\n조용히 - 소리 끄기\n볼륨=0-100 - 기본 볼륨 (퍼센트)"
mediaInfo=이미지 정보
mediaInfoTip="커스텀 정보를 탭의 제목에 표시합니다. 아래의 변수를 포함할 수 있습니다:\n%ow - 실제 폭\n%oh - 실제 높이\n%ratio - 현재 폭 / 현재 높이\n%w - 현재 폭\n%h - 현재 높이\n%perc - 실제 크기에 대한 퍼센트\n%url - 전체 URL\n%name - 파일명"
minUpscale=작은 이미지를 확대
minUpscaleTip="보통 작은 이미지는 표시 영역에 맞춰 확대되지 않지만 이 옵션은 이것을 강제합니다.\n 이 값은 퍼센트로 되어 있습니다. 이전 옵션에 따라 표시 영역의 폭이나 높이의 퍼센트보다 큰 이미지는 표시 영역에 맞춰 확대됩니다."
modeAutoFit=포함
modeBestFit=최적
modeNatural=자연스럽게
navGeneral=기본
navInfo=정보
opener=일반 웹 페이지에서 이미지 열기
openerBoth=둘 다
openerCtrlAltClick=Ctrl + Alt + 오른쪽 클릭
openerRightLong=오른쪽 길게 누르기
phClickForExample=예시를 보려면 클릭...
scCycleModes=크기 조절 모드를 차례로 순환: 자연스럽게, 폭 맞춤, 높이 맞춤
scDragndrop=끌어서 놓기를 허용하려면 Ctrl 또는 Alt를 누르고 있거나, 창과 맞다면 이미지의 오른쪽 가장자리에서 끌면 됩니다
scFitToHeight=높이 맞춤
scFitToWidth=폭 맞춤
scFlipHorizontal=위아래 뒤집기
scFlipVertical=좌우 뒤집기
scFloatMenu=메뉴를 표시하려면 커서를 페이지 왼쪽 위 모서리로 이동하세요
scFreeZoom=이미지 위에서 Shift + 끌기를 하여 자유 확대 / 축소를 하고, Ctrl을 누른 상태에서는 선택 영역을 이동할 수 있습니다
scHorizontalScroll=큰 이미지를 좌우로 움직이려면 페이지 왼쪽 아래 모서리에서 마우스 휠을 사용하면 됩니다
scModeContain=자동 맞춤
scModeNatural=자연스러운 크기
scReset=Esc는 이미지를 원래 모습으로 되돌리거나, 자유 확대 / 축소를 취소합니다
scRotateLeft=시계 반대 방향 회전
scRotateRight=시계 방향 회전
scZoom=확대 / 축소
sendTo=이미지를 다음으로 보내기...
shortcuts=바로가기
wheelZoom=마우스 휠로 확대 / 축소
[lang]
buttonReset=Reset
buttonSave=Opslaan
customCss=Aangepaste stijl (CSS)
defaultMode=Oorspronkelijke pas-modus
disabled=uit
favicon=Aangepaste favicon
faviconTip="Deze optie maakt het mogelijk om een aangepaste tab-icoon te gebruiken voor de geopende afbeelding.\nHet adres van de afbeelding kan gebruikt worden als variabele: %url"
infoTranslations=Vertalingen
longpressActionFitImage=breedte/hoogte passend maken
longpressLeft=Linker lange druk aktie
longpressRight=Rechter lange druk aktie
mediaInfo=Afbeeldings informatie
minUpscale=Kleine afbeeldingen vergroten
minUpscaleTip="Normaal gesproken worden kleinere afbeeldingen niet vergroot. Deze optie dwingt afbeeldingen te vergroten.\nDe waarde is in procenten, en vertelt het script om afbeeldingen die groter zijn de gegeven procenten van de breedte of hoogte van de kijker te vergroten (afhankelijk van de vorige optie)."
modeAutoFit=bevatten
modeBestFit=best afstemmen
modeNatural=natuurlijk formaat
phClickForExample=klikken voor voorbeelden...
scCycleModes=Door sizing modi wisselen: normaal, breedte passend maken, hoogte passend maken
scFitToHeight=Hoogte passend maken
scFitToWidth=Breedte passend maken
scFlipHorizontal=Horizontaal omdraaien
scFlipVertical=Verticaal omdraaien
scFreeZoom=Shift + Sleep de afbeelding om free-zoom te gebruiken, Ctrl ingedrukt houden om de selectie te verplaatsen
scModeContain=Automatisch passen
scModeNatural=Normale grootte
scReset=Esc herstelt de afbeelding naar origineel formaat, of verlaat de vrije-zoom
scRotateLeft=Links roteren
scRotateRight=Rechts roteren
scZoom=In-/uitzoomen
sendTo=Afbeelding sturen naar...
shortcuts=Snelkoppelingen
wheelZoom=Zoomen met muiswiel
[lang]
appDescriptionShort=Rozszerzenie standardowej przeglądarki obrazów i filmów o nowe funkcje.
buttonReset=Resetuj
buttonSave=Zapisz
centerContent=Wyśrodkuj
customCss=Własne style (CSS)
customCssTextareaPh="Pozwala zmienić kolor tła, obramowanie i cień dla obrazka i ukryć paski przewijania, lub menu z dodatkowymi funkcjami.\nNajedź na znak zapytania by zobaczyć przykładowy kod. Użyj pipety kolorów powyżej, by znaleźć kod wybranego koloru."
customCssTip="body {\n background: #f3f3f5; /* Dowolna deklaracja tła zgodna z CSS (color, url(), gradient...). */\n overflow: hidden; /* Ukrywa paski przewijania. Aby je przywrócić, zmień \"hidden\" na \"auto\". */\n}\n\n#media {\n background: #eef; /* Inne tło dla obrazka. */\n border: 10px solid white; /* Obramowanie obrazka. */\n box-shadow: 0 0 10px grey; /* Cień obrazka. */\n cursor: default !important; /* Nie pozwala na zmianę wyglądu kursora. */\n}\n\n.mask {\n color: rgba(0, 0, 0, .4); /* Kolor maski w trybie powiększania wybranego obszaru. */\n}\n\n#menu {\n display: none; /* Wyłącza menu z dodatkowymi funkcjami. */\n}\n
"
defaultMode=Skalowanie obrazów
disabled=brak
favicon=Własna ikona pliku
faviconTip="Zmienia ikonę pliku w pasku tytułu (domyślnie przeglądarka używa obrazka jako ikony).\nAdres obrazka można wprowadzić za pomocą zmiennej: %url"
infoTranslations=Tłumaczenia
longpressActionFitImage=zmieść w oknie
longpressLeft=Funkcja dla przytrzymania lewego przycisku
longpressRight=Funkcja dla przytrzymania prawego przycisku
mediaAttributesTip="Dopuszczalne parametry:\nautoplay - film jest odtwarzany automatycznie\nloop - odtwórz ponownie po zakończeniu\ncontrols - pokazuj przyciski kontrolne odtwarzacza\nmuted - wycisz film\nvolume=0-100 - domyślna głośność (wyrażona w procentach)"
mediaInfo=Informacje o obrazku
mediaInfoTip="Wyświetlaj wybrane informacje o pliku w tytule karty przeglądarki. Lista możliwych opcji:\n%ow - rzeczywista szerokość\n%oh - rzeczywista wysokość\n%ratio - aktualna szerokość / aktualna wysokość\n%w - aktualna szerokość\n%h - aktualna wysokość\n%perc - procent powiększenia\n%url - pełny adres pliku\n%name - nazwa pliku"
minUpscale=Powiększanie małych obrazków
minUpscaleTip="Domyślnie małe obrazki nie są powiększane do rozmiarów okna. Ta funkcja wymusza ich skalowanie.\nFunkcja ta powoduje powiększenie tych obrazków, których wymiary przekraczają określony procent wysokości lub szerokości okna (w zależności od ustawień poprzedniej funkcji)."
modeAutoFit=zmieść na ekranie
modeBestFit=automatyczne dopasowanie
modeNatural=rzeczywisty wymiar
navGeneral=Ogólne
opener=Otwieraj zwykłe obrazki na stronach
openerBoth=obydwa
openerCtrlAltClick=Ctrl + Alt + prawy przycisk myszy
openerRightLong=przytrzymując prawy klawisz myszy
phClickForExample=kliknij, by zobaczyć przykłady...
scCycleModes=Przełącza tryby powiększenia: rzeczywiste wymiary, zmieść w poziomie, zmieść w pionie
scDragndrop=Przytrzymaj Ctrl lub Alt by włączyć tryb przeciągania i upuszczania, lub przeciągnij z prawej strony obrazka, jeśli mieści się w oknie przeglądarki
scFitToHeight=Dopasuj do wysokości
scFitToWidth=Dopasuj do szerokości
scFlipHorizontal=Odbij w poziomie
scFlipVertical=Odbij w pionie
scFloatMenu=Najedź na lewy górny róg strony by zobaczyć menu
scFreeZoom=Przeciągnij z Shiftem na obrazku, by aktywować powiększanie obszarowe. Przytrzymaj Ctrl aby przesunąć zaznaczenie
scHorizontalScroll=Aby przewijać obrazek w poziomie, użyj kółka myszy w lewym dolnym rogu strony
scModeContain=Auto dopasowanie
scModeNatural=Rzeczywisty wymiar
scReset=Esc przywraca domyślne ustawienia obrazka lub opuszcza tryb powiększania wybranego obszaru
scRotateLeft=Obróć w lewo
scRotateRight=Obróć w prawo
scZoom=Powiększ / Pomniejsz
sendTo=Wyślij obrazek do...
shortcuts=Skróty
wheelZoom=Powiększaj za pomocą kółka myszki
[lang]
buttonReset=Padrão
buttonSave=Salvar
customCss=Estilo de CSS personalizado
defaultMode=Tamanho de exibição
disabled=desativado
favicon=Ícone personalizado
faviconTip="Esta opção possibilita adicionar um ícone personalizado à imagem aberta.\nO endereço da imagem pode ser usado como variável: %url"
infoTranslations=Traduções
longpressActionFitImage=caber na altura/largura
longpressLeft=Clique longo com o botão esquerdo do mouse
longpressRight=Clique longo com o botão direito do mouse
mediaInfo=Informações da imagem.
minUpscale=Aumentar imagens pequenas
minUpscaleTip="Geralmente imagens pequenas não são exibidas em grande parte da tela. Esta função força que elas sejam.\nO valor é dado em porcentagem, e informa ao script para deixa-las de acordo com os dados de altura e largura fornecidos (isso depende das opções selecionadas)."
modeAutoFit=redimensionar à tela
modeBestFit=redimensionar da melhor forma
modeNatural=tamanho original
navInfo=Dados
phClickForExample=clique para ver exemplos...
scCycleModes=Trocar entre os modos: tamanho original, caber na altura, caber na largura
scFitToHeight=Dimensionar à altura
scFitToWidth=Dimensionar à largura
scFlipHorizontal=Virar à horizontal
scFlipVertical=Virar à vertical
scFreeZoom=Shift + arrastrar em cima da imagem para usar o modo de ampliação de seleção, mantenha pressionado Ctrl (sem soltar Shift) para mover a seleção
scModeContain=Dimensionar automaticamente
scModeNatural=Tamanho original
scReset=Esc voltará a imagem à sua forma normal, ou sairá do zoom-livre
scRotateLeft=Rodar à esquerda
scRotateRight=Rodar à direita
scZoom=Zoom mais/menos
sendTo=Enviar imagem para...
shortcuts=Atalhos do teclado
wheelZoom=Fazer zoom ao rodar roda do mouse
[lang]
appDescriptionShort=Дополнительная функциональность при просмотре изображений и видео в браузере.
buttonReset=По умолчанию
buttonSave=Сохранить
centerContent=Центрировать содержимое
customCss=Пользовательский стиль (CSS)
customCssTextareaPh="Можно изменять цвета фона, границу/тень изображения, скрывать полосы прокрутки или всплывающее меню...\nНаведите курсор на вопросительный знак, чтобы увидеть примеры, используйте палитру цветов выше для получения кодов цвета."
customCssTip="body {\n background: #f3f3f5; /* Любое допустимое свойство фона (color, url(), gradient...). */\n overflow: hidden; /* Скрыть полосы прокрутки. Чтобы показать их, измените \"hidden\" на \"auto\". */\n}\n\n#media {\n background: #eef; /* Различный фон для изображения. */\n border: 10px solid white; /* Граница изображения. */\n box-shadow: 0 0 10px grey; /* Тень изображения. */\n cursor: default !important; /* Запретить изменение курсора. */\n}\n\n.mask {\n color: rgba(0, 0, 0, .4); /* Цвет маски свободного масштабирования. */\n}\n\n#menu {\n display: none; /* Отключить всплывающее меню. */\n}\n
"
defaultMode=Размер по умолчанию
disabled=отключено
favicon=Пользовательская иконка
faviconTip="Этот параметр позволяет назначить произвольную иконку для вкладки с открытым изображением.\nАдрес изображения можно использовать как переменную: %url"
infoTranslations=Переводы
longpressActionFitImage=подогнать по ширине/высоте
longpressActionWheelZoom=переключить масштабирование колесом
longpressLeft=Действие длительного нажатия левой кнопкой мыши
longpressRight=Действие длительного нажатия правой кнопкой мыши
mediaAttributes=Атрибуты медиа
mediaAttributesTip="Допустимые атрибуты\nautoplay - видео начинается автоматически\nloop - повторить воспроизведение\ncontrols - показывать элементы управления плейером\nmuted - отключение звука\nvolume=0-100 - уровень громкости по умолчанию (процент)"
mediaInfo=Информация об изображении
mediaInfoTip="Отображение пользовательской информации в заголовке вкладки. Она может содержать следующие переменные:\n%ow - оригинальная ширина\n%oh - оригинальная высота\n%ratio - текущая ширина / текущая высота\n%w - текущая ширина\n%h - текущая высота\n%perc - процент от оригинального размера\n%url - полный URL\n%name - имя файла"
minUpscale=Увеличивать маленькие изображения
minUpscaleTip="Как правило, небольшие изображения не увеличиваются до размеров области просмотра при масштабировании. Этот параметр заставит их это делать.\nЗначение задаётся в процентах, скрипт увеличит те изображения, размер которых больше данного процента от ширины или высоты области просмотра (в зависимости от предыдущей настройки)."
modeAutoFit=вписать
modeBestFit=наилучшее заполнение
modeNatural=оригинальный размер
navGeneral=Настройки
navInfo=Инфо
opener=Открытие изображений c обычных веб-страниц
openerBoth=оба
openerCtrlAltClick=Ctrl + Alt + правая кнопка мыши
openerRightLong=длительное нажатие правой кнопки мыши
phClickForExample=посмотреть примеры...
scChangeVolume=Вверх / Вниз Увеличить/уменьшить громкость
scCycleModes=Переключить между режимами: оригинальный, подгон по ширине, подгон по высоте
scDragndrop=Зажмите Ctrl или Alt, чтобы позволить drag-and-drop, или протяните от правого края изображения, если оно вписано в окно
scFitToHeight=Подогнать по высоте
scFitToWidth=Подогнать по ширине
scFlipHorizontal=Отразить по горизонтали
scFlipVertical=Отразить по вертикали
scFloatMenu=Подведите курсор к верхнему левому краю страницы, чтобы показать меню
scFreeZoom=Зажать Shift + левую кнопку мыши на изображении для свободного масштабирования, дополнительно зажать Ctrl для перемещения выделения
scHorizontalScroll=Для прокрутки изображения по горизонтали используйте колёсико мыши над левым нижним краем
scImgBg=Переключать фон изображений: по умолчанию, чёрный, белый, шахматная доска; либо удерживайте Shift для установки пользовательского значения
scModeContain=Вписать
scModeNatural=Оригинальный размер
scPixelate=Пикселизировать изображение
scReset=Esc возвращает изображение к первоначальному виду или выходит из режима свободного масштабирования.
scRotateLeft=Повернуть влево
scRotateRight=Повернуть вправо
scTogglePlay=Пробел Переключить воспроизведение/пауза
scWheelZoom=Переключить масштабирование колесом
scZoom=Увеличить / уменьшить
sendTo=Отправить изображение в...
shortcuts=Сочетания клавиш
wheelZoom=Масштабировать колесом мыши
[lang]
appDescriptionShort=Extra funktionalitet till webbläsarens egen bildvisare och videospelare.
buttonReset=Nollställ
buttonSave=Spara
centerContent=Centrera innehållet
customCss=Egen stilmall (CSS)
customCssTextareaPh="Byt bakgrundsfärgen, ändra bilden skugga och ram, dölj skrollisterna och de flytande menyerna...\nMed musen över frågetecknet, kan du se fler exempel. Använd färgpaletten ovan för att få färghexkoder."
customCssTip="body {\n background: #f3f3f5; /* Välj en acceptabel bakgrundsegenskap (color, url(), gradient, etc.). */\n overflow: hidden; /* Döljer skrollisterna. För att visa dem, byt från \"hidden\" till \"auto\". */\n}\n\n# media {\n background: #eef; /* Annan bakgrundsfärg för bilden. */\n border: 10px solid white; /* Bildram. */\n box-shadow: 0 0 10px grey; /* Bildskugga. */\n cursor: default !important; /* Tillåter inte muspekaren att ändras. */\n}\n\n.mask {\n color: rgba(0, 0, 0, .4); /* Färg för fri-zoommasken. */\n}\n\n#menu {\n display: none; /* Tillåt inte flytande menyer. */\n}\n
"
defaultMode=Initalstorlek
disabled=avstängt
favicon=Egen adressikon
faviconTip="Med denna inställning, ställer du in egen adressikon för de öppnade bilderna.\nBildens adress kan användas med variabeln %url"
infoTranslations=Översättningar
longpressActionFitImage=passa till höjd eller bredd
longpressActionWheelZoom=skifta skrollhjulszoomning
longpressLeft=Handling vid långvarig vänsterklick
longpressRight=Handling vid långvarig högerklick
mediaAttributes=Medieattribut
mediaAttributesTip="Accepterade attribut\nautoplay - starta videon automatiskt\nloop - loopa uppspelning\ncontrols - visa kontroller\nmuted - tysta videon\nvolume=0-100 - standardvolym i procent"
mediaInfo=Bildinformation
mediaInfoTip="Visa egenanpassad information i flikens titelfält. Den kan innehålla följande variabler:\n%ow - originalbredd\n%oh - originalhöjd\n%ratio - förhållande mellan nuvarande bredd och höjd\n%w - nuvarande bredd\n%h - nuvarande höjd\n%perc - procent av originalstorleken\n%url - hela adressen\n%name - filnamnet"
minUpscale=Förstora små bilder
minUpscaleTip="Normalt burkar små bilder inte skalas upp i bildvyn. Detta tvingar små bilder att växa.\nVärdet är givet i procent och anger gränsen för hur små bilderna är i förhållande till bildvyns storlek."
modeAutoFit=fyll
modeBestFit=optimal anpassning
modeNatural=naturlig storlek
navGeneral=Generellt
navInfo=Information
opener=Öppna bilder från vanliga webbplatser
openerBoth=både och
openerCtrlAltClick=Ctrl + Alt + högerklick
openerRightLong=långvarig högerklick
phClickForExample=klicka för exempel...
scChangeVolume=Upp eller ned för att höja eller sänka volymen
scCycleModes=Bläddra igenom storlekslägen: naturlig, passa till bredd, passa till höjd
scDragndrop=Håll Ctrl eller AltSkift + dra i bilden för att använda fri zoomning; håll Ctrl för att flytta valet
scHorizontalScroll=För att skrolla bilden horisontellt: använd skrollhjulet vid nedre vänstra kanten
scImgBg=Bläddra igenom bildbakgrunder: default, black, white, check eller håll Skift för egna värden
scModeContain=Autoanpassning
scModeNatural=Naturlig storlek
scPixelate=Pixelera bild
scReset=Esc kommer nollställa bilden eller avsluta zoomläget
scRotateLeft=Rotera åt vänster
scRotateRight=Rotera åt höger
scTogglePlay=Blanksteg för att växla mellan spela och pausa
scWheelZoom=Skifta skrollhjulszoomning
scZoom=Zooma in eller ut
sendTo=Skicka bilden till...
shortcuts=Genvägar
wheelZoom=Zooma med skrollhjulet
[lang]
buttonReset=Varsayılan
buttonSave=Kaydet
defaultMode=İlk boyutlandırma modu
disabled=devre dışı
favicon=Özel favicon
mediaInfo=Resim bilgileri
minUpscale=Küçük resimleri büyüt
modeAutoFit=sığdır
navInfo=Bilgi
phClickForExample=örnekler için tıkla...
scFitToHeight=Yüksekliğe sığdır
scFitToWidth=Genişliğe sığdır
scFlipVertical=Dikey çevir
scModeNatural=Orijinal boyutlar
scRotateRight=Sağa döndür
shortcuts=Kısayollar
wheelZoom=Fare tekeriyle yakınlaştır
[lang]
buttonReset=Дефолні налаштування
buttonSave=Зберегти
customCss=Стиль (CSS)
defaultMode=Розмір за замовчуванням
disabled=відключено
favicon=Іконка
faviconTip="Цей параметр дозволяє призначити довільну іконку для вкладки з відкритим зображенням.\nАдреса зображення можна використовувати як змінну: %url"
infoTranslations=Переклади
longpressActionFitImage=підігнати по ширині / висоті
longpressLeft=Дія тривалого натискання лівою кнопкою миші
longpressRight=Дія тривалого натискання правою кнопкою миші
mediaInfo=Інформація про зображення
minUpscale=Збільшувати маленькі зображення
minUpscaleTip="Як правило, невеликі зображення не збільшуються до розмірів області перегляду при масштабування. Цей параметр змусить їх це робити.\nЗначення задається у відсотках, скрипт збільшить ті зображення, розмір яких більше даного відсотка від ширини або висоти області перегляду (залежно від попередньої настройки)."
modeAutoFit=вписати
modeBestFit=найкраще заповнення
modeNatural=оригінальний розмір
navInfo=Інфо
phClickForExample=Дивитить приклади...
scCycleModes=Переключити між режимами: оригінальний, підгін по ширині, підгін по висоті
scFitToHeight=Підігнати по висоті
scFitToWidth=Підігнати по ширині
scFlipHorizontal=Відобразити по горизонталі
scFlipVertical=Відобразити по вертикалі
scFreeZoom=Зажати Shift + ліву кнопку миші на зображенні для вільного масштабування, додатково затиснути Ctrl для переміщення виділення
scModeContain=Вписати
scModeNatural=Оригінальний розмір
scReset=Esc повертає зображення до первісного вигляду або виходить з режиму вільного масштабування.
scRotateLeft=Повернути вліво
scRotateRight=Повернути вправо
scZoom=Збільшити / зменшити
sendTo=Надіслати зображення в...
shortcuts=Поєднання клавіш
wheelZoom=Масштабувати колесом миші
[lang]
buttonReset=重置
buttonSave=保存
customCss=自定义样式 (CSS)
defaultMode=图片默认显示模式
disabled=禁用
favicon=自定义 favicon
faviconTip="该选项用于为打开的图片设置一个自定义的标签页图标。\n图片地址可使用以下变量:%url"
infoTranslations=翻译
longpressActionFitImage=适应宽度/高度
longpressLeft=鼠标左键长按时的操作
longpressRight=鼠标右键长按时的操作
mediaInfo=图片信息
minUpscale=放大小图片
minUpscaleTip="通常小图片不会被放大到视图窗口(view-port)那么大,而该选项可以强制放大这些小图片。\n该选项值表示视图窗口宽度和高度值(这由前一个选项来决定)的百分比,用于告知脚本凡是大于该百分比的图片都强制放大。"
modeAutoFit=嵌入查看器
modeBestFit=最佳适应方式
modeNatural=原始尺寸
navInfo=信息
phClickForExample=点击查看样例...
scCycleModes=在原始大小,适应宽度和适应高度三种显示模式中切换
scFitToHeight=适应高度
scFitToWidth=适应宽度
scFlipHorizontal=水平翻转
scFlipVertical=垂直翻转
scFreeZoom=Shift + 拖动 图片进入自由缩放模式,按住 Ctrl 时可移动选区
scModeContain=自动适应
scModeNatural=原始尺寸
scReset=Esc 键可重置图片为原始显示方式,或退出自由缩放模式
scRotateLeft=向左旋转
scRotateRight=向右旋转
scZoom=缩小 / 放大
sendTo=发送图片到...
shortcuts=快捷键
wheelZoom=使用鼠标滚轮缩放
[lang]
buttonReset=預設
buttonSave=儲存
defaultMode=初始尺寸模式
disabled=停用
favicon=自訂網站圖標
longpressActionFitImage=符合寬度/高度
longpressLeft=左鍵長按動作
longpressRight=右鍵長按動作
mediaInfo=影像資訊
minUpscale=放大小圖片
modeAutoFit=自動縮放
modeBestFit=適合圖片
modeNatural=原始大小
navInfo=相關訊息
phClickForExample=點擊以做為範例...
scFitToHeight=適合高度
scFitToWidth=適合寬度
scFlipVertical=垂直翻轉
scModeNatural=原始大小
scRotateRight=向右旋轉
shortcuts=快捷鍵
wheelZoom=以滑鼠滾輪縮放
{"_":"en","cs":{"name":"Czech [čeština]","translators":[{"email":"jaramat(at)email(dot)cz","name":"jaramat","realname":"Jaroslav Matura"}]},"de":{"name":"German [Deutsch]","translators":[{"name":"sioh"}]},"el":{"name":"Greek [Ελληνικά]","translators":[{"email":"farow(dot)the(dot)time(dot)traveler(at)gmail(dot)com","name":"Farow"}]},"en":{"name":"English","translators":[{"email":"deathamns(at)gmail(dot)com","name":"Deathamns"}]},"es":{"name":"Spanish [español]","translators":[{"email":"nightroad(at)mail(dot)com","name":"DurianZheitk","realname":"Javier Vera"},{"name":"alm","realname":"A LM"}]},"fi":{"name":"Finnish [suomi]","translators":[{"email":"opeeera(at)myopera(dot)com","name":"Opeeera"}]},"fr":{"name":"French [français]","translators":[{"email":"tmnath2(at)gmail(dot)com","name":"Tmnath"}]},"hu":{"name":"Hungarian [magyar]","translators":[{"email":"deathamns(at)gmail(dot)com","name":"Deathamns"}]},"ko":{"name":"Korean [한국어]","translators":[{"email":"yut951121(at)gmail(dot)com","name":"QbsidianH20","realname":"유태종"}]},"nl":{"name":"Dutch [Nederlands]","translators":[{"email":"kackar(at)outlook(dot)com","name":"Kaçkar"}]},"pl":{"name":"Polish [polski]","translators":[{"name":"pafflick","realname":"Paweł Pawlak","web":"http://www.pafflick.com/"}]},"pt-BR":{"name":"Portuguese (Brazil) [português (Brasil)]","translators":[{"email":"romulo(at)brazilmail(dot)com","realname":"Rômulo Godoi"}]},"ru":{"name":"Russian [русский]","translators":[{"email":"rodny0(at)gmail(dot)com","name":"Rodny"}]},"sv":{"name":"Swedish [svenska]","translators":[{"email":"johanohlin(at)gmx(dot)com","name":"Jojan","realname":"Johan Öhlin"}]},"tr":{"name":"Turkish [Türkçe]","translators":[{"email":"sanerapaydin86(at)gmail(dot)com","realname":"Saner Apaydın"}]},"uk":{"name":"Ukrainian [українська]","translators":[{"email":"simofon(at)yandex(dot)ru","name":"Simofon"}]},"zh-CN":{"name":"Chinese (Simplified Han) [中文(简体中文)]","translators":[{"email":"wlq105556(at)gmail(dot)com","name":"fang5566"}]},"zh-TW":{"name":"Chinese (Traditional Han) [中文 (繁體中文)]","translators":[{"email":"tingyang(at)gmail(dot)com","name":"TYKuo"}]}}