mx pak1!V�mbackground.html�wI css\options.css� ֚��def.json�&�)�x
defaults.json�)�'x�Zicon-18.png�-��r&"icons\icon_16.pngr1���#Jicons\icon_32.pngl5'��Uicons\icon_48.png�<�- �^�includes\app.js�E�ڃ
�includes\opener.jswTmkz�includes\viewer.js�d����50js\app_bg.js~Iw�pjs\background.js���c�js\frames.js��LJM�
js\options.js�f�1G�#locale\cs-cz.ini ����locale\el-gr.ini���d|�
locale\en.ini���-ϖ�locale\es-mx.ini�����Nlocale\fi-fi.ini?�ev�locale\fr-ca.ini���
lYMlocale\hu-hu.inix�����locale\ko-kr.inio�
2�=locale\nl-nl.ini���=plocale\pl-pl.inii�V��locale\pt-br.iniT$Z�K��locale\ru-ru.ini�,1��QZlocale\tr-tr.ini�F�� ��locale\uk-ua.ini�I�� )�locale\zh-cn.ini�VW�x4locale\zh-tw.ini�]�n%olocales.jsona�ƿ��options.html6i@
::-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;
padding: 6px 15px 15px;
border-top: 0;
box-shadow: 0 0 6px #666;
-webkit-box-shadow: 0 0 6px #666;
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 {
content: "";
display: block;
clear: both;
}
hr {
border: 1px solid #eee;
margin: 10px 0;
}
#right-panel {
position: absolute;
left: 100%;
top: 0;
}
#right-panel > aside {
max-width: 140px;
position: fixed;
top: 0;
padding: 0 5px 3px 8px;
box-shadow: 2px 2px 2px #aaa;
-webkit-box-shadow: 2px 2px 2px #aaa;
background-color: rgba(255, 255, 255, .8);
overflow: hidden;
text-align: center;
}
#right-panel > aside, section {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
aside > .app-info {
font-weight: bold;
}
#platform-info {
font: normal 8px sans-serif;
color: gray;
}
.hidden,
body.opera .opera, body.firefox .firefox, body.chrome .chrome,
body.safari .safari, body.maxthon .maxthon {
display: none;
}
.logo {
display: block;
width: 128px;
height: 128px;
margin-top: 5px;
border-radius: 10px;
background: url(../icon.png) no-repeat center;
-webkit-transition: -webkit-box-shadow .2s;
transition: box-shadow .2s;
}
.logo:hover {
box-shadow: 0 0 10px #bef;
-webkit-box-shadow: 0 0 10px #bef;
}
body > form > section {
display: none;
}
nav {
margin-bottom: 20px;
text-align: center;
}
nav > a {
display: inline-block;
border-bottom: 3px solid transparent;
padding: 5px 6px;
color: #1155ef;
text-decoration: none;
-webkit-transition: border-bottom-color .5s;
transition: border-bottom-color .5s;
}
nav > a:hover {
-webkit-transition: border-bottom-color 0s;
transition: border-bottom-color 0s;
border-bottom: 3px solid #aaf;
color: #000;
}
nav > .active {
color: #000;
border-bottom: 3px solid #000;
}
.prow {
clear: both;
padding-bottom: 3px;
}
.prow, .tiptop {
position: relative;
}
.tip {
visibility: hidden;
max-width: 100%;
width: 33px;
height: 25px;
z-index: 1;
position: absolute;
left: -48px;
top: -5px;
border: 1px solid transparent;
padding: 5px 7px;
overflow: hidden;
opacity: 0;
font: 12px/150% Verdana, sans-serif;
white-space: pre-wrap;
color: rgba(0, 0, 0, 0);
-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 {
width: auto;
height: auto;
left: -45px;
border: 1px solid #ddd;
border-left: none;
border-radius: 6px;
padding: 10px;
padding-left: 40px;
box-shadow: 0 0 10px #666;
-webkit-box-shadow: 0 0 10px #666;
background-color: rgba(245, 245, 255, .9);
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #fff), color-stop(100%, rgba(245, 245, 255, 0)));
background-image: linear-gradient(to bottom, #fff, rgba(245, 245, 255, 0));
overflow: visible;
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;
left: 5px;
top: 5px;
}
.prow > label, .prow > span:not(.clean) {
display: inline-block;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
width: 49.6%;
}
.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 {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
margin: 2px;
border: 1px solid #ddd;
border-radius: 3px;
padding: 3px;
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #fff), color-stop(100%, #f5f5f5));
background-image: linear-gradient(to bottom, #fff, #f5f5f5);
background-color: rgba(242, 242, 242, 0);
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;
}
code {
display: inline-block;
border: 1px solid silver;
padding: 3px 5px;
background-image: linear-gradient(to bottom, #FFFFFF, #F5F5F5);
}
select {
max-width: 100%;
}
textarea {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
width: 100%;
overflow-x: hidden;
resize: none;
-webkit-tab-size: 4;
-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 {
display: inline-block;
width: 20px;
height: 20px;
position: relative;
padding: 0;
vertical-align: middle;
color: transparent;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.checkbox::after {
position: absolute;
left: 3px;
top: 0;
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"] {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
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 {
width: 35px;
margin: 5px;
text-align: center;
}
.sub-shortcuts input {
margin: 0;
}
.sub-shortcuts li {
line-height: 200%;
}
.op-buttons > button, .action-buttons > span {
position: relative;
border-radius: 3px;
border: 1px solid #ddd;
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #fff), color-stop(100%, #f5f5f5));
background-image: linear-gradient(to bottom, #fff, #f5f5f5);
font-weight: 700;
font-size: 14px;
color: #000;
cursor: pointer;
}
.op-buttons > button {
width: 95%;
margin-bottom: 10px;
padding: 10px 0;
box-shadow: 0 1px 2px rgba(0, 0, 0, .5);
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .5);
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": "1.0.1",
"title": {"en": "Viewhance"},
"description": {"_t": "appDescriptionShort"},
"author": {
"name": "Deathamns",
"email": "deathamns@gmail.com"
},
"permissions": {"httpRequest": ["*"]},
"config": "options.html",
"service": {
"main": "background.html#Viewhance,1.0.1"
},
"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": "",
"customCSS": "",
"center": true,
"wheelZoom": false,
"mediaAttrs": "autoplay controls",
"lpDelay": 350,
"lpLeft": 1,
"lpRight": 0,
"sendTo": [
"TinEye|https://www.tineye.com/search?sort=size&order=desc&url=%url",
"Google|https://images.google.com/searchbyimage?image_url=%url",
"Bing|https://www.bing.com/images/searchbyimage?cbir=sbi&imgurl=%url",
"Yandex|https://images.yandex.ru/yandsearch?rpt=imagecbir&img_url=%url",
"KarmaDecay|http://karmadecay.com/%url",
"ZXing QRCode|http://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": "Q",
"key_flipV": "W",
"key_cycle": "C",
"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��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'
);
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;
}
return this._mediaType = media.nodeName.toLowerCase();
}, set: function(type) {
this._mediaType = type;
}});
vAPI.messaging = {
listenerId: Math.random().toString(36).slice(2),
emptyListener: function() {},
listen: function(listener, once) {
if ( this.listener ) {
vAPI.runtime.listen(this.listenerId, this.emptyListener);
}
if ( typeof listener !== 'function' ) {
this.listener = null;
return;
}
this.listener = function(e) {
listener(e);
if ( once ) {
vAPI.messaging.listen(null);
}
};
vAPI.runtime.listen(this.listenerId, this.listener);
},
send: function(message, callback) {
if ( typeof callback === 'function' ) {
this.listen(callback, true);
}
vAPI.runtime.post('service', {
message: message,
listenerId: this.listenerId,
origin: location.href
});
}
};
if ( location.protocol === 'mxaddon-pkg:' ) {
vAPI.i18n = function(s) {
var t = this.runtime.locale.t(s);
return t[0] === '"' ? JSON.parse(t) : t || s;
};
vAPI.insertHTML = function(n, html) {
n.innerHTML = html;
};
}
'use strict';
(function() {
if ( document instanceof window.HTMLDocument === false ) {
return;
}
// Should not run on media documents
if ( vAPI.mediaType ) {
return;
}
if ( vAPI.safari && location.protocol === 'safari-extension:' ) {
return;
}
vAPI.messaging.send({cmd: 'loadPrefs', property: 'opener'}, function(response) {
var opener = response && response.prefs;
if ( !opener ) {
return;
}
var lastMouseDownTime, lastMouseDownX, lastMouseDownY;
var checkBG = function(cs) {
// ("...\"") - Gecko
// (...) or ('...)') - WebKit
// ("..."") - Presto
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.nodeName.toUpperCase();
if ( nname === 'IMG' || nname === 'EMBED' || node.type === 'image' ) {
return node.src;
} 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' ) {
nname = document.createElement('canvas');
nname.width = node.clientWidth;
nname.height = node.clientHeight;
nname.getContext('2d').drawImage(
node, 0, 0, nname.width, nname.height
);
return nname.toDataURL('image/jpeg');
} 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;
};
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);
window.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 url, r;
var urls = [];
var el = 30;
var rgxIgnore = /^(html|body)$/i;
// not exactly what we want
var xpath = document.evaluate([
'.',
'./ancestor::*[position()<' + el + ']',
'./preceding::*[position()<' + el + '][not(head) and not(ancestor::head)]',
'./descendant::*[position()<' + el + ']',
'./following::*[position()<' + el + ']'
].join(' | '),
e.target,
null,
4,
null
);
while ( el = xpath.iterateNext() ) {
if ( rgxIgnore.test(el.nodeName) && !rgxIgnore.test(e.target.nodeName) ) {
continue;
}
r = el.getBoundingClientRect();
if ( !r ) {
continue;
}
if ( e.clientX < r.left || e.clientX > r.left + r.width
|| e.clientY < r.top || e.clientY > r.top + r.height ) {
continue;
}
if ( url = checkIMG(el) ) {
urls.push(url);
}
if ( url = checkBG(window.getComputedStyle(el)) ) {
urls = urls.concat(url);
}
}
if ( !urls || !urls.length ) {
return;
}
e.stopImmediatePropagation();
e.preventDefault();
var i;
var filter = {};
for ( i = 0; i < urls.length; ++i ) {
if ( urls[i] === 'about:blank' ) {
continue;
}
filter[urls[i]] = true;
}
vAPI.messaging.send({
cmd: 'open',
url: Object.keys(filter).reverse()
});
}, true);
});
})();
'use strict';
var init = function(win, doc, response) {
if ( !doc || !doc.body || !response || !response.prefs ) {
init = null;
return;
}
var cfg = response.prefs;
var media = doc.body.querySelector('img, video');
if ( !media ) {
init = null;
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: '/',
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();
}
};
var root, head, initParams, panning, winW, winH, sX, sY;
var noFit = {cur: false, real: false};
var lastEvent = {};
var progress = null;
var cancelAction = false;
var freeZoom = null;
var dragSlide = [];
var borderSize = 0;
var MAXSIZE = 0x7fff;
['class', 'style', 'name'].forEach(function(attr) {
doc.documentElement.removeAttribute(attr);
doc.body.removeAttribute(attr);
media.removeAttribute(attr);
});
media.style.display = 'none';
if ( head = doc.querySelector('head') ) {
doc.documentElement.removeChild(head);
}
head = doc.createElement('head');
if ( cfg.favicon ) {
root = doc.createElement('link');
root.rel = 'shortcut icon';
root.href = cfg.favicon === '%url' && vAPI.mediaType === 'img'
? win.location.href
: cfg.favicon.replace('%url', encodeURIComponent(win.location.href));
head.appendChild(root);
}
head.appendChild(doc.createElement('style')).textContent = [
'html, body {',
'width: 100%;',
'height: 100%;',
'-webkit-user-select: none;',
'-moz-user-select: none;',
'-ms-user-select: none;',
'}',
'body {',
'margin: 0;',
'padding: 0;',
'font: 12px "Trebuchet MS", sans-serif;',
'cursor: default;',
'}',
'#main-media {',
vAPI.browser['box-sizing-css'], ': border-box;',
'position: absolute;',
'margin: 0;',
'background-clip: padding-box;',
'}',
'html.audio #main-media {',
'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 #main-media {',
'margin: auto',
'box-shadow: 0 0 10px red;',
'}',
'html.fullscreen #main-media {',
'background: black !important;',
'}',
'#main-media:-moz-full-screen {',
'background: black !important;',
'}',
'html.load-failed > body > h2 {',
'text-shadow: 1px 1px 15px firebrick;',
'}',
'#main-media.m-1 {',
'width: auto;',
'height: auto;',
'max-width: 100%;',
'max-height: 100%;',
'}',
'#main-media.m-2 {',
'width: 100%;',
'height:auto;',
'}',
'#main-media.m-3 {',
'height: 100%;',
'width: auto;',
'}',
'h2 {',
'margin: 0;',
'padding-top: 15%;',
'text-align: center;',
'text-shadow: 1px 1px 15px #000;',
'font: 700 30px "Trebuchet MS", sans-serif;',
'color: #fff;',
'}',
'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['transition-css'], ': opacity .25s, 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 {',
'display: block;',
'position: relative;',
'}',
'li[data-cmd] {',
'cursor: pointer;',
'}',
'li[data-cmd=cycle], li[data-cmd=rotate] {',
'position: relative;',
'}',
'li[data-cmd=cycle]::after {',
'position: absolute;',
'left: 25%;',
'content: "\u2195";',
'}',
'li[data-cmd=rotate]::after {',
'position: absolute;',
'left: 2px;',
'content: "\u21BB";',
'}',
'li ul {',
'visibility: hidden;',
'position: absolute;',
'left: 100%;',
'top: 0;',
'text-align: left;',
'opacity: 0;',
vAPI.browser['transition-css'], ': visibility .4s, opacity .2s .3s;',
'}',
'li:hover ul {',
'display: block;',
'visibility: visible;',
'opacity: 1;',
'}',
'li ul > li {',
'display: block !important;',
'padding: 3px 0;',
'font-size: 15px;',
'}',
'.send-hosts li > a {',
'padding-left: 25px;',
'background-size: 16px 16px;',
'background-repeat: no-repeat;',
'background-position: 0 3px;',
'color: #fff;',
'}',
'#menu > ul > li:hover, .send-hosts li > a:hover {',
'color: silver;',
'}',
'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 or default styling
cfg.customCSS || 'body {background: silver; overflow: hidden;}' +
'#main-media {background: white; box-shadow: 0 0 5px grey;}'
].join('');
doc.documentElement.insertBefore(head, doc.body);
init = function() {
if ( !(media.naturalWidth || media.width || media.videoWidth
|| vAPI.mediaType === 'audio' || initParams === null) ) {
if ( initParams && ++initParams.loop >= initParams.maxLoop && progress ) {
clearInterval(progress);
}
return;
}
if ( progress ) {
clearInterval(progress);
progress = null;
}
root.classList.add(vAPI.mediaType);
if ( vAPI.mediaType === 'img' ) {
doc.body.replaceChild(media, doc.images[0]);
} else if ( vAPI.mediaType === 'video' ) {
media.naturalWidth = media.videoWidth;
media.naturalHeight = media.videoHeight;
}
[].forEach.call(doc.body.childNodes, function(node) {
if ( media !== node ) {
node.parentNode.removeChild(node);
}
});
media.style.display = 'block';
if ( vAPI.mediaType === 'audio' ) {
return;
}
head.appendChild(doc.createElement('style')).textContent =
'#main-media {max-width:' +
Math.min(
MAXSIZE,
Math.floor(media.naturalWidth * MAXSIZE / media.naturalHeight)
) +
'px;max-height:' +
Math.min(
MAXSIZE,
Math.floor(media.naturalHeight * MAXSIZE / media.naturalWidth)
) + 'px}';
if ( !cfg.mediaInfo ) {
cfg.mediaInfo = false;
}
cfg.hiddenScrollbars = win.getComputedStyle(root).overflow === 'hidden'
|| win.getComputedStyle(doc.body).overflow === 'hidden';
var menu = doc.body.appendChild(doc.createElement('div'));
menu.id = 'menu';
if ( win.getComputedStyle(menu).display === 'none' ) {
doc.body.removeChild(menu);
menu = null;
} else {
menu.style.cssText = '-webkit-filter: blur(0px); filter: blur(0px)';
if ( menu.style.filter || menu.style.webkitFilter ) {
var onMenuChange = function(e) {
var t = e.target;
var filterCSS = '';
var filterName;
if ( !t.value ) {
media.style.filter = media.style.webkitFilter = 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] + ') ';
}
media.style.filter = media.style.webkitFilter = filterCSS;
};
media.filters = Object.create(null);
menu.addEventListener('change', onMenuChange);
}
vAPI.buildNodes(menu.appendChild(doc.createElement('ul')), [
{tag: 'li', attrs: {'data-cmd': 'cycle'}, text: '\u2194'},
{tag: 'li', attrs: {'data-cmd': 'zoom'}, nodes: [
{tag: 'span', attrs: {style: 'visibility: hidden'}, text: '.'},
{
tag: 'span',
attrs: {
style: [
'transform: rotate(-45deg)',
'position: absolute',
'left: 20%',
'font-size: 125%'
].join(';')
},
text: '\u26B2'
}
]},
{tag: 'li', attrs: {'data-cmd': 'flip'}, text: '\u21CB'},
{tag: 'li', attrs: {'data-cmd': 'rotate'}, text: '\u21BA'},
media.filters ? {tag: 'li', attrs: {'class': 'filters'}, nodes: [
'\u2261',
{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'}, text: '\u2715'},
/^https?:$/.test(win.location.protocol) && cfg.sendTo.length
? {tag: 'li', attrs: {'class': 'send-hosts'}, nodes: [
'\u2197', {tag: 'ul', nodes: cfg.sendTo.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'}, text: '\u22EF'} : '',
{tag: 'li', attrs: {'data-cmd': 'options'}, text: '\u2713'}
]);
menu.style.cssText = 'display: none; left: -' + menu.offsetWidth + 'px';
menu.addEventListener('mousedown', function(e) {
var t = e.target;
if ( t.href && t.href.indexOf('%', t.host.length) > -1 ) {
t.href = t.href.replace(/%url/, encodeURIComponent(media.src));
}
pdsp(e, !!t.textContent);
}, false);
// Load favicons only when the menu item is hovered the first time
if ( /^https?:$/.test(win.location.protocol) && cfg.sendTo.length ) {
menu.querySelector('.send-hosts')
.addEventListener('mouseover', function onHostsHover() {
var links = this.querySelectorAll('.send-hosts > ul > li > a');
[].forEach.call(links, function(a) {
var url = a.getAttribute('data-favicon')
|| a.host + '/favicon.ico';
url = a.protocol + '//' + url;
a.style.backgroundImage = 'url(' + url + ')';
});
this.removeEventListener('mouseover', onHostsHover);
});
}
var handleCommand = function(cmd, e) {
if ( e.button === 1 ) {
return;
}
var p = e.button === 2
|| e.type.indexOf('wheel') > -1
&& (-e.wheelDelta || e.deltaY) > 0;
if ( cmd === 'cycle' ) {
media.cycle(!p);
} else if ( cmd === 'flip' ) {
media.flip(media, p);
} else if ( cmd === 'rotate' ) {
media.rotate(!p, e.ctrlKey);
} else if ( cmd === 'zoom' ) {
pdsp(e);
media.zoomToCenter({wheelDelta: p ? -1 : 1});
} else if ( cmd === 'reset' && e.button === 0 ) {
media.reset();
} else if ( cmd === 'frames' ) {
vAPI.messaging.send({cmd: 'frames.js'}, function(data) {
var errorHandler = function(msg) {
// Success
if ( msg !== null ) {
alert(msg); // eslint-disable-line
var frms = menu.querySelector('li[data-cmd="frames"]');
frms.removeAttribute('data-cmd');
frms.style.opacity = '0.2';
return;
}
if ( vAPI.maxthon ) {
win.addEventListener('mousedown', function(ev) {
pdsp(ev, false);
}, true);
}
};
Function(
'win',
'drawFullFrame',
'errorHandler',
data['frames.js']
)(win, e.button === 0, errorHandler);
});
} else if ( cmd === 'options' && e.button === 0 ) {
vAPI.messaging.send({cmd: 'open', url: 'options.html'});
} else {
p = null;
}
if ( p !== null ) {
pdsp(e);
}
};
var onMenuClick = function(e) {
var target = e.target;
if ( !target.hasAttribute('data-cmd') ) {
target = target.parentNode;
}
if ( target.hasAttribute('data-cmd') ) {
handleCommand(target.getAttribute('data-cmd'), e);
}
};
var menuTrigger = function(e) {
if ( panning || freeZoom ) {
return;
}
if ( e.clientX > 40 || e.clientY > win.innerHeight / 3 ) {
return;
}
if ( menu.style.display === 'block' ) {
return;
}
menu.style.display = 'block';
setTimeout(function() {
menu.style.left = '0';
menu.style.opacity = '1';
}, 50);
doc.removeEventListener('mousemove', menuTrigger, false);
};
if ( win.Node.prototype && !win.Node.prototype.contains ) {
win.Node.prototype.contains = function(n) {
if ( n instanceof Node === false ) {
return false;
}
return this === n || !!(this.compareDocumentPosition(n) & 16);
};
}
menu.addEventListener(vAPI.browser.wheel, function(e) {
var t = e.target;
if ( t.nodeType === 3 ) {
t = t.parentNode;
}
if ( t.type === 'range' ) {
var delta = (-e.wheelDelta || e.deltaY) > 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);
pdsp(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] === '-' ) {
menu.style.display = 'none';
}
});
menu.addEventListener('mouseover', function() {
if ( !menu.mtimer ) {
return;
}
clearTimeout(menu.mtimer);
menu.mtimer = null;
menu.style.left = '0';
menu.style.opacity = '1';
});
menu.addEventListener('mouseout', function(e) {
if ( this.contains(e.relatedTarget) ) {
return;
}
doc.addEventListener('mousemove', menuTrigger, false);
menu.mtimer = setTimeout(function() {
menu.style.left = '-' + menu.offsetWidth + 'px';
menu.style.opacity = '0';
menu.mtimer = null;
}, 800);
});
// Safari showed the menu even if the cursor wasn't at the edge
setTimeout(function() {
doc.addEventListener('mousemove', menuTrigger, false);
}, 500);
}
var convertInfoParameter = function(a, param) {
var m = media;
switch ( param ) {
case 'w': return m.clientWidth;
case 'h': return m.clientHeight;
case 'ow': return m.naturalWidth;
case 'oh': return m.naturalHeight;
case 'url': return win.location.href;
case 'name': return m.alt;
case 'ratio':
return Math.round(m.clientWidth / m.clientHeight * 100) / 100;
case 'perc': return Math.round(m.clientWidth * 100 / m.naturalWidth);
}
};
var afterCalcCallback = function() {
// Gecko and WebKit/Blink render scrollbars for a split of a second,
// even if the image fits into the view-port
winH = doc.compatMode[0] === 'B' ? doc.body : root;
winW = winH.clientWidth;
winH = winH.clientHeight;
var m = media;
m.calcFit();
// Change curosr according to sizing
if ( m.clientWidth > winW || m.clientHeight > winH ) {
m.style.cursor = 'move';
} else if ( winH >= m.clientHeight && winW >= m.clientWidth
&& winH < m.naturalHeight || winW < m.naturalWidth ) {
m.style.cursor = vAPI.browser['zoom-in'];
} else if ( noFit.cur && noFit.real
&& (m.clientHeight < m.naturalHeight
|| m.clientWidth < m.naturalWidth) ) {
m.style.cursor = vAPI.browser['zoom-in'];
} else {
m.style.cursor = 'default';
}
if ( !cfg.mediaInfo || !(m.naturalWidth && m.naturalHeight) ) {
return;
}
doc.title = cfg.mediaInfo.replace(
/%(o?[wh]|url|name|ratio|perc)/g,
convertInfoParameter
);
};
var afterCalc = function() {
if ( !media.calcFit ) {
return;
}
winH = doc.compatMode[0] === 'B' ? doc.body : root;
winW = winH.clientWidth;
winH = winH.clientHeight;
media.setPos();
setTimeout(afterCalcCallback, 0xf);
};
media.resize = function(m, w) {
var mode = m === void 0 ? 1 : m;
if ( mode === -1 ) {
if ( w ) {
this.style.width = w;
}
} else if ( this.mode === -1 ) {
this.style.width = '';
this.style.height = '';
}
this.mode = mode;
this.className = 'm-' + mode;
if ( this.naturalWidth ) {
afterCalc();
}
};
media.setPos = function() {
var s = this.style;
if ( cfg.center ) {
s.top = Math.max(0, (winH - this.offsetHeight) / 2) + 'px';
s.left = Math.max(0, (winW - this.offsetWidth) / 2) + 'px';
} else {
s.top = s.left = '0';
}
var box = this.getBoundingClientRect();
this.box = box;
if ( box.left < 0 ) {
s.left = (parseInt(s.left, 10) - box.left - win.pageXOffset) + 'px';
}
if ( box.top < 0 ) {
s.top = (parseInt(s.top, 10) - box.top - win.pageYOffset) + 'px';
}
};
media.calcFit = function() {
var box = this.box || this.getBoundingClientRect();
noFit = {
cur: box.width <= winW && box.height <= winH,
real: this.naturalWidth <= winW && this.naturalHeight <= winH
};
};
media.wheelZoom = function(e) {
stopScroll(); // eslint-disable-line
pdsp(e);
var w = media.offsetWidth;
var h = media.offsetHeight;
if ( (-e.wheelDelta || e.deltaY) > 0 ) {
media.resize(-1, Math.max(1, w * 0.75) + 'px');
} else {
var width = w * (4 / 3);
media.resize(-1, (width > 10 ? width : width + 3) + 'px');
}
if ( !e.keypress && e.target.nodeName.toUpperCase() !== 'IMG' ) {
return;
}
var layerX = e.offsetX || e.layerX || 0;
var layerY = e.offsetY || e.layerY || 0;
win.scrollTo(
layerX * media.offsetWidth / w - e.clientX + borderSize,
layerY * media.offsetHeight / h - e.clientY + borderSize
);
};
media.zoomToCenter = function(e) {
pdsp(e);
this.wheelZoom({
keypress: true,
wheelDelta: e.wheelDelta,
clientX: winW / 2,
clientY: winH / 2,
offsetX: win.pageXOffset + media.offsetLeft + winW / 2,
offsetY: win.pageYOffset + media.offsetTop + winH / 2
});
};
media.cycle = function(back) {
var mode = (this.mode === 1 ? 0 : this.mode) - (back ? 1 : -1);
if ( mode === 1 ) {
mode -= back ? 1 : -1;
} else if ( mode < 0 ) {
mode = 3;
} else if ( mode > 3 ) {
mode = 0;
}
this.resize(mode);
};
media.reset = function() {
if ( freeZoom ) {
doc.removeEventListener('mousemove', drawMask, false);
doc.body.removeChild(media.mask);
freeZoom = null;
cancelAction = false;
return;
}
// Firefox document readyState stucks in 'interactive' for videos,
// but videos don't need to be loaded anyway
if ( vAPI.mediaType === 'img' && doc.readyState !== 'complete' ) {
return;
}
var filters = doc.body.querySelector('#menu li.filters > form');
var style = this.style;
if ( filters ) {
style.filter = style.webkitFilter = '';
media.filters = {};
filters.reset();
}
delete this.curdeg;
delete this.scale;
style[vAPI.browser.transform] = '';
style.width = '';
style.height = '';
this.resize(0);
};
media.flip = function(el, horizontal) {
if ( !this.scale ) {
this.scale = {h: 1, v: 1};
}
this.scale[horizontal ? 'h' : 'v'] *= -1;
var transformCss = this.scale.h !== 1 || this.scale.v !== 1
? 'scale(' + this.scale.h + ',' + this.scale.v + ')'
: '';
if ( this.curdeg ) {
transformCss += ' rotate(' + this.curdeg + 'deg)';
}
this.style[vAPI.browser.transform] = transformCss;
};
media.rotate = function(deg, fine) {
var rot;
if ( !this.curdeg ) {
this.curdeg = 0;
}
if ( deg ) {
this.curdeg += fine ? 10 : 90;
} else {
this.curdeg -= fine ? 10 : 90;
}
win.status = this.curdeg + '°';
rot = 'rotate(' + this.curdeg + 'deg)';
if ( this.scale ) {
rot += ' scale(' + this.scale.h + ', ' + this.scale.v + ')';
}
this.style[vAPI.browser.transform] = rot;
this.setPos();
};
if ( cfg.wheelZoom ) {
doc.addEventListener(vAPI.browser.wheel, media.wheelZoom, false);
} else {
doc.addEventListener(vAPI.browser.wheel, function(e) {
if ( media.clientWidth <= winW && media.clientHeight <= winH ) {
return;
}
stopScroll(); // eslint-disable-line
var x = 0;
var y = ((-e.wheelDelta || e.deltaY) > 0 ? winH : -winH) / 5;
if ( media.clientWidth <= winW && media.clientHeight > winH ) {
if ( !cfg.hiddenScrollbars ) {
return;
}
} else if ( media.clientHeight <= winH && media.clientWidth > winW
|| e.clientX < winW / 2 && e.clientY > winH - 100 ) {
x = (y < 0 ? -winW : winW) / 5;
y = 0;
} else if ( !cfg.hiddenScrollbars ) {
return;
}
win.scrollBy(x, y);
pdsp(e);
}, false);
}
win.addEventListener('resize', afterCalc, false);
doc.addEventListener('contextmenu', function(e) {
doc.removeEventListener('mousemove', onMove, true); // eslint-disable-line
if ( progress ) {
clearTimeout(progress);
progress = null;
}
if ( cancelAction ) {
e.preventDefault();
}
}, false);
var lastMoveX, lastMoveY;
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 ) {
panning = win.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 = Date.now();
};
var startScroll = function() {
progress = setInterval(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 atRight = root.scrollWidth - win.pageXOffset === winW;
var atBottom = root.scrollHeight - win.pageYOffset === winH;
if ( !(dragSlide[0] && dragSlide[1])
|| !win.pageYOffset && !win.pageXOffset
|| !win.pageYOffset && atRight
|| atBottom && !win.pageXOffset
|| atBottom && atRight ) {
stopScroll();
}
}, 25);
};
var stopScroll = function(e) {
if ( e ) {
doc.removeEventListener(e.type, stopScroll);
}
if ( !dragSlide.length ) {
return;
}
clearInterval(progress);
progress = null;
cancelAction = false;
dragSlide.length = 0;
media.dragSlideTime = 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.X += rx;
freeZoom.Y += ry;
} else {
if ( freeZoom.prevX ) {
delete freeZoom.prevX;
delete freeZoom.prevY;
}
freeZoom.w = Math.abs(freeZoom.X - x);
freeZoom.h = Math.abs(freeZoom.Y - y);
freeZoom.x = freeZoom.X < x ? freeZoom.X : freeZoom.X - freeZoom.w;
freeZoom.y = freeZoom.Y < y ? freeZoom.Y : freeZoom.Y - 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);
};
var longpressHandler = function() {
cancelAction = true;
progress = null;
var action = cfg[lastEvent.button === 2 ? 'lpRight' : 'lpLeft'];
if ( action === 1 ) {
var x, y;
var b = doc.body;
if ( media.mode === 2 || media.clientWidth === b.clientWidth
|| b.clientHeight > media.clientHeight && winW < b.clientWidth ) {
x = media.clientWidth;
media.resize(3);
x = lastEvent.layerX * media.clientWidth / x - winW / 2;
y = 0;
} else {
y = media.clientHeight;
media.resize(2);
x = 0;
y = lastEvent.layerY * media.clientHeight / y - winH / 2;
}
win.scrollTo(x, y);
}
};
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 ( !e.shiftKey && vAPI.mediaType === 'video' ) {
var topPart = Math.min(
this.clientHeight - 40,
this.clientHeight / 2
);
if ( (e.offsetY || e.layerY || 0) > topPart ) {
return;
}
}
if ( e.button === 0 && this.mode < 4 || e.button === 2 ) {
if ( e.button === 2 ) {
sX = true;
} else {
if ( !e.shiftKey && noFit.cur && this.clientWidth >= 60 ) {
if ( this.clientWidth - (e.offsetX || e.layerX || 0) <= 30 ) {
lastEvent.clientX = e.clientX;
lastEvent.clientY = e.clientY;
return;
}
}
e.preventDefault();
win.focus();
sX = e.clientX;
sY = e.clientY;
}
if ( !e.shiftKey ) {
doc.addEventListener('mousemove', onMove, true);
}
}
if ( !cfg.lpDelay ) {
return;
}
// For fine move and free zoom
if ( e.shiftKey ) {
cancelAction = true;
if ( e.button === 0 ) {
freeZoom = {
counter: 0,
left: parseInt(this.style.left, 10),
top: parseInt(this.style.top, 10)
};
freeZoom.X = e.clientX - freeZoom.left;
freeZoom.Y = e.clientY - freeZoom.top;
if ( !this.mask ) {
this.mask = doc.createElement('canvas');
this.mask.className = 'mask';
this.mask.style.cssText = [
'display: block',
'position: fixed',
'left: 0',
'top: 0'
].join(';');
this.mctx = this.mask.getContext('2d');
}
doc.addEventListener('mousemove', drawMask, false);
var h = this.curdeg && Math.sin(this.curdeg) ? true : false;
var w = h ? this.offsetHeight : this.offsetWidth;
h = h ? this.offsetWidth : this.offsetHeight;
this.mask.width = Math.min(winW, w);
this.mask.height = Math.min(winH, h);
this.mask.style.left = this.style.left;
this.mask.style.top = this.style.top;
this.mctx.clearRect(0, 0, this.mask.width, this.mask.height);
doc.body.appendChild(this.mask);
w = win.getComputedStyle(this.mask).color;
this.mctx.fillStyle = !w || w === 'rgb(0, 0, 0)'
? 'rgba(0,0,0,.4)'
: w;
}
}
// Is dragSlideing
if ( progress ) {
if ( stopScroll ) {
stopScroll();
cancelAction = e.button === 0;
}
if ( e.button === 0 ) {
return;
}
}
if ( e.shiftKey || e.button === 0 && !cfg.lpLeft
|| e.button === 2 && !cfg.lpRight ) {
return;
}
lastEvent.clientX = e.clientX;
lastEvent.clientY = e.clientY;
lastEvent.layerX = e.offsetX || e.layerX || 0;
lastEvent.layerY = e.offsetY || e.layerY || 0;
lastEvent.button = e.button;
progress = setTimeout(longpressHandler, cfg.lpDelay);
}, true);
doc.addEventListener('mouseup', function(e) {
if ( e.button !== 0 ) {
return;
}
if ( vAPI.fullScreenElement === media && vAPI.mediaType === 'video' ) {
return;
}
var x, y;
if ( media.mode < 4 ) {
doc.removeEventListener('mousemove', onMove, true);
if ( freeZoom ) {
doc.removeEventListener('mousemove', drawMask, false);
doc.body.removeChild(media.mask);
var w = Math.min(
media.clientWidth,
freeZoom.w + Math.min(freeZoom.x, 0)
+ (freeZoom.x + freeZoom.w > media.mask.width
? media.mask.width - freeZoom.x - freeZoom.w
: 0)
);
var h = Math.min(
media.clientHeight,
freeZoom.h + Math.min(freeZoom.y, 0)
+ (freeZoom.y + freeZoom.h > media.mask.height
? media.mask.height - freeZoom.y - freeZoom.h
: 0)
);
x = Math.max(0, freeZoom.x);
y = Math.max(0, freeZoom.y);
freeZoom = null;
cancelAction = false;
if ( !w || !h ) {
return;
}
if ( x >= media.clientWidth || y >= media.clientHeight ) {
return;
}
var nimgw, nimgh;
var scrollbars = win.innerWidth - winW || win.innerHeight - winH;
var fitW = winW < w * winH / h;
fitW = e.ctrlKey ? !fitW : fitW;
if ( fitW ) {
nimgw = media.clientWidth * winW / w;
nimgh = nimgw * media.clientHeight / media.clientWidth;
} else {
nimgh = media.clientHeight * winH / h;
nimgw = nimgh * media.clientWidth / media.clientHeight;
}
if ( nimgw > MAXSIZE ) {
nimgw = MAXSIZE;
nimgh = media.clientHeight * MAXSIZE / media.clientWidth;
}
if ( nimgh > MAXSIZE ) {
nimgw = media.clientWidth * MAXSIZE / media.clientHeight;
nimgh = MAXSIZE;
}
var cx = (win.pageXOffset + x + w / 2) * nimgw /
media.clientWidth - winW / 2 - scrollbars;
var cy = (win.pageYOffset + y + h / 2) * nimgh /
media.clientHeight - winH / 2 - scrollbars;
media.resize(-1, nimgw + 'px');
win.scrollTo(cx, cy);
return;
} else if ( dragSlide.length === 3 ) {
x = dragSlide[0][0] - dragSlide[2][0];
y = dragSlide[0][1] - dragSlide[2][1];
if ( Date.now() - media.dragSlideTime > 100 ) {
cancelAction = false;
dragSlide.length = 0;
return;
}
if ( x || y ) {
dragSlide.length = 2;
dragSlide[0] = x;
dragSlide[1] = y;
startScroll();
doc.addEventListener(vAPI.browser.wheel, stopScroll);
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 < 2 && noFit.real ) {
if ( media.mode === -1 ) {
media.resize(0);
} else if ( winW / winH < media.naturalWidth / media.naturalHeight ) {
media.resize(2);
} else if ( winH === media.offsetHeight && winW > media.offsetWidth ) {
media.resize(2);
} else {
media.resize(3);
}
} else if ( media.mode === 1 || noFit.cur ) {
if ( media.naturalWidth === media.clientWidth
&& media.naturalHeight === media.clientHeight ) {
return;
}
x = e.offsetX || e.layerX || 0;
y = e.offsetY || e.layerY || 0;
if ( media.scale ) {
if ( media.scale.h === -1 ) {
x = media.clientWidth - x;
}
if ( media.scale.v === -1 ) {
y = media.clientHeight - y;
}
}
x = x * media.naturalWidth / media.clientWidth - winW / 2;
y = y * media.naturalHeight / media.clientHeight - winH / 2;
media.resize(0);
win.scrollTo(x, y);
} else {
media.resize(1);
}
}, 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 === '-' ) {
e.wheelDelta = key === '+' ? 1 : -1;
media.zoomToCenter(e);
return;
}
var x, y, z;
switch ( key ) {
case 'Esc':
media.reset();
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 ? root.scrollWidth : win.pageXOffset;
y = e.shiftKey ? win.pageYOffset : root.scrollHeight;
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);
e.preventDefault();
}
return;
}
switch ( key ) {
case cfg.key_mOrig: media.resize(0); break;
case cfg.key_mFit: media.resize(1); break;
case cfg.key_mFitW: media.resize(2); break;
case cfg.key_mFitH: media.resize(3); break;
case cfg.key_cycle: media.cycle(e.shiftKey); break;
case cfg.key_rotL: media.rotate(false, e.shiftKey); break;
case cfg.key_rotR: media.rotate(true, e.shiftKey); break;
case cfg.key_flipH: media.flip(media, 0); break;
case cfg.key_flipV: media.flip(media, 1); 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;
}
}
if ( x !== true ) {
pdsp(e);
}
}, true);
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);
}
});
}
media.mode = cfg.mode;
media.calcFit();
progress = [];
if ( cfg.minUpscale ) {
if ( media.naturalWidth >= winW * cfg.minUpscale / 100 ) {
progress[0] = 1;
}
if ( media.naturalHeight >= winH * cfg.minUpscale / 100 ) {
progress[1] = 1;
}
}
if ( media.mode === 4 ) {
if ( media.naturalWidth / media.naturalHeight > winW / winH ) {
media.mode = 3;
} else {
media.mode = 2;
}
} else if ( media.mode === 1 || media.mode === 0 && noFit.real ) {
if ( progress.length ) {
if ( media.naturalWidth / media.naturalHeight > winW / winH ) {
media.mode = 2;
} else {
media.mode = 3;
}
}
}
if ( media.mode === 2 && media.naturalWidth < winW && !progress[0] ) {
media.mode = 0;
} else if ( media.mode === 3 && media.naturalHeight < winH && !progress[1] ) {
media.mode = 0;
}
progress = null;
media.resize(media.mode);
// Some browsers (Safari, Firefox) won't position the media without this
setTimeout(function() {
media.setPos();
}, 30);
};
if ( vAPI.mediaType === 'video' ) {
var attributeValues = {};
var mediaAttributes = ['autoplay', 'loop', 'controls', '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);
if ( media.autoplay ) {
setTimeout(media.play.bind(media), 50);
}
if ( this.videoHeight ) {
return;
}
vAPI.mediaType = 'audio';
media.controls = true;
doc.title = media.alt;
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 ( 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=';
});
});
} else {
media = doc.createElement('img');
media.src = win.location.href;
}
root = doc.documentElement;
media.id = 'main-media';
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 ( media.naturalWidth || media.videoWidth || vAPI.mediaType === 'audio' ) {
initParams = null;
init();
return;
}
initParams = {loop: 0, wait: 150, maxLoop: 900};
progress = setInterval(init, initParams.wait);
setTimeout(function() {
if ( root.classList.contains(vAPI.mediaType) ) {
return;
}
// Firefox won't show the image if a site uses CSP settings,
// so we should use the default image
if ( (vAPI.firefox || vAPI.maxthon)
&& (vAPI.mediaType === 'img'
? !media.naturalWidth && doc.images[0].naturalWidth
: !media.videoWidth && doc.body.querySelector('video').videoWidth) ) {
// TODO: audio/video
doc.images[0].style.display = 'block';
clearInterval(progress);
return;
}
media.style.display = 'none';
var header = doc.body.appendChild(doc.createElement('h2'));
header.textContent = media.alt;
header.addEventListener('click', function() {
doc.body.removeChild(this);
media.style.display = 'block';
});
}, 1000);
};
(function() {
if ( vAPI.safari && location.protocol === 'safari-extension:' ) {
init = null;
return;
}
if ( vAPI.opera || vAPI.firefox ) {
if ( !vAPI.mediaType ) {
init = null;
return;
}
vAPI.messaging.send({cmd: 'loadPrefs'}, function(response) {
init(window, document, response);
});
return;
}
vAPI.messaging.send({cmd: 'loadPrefs'}, function(response) {
if ( !vAPI.mediaType ) {
init = null;
return;
}
init(window, document, response);
});
})();
'use strict';
var vAPI = Object.create(null);
// Extension info is passed through the URL for Firefox, Safari, and Maxthon,
// in order to get it synchronously
if ( location.hash ) {
vAPI.app = location.hash.slice(1).split(',');
vAPI.app = {
name: vAPI.app[0],
version: vAPI.app[1]
};
}
vAPI.app.platform = 'Maxthon ' +
external.mxVersion +
' (' + navigator.platform + ')';
vAPI.runtime = external.mxGetRuntime();
vAPI.storage = {
mxStorage: vAPI.runtime.storage,
get: function(key, callback) {
callback(this.mxStorage.getConfig(key));
},
set: function(key, value) {
return this.mxStorage.setConfig(key, value);
}
};
vAPI.tabs = {
mxTabs: new mx.browser.tabs, // eslint-disable-line
getSelected: function(callback) {
callback(this.mxTabs.getCurrentTab());
},
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 = {
parseMessage: function(msg) {
var listenerId = msg.listenerId;
return {
msg: msg.message,
origin: msg.origin,
postMessage: function(message) {
vAPI.runtime.post(listenerId, message);
}
};
},
listen: function(callback, name) {
vAPI.runtime.listen(name || 'service', callback);
}
};
'use strict';
var cachedPrefs;
var updatePrefs = function(newPrefs, oldPrefs, forceUpdate) {
var needsUpdate = forceUpdate || false;
for ( var prefName in oldPrefs ) {
if ( !newPrefs.hasOwnProperty(prefName) ) {
newPrefs[prefName] = oldPrefs[prefName];
needsUpdate = true;
}
}
if ( needsUpdate ) {
vAPI.storage.set('cfg', JSON.stringify(newPrefs));
}
return newPrefs;
};
vAPI.storage.get('cfg', function(prefs) {
var xhr = new XMLHttpRequest;
xhr.overrideMimeType('application/json;charset=utf-8');
xhr.open('GET', 'defaults.json', true);
xhr.addEventListener('load', function() {
var forceUpdate = false;
var defaultPrefs = JSON.parse(this.responseText);
cachedPrefs = prefs ? JSON.parse(prefs) : {};
// Cleanup unused preferences
for ( var prefName in cachedPrefs ) {
if ( !defaultPrefs.hasOwnProperty(prefName) ) {
delete cachedPrefs[prefName];
forceUpdate = true;
}
}
cachedPrefs = updatePrefs(cachedPrefs, defaultPrefs, forceUpdate);
});
xhr.send();
});
vAPI.messaging.listen(function(e, origin, postMessage) {
var channel = vAPI.messaging.parseMessage(e, origin, postMessage);
var message = channel.msg;
if ( !message.cmd ) {
return;
}
switch ( message.cmd ) {
case 'loadPrefs':
var response = {
prefs: message.property
? cachedPrefs[message.property]
: cachedPrefs
};
if ( message.getAppInfo ) {
response.app = vAPI.app;
}
channel.postMessage(response);
break;
case 'savePrefs':
cachedPrefs = updatePrefs(message.prefs, cachedPrefs, true);
break;
case 'open':
if ( !Array.isArray(message.url) ) {
message.url = [message.url];
}
vAPI.tabs.getSelected(function(tab) {
for ( var i = 0; i < message.url.length; ++i ) {
vAPI.tabs.create({
incognito: !!tab.incognito,
url: message.url[i],
active: !message.nf
});
}
});
break;
case 'frames.js':
var xhr = new XMLHttpRequest;
xhr.overrideMimeType('text/plain;charset=utf-8');
xhr.open('GET', 'js/frames.js', true);
xhr.addEventListener('load', function() {
channel.postMessage({'frames.js': this.responseText});
});
xhr.send();
break;
}
// Chrome
return true; // eslint-disable-line
});
/* 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 length = s.length;
var crc = -1;
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;
if ( position === void 0 || position < 0 ) {
pos = this.pos;
this.pos += bytes;
} else {
pos = position;
}
var i;
var integer = 0;
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 b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
var c1, c2;
var pos = 0;
var res = '';
var mod = b64str.length % 3;
var l = b64str.length - mod;
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 ) {
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;
}
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 && (this.responseText[1] === 'P' && (chunkSize = 8)
|| this.responseText[0] === 'G' && (chunkSize = 6)
|| this.responseText[0] === 'R' && (chunkSize = 16)) ) {
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 i, IHDR, chunkType, chunkSize;
var frames = [];
var bin = new BinaryTools(this.responseText);
var animation = {};
var 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 ( !frames.length && chunkType === 'acTL' ) {
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 ) {
// Read the full chunk (length + chunk type + chunkdate + crc)
imgHead += bin.readString(bin.readInt(4, bin.pos) + 12);
} else {
bin.pos += 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 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');
var img = new Image;
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 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);
}
};
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 = new Image;
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, false);
} else {
this.removeEventListener(vAPI.browser.wheel, this.wheeler, false);
}
this.classList.toggle('showall');
};
wrap.addEventListener('mouseup', onWrapMouseUp);
wrap.addEventListener(vAPI.browser.wheel, wrap.wheeler, false);
currentFrame.addEventListener(vAPI.browser.wheel, wrap.wheeler, false);
currentFrame.addEventListener('input', function() {
if ( parseFloat(speed.value, 10) !== 0 ) {
wrap.stop();
}
if ( wrap.classList.contains('showall') ) {
onWrapMouseUp({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, false);
return;
}
wrap.classList.remove('showall');
wrap.removeEventListener(vAPI.browser.wheel, wrap.wheeler, false);
wrap.animate();
});
wrap.wheeler = function(e) {
wrap.step((e.deltaY || -e.wheelDelta) > 0);
wrap.sotp();
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;
};
};
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-i18n]');
var l = els.length;
while ( l-- ) {
var i18nString = vAPI.i18n(els[l].dataset.i18n);
var i18nAttr = els[l].dataset.i18nAttr;
els[l].removeAttribute('data-i18n');
if ( !i18nAttr ) {
vAPI.insertHTML(els[l], i18nString);
continue;
}
if ( /^(title|placeholder)$/i.test(i18nAttr) ) {
els[l][i18nAttr] = i18nString;
}
els[l].removeAttribute('data-i18n-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, null);
}, 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;
return;
}
if ( /^SELECT/i.test(el.type) ) {
var i = el.length;
while ( i-- ) {
if ( el[i].hasAttribute('selected') ) {
el.selectedIndex = i;
break;
}
}
return;
}
el.value = el.defaultValue;
if ( el.type === 'range' ) {
fillOutput(el);
}
});
};
var load = function(prefs) {
var m, field, fieldType, pref;
var fields = document.querySelectorAll('form [name]');
var i = fields.length;
while ( i-- ) {
field = fields[i];
pref = field.name;
if ( field.disabled || field.readOnly || defaultPrefs[pref] === void 0 ) {
continue;
}
fieldType = field.getAttribute('type') || 'text';
if ( field.type !== fieldType ) {
fieldType = field.type;
}
if ( fieldType === 'checkbox' ) {
field.defaultChecked = defaultPrefs[pref];
pref = !!(prefs[pref] === void 0 ? defaultPrefs : prefs)[pref];
field.checked = field.defChecked = pref;
continue;
}
if ( pref === 'sendTo' ) {
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 ( fieldType.slice(0, 6) === 'select' ) {
/* 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 ( fieldType === 'range' ) {
m = field.previousElementSibling;
if ( m && m.nodeName === 'OUTPUT' ) {
fillOutput(field);
}
m = m.previousElementSibling;
if ( m && m.getAttribute('type') === 'color' ) {
m.style.opacity = field.value;
}
field.addEventListener('change', fillOutput);
} else if ( fieldType === '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 i, field, fieldType, pref;
var fields = document.querySelectorAll('form [name]');
var prefs = Object.create(null);
for ( i = 0; i < fields.length; ++i ) {
field = fields[i];
pref = field.name;
if ( field.disabled || field.readOnly || defaultPrefs[pref] === void 0 ) {
continue;
}
fieldType = field.getAttribute('type');
if ( fieldType === 'checkbox' ) {
prefs[pref] = field.checked;
} else if ( fieldType === 'range' || fieldType === '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 {
if ( pref === 'sendTo' ) { // eslint-disable-line
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();
}
var section = $(hash + '-sec') || $((hash = 'general') + '-sec');
if ( hash === 'info' ) {
if ( !section._nodeLocalized ) {
if ( args[0] ) {
args = args[0] === '0' ? 'app-installed' : 'app-updated';
$(args).style.display = 'block';
}
var xhr = new XMLHttpRequest;
xhr.overrideMimeType('application/json;charset=utf-8');
xhr.open('GET', 'locales.json', true);
xhr.addEventListener('load', function() {
var translators;
var rows = [];
var locales = JSON.parse(this.responseText);
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);
});
xhr.send();
}
}
if ( prevHash !== hash && (prevHash = $(prevHash + '-sec')) ) {
prevHash.style.display = 'none';
}
if ( section ) {
localizeNodes([section]);
section.style.display = 'block';
}
if ( menu.activeLink ) {
menu.activeLink.classList.remove('active');
}
if ( menu.activeLink = menu.querySelector('a[href="#' + hash + '"]') ) {
menu.activeLink.classList.add('active');
}
};
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;
}
});
onHashChange();
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;
} else if ( t.type !== 'checkbox'
&& t[defval + 'Value'] != t.value ) { // eslint-disable-line
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 || e.target.name.indexOf('key_') !== 0
|| 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: '/',
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);
delete this.pending;
this.style.color = '';
this.nextElementSibling.style.color = '#e03c00';
inputChanges.formReset = true;
if ( e.ctrlKey ) {
e.preventDefault();
var sec = (location.hash || '#general') + '-sec ';
setDefault(e + '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');
});
[].forEach.call(document.body.querySelectorAll('.action-buttons') || [], function(el) {
el.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 + ' ::';
var xhr = new XMLHttpRequest;
xhr.overrideMimeType('application/json;charset=utf-8');
xhr.open('GET', 'defaults.json', true);
xhr.addEventListener('load', function() {
defaultPrefs = JSON.parse(this.responseText);
load(data.prefs);
document.body.style.display = 'block';
});
xhr.send();
});
});
; @language cs, Czech (čeština)
; @translators jaramat (Jaroslav Matura)
[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#main-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
longpressDelay=Prodleva dlouhého stisku
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
modeFitToHeight=roztáhnout na výšku
modeFitToWidth=roztáhnout na šířku
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
; @language el, Greek (Ελληνικά)
; @translators Farow
[lang]
appDescriptionShort=Additional functionality for the browser's default image and video viewer.
buttonReset=Επαναφορά
buttonSave=Αποθήκευση
customCss=Προσαρμοσμένο στυλ
defaultMode=Αρχικό μεγέθος
disabled=απενεργοποιημένο
favicon=Προσαρμοσμένο εικονίδιο
faviconTip="Η επιλογή αυτή ορίζει ένα εικονίδιο καρτέλας για την ανοιγμένη εικόνα.\nΗ διεύθυνση της εικόνας μπορεί να χρησιμοποιηθεί και ως μια μεταβλητή: %url"
infoTranslations=Μεταφράσεις
longpressActionFitImage=προσαρμογή στο πλάτος/ύψος
longpressDelay=Καθυστέριση παρατετημένου πατήματος (ms)
longpressLeft=Λειτουργία παρατετημένου πατήματος αριστερού κουμπιού
longpressRight=Λειτουργία παρατετημένου πατήματος δεξιού κουμπιού
mediaInfo=Πληροφορίες εικόνας
minUpscale=Μεγέθυνση μικρών εικόνων
minUpscaleTip="Μικρές εικόνες δεν μεγεθύνονται. Αυτή η επιλογή τις αναγκάζει να μεγεθυνθούν.\nΗ τιμή είναι σε ποσοστό και μεγεθύνει τις εικόνες που είναι μεγαλύτερες από το επιλεγμένο ποσοστό του ύψους ή του πλάτους της οθόνης."
modeAutoFit=αυτόματη προσαρμογή
modeBestFit=βέλτιστη προσαρμογή
modeFitToHeight=προσαρμογή στο ύψος
modeFitToWidth=προσαρμογή στο πλάτος
modeNatural=φυσικό μέγεθος
navInfo=Πληροφορίες
scCycleModes=Εναλαγή μεταξύ μεγεθών: φυσικό, προσαρμογή στο πλάτος, προσαρμογή στο ύψος
scFitToHeight=Προσρμογή στο ύψος
scFitToWidth=Προσρμογή στο πλάτος
scFlipHorizontal=Οριζόντια αναστροφή
scFlipVertical=Κάθετη αναστροφή
scFreeZoom=Shift + μεταφορά στην εικόνα για ελεύθερη μεγέθυνση, κρατήστε το Ctrl για να μετακινήσετε την επιλογή
scModeContain=Αυτόματη προσαρμογή
scModeNatural=Φυσικό μέγεθος
scReset=To Esc θα επαναφέρει την εικόνα στην αρχική της μορφή ή θα κλείσει την ελεύθερη μεγέθυνση
scRotateLeft=Περιστροφή αριστερά
scRotateRight=Περιστροφή δεξιά
sendTo=Αποστολή εικόνας προς...
shortcuts=Συντομεύσεις
wheelZoom=Μεγεύθυνση με τη ροδέλα του ποντικιού
; @language en, English
; @translators Deathamns
[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#main-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
longpressDelay=Long-press delay (ms)
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 (percent)"
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
modeFitToHeight=fit to height
modeFitToWidth=fit to width
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
scModeContain=Auto fit
scModeNatural=Natural size
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
scZoom=Zoom in / out
sendTo=Send image to...
shortcuts=Shortcuts
wheelZoom=Zoom with mouse wheel
; @language es, Spanish (español)
; @translators DurianZheitk (Javier Vera)
[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#main-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
longpressDelay=Retraso para activar una pulsación larga (ms)
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
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
modeFitToHeight=ajustar solo a lo alto
modeFitToWidth=ajustar solo a lo ancho
modeNatural=tamaño original
navGeneral=General
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...
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
scZoom=Acercar/alejar la imagen
sendTo=Enviar imagen a...
shortcuts=Atajos
wheelZoom=Ampliar (zoom) con la rueda del ratón
; @language fi, Finnish (suomi)
; @translators Opeeera
[lang]
appDescriptionShort=Additional functionality for the browser's default image and video viewer.
buttonReset=Palauta oletukset
buttonSave=Tallenna
defaultMode=Oletuskoko
disabled=poissa käytöstä
favicon=Oma kuvake
longpressActionFitImage=sovita leveyteen tai korkeuteen
longpressDelay=Pitkän hiiren painalluksen viive (ms)
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
modeFitToHeight=sovita korkeuteen
modeFitToWidth=sovita leveyteen
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
; @language fr, French (français)
; @translators Tmnath
[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
longpressDelay=Durée du clic prolongé (ms)
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
modeFitToHeight=adapter à la hauteur
modeFitToWidth=adapter à la largeur
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
; @language hu, Hungarian (magyar)
; @translators Deathamns
[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#main-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
longpressDelay=Egérgomb hosszan-tartás ideje (ms)
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ő (százalék)"
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
modeFitToHeight=magassághoz méretez
modeFitToWidth=szélességhez méretez
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.
scModeContain=Ablakhoz méretez
scModeNatural=Eredeti méret
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
scZoom=Nagyítás / kicsinyítés
sendTo=Kép küldése...
shortcuts=Billentyűparancsok
wheelZoom=Nagyítás görgetéssel
; @language ko, Korean (한국어)
; @translators QbsidianH20 (유태종)
[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#main-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=폭/높이에 맞춤
longpressDelay=길게 누르기 지연시간 (ms)
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=최적
modeFitToHeight=높이 맞춤
modeFitToWidth=폭 맞춤
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=마우스 휠로 확대 / 축소
; @language nl, Dutch (Nederlands)
; @translators Kaçkar
[lang]
appDescriptionShort=Additional functionality for the browser's default image and video viewer.
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
longpressDelay=Lange druk vertraging (ms)
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
modeFitToHeight=hoogte passend maken
modeFitToWidth=breedte passend maken
modeNatural=natuurlijk formaat
navInfo=Info
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
; @language pl, Polish (polski)
; @translators pafflick (Paweł Pawlak) [http://www.pafflick.com/]
[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#main-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
longpressDelay=Opóźnienie długiego przytrzymania (ms)
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
modeFitToHeight=dopasuj do wysokości
modeFitToWidth=dopasuj do szerokości
modeNatural=rzeczywisty wymiar
navGeneral=Ogólne
navInfo=Info
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
; @language pt-BR, Portuguese (Brazil) (português (Brasil))
; @translators Rômulo Godoi
[lang]
appDescriptionShort=Additional functionality for the browser's default image and video viewer.
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
longpressDelay=Atraso de resposta (ms)
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
modeFitToHeight=redimensionar à altura
modeFitToWidth=redimensionar à largura
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
; @language ru, Russian (русский)
; @translators Rodny
[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#main-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=подогнать по ширине/высоте
longpressDelay=Длительность нажатия (мс)
longpressLeft=Действие длительного нажатия левой кнопкой мыши
longpressRight=Действие длительного нажатия правой кнопкой мыши
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=наилучшее заполнение
modeFitToHeight=подогнать по высоте
modeFitToWidth=подогнать по ширине
modeNatural=оригинальный размер
navGeneral=Настройки
navInfo=Инфо
opener=Открытие изображений c обычных веб-страниц
openerBoth=оба
openerCtrlAltClick=Ctrl + Alt + правая кнопка мыши
openerRightLong=длительное нажатие правой кнопки мыши
phClickForExample=посмотреть примеры...
scCycleModes=Переключить между режимами: оригинальный, подгон по ширине, подгон по высоте
scDragndrop=Зажмите Ctrl или Alt, чтобы позволить drag-and-drop, или протяните от правого края изображения, если оно вписано в окно
scFitToHeight=Подогнать по высоте
scFitToWidth=Подогнать по ширине
scFlipHorizontal=Отразить по горизонтали
scFlipVertical=Отразить по вертикали
scFloatMenu=Подведите курсор к верхнему левому краю страницы, чтобы показать меню
scFreeZoom=Зажать Shift + левую кнопку мыши на изображении для свободного масштабирования, дополнительно зажать Ctrl для перемещения выделения
scHorizontalScroll=Для прокрутки изображения по горизонтали используйте колёсико мыши над левым нижним краем
scModeContain=Вписать
scModeNatural=Оригинальный размер
scReset=Esc возвращает изображение к первоначальному виду или выходит из режима свободного масштабирования.
scRotateLeft=Повернуть влево
scRotateRight=Повернуть вправо
scZoom=Увеличить / уменьшить
sendTo=Отправить изображение в...
shortcuts=Сочетания клавиш
wheelZoom=Масштабировать колесом мыши
; @language tr, Turkish (Türkçe)
; @translators Saner Apaydın
[lang]
appDescriptionShort=Additional functionality for the browser's default image and video viewer.
buttonReset=Varsayılan
buttonSave=Kaydet
defaultMode=İlk boyutlandırma modu
disabled=devre dışı
favicon=Özel favicon
longpressDelay=Uzun basış gecikmesi (ms)
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
; @language uk, Ukrainian (українська)
; @translators Simofon
[lang]
appDescriptionShort=Additional functionality for the browser's default image and video viewer.
buttonReset=Дефолні налаштування
buttonSave=Зберегти
customCss=Стиль (CSS)
defaultMode=Розмір за замовчуванням
disabled=відключено
favicon=Іконка
faviconTip="Цей параметр дозволяє призначити довільну іконку для вкладки з відкритим зображенням.\nАдреса зображення можна використовувати як змінну: %url"
infoTranslations=Переклади
longpressActionFitImage=підігнати по ширині / висоті
longpressDelay=Тривалість натискання (мс)
longpressLeft=Дія тривалого натискання лівою кнопкою миші
longpressRight=Дія тривалого натискання правою кнопкою миші
mediaInfo=Інформація про зображення
minUpscale=Збільшувати маленькі зображення
minUpscaleTip="Як правило, невеликі зображення не збільшуються до розмірів області перегляду при масштабування. Цей параметр змусить їх це робити.\nЗначення задається у відсотках, скрипт збільшить ті зображення, розмір яких більше даного відсотка від ширини або висоти області перегляду (залежно від попередньої настройки)."
modeAutoFit=вписати
modeBestFit=найкраще заповнення
modeFitToHeight=підігнати по висоті
modeFitToWidth=підігнати по ширині
modeNatural=оригінальний розмір
navInfo=Інфо
phClickForExample=Дивитить приклади...
scCycleModes=Переключити між режимами: оригінальний, підгін по ширині, підгін по висоті
scFitToHeight=Підігнати по висоті
scFitToWidth=Підігнати по ширині
scFlipHorizontal=Відобразити по горизонталі
scFlipVertical=Відобразити по вертикалі
scFreeZoom=Зажати Shift + ліву кнопку миші на зображенні для вільного масштабування, додатково затиснути Ctrl для переміщення виділення
scModeContain=Вписати
scModeNatural=Оригінальний розмір
scReset=Esc повертає зображення до первісного вигляду або виходить з режиму вільного масштабування.
scRotateLeft=Повернути вліво
scRotateRight=Повернути вправо
scZoom=Збільшити / зменшити
sendTo=Надіслати зображення в...
shortcuts=Поєднання клавіш
wheelZoom=Масштабувати колесом миші
; @language zh-CN, Chinese (Simplified Han) (中文(简体中文))
; @translators fang5566
[lang]
appDescriptionShort=Additional functionality for the browser's default image and video viewer.
buttonReset=重置
buttonSave=保存
customCss=自定义样式 (CSS)
defaultMode=图片默认显示模式
disabled=禁用
favicon=自定义 favicon
faviconTip="该选项用于为打开的图片设置一个自定义的标签页图标。\n图片地址可使用以下变量:%url"
infoTranslations=翻译
longpressActionFitImage=适应宽度/高度
longpressDelay=鼠标点击时长(毫秒)
longpressLeft=鼠标左键长按时的操作
longpressRight=鼠标右键长按时的操作
mediaInfo=图片信息
minUpscale=放大小图片
minUpscaleTip="通常小图片不会被放大到视图窗口(view-port)那么大,而该选项可以强制放大这些小图片。\n该选项值表示视图窗口宽度和高度值(这由前一个选项来决定)的百分比,用于告知脚本凡是大于该百分比的图片都强制放大。"
modeAutoFit=嵌入查看器
modeBestFit=最佳适应方式
modeFitToHeight=适应高度
modeFitToWidth=适应宽度
modeNatural=原始尺寸
navInfo=信息
phClickForExample=点击查看样例...
scCycleModes=在原始大小,适应宽度和适应高度三种显示模式中切换
scFitToHeight=适应高度
scFitToWidth=适应宽度
scFlipHorizontal=水平翻转
scFlipVertical=垂直翻转
scFreeZoom=Shift + 拖动 图片进入自由缩放模式,按住 Ctrl 时可移动选区
scModeContain=自动适应
scModeNatural=原始尺寸
scReset=Esc 键可重置图片为原始显示方式,或退出自由缩放模式
scRotateLeft=向左旋转
scRotateRight=向右旋转
scZoom=缩小 / 放大
sendTo=发送图片到...
shortcuts=快捷键
wheelZoom=使用鼠标滚轮缩放
; @language zh-TW, Chinese (Traditional Han) (中文 (繁體中文))
; @translators TYKuo
[lang]
appDescriptionShort=Additional functionality for the browser's default image and video viewer.
buttonReset=預設
buttonSave=儲存
defaultMode=初始尺寸模式
disabled=停用
favicon=自訂網站圖標
longpressActionFitImage=符合寬度/高度
longpressDelay=長按延遲(毫秒)
longpressLeft=左鍵長按動作
longpressRight=右鍵長按動作
mediaInfo=影像資訊
minUpscale=放大小圖片
modeAutoFit=自動縮放
modeBestFit=適合圖片
modeFitToHeight=符合高度
modeFitToWidth=符合寬度
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"}]},"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"}]},"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"}]},"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"}]}}