mx pak1$Vmbackground.htmlcss\menu_icons.b64png6wI css\options.cssQ֚def.json58)x defaults.json-;k'xZ icon-18.png?s icon.png}Cr&"icons\icon_16.png]#Jicons\icon_32.pnga'Uicons\icon_48.pngh- ^includes\app.jsq ڃ includes\opener.js~kzincludes\viewer.jsY50 js\app_bg.js@wpjs\background.js{F] c js\frames.jsRMJM js\options.js0G#locale\cs-cz.iniÕlocale\el-gr.iniD[ d| locale\en.ini-ϖlocale\es-mx.ini>Nlocale\fi-fi.ini 5vlocale\fr-ca.ini' lYMlocale\hu-hu.ini*1locale\ko-kr.ini[.8 2=locale\nl-nl.ini>=plocale\pl-pl.ini?EVlocale\pt-br.ini+UKlocale\ru-ru.ini1\dZlocale\sv-sv.iniExQZlocale\tr-tr.ini  locale\uk-ua.ini[ )locale\zh-cn.iniZx4locale\zh-tw.inij`n%o locales.jsonʝYƿ options.html# data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEoAAAKaCAMAAACurz9FAAAB3VBMVEVMaXH////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////9/f39/f3////////9/f39/f39/f39/f39/f39/f39/f3////////9/f39/f39/f39/f39/f3////////+/v7+/v7+/v7+/v7+/v7////////+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7////////+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7////////+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7////////+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7///////97uGncAAAAn3RSTlMAAQIDBAUGBwgJCgwODxARExQVFhgZGhscHR4fICEiJCYnKywvMDIzNDY4Ojw9P0BDRkdJSk9QUlVWWVxeX2BiZGhpa2xtb3BxdXZ7fH1/gIaJj5CRk5WWl5qbn6Cio6Wnqa+ws7e4vL2/wMHDxMXGx8jJysvNz8/Q0dLT1NXX2Nrb3N/f4OLj5OXm6Orr7u/v8PLz9PX2+Pn6/P3+/8woVNI3AAAMpUlEQVR42uycP3LqMBCH9wQ6gVq1cRW6uHzurBkoocKVfQE4gN3LB9BdHxmc/BCytfiJGfLe26/JRMFf/Ge1LJpF9EMR1LZ3R/0U08lfcOY5JrhyTXDlmuDKN8GVb4Ir3wRXvgmuXBPoFa0HpoATrab0C5S0FuuvjM31ZzNOA5bWUk0mYyeDmVwVrUUNVxN9qejqGhStxpy9PxuC6mvkT1CKCKppJAOoMshWfdS/FK9Sv+oPRqQ/Y7w3nMr0n3GvKIFxmBxLKkyq3nCmCyqtUsgTnIlXwcWYztwFnuFKm0b+to9w8aZYxbh4E1SsC6aJYx3SXofbOuTo513a+QycJtD4LBoCLk/lCAx5qoHALk+1I6DOOaazonlXY0O663BnQ5rIFLvcYyHqIhPngoo18S6oeFPs4rNo2gQXn/o4E1y8CibGxWdRmNKugb/tA0zLlLZ65C21suWPqhleWxSZk/cnAxVG1qLcdQ5BZRxTuDNlrUNZ65iyli223XF6T3Motl/zEQCTI+ZM61FnJo9nuFBQ5LlgynXBlOuCKdcFU64LplwXTPkumLJdu2FsND0HQRCEbe+/6WvKYAdRbonmQlWfofJ3POlw/yAERCWqvBDlGUPTkKGy+dMZrgGiwdJrEbbOf+P+35zvH4TXikpUDJLzBcnhUreLSup2yeEvRxAEQfiBCIJg6rat3zXlgt4Ld/EpykH7W/pj/ZbwvTFtKhH9fvYQtffeFfFw3fujoQuFn6NVCy3tTt2LHHomG65FMCyzy0iE16tZl4tbf+JK/QOfpLspGnZd7Fp60CVEvQcHQnCVXbp35us4TRCBURNUrQ84UMgGFxKL/FAguPb+joJC2tvx4hSKylgEBgoxGKcivICxCkRsw9LhazwSWXUbwjHjwuwa50UIsRib/hTIi7oCbedReMbsEiIqEQlsD9gBkRSLEIaGQvqUCCEGERUIw4AiISogQoghDDdzkQA6iMjMifDEh/R3b9oPE/4XiJbmPvAR7XbSdTMiBM+oEssUYK+wiogQC8/KJlcdwZEu6BEiAmpcaPJTuIwoeZhmHCDCgx0RwiHmMMSqilIUtIgqbBP6NPEkfd2IB52N3tius5r+bgRBEARBEARBEARB17dg34hNOP6OPSMCdGL1o8H6ZsBm/mv3fWJNpltYtbNYpwn4F1WiEpWohgeTTDGfZAYCurK3VN+pzwZMJlJ3L9f0dyMIgiAIgiBsWje1gVEuaNUwlIcKatosCqgqyqOCakd59FA5tfqR1Rq/2KWWtDdDLFts0RZ14pS3fUpbYtj7T7aaLug2auFQhO6sPSX5PvjUtr0HkNX1tEEF49r7VezzTXx8GL+agolsHn4GHNaaBsXuxMWDHZWec4mWQOZpKUpg15g6eprq8DxVQymauSPshWbt3s96ud9QlYMHfCfUMTojhT+qKIJbWqRmbmz16H50Oj4ndmZt49Ay73UkQqcdiO6X295lectOeyR7Znfx7uF5MXJh75gIZPJQT4CZ9+yt+CNV8QpV/gWOzG1nGi8HLhgcU9mALt4omZ9hxQOxbH6zd/c4bsNAFIDnBHMCtmrNatWZZdyZwLq0KruyLmAdQOrFA/CuAbILTBzaepyMsgkQvXJtfKD+zOF4JftTwY0VT61PXfRNxX44w53ece3DLQN8/WX6xXEdwTEGH8hjS5/xd3C94yl1Ph93u2/vo3bG6a3zvKSzU+uPirMmd/M8L/H4qfL2YbEccGu1ffgbFTJeuZ4MSwBjtd3VlGrT6Xl1loe+H7Ak4xo8yY1K5a0L7iQSsDpCS8smVT2MoPEP8PPZwEVPynAqZjscfEyDkYp/pPvBRqqRyZOs+bxhYepbWsyWLVv47f2jE3a33avL+1t+yGWvAxZvOBx/B2tf1A2jV0K80KI7qiR3XyyBGAKwvNJb/LPUH7xn9j4Oeov4/tiIkdkzLXROQFNUoKIZE2ukdqkXGFJZm+E6dHAkKdeeN8WPijkwHwZ89NAGhKLABm+MuBDxVNVnT4zXih3YPhkUHNZcdyYwqkTw+XDC7VdpqR3QMhC/ibqaM36sOjixZuy5imoVFINickXqizdwWG+393KYrSdDxFe9dE/bqgvH1awGnP1yvtStmq74O05fOVME/GF0A9tXNNID+vDv65+j0oC5zRPMtGi1s+wBxcIvLH3/sWfVevTsSFI8JePisDVkwRr58+6i/6FTHrJkPB/fdru341kqJaUForB6syWJK1rNi4F1QW9RGEqo98S5tHB8l3KWTFEeu1NYOM0h9j8SW0cfcUlhIf5Lrc3aLF7PirSaNdJ6Fq1n0WrWlVazApktUJHorZ7JHI5TztdA/222bHHnOY9H1vZQxzz/Wk8HmTzUbcY5FK2b0sJS+VPRXRZLJZWrlTmrLJHK5hGYbIFU3l4nllaainK9sLBUzs6cCkshTfzwosISSXqyyNJL2MIStvQStrCELSwpLSxhC0t6C0vYwpLewhK2gKSygKSygKSygKSxgKSxgIQsJNktLGFLJLslkt3CErawhKkZL7j1klh2SSy7hC0sYQtLwLJI2MJSSsCql5oGWJqqB1gKCVgKCVgKCVhKCVtY+idq36323WpfttW+TJJoq30jSUZb7TuSxFr7kiTZat9Eks5W+3YkcclS+yb35F+Zpu/s3OlP1FAUBfAziyCuKAIqrkgUFQ2Oxg0BFYgriSa4xjUBNXFBGSVREQQScdzIsDMzh7/VzNw3Zdrpa1/5yvw+Ns157WvvfU2TdiXPvsk22Ox6lKT8xTzg69rko11Y3UpKTrxfpE1m9GoYOeGroxnaLL4/Aa3TaRa7g5w7LJY+DY3QOF1k9gPA/gxdjIdMv/ISFwHgIl3pukI1XV3x+FanGhpLQaOWoHMwGSwqeRBau+8ODGYNe0cND2YN3N0NX83fvaO+N8NMeU/G7wQzPeUwsCNuMlfxHfDV8NNs2n82wEfjpOkVnGyEpwP/zG+GfwfgoWaClk/33aLuf6JlogZaZf3MW7gWaXOLaotcW2Befxl0bjPvRyPgHgU0/mDebWg0pal8qYY+CtVfqKSb4Co6ROVrJQBcoOgEgE6KCwBQ+ZXKUBRuOqkkapF1lCIGADGKo8iqTdAax0XFb4rFI6qpxuUQcwNH5UDiqm0eWaT4XYFiHVRuQtmezfq8Bzl7PmeTtkO5SaUDRUIjFENrkBduaj0egRI53toURt6aIYqREJyOUTkJIyepHIPTPYoBGBqguAeHUILiPAydp0iEnHVMkVwLQ2uTFM6qvkTxFMaeUlyC3QOKVhhrpXgAu7cU+2BsH8Vb2KlZnwvDWHhOzbtjc0qtcAhArZYp+/AbKF4jgNcUG1BoG0UfAuij2IZCWyleIIAXFFtRaD3FOwTwjmI9bFTvH0MAY2pFgd24antlMFam2t847F5RNMBYA8Ur2PVYTdFYB0UP7FooemGsl6IFdnUU85thaPM8RZ2mCtgFQ13U1dotirEojETHKG7BqZ5KO4y0U6nX37u/NsLAxl8e9XGWykMYeEjlLIpFvlE5B1/nqHyLwMUZKjOH4OPQDJUzcPWSyp96eKr/Q+Ul3O2dtbIOw8NhK2l2LzQu09qnBVots8y7DK1ntDyphKvKJ7Q8g966OC1/u8pRpLzrLy3xdfBQNcJliRu1sKm9keCykSp4qhlmgfSb7uYtyNnS3P0mzQLDNfBR9YEOU6ODg6NTdPhQBV8Vj2ngcYVZ0U/Tx3Q7DNX10lNvHczFPlLrYwyBhGJ9abpI98VCCGzn9f4UbVL913dihTad6n4en5hJpWYm4s+7T21CSUlJSckq+KfH/3bOGMdBGAqinMAncOt2XS1dKDddLIVyqTYVXGB9AKfHB8hdU4A0IR9rME7JFGmivPBRniMhe/6xabwIgwaIQgziSjFIKMYgn8D46TWD83VZwQzOzg0DzWZMv4rBaV1fikHVoS3E4Glwl4/x7dvX6xFNEzmYWiXOnTeFGNzzoRSD0hEjO2lGghFx6/qpQDAyOlHT3G3B2MUsfaJ/INCr0Zew+FyTOlc3c5JDnf4ej1iLjTVRJ0+Y93r1gq6j2MrR4p6nzu6LdVqdJs883iAat691m4j9HUWZMdXY3mcWplQ/IVHyxzR2cTHl92QYNOMaI/qGNqhrACjWORpjSploiMZkSsRrojGZEhkU0XjzlB3RmLFEHxTRmKPwi2Uac5T0Ehrno+Al0ZigMCXVmKMwJdWYozAl05ijMCXRmKJuNVYfojFBnYWXQ7ULFa300uxCeSW9dNUeVCtWH9CzUHLjH1qn81DeVCKCQ2PwZ1WcLp4/Azpy5MiRJ7p8llfzx3Q5AAAAAElFTkSuQmCC::-moz-selection { background: #adf; } ::selection { background: #adf; } html { min-height: 100%; background-color: #f3f3f5; cursor: default; } body { display: none; position: relative; max-width: 700px; min-height: 300px; margin: 0 auto; box-shadow: 0 0 4px #999; border-top: 0; padding: 6px 15px 15px; background-color: #fff; font: 13px "Lucida Grande", "Lucida Sans Unicode", Tahoma, sans-serif; } a { text-decoration: none; color: #1155ef; } a:hover { color: #000; } :focus { outline: none; } .fn { float: none; } /* http://nicolasgallagher.com/micro-clearfix-hack/ */ .cf::after { display: block; clear: both; content: ""; } hr { border: 1px solid #eee; margin: 10px 0; } #right-panel { position: absolute; top: 0; left: 100%; } #right-panel > aside { z-index: -1; overflow: hidden; position: fixed; box-shadow: 2px 2px 2px #ccc; max-width: 145px; padding: 0 5px 3px 8px; background-color: #fff; text-align: center; } #right-panel > aside, section { box-sizing: border-box; } 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: box-shadow .2s; transition: box-shadow .2s; } .logo:hover { 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; text-decoration: none; color: #1155ef; -webkit-transition: border-bottom-color .5s; transition: border-bottom-color .5s; } nav > a:hover { border-bottom: 3px solid #aaf; color: #000; -webkit-transition: border-bottom-color 0s; transition: border-bottom-color 0s; } nav > .active { border-bottom: 3px solid #000; color: #000; } .prow { clear: both; padding-bottom: 3px; } .prow, .tiptop { position: relative; } .tip { z-index: 1; visibility: hidden; overflow: hidden; position: absolute; left: -48px; top: -5px; max-width: 100%; width: 33px; height: 25px; border: 1px solid transparent; padding: 5px 7px; opacity: 0; white-space: pre-wrap; color: rgba(0, 0, 0, 0); font: 12px/150% Verdana, sans-serif; -webkit-transition: visibility 0s 0.5s, opacity 0.5s, color .7s; transition: visibility 0s 0.5s, opacity 0.5s, color .7s; } .tiptop:hover > .tip:not(:empty) { visibility: visible; opacity: 1; -webkit-transition-delay: 0s; transition-delay: 0s; } .tip:hover { overflow: visible; left: -45px; width: auto; height: auto; box-shadow: 0 0 10px #dedede; border: 1px solid #ddd; border-left: none; border-radius: 6px; padding: 10px; padding-left: 40px; background-color: #fff; color: #000; } .tip::before { display: inline-block; margin-right: 20px; border: 3px solid #aaa; border-right: none; border-radius: 10px 6px 6px 10px; padding: 0 6px 2px; text-align: center; text-shadow: 0 0 3px #000, 0 0 3px #000; font: 700 17px Verdana, sans-serif; color: #fff; content: "?"; } .tip:hover::before { position: absolute; top: 5px; left: 5px; } .prow > label, .prow > span:not(.clean) { display: inline-block; width: 49.6%; box-sizing: border-box; } .prow > label { padding-top: 8px; } .prow:hover label:not(.checkbox), label:not(.checkbox):hover { color: #45f; } .prow > span:not(.clean) { float: right; max-width: 50%; margin-top: 4px; text-align: right; } .prow input[type="text"] { width: 300px; } .prow select { max-width: 308px; } .prow input[type="color"] + input[type="text"], .shorter-input { width: 242px; vertical-align: middle; } .prowone > label, .prowone > span { width: auto !important; padding: 2px 0; } .sub-opt { padding-left: 20px; } input, textarea, select, code, .checkbox, .pager > a { box-sizing: border-box; margin: 2px; border: 1px solid #ddd; border-radius: 3px; padding: 3px; background-color: rgba(242, 242, 242, 0); background-image: linear-gradient(to bottom, #fff, #f5f5f5); font: 13px Verdana, sans-serif; -webkit-transition: color .2s, border-color .2s; transition: color .2s, border-color .2s; } pre, code, textarea { font: 13px Consolas, Monaco, monospace; transition: all 0s 0s; } code { display: inline-block; border: 1px solid silver; padding: 3px 5px; background-image: linear-gradient(to bottom, #fff, #f5f5f5); } select { max-width: 100%; } textarea { overflow-x: hidden; box-sizing: border-box; width: 100%; resize: none; -moz-tab-size: 4; -o-tab-size: 4; tab-size: 4; } select:focus, textarea:focus, input[type="text"]:focus, input:hover, select:hover, textarea:hover, .prow:hover input, .prow:hover select, label:hover input, .pager > a:hover, .prow:hover .checkbox, label:hover > .checkbox, .checkbox:hover, .sub-shortcuts > li:hover > input:first-child { border: 1px solid #888; } input[type="checkbox"] { display: none; } .checkbox { position: relative; display: inline-block; width: 20px; height: 20px; padding: 0; color: transparent; vertical-align: middle; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .checkbox::after { position: absolute; top: 0; left: 3px; font-weight: 700; content: "✔"; } input[type="checkbox"]:checked + .checkbox { color: #616161; } input[type="number"], input[type="color"] { width: 50px; text-align: center; } input[type="color"] { box-sizing: border-box; padding: 2px; background: none; vertical-align: middle; } input[type="number"] { width: 60px; box-shadow: none; /* Firefox marks "invalid" inputs */ } input[type="range"] { height: 24px; vertical-align: middle; } output { display: inline-block; min-width: 24px; } h3 { clear: left; } .color-helper { float: right; opacity: 0.3; transition: opacity .3s; } .color-helper:hover { opacity: 1; } .color-helper > input[type="text"] { width: 80px !important; } .shortcuts > label { display: block; } .shortcuts > label:hover input { border: 1px solid #aaa; } .shortcuts input, .sub-shortcuts input { margin: 5px; width: 35px; text-align: center; } .sub-shortcuts input { margin: 0; } .sub-shortcuts li { line-height: 200%; } .op-buttons > button, .action-buttons > span { position: relative; border: 1px solid #ddd; border-radius: 3px; background-color: #fff; background-image: linear-gradient(to bottom, #fff, #f5f5f5); font-weight: 700; font-size: 14px; cursor: pointer; color: #000; } .op-buttons > button { width: 95%; box-shadow: 0 1px 2px rgba(0, 0, 0, .5); margin-bottom: 10px; padding: 10px 0; font: 700 14px Arial; -webkit-transition: border-color .3s, color .3s; transition: border-color .3s, color .3s; } .op-buttons > button:hover { border: 1px solid #999; } .container-info { text-align: center; } #info-sec > pre { white-space: pre-line; } #locales-table { border-collapse: separate; padding: 0 40px; font: 13px/1.4em Consolas, Monaco, monospace; } #locales-table > div > span:not(:empty)::before { margin: 0 10px; content: "\2014"; } [{ "type": "extension", "frameworkVersion": "1.0.1", "guid": "{000008f5-8a32-4389-a7da-2daa0e9d7760}", "version": "1.0.5", "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.5" }, "actions": [ { "type": "script", "entryPoints": ["doc_start"], "exclude": ["res"], "js": [ "includes/app.js", "includes/viewer.js" ], "includeFrames": true }, { "type": "script", "entryPoints": ["doc_end"], "exclude": ["res"], "js": [ "includes/opener.js" ], "includeFrames": true } ] }] { "mode": 1, "minUpscale": 0, "mediaInfo": "%ow\u00d7%oh | %name (%perc%)", "favicon": "", "css": "body { background: silver; overflow: hidden; }\n#media { background: #fafafa; box-shadow: 0 0 5px grey; }", "center": true, "wheelZoom": false, "mediaAttrs": "autoplay controls loop", "lpLeft": 1, "lpRight": 2, "sendToHosts": [ "TinEye|https://www.tineye.com/search?sort=size&order=desc&url=%url", "Google|https://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|https://zxing.org/w/decode?full=true&u=%url", "ImgOps|https://imgops.com/%url", "Pixlr|https://apps.pixlr.com/editor/?image=%url", "PicMonkey|https://www.picmonkey.com/service?_import=%url" ], "key_mOrig": "0", "key_mFit": "1", "key_mFitW": "2", "key_mFitH": "3", "key_rotL": "E", "key_rotR": "R", "key_flipH": "Q", "key_flipV": "W", "key_cycle": "C", "key_wheelZoom": "Z", "key_imgBg": "B", "key_pixelate": "P", "opener": 0 } PNG  IHDRVΎWIDAT8oTU3Ngj -!Z0jq>\r^]pmA6IiJC;;y9~>n%R %"ԍsxywy?RRh0ZhEV_7b]1rlXg)QR?o]k@1es˫K\ѣ/D!pej38Ȑo}gNҡYzuH70Q184XYhr ,.&YO,ZE&^%Ĭ%s'dU1³cc䝘c:1//'ZOk[zTOxLf<WJ+r9HC{k/MnmDŽZ]#BCLYY@`+P*/lw"wIDATx^}\y{oL!"aB CJfM ;ة-QFF&6 ,JZvx7"Ļ|H`&,rbhFf43=}ϻ;ۭAVܹV?yޏVrAE0- $ @9BNLO%2P''`L(}yD!8Ao'^TU4JS@+CyAބ.~'{U5TQ* hO0mʊ>^9УLV9䑲"NEmY; iN_?+A%l aWB:V01EK1>7W 8YP-2W%=ƔdWR_9J>b' Z'QP,Ok'ӬF#SB#>· wAB'VP ,;_M& <8Iޛ +bi}y pն,LE,?I!%arrYc/N^R9(XNPa`gloV)y&"]fz\VL ? !,K'p"~Y;YKؒ\^HOz@Y)X~f.{G$[@j$(81I!]/Jo!TqNkTpdoOSs_Q@8C0t.лٯ鍴uGVTC1>~7NhCR>|ƚ@o pe Y#,Ƒ 4k.'=OlOUƝyOؚ@Qa IDI+9<9]H < u[MEXCJ 8%Lr\`9 pP#lO2pGDu'#hIbGNqHWTp1(Fѫ!(VH^o茂/E3XMfJfb%8pD}Eq2 {ŮGYNYeMvu)`yǂw5$EZ̒P$@mHiΤ>,i; F~DpBOe(Y9+E1P~ {m>& 㰮 Vvnd@ ¾@)#{U( ?Bf >~=C7\ h("{zt'ɳ nBN7\Dҳbƻ{&BoOVSčk4sU #iǚX8S*#E`2cMcLM QmBi,8fʖ _~n߽{LdD8Xa`S$m34]λ~ {GENHV P_pMH7j^v+u`h ;lpv2VBy&!`8@rH;C避xw1>?% i׌Ǐv݀ˊNˉ ,7atXI$.xkHnչWuXpoٞm;Wv\u0p9xL<+Q"WZRIcɲ1$!/3ː=#+/;p^ᤁv@T5XpW :fw92(܀2/ o3",F,qJG[>8{7TPgR2?'=9K۹ARE:et6&>yu]^D%1$= gO8p~;Aё^/kҀdlPyPˁݺ8g&"ZCu,+ 9B038~- 㴂CNxx׌ .Vގi;]x<`G[Rъj)椠 CI( kĕ{vYBv(vxi?AQj d9ۂAj/\noR( x;R!rCv%;lㅀytz`‹f?]>vզ}lE$\_cZp,?@$p໮֦<@{1{uGú)ǸQHQc͉'r5C x c< .Q7t#@υ7@[Ӑ~\vٺuTLj@b]pIgC\24fJo)g8.v˜*+OdX%,~El]}яͳOѫH'ޔ@A]>)tFv\^Qk'>xstN9p@MPE%N`GgϭɊ.R塆0J^@8 LՐeUhUV} <^nW 53to&˝+ \NZD^2!E~TIBPgk\*WGgPm:)_2JpH_qb 1@vHr z!t,Z-e&aΩQBxޓi_KODsZ*()-Sc:@]o%?67waL,ZSO ɫ02U~Uk?hC_RoBHJ7ح ߕӑ#i jODHVt I(laS`DtVh/挗0&I1/: 8###x5󟭶Xn{E?ъUg<3SӐ> \^^l=3fDpI_Aӿ(N[JyH`]lh3Pi+R#SPձN9BvҾ;Ib7(7\MXSSY8[ٰ[B`t$\cB@&p)*uy|ݭ'?kS+3dž9rJ&r*74~]@{iZC FTƐ#p>BGzY?ҬQUS6qp2W&зRjdZ3G3)SOj:G,xJPo2Y [FDgϋ{.8 94R͏wj~Dbmt~dՈ p%%ڋ 9:Sq倫4(H_I:!}چ KN"(o=]u GN\G"m Xno X;-ʃX Gj|BiLQYm0 o6γI#,_p^ܙOYX0rDP_@VFK̉Sqp\8xTj8ʷL.oE` . 9/9u? 2(־9;)Vlv{ҥ_$\2A’k.Tj="=,? yߨEoB<}A蟟8οs$P`p rMSC A,S}3X»ܩ/8;pAsh%k@0ȋ8 n|c7́I3tǔ4:ہ`R၍3Q_>>)Li,}eblVZkCz@X[Ṕj( /ŝȡ].>;"s4S䮸@[9Yq;sG[?g;ز|0#_ȁC?5 2^p>%78vkjǥ 6>{r`LJ+ |Ng,]q;ՂAD~d@y;G ;pO?>Efas q7F1P 0qd3̱! 9c|vӓAB2_󡒘6|{;+>q>qX Ld!P8hC}ɂDhpON:tqgI*zŤzǐ<'9 A,.-A /d^36wu; '#ä~++s΃&0"zfQXxKib|X߼AAOG`EꄽfqHh *J(*z\  2!w^1 y̿ mT^ <\O4zt R"@8@'2priE:o8H`~U@? Uc[tR %qq/ZE3SS @GD71%[1h肜J~A`pcoe* b5RxQDdP*$Ah Ϋ eE߷&]8qL;=F2D1 lD|h*Sj?:L!n g0y V~y[}ndlfuJ\ ](! 1'\eJ_~jHnqB/.IrԄnIENDB`PNG  IHDRasRGBgAMA a pHYsodtEXtSoftwarepaint.net 4.0;imIDAT8O-Ogg-zv%[nD3c&u )ȀЁRhK-WGKKm)-`2~{J<;s]ܒTy[ǁx#PLm#HCIO|/cQ9K^ex)`UxUJ&Dps 7vrᵋ̆"K#ĥlNd<;q5,]J6}/d&'IrB ͨYEaG.G[ G+GS5cIQtk M?!.!OCR9*\<`iSbMZ Uzp-@SG>@f(%7R4xtv)e|] wpoZ x@#͗C>jܚKro]t,'(LIFW;Ẓ^'< qFb1M=EXjwtyDq *=.bk[vNiԌopJ,:g#\jRP?9CBl:~vɯln3F~kf8U9Li<:*tV:3 q /7Ňl}{{\OsM^f?UkLs;3?(yN >R=J6`r&^I.?n(%-xﺞ_aa+U[LwYYiz3M׊Jz(}sa:*wE:ߋ2OMiLE2 ~эyh 0Q4K{]9ߟ4nd KF?֌r﹋ujcqGW+aIENDB`PNG  IHDR DPLTEֱԭԣϝԝˍЊ҇ч҇ӋՍԌҐ֔Քڙڔ֑Շ΃͂Ђ̅}urrk|ۄޅ}uruvzrnpswx~ܑܛޡߠݩݮ۳ڮ֚ڙ̍ЅȒÌʷyzrĴsqfgc^TNI}Bw:t>p9f2e5_;Z8T1W3N2I1F8B@IEMCXHbJdPoWwVvbjkukxj|lor|}{}jph{nj[_Q_F~EB8ӌ+fH؀ D fl8{sM8 ]#r;c=ht!Z!֋ay|[u߽7nˆe [of_-vb.@|yҐ,o~AX4/ޓh.8?є4*KvGC,Fo?װXBSez+QLő #L'֛፣CNڪ?EC,e䋭`nj~L&kӓBteL}08!$5J('U~^ja4(v)0~@T+nH "h%@K3 ^#UQ MT@9_ zĚ^'[IENDB`PNG  IHDR00` PLTEms$v(z084:?H~EzBw?q;k3i9c3`2Z:[:T2S9N7J0J4C;EBLCXASNZHaPfPn^hm`TT2;1rMVQX\dblluqkox~}ل܇҇ыӑ֌ԍѐՌדٔ՘טܕےݗٛߵݦוӖztwvsmmg`V^bhqy~}ysouqɃЂ~̂̇φЍӉɅ̝ʤΗ٤ܵ٥ɠqlxY\cSSrJKA@S`lzeqZ{b}jϴ֖omyqidyъޠűǣܧިץ̟s8itRNS0>I|IDATx]ole img#img_elem:first-child, ' + 'body > ' + 'video[name=media][controls][autoplay]:first-child:not([src]) >' + 'source[src]:only-child' ); this._mediaType = ''; if ( !media ) { return this._mediaType; } if ( media.src !== location.href && media.currentSrc !== location.href ) { return this._mediaType; } if ( media.parentNode !== document.body ) { media = document.body.firstElementChild; } else if ( media.localName === 'img' ) { var stopPropagation = function(e) { e.stopPropagation(); }; // Suppress event listeners added by Maxthon document.documentElement.addEventListener('mousedown', stopPropagation); document.documentElement.addEventListener('keydown', stopPropagation); media.parentNode.replaceChild(media.cloneNode(false), media); } this._mediaType = media.localName; return this._mediaType; }, set: function(type) { this._mediaType = type; } }); vAPI.buildNodes = function(host, items) { if ( !host || !Array.isArray(items) ) { return null; } if ( !items.length ) { return host; } var doc = host.ownerDocument; var fragment = doc.createDocumentFragment(); for ( var i = 0, l = items.length; i < l; ++i ) { if ( !items[i] ) { continue; } if ( typeof items[i] === 'string' ) { fragment.appendChild(doc.createTextNode(items[i])); continue; } var element = doc.createElement(items[i].tag); if ( items[i].attrs ) { for ( var attr in items[i].attrs ) { // bypass CSP if ( attr === 'style' ) { element.style.cssText = items[i].attrs[attr]; } else { element.setAttribute(attr, items[i].attrs[attr]); } } } if ( items[i].nodes ) { this.buildNodes(element, items[i].nodes); } else if ( items[i].text ) { element.textContent = items[i].text; } fragment.appendChild(element); } if ( fragment.childNodes.length ) { host.appendChild(fragment); } return host; }; '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.localName; 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' ) { var canvas = document.createElement('canvas'); canvas.width = node.clientWidth; canvas.height = node.clientHeight; canvas.getContext('2d').drawImage( node, 0, 0, canvas.width, canvas.height ); return canvas.toDataURL('image/jpeg'); } 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); document.addEventListener('contextmenu', function(e) { if ( e.button !== 2 || !lastMouseDownTime ) { return; } if ( lastMouseDownX !== e.clientX || lastMouseDownY !== e.clientY ) { return; } var elapsed = e.timeStamp - lastMouseDownTime >= 300; if ( !(e.ctrlKey && e.altKey && !e.shiftKey && !elapsed && opener > 1 || elapsed && (opener === 1 || opener === 3) && !e.ctrlKey && !e.shiftKey && !e.altKey) ) { return; } var url, r; var urls = []; var el = 30; var rgxIgnore = /^(html|body)$/; // 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.localName) ) { if ( !rgxIgnore.test(e.target.localName) ) { 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 filter = {}; for ( var 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); }); })(); /* eslint indent:0 */ '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 noFit = {cur: false, real: false}; var lastEvent = {}; var progress = null; var cancelAction = false; var freeZoom = null; var dragSlide = []; var borderSize = 0; var MAXSIZE = 0x7fff; var initPingsLeft = 600; var root, panning, winW, winH, sX, sY; [doc.documentElement, doc.body, media].forEach(function(node) { var i = node.attributes.length; while ( i-- ) { var attrName = node.attributes[i].name; if ( node !== media || attrName !== 'src' ) { node.removeAttribute(attrName); } } }); var head = doc.querySelector('head'); if ( 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%;', 'margin: 0;', 'padding: 0;', 'font: 12px "Trebuchet MS", sans-serif;', 'cursor: default;', '-webkit-user-select: none;', '-moz-user-select: none;', '-ms-user-select: none;', '}', '#media {', 'display: block', 'box-sizing: border-box;', 'position: absolute;', 'margin: 0;', 'background-clip: padding-box;', 'image-orientation: from-image;', '}', 'html.audio #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 #media {', 'margin: auto', 'box-shadow: 0 0 10px red;', '}', 'html.fullscreen #media {', 'background: black !important;', '}', '#media:-moz-full-screen {', 'background: black !important;', '}', '#media.m-1 {', 'width: auto;', 'height: auto;', 'max-width: 100%;', 'max-height: 100%;', '}', '#media.m-2 {', 'width: 100%;', 'height:auto;', '}', '#media.m-3 {', 'height: 100%;', 'width: auto;', '}', 'a {', 'text-decoration: none;', '}', ':focus {', 'outline: 0;', '}', ':invalid {', 'box-shadow: none;', '}', '#menu {', 'width: 50px;', 'height: 33.33%;', 'position: fixed;', 'top: 0;', 'opacity: 0;', vAPI.browser.transitionCSS, ': opacity .15s, left .2s;', '}', 'ul {', 'display: inline-block;', 'margin: 0;', 'padding: 5px 15px;', 'background: rgba(0, 0, 0, .6); color: #fff;', 'font-size: 25px; font-weight: 700;', 'text-align: center;', 'list-style: none;', '}', 'li {', 'position: relative;', 'display: block;', '}', 'li[data-cmd] > div {', 'width: 25px;', 'height: 25px;', 'margin: 8px 0;', 'background-repeat: no-repeat;', 'background-size: 100%;', 'cursor: pointer;', '}', 'li[data-cmd] > div:hover {', 'opacity: .6;', '}', 'li[data-cmd="cycle"] > div {', 'background-position: 0 0;', '}', 'li[data-cmd="zoom"] > div {', 'background-position: 0 -125px;', '}', 'li[data-cmd="flip"] > div {', 'background-position: 0 -50px;', '}', 'li[data-cmd="rotate"] > div {', 'background-position: 0 -175px;', '}', 'li[data-cmd].filters > div {', 'background-position: 0 -25px;', '}', 'li[data-cmd="reset"] > div {', 'background-position: 0 -150px;', '}', 'li[data-cmd].send-hosts > div {', 'background-position: 0 -200px;', '}', 'li[data-cmd="frames"] > div {', 'background-position: 0 -75px;', '}', 'li[data-cmd="options"] > div {', 'background-position: 0 -100px;', '}', 'li ul {', 'visibility: hidden;', 'position: absolute;', 'top: 0;', 'left: 100%;', 'text-align: left;', 'opacity: 0;', '}', 'li:hover ul {', 'display: block;', 'visibility: visible;', 'opacity: 1;', vAPI.browser.transitionCSS, ': visibility .4s, opacity .2s .3s;', '}', 'li ul > li {', 'display: block !important;', 'padding: 3px 0;', 'font-size: 15px;', '}', '.send-hosts li > a {', 'padding-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;', '}', 'input[type="range"] {', 'vertical-align: middle;', '}', 'li ul > li {', 'white-space: nowrap;', '}', '.filters > ul {', 'font-size: 15px;', '}', '.filters > form {', 'margin: 0;', 'padding: 0;', '}', 'body.frames {', 'overflow-y: scroll !important;', 'text-align: center;', '}', 'body.frames * {', 'margin: 2px;', '}', '#frames > canvas, #frames > img {', 'display: none;', '}', '#current-frame + output {', 'display: inline-block;', 'width: 65px;', 'font-family: Conoslas, monospace;', 'text-align: right;', '}', '.back {', 'font-size: 150%;', 'text-decoration: none;', 'color: black;', '}', '#frames.showall > img, #frames.showall > canvas {', 'display: inline-block !important;', '}', // Custom CSS cfg.css ].join(''); doc.documentElement.insertBefore(head, doc.body); init = function() { if ( vAPI.mediaType === 'img' && !media.naturalWidth ) { if ( progress && --initPingsLeft < 1 ) { clearInterval(progress); } return; } if ( progress ) { clearInterval(progress); progress = null; } media.id = 'media'; root.classList.add(vAPI.mediaType); if ( media.parentNode !== doc.body ) { doc.body.replaceChild(media, doc.body.firstElementChild); } while ( media.previousSibling || media.nextSibling) { media.parentNode.removeChild( media.previousSibling || media.nextSibling ); } if ( vAPI.mediaType === 'audio' ) { return; } var mediaWidth, mediaHeight; if ( vAPI.mediaType === 'img' ) { mediaWidth = media.naturalWidth; mediaHeight = media.naturalHeight; if ( mediaWidth !== mediaHeight ) { // image-orientation in Firefox doesn't flip natural sizes if ( mediaWidth / mediaHeight === media.height / media.width ) { mediaWidth = media.naturalHeight; mediaHeight = media.naturalWidth; } } } else { mediaWidth = media.videoWidth; mediaHeight = media.videoHeight; } doc.head.querySelector('style').sheet.insertRule( '#media {max-width:' + Math.min( MAXSIZE, Math.floor(mediaWidth * MAXSIZE / mediaHeight) ) + 'px; max-height:' + Math.min( MAXSIZE, Math.floor(mediaHeight * MAXSIZE / mediaWidth) ) + 'px}', 0 ); if ( !cfg.mediaInfo ) { cfg.mediaInfo = false; } cfg.hiddenScrollbars = win.getComputedStyle(root).overflow === 'hidden' || win.getComputedStyle(doc.body).overflow === 'hidden'; var menu = root.appendChild(doc.createElement('div')); menu.id = 'menu'; if ( win.getComputedStyle(menu).display === 'none' ) { doc.body.removeChild(menu); menu = null; } else { var onMenuChange; menu.style.cssText = '-webkit-filter: blur(0px); filter: blur(0px)'; if ( menu.style.filter || menu.style.webkitFilter ) { 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'}, nodes: [{tag: 'div'}]}, {tag: 'li', attrs: {'data-cmd': 'zoom'}, nodes: [{tag: 'div'}]}, {tag: 'li', attrs: {'data-cmd': 'flip'}, nodes: [{tag: 'div'}]}, {tag: 'li', attrs: {'data-cmd': 'rotate'}, nodes: [{tag: 'div'}]}, media.filters ? {tag: 'li', attrs: {class: 'filters', 'data-cmd': 'filters'}, nodes: [ {tag: 'div'}, {tag: 'form', nodes: [{tag: 'ul', nodes: [ {tag: 'li', nodes: [ { tag: 'input', attrs: { type: 'range', min: 0, max: 250, step: 10, value: 100, unit: '%' } }, ' brightness' ]}, {tag: 'li', nodes: [ { tag: 'input', attrs: { type: 'range', min: 0, max: 300, step: 25, value: 100, unit: '%' } }, ' contrast' ]}, {tag: 'li', nodes: [ { tag: 'input', attrs: { type: 'range', min: 0, max: 1000, step: 50, value: 100, unit: '%' } }, ' saturate' ]}, {tag: 'li', nodes: [ { tag: 'input', attrs: { type: 'range', min: 0, max: 100, step: 25, value: 0, unit: '%' } }, ' grayscale' ]}, {tag: 'li', nodes: [ { tag: 'input', attrs: { type: 'range', min: 0, max: 100, step: 100, value: 0, unit: '%' } }, ' invert' ]}, {tag: 'li', nodes: [ { tag: 'input', attrs: { type: 'range', min: 0, max: 100, step: 20, value: 0, unit: '%' } }, ' sepia' ]}, {tag: 'li', nodes: [ { tag: 'input', attrs: { type: 'range', min: 0, max: 360, step: 36, value: 0, unit: 'deg' } }, ' hue-rotate' ]}, {tag: 'li', nodes: [ { tag: 'input', attrs: { type: 'range', min: 0, max: 20, step: 1, value: 0, unit: 'px' } }, ' blur' ]} ]}]} ]} : '', {tag: 'li', attrs: {'data-cmd': 'reset'}, nodes: [{tag: 'div'}]}, /^https?:$/.test(win.location.protocol) && cfg.sendToHosts.length ? {tag: 'li', attrs: {class: 'send-hosts', 'data-cmd': ''}, nodes: [ {tag: 'div'}, {tag: 'ul', nodes: cfg.sendToHosts.map(function(item) { var host = item.split('|'); return {tag: 'li', nodes: [{ tag: 'a', attrs: { href: host.slice(1).join('|') }, text: host[0] }]}; })} ]} : null, vAPI.mediaType === 'img' ? {tag: 'li', attrs: {'data-cmd': 'frames'}, nodes: [{tag: 'div'}]} : '', {tag: 'li', attrs: {'data-cmd': 'options'}, nodes: [{tag: 'div'}]} ]); menu.style.cssText = 'display: none; left: -' + menu.offsetWidth + 'px'; menu.addEventListener('mousedown', function(e) { var t = e.target; if ( t.href && t.href.indexOf('%', t.host.length) > -1 ) { t.href = t.href.replace(/%url/, encodeURIComponent(media.src)); } pdsp(e, !!t.textContent); }); // Load favicons only when the menu item is hovered the first time if ( /^https?:$/.test(win.location.protocol) && cfg.sendToHosts.length ) { menu.onHostsHover = function(e) { this.removeEventListener(e.type, menu.onHostsHover); delete menu.onHostsHover; var links = this.querySelectorAll('.send-hosts > ul > li > a'); [].forEach.call(links, function(a) { a.style.backgroundImage = 'url(//' + a.host + '/favicon.ico)'; }); }; menu.querySelector('.send-hosts > ul').addEventListener( vAPI.browser.transitionend, menu.onHostsHover ); } var handleCommand = function(cmd, e) { if ( e.button === 1 ) { return; } var p = e.button === 2 || e.type === vAPI.browser.wheel && (e.deltaY || -e.wheelDelta) > 0; if ( cmd === 'cycle' ) { cycleModes(!p); } else if ( cmd === 'flip' ) { flipMedia(media, p); } else if ( cmd === 'rotate' ) { rotateMedia(!p, e.ctrlKey); } else if ( cmd === 'zoom' ) { pdsp(e); zoomToCenter({deltaY: p ? 1 : -1}); } else if ( cmd === 'reset' ) { if ( e.button === 0 ) { resetMedia(); } } else if ( cmd === 'filters' ) { if ( e.button === 2 ) { media.style.filter = media.style.webkitFilter = ''; media.filters = {}; doc.querySelector('#menu li.filters > form').reset(); } } else if ( cmd === 'frames' ) { var message = {cmd: 'loadFile', path: 'js/frames.js'}; vAPI.messaging.send(message, function(data) { var errorHandler = function(alertMessage) { // Success if ( alertMessage !== null ) { alert(alertMessage); // eslint-disable-line menu.querySelector('li[data-cmd="frames"]') .removeAttribute('data-cmd'); return; } if ( menu ) { menu.parentNode.removeChild(menu); } }; Function('win', 'drawFullFrame', 'errorHandler', data)( win, e.button === 0, errorHandler ); }); } else if ( cmd === 'options' && e.button !== 1 ) { vAPI.messaging.send({ cmd: 'open', url: 'options.html' + (e.button === 2 ? '#shortcuts' : '') }); } else { p = null; } if ( p !== null ) { pdsp(e); } }; var onMenuClick = function(e) { var cmd = e.target.parentNode.getAttribute('data-cmd'); if ( cmd ) { handleCommand(cmd, e); } }; var menuTrigger = function(e) { if ( panning || freeZoom || e.shiftKey ) { return; } if ( e.clientX > 40 || e.clientY > win.innerHeight / 3 ) { return; } if ( menu.style.display === 'block' ) { return; } if ( !menu.iconsLoaded ) { var bgImage = win.getComputedStyle(menu).backgroundImage; if ( bgImage && bgImage !== 'none' ) { menu.iconsLoaded = true; } } if ( !menu.iconsLoaded ) { var message = {cmd: 'loadFile', path: 'css/menu_icons.b64png'}; vAPI.messaging.send(message, function(img) { var sheet = doc.head.querySelector('style').sheet; sheet.insertRule( 'li[data-cmd] > div { background-image: url(' + img + '); }', sheet.cssRules.length ); menu.iconsLoaded = true; }); } menu.style.display = 'block'; setTimeout(function() { menu.style.left = '0'; menu.style.opacity = '1'; }, 50); doc.removeEventListener('mousemove', menuTrigger); }; 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) { pdsp(e); var t = e.target; if ( t.nodeType === 3 ) { t = t.parentNode; } if ( t.type === 'range' ) { var delta = (e.deltaY || -e.wheelDelta) > 0 ? -1 : 1; t.value = Math.max( t.getAttribute('min'), Math.min( parseInt(t.value, 10) + t.getAttribute('step') * delta, t.getAttribute('max') ) ); onMenuChange(e); } else if ( !/reset|frames|options/.test(t.getAttribute('data-cmd') || (t = t.parentNode) && t.getAttribute('data-cmd')) ) { handleCommand(t.getAttribute('data-cmd'), e); } }); menu.addEventListener('click', onMenuClick); menu.addEventListener('contextmenu', function(e) { var target = e.target; if ( target.type === 'range' ) { target.value = target.defaultValue; onMenuChange(e); pdsp(e); return; } onMenuClick(e); }); menu.addEventListener(vAPI.browser.transitionend, function(e) { if ( e.propertyName === 'left' && this.style.left[0] === '-' ) { 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); 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); }, 500); } var convertInfoParameter = function(a, param) { var m = media; switch ( param ) { case 'w': return m.clientWidth; case 'h': return m.clientHeight; case 'ow': return mediaWidth; case 'oh': return mediaHeight; 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 / mediaWidth); } }; var adjustPosition = function() { var s = media.style; if ( cfg.center ) { s.top = Math.max(0, (winH - media.offsetHeight) / 2) + 'px'; s.left = Math.max(0, (winW - media.offsetWidth) / 2) + 'px'; } else { s.top = s.left = '0'; } var box = media.getBoundingClientRect(); media.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'; } }; var calcFit = function() { winH = doc.compatMode[0] === 'B' ? doc.body : root; winW = winH.clientWidth; winH = winH.clientHeight; var box = media.box || media.getBoundingClientRect(); noFit = { cur: box.width <= winW && box.height <= winH, real: mediaWidth <= winW && mediaHeight <= winH }; }; var afterCalcCallback = function() { var m = media; calcFit(); // Change cursor according to sizing if ( m.clientWidth > winW || m.clientHeight > winH ) { m.style.cursor = 'move'; } else if ( winH >= m.clientHeight && winW >= m.clientWidth && winH < mediaHeight || winW < mediaWidth ) { m.style.cursor = vAPI.browser.zoomIn; } else if ( noFit.cur && noFit.real && (m.clientHeight < mediaHeight || m.clientWidth < mediaWidth) ) { m.style.cursor = vAPI.browser.zoomIn; } else { m.style.cursor = 'default'; } if ( !cfg.mediaInfo || !(mediaWidth && mediaHeight) ) { return; } doc.title = cfg.mediaInfo.replace( /%(o?[wh]|url|name|ratio|perc)/g, convertInfoParameter ); }; var afterCalc = function() { if ( !calcFit ) { return; } calcFit(); adjustPosition(); setTimeout(afterCalcCallback, 0xf); }; var resizeMedia = function(m, w) { var mode = m === void 0 ? 1 : m; if ( mode === -1 ) { if ( w ) { media.style.width = w; } } else if ( media.mode === -1 ) { media.style.width = ''; media.style.height = ''; } media.mode = mode; media.className = 'm-' + mode; if ( mediaWidth ) { afterCalc(); } }; var cycleModes = function(back) { var mode = (media.mode === 1 ? 0 : media.mode) - (back ? 1 : -1); if ( mode === 1 ) { mode -= back ? 1 : -1; } else if ( mode < 0 ) { mode = 3; } else if ( mode > 3 ) { mode = 0; } resizeMedia(mode); }; var resetMedia = function() { if ( freeZoom ) { doc.removeEventListener('mousemove', drawMask); doc.body.removeChild(media.mask); freeZoom = null; cancelAction = false; return; } if ( vAPI.mediaType === 'img' && doc.readyState !== 'complete' ) { return; } var filters = doc.querySelector('#menu li.filters > form'); var mediaStyle = media.style; if ( filters ) { mediaStyle.filter = mediaStyle.webkitFilter = ''; media.filters = {}; filters.reset(); } delete media.curdeg; delete media.scale; delete media.bgList; delete media.bgListIndex; mediaStyle[vAPI.browser.transform] = ''; mediaStyle.background = ''; mediaStyle.width = ''; mediaStyle.height = ''; resizeMedia(0); }; var flipMedia = function(el, horizontal) { if ( !media.scale ) { media.scale = {h: 1, v: 1}; } media.scale[horizontal ? 'h' : 'v'] *= -1; var transformCss = media.scale.h !== 1 || media.scale.v !== 1 ? 'scale(' + media.scale.h + ',' + media.scale.v + ')' : ''; if ( media.curdeg ) { transformCss += ' rotate(' + media.curdeg + 'deg)'; } media.style[vAPI.browser.transform] = transformCss; }; var rotateMedia = function(deg, fine) { var rot; if ( !media.curdeg ) { media.curdeg = 0; } if ( deg ) { media.curdeg += fine ? 10 : 90; } else { media.curdeg -= fine ? 10 : 90; } win.status = media.curdeg + '°'; rot = 'rotate(' + media.curdeg + 'deg)'; if ( media.scale ) { rot += ' scale(' + media.scale.h + ', ' + media.scale.v + ')'; } media.style[vAPI.browser.transform] = rot; adjustPosition(); }; var isValidWheelTarget = function(t) { var d = doc; return t === media || t === d.body || t === d.documentElement; }; var wheelZoom = function(e) { if ( !isValidWheelTarget(e.target) ) { return; } pdsp(e); stopScroll(); // eslint-disable-line var w = media.offsetWidth; var h = media.offsetHeight; if ( (e.deltaY || -e.wheelDelta) > 0 ) { resizeMedia(-1, Math.max(1, w * 0.75) + 'px'); } else { var width = w * (4 / 3); resizeMedia(-1, (width > 10 ? width : width + 3) + 'px'); } if ( !e.keypress && e.target.localName !== '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 ); }; var zoomToCenter = function(e) { wheelZoom({ target: media, keypress: true, deltaY: e.deltaY || -e.wheelDelta, clientX: winW / 2, clientY: winH / 2, offsetX: win.pageXOffset + media.offsetLeft + winW / 2, offsetY: win.pageYOffset + media.offsetTop + winH / 2 }); }; var onContextMenu = function(e) { doc.removeEventListener('mousemove', onMove, true); // eslint-disable-line if ( progress ) { clearTimeout(progress); progress = null; } if ( cancelAction ) { cancelAction = false; pdsp(e, true, false); } }; var onWheel = function(e) { if ( !isValidWheelTarget(e.target) ) { return; } pdsp(e); if ( media.clientWidth <= winW && media.clientHeight <= winH ) { return; } stopScroll(); // eslint-disable-line var x = 0; var y = ((e.deltaX || e.deltaY || -e.wheelDelta) > 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 || e.deltaX && !e.deltaY ) { x = (y < 0 ? -winW : winW) / 5; y = 0; } else if ( !cfg.hiddenScrollbars ) { return; } win.scrollBy(x, y); }; var toggleWheelZoom = function() { var evName = vAPI.browser.wheel; var zoomMenuItemStyle = menu.querySelector('li[data-cmd=zoom]').style; if ( cfg.wheelZoom ) { doc.removeEventListener(evName, onWheel, true); doc.addEventListener(evName, wheelZoom, true); zoomMenuItemStyle.display = 'none'; } else { doc.removeEventListener(evName, wheelZoom, true); doc.addEventListener(evName, onWheel, true); zoomMenuItemStyle.display = ''; } cfg.wheelZoom = !cfg.wheelZoom; }; 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 ) { // Smoother in Opera without setTimeout if ( vAPI.opera ) { onMoveFrame(); } else { 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(); pdsp(e); }; var stopScroll = function(e) { if ( e ) { this.removeEventListener(e.type, stopScroll); } if ( !dragSlide.length ) { return; } clearInterval(progress); progress = null; cancelAction = false; dragSlide.length = 0; media.dragSlideTime = false; }; var startScroll = function() { win.scrollBy(dragSlide[0], dragSlide[1]); if ( dragSlide[0] ) { if ( Math.abs(dragSlide[0]) < 1 ) { dragSlide[0] = 0; } dragSlide[0] /= 1.11; } if ( dragSlide[1] ) { if ( Math.abs(dragSlide[1]) < 1 ) { dragSlide[1] = 0; } dragSlide[1] /= 1.11; } var 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(); return; } progress = setTimeout(startScroll, 25); }; 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); pdsp(e); }; var longpressHandler = function() { cancelAction = true; progress = null; var action = cfg[lastEvent.button === 2 ? 'lpRight' : 'lpLeft']; if ( action === 1 ) { var x, y; if ( mediaWidth / mediaHeight > winW / winH && media.mode !== 3 || media.mode === 2 ) { x = media.clientWidth; resizeMedia(3); x = lastEvent.layerX * media.clientWidth / x - winW / 2; y = 0; } else { y = media.clientHeight; resizeMedia(2); x = 0; y = lastEvent.layerY * media.clientHeight / y - winH / 2; } win.scrollTo(x, y); } else if ( action === 2 ) { toggleWheelZoom(); } }; media.addEventListener('mousedown', function(e) { pdsp(e, false); if ( e.button === 1 || e.ctrlKey || e.altKey ) { return; } if ( vAPI.fullScreenElement === media && vAPI.mediaType === 'video' ) { return; } if ( menu && menu.style.display === 'block' ) { menu.style.display = 'none'; } if ( !e.shiftKey && vAPI.mediaType === 'video' ) { var topPart = this.clientHeight; topPart = Math.min(topPart - 40, topPart / 2); if ( (e.offsetY || e.layerY || 0) > topPart ) { return; } } if ( e.button === 0 && this.mode < 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; } } pdsp(e, true, false); win.focus(); sX = e.clientX; sY = e.clientY; } if ( !e.shiftKey ) { doc.addEventListener('mousemove', onMove, true); } } // For fine move and free zoom if ( e.shiftKey ) { cancelAction = true; if ( e.button === 0 ) { 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); var h = !!(this.curdeg && Math.sin(this.curdeg)); 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 ) { return; } if ( e.button === 0 && !cfg.lpLeft ) { return; } if ( 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, 300); }, 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); 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; } x = (win.pageXOffset + x + w / 2) * nimgw / media.clientWidth - winW / 2 - scrollbars; y = (win.pageYOffset + y + h / 2) * nimgh / media.clientHeight - winH / 2 - scrollbars; resizeMedia(-1, nimgw + 'px'); win.scrollTo(x, y); 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(); win.addEventListener(vAPI.browser.wheel, stopScroll, true); return; } } } if ( progress ) { clearTimeout(progress); progress = null; } if ( cancelAction ) { cancelAction = false; return; } if ( e.shiftKey || e.ctrlKey || e.altKey ) { return; } if ( e.target !== media || lastEvent.button === null ) { return; } if ( e.clientX !== lastEvent.clientX || e.clientY !== lastEvent.clientY ) { return; } if ( media.mode < 2 && noFit.real ) { if ( media.mode === -1 ) { resizeMedia(0); } else if ( winW / winH < mediaWidth / mediaHeight ) { resizeMedia(2); } else if ( winH === media.offsetHeight && winW > media.offsetWidth ) { resizeMedia(2); } else { resizeMedia(3); } } else if ( media.mode === 1 || noFit.cur ) { if ( mediaWidth === media.clientWidth && mediaHeight === 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 * mediaWidth / media.clientWidth - winW / 2; y = y * mediaHeight / media.clientHeight - winH / 2; resizeMedia(0); win.scrollTo(x, y); } else { resizeMedia(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 === '-' ) { pdsp(e); zoomToCenter({deltaY: key === '+' ? -1 : 1}); return; } var x, y, z; switch ( key ) { case 'Esc': resetMedia(); break; case 'Left': x = e.shiftKey ? -10 : -50; y = 0; break; case 'Right': x = e.shiftKey ? 10 : 50; y = 0; break; case 'Up': x = 0; y = e.shiftKey ? -10 : -50; break; case 'Down': x = 0; y = e.shiftKey ? 10 : 50; break; case 'PgUp': x = e.shiftKey ? -winW / 2 : 0; y = e.shiftKey ? 0 : -winH / 2; break; case 'PgDn': x = e.shiftKey ? winW / 2 : 0; y = e.shiftKey ? 0 : winH / 2; break; case 'End': x = e.shiftKey ? 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); pdsp(e, true, false); } return; } switch ( key ) { case cfg.key_mOrig: resizeMedia(0); break; case cfg.key_mFit: resizeMedia(1); break; case cfg.key_mFitW: resizeMedia(2); break; case cfg.key_mFitH: resizeMedia(3); break; case cfg.key_cycle: cycleModes(e.shiftKey); break; case cfg.key_rotL: rotateMedia(false, e.shiftKey); break; case cfg.key_rotR: rotateMedia(true, e.shiftKey); break; case cfg.key_flipH: flipMedia(media, 0); break; case cfg.key_flipV: flipMedia(media, 1); break; case cfg.key_wheelZoom: toggleWheelZoom(); break; case cfg.key_pixelate: if ( vAPI.mediaType !== 'img' ) { break; } media.style.imageRendering = media.style.imageRendering === '' ? vAPI.browser.irPixelated : ''; break; case cfg.key_imgBg: if ( vAPI.mediaType !== 'img' ) { break; } var bgValue = e.shiftKey && prompt( // eslint-disable-line 'background', media.style.background ); if ( bgValue === null ) { break; } if ( bgValue !== false ) { media.style.background = bgValue; break; } if ( !media.bgList ) { media.bgList = {}; bgValue = win.getComputedStyle(media); bgValue = bgValue.background || bgValue.backgroundColor; media.bgList[bgValue] = true; media.bgList['rgb(0, 0, 0)'] = true; media.bgList['rgb(255, 255, 255)'] = true; media.bgList['url(data:image/gif;base64,R0lGODlhFAAUAPABAOjo6P///yH5BAAKAAAALAAAAAAUABQAAAIohI+hy+jAYnhJLnrsxVBP7n1YyHVaSYKhh7Lq+VotPLo1TaW3HEtlAQA7)'] = true; media.bgList = Object.keys(media.bgList).filter(Boolean); media.bgListIndex = 0; } media.style.background = media.bgList[ ++media.bgListIndex % media.bgList.length ]; break; default: x = true; } if ( vAPI.mediaType === 'video' ) { x = null; if ( key === 'Space' ) { media.togglePlay(); } else if ( key === 'Up' || key === 'Down' ) { key = media.volume + (key === 'Up' ? 0.1 : -0.1); // Must check the range manually, // otherwise browsers will throw an error media.volume = key < 0 ? 0 : key > 1 ? 1 : key; } else { x = true; } } pdsp(e, x !== true, true); }, true); doc.addEventListener('contextmenu', onContextMenu, true); win.addEventListener('resize', function() { media.removeAttribute('width'); media.removeAttribute('height'); afterCalc(); }); toggleWheelZoom(); if ( vAPI.mediaType === 'video' ) { media.addEventListener('click', function(e) { if ( e.button !== 0 ) { return; } var y = e.offsetY || e.layerY || 0; if ( y > media.clientHeight - 40 ) { return; } if ( vAPI.fullScreenElement === this || y > media.clientHeight / 2 ) { media.togglePlay(); } pdsp(e); }); media.addEventListener('dblclick', function(e) { if ( (e.offsetY || e.layerY || 0) < media.clientHeight / 2 ) { pdsp(e); } }); } calcFit(); progress = []; if ( vAPI.mediaType === 'img' && cfg.minUpscale ) { if ( mediaWidth >= winW * cfg.minUpscale / 100 ) { progress[0] = true; } if ( mediaHeight >= winH * cfg.minUpscale / 100 ) { progress[1] = true; } } if ( cfg.mode === 2 ) { media.mode = mediaWidth / mediaHeight > winW / winH ? 3 : 2; } else if ( cfg.mode > 2 ) { media.mode = 0; } else { media.mode = cfg.mode; if ( progress.length ) { if ( media.mode === 1 || media.mode === 0 && noFit.real ) { media.mode = mediaWidth / mediaHeight > winW / winH ? 2 : 3; } } } if ( media.mode === 2 && mediaWidth < winW && !progress[0] ) { media.mode = 0; } else if ( media.mode === 3 && mediaHeight < winH && !progress[1] ) { media.mode = 0; } progress = null; resizeMedia(media.mode); // Some browsers (Safari, Firefox) won't position the media without this setTimeout(adjustPosition, 30); }; root = doc.documentElement; media.addEventListener('error', function() { // Opera fires an error event on local video files when they're close to the end // Firefox did it a few times too, even if there was nothing wrong with the video if ( media.currentTime > 0.1 && win.location.protocol === 'file:' ) { return; } clearInterval(progress); root.classList.add('load-failed'); }); if ( win.location.protocol === 'data:' ) { media.alt = vAPI.mediaType + ' (data:)'; if ( !cfg.mediaInfo ) { doc.title = media.alt; } } else { media.alt = (win.location.href .replace(/#.*/, '') .match(/(?:[^\/]+)?$/)[0] || vAPI.mediaType ).split('?')[0]; try { // Some Unicode characters caused problems for decodeURIComponent media.alt = decodeURIComponent(media.alt); } catch ( ex ) { // } } if ( vAPI.mediaType === 'img' ) { // Try to prevent default browser action doc.body.addEventListener('click', function(e) { e.stopImmediatePropagation(); }, true); if ( media.naturalWidth ) { initPingsLeft = 0; init(); return; } progress = setInterval(init, 100); } else { var attributeValues = {}; var mediaAttributes = ['autoplay', 'controls', 'loop', 'muted', 'volume']; cfg.mediaAttrs.split(/\s+/).forEach(function(attribute) { var attr = attribute.split('='); if ( attr[0] === 'volume' ) { attributeValues[attr[0]] = Math.min( 100, Math.max(0, parseInt(attr[1], 10) / 100) ); } else { attributeValues[attr[0]] = true; } }); mediaAttributes.forEach(function(attr) { if ( attr === 'volume' ) { media[attr] = attributeValues[attr] === void 0 ? 1 : attributeValues[attr]; } else { media[attr] = attributeValues[attr] || false; } }); media.togglePlay = function() { if ( this.paused || Math.abs(this.duration - this.currentTime) < 0.01 ) { this.play(); } else { this.pause(); } }; media.addEventListener('loadedmetadata', function onLoadedMetadata(e) { this.removeEventListener(e.type, onLoadedMetadata); if ( this.videoHeight && (vAPI.opera || vAPI.chrome) ) { doc.addEventListener('fullscreenchange', function() { root.classList.toggle('fullscreen'); }); } var playerStateSaver; var monitoredAttrs = mediaAttributes.slice(1, -2); var savePlayerState = function() { var mediaAttrs = []; mediaAttributes.forEach(function(attr) { if ( attr === 'volume' ) { if ( media.volume < 1 ) { mediaAttrs.push(attr + '=' + (100 * media.volume | 0)); } } else if ( media[attr] ) { mediaAttrs.push(attr); } }); vAPI.messaging.send({cmd: 'savePrefs', prefs: { mediaAttrs: mediaAttrs.join(' ') }}); }; var onAttributeChange = function() { if ( !media.controls && vAPI.mediaType === 'audio' ) { media.controls = true; } clearTimeout(playerStateSaver); playerStateSaver = setTimeout(savePlayerState, 500); }; if ( win.MutationObserver ) { new MutationObserver(onAttributeChange).observe(media, { attributes: true, attributeFilter: monitoredAttrs }); } else { // Legacy media.addEventListener('DOMAttrModified', function(ev) { if ( monitoredAttrs.indexOf(ev.attrName) > -1 ) { onAttributeChange(); } }); } media.addEventListener('volumechange', onAttributeChange); if ( media.autoplay ) { setTimeout(media.play.bind(media), 50); } if ( this.videoHeight ) { init(); return; } vAPI.mediaType = 'audio'; media.controls = true; doc.title = media.alt; init(); 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='; }); }); } }; (function() { if ( vAPI.safari && location.protocol === 'safari-extension:' ) { init = null; return; } var firstContact = function() { if ( vAPI.opera || vAPI.firefox ) { if ( !vAPI.mediaType ) { init = null; return; } vAPI.messaging.send({cmd: 'loadPrefs'}, function(response) { firstContact = null; init(window, document, response); }); return; } vAPI.messaging.send({cmd: 'loadPrefs'}, function(response) { firstContact = null; if ( !vAPI.mediaType ) { init = null; return; } init(window, document, response); }); }; firstContact(); var count = 0; var pingBackground = setInterval(function() { if ( firstContact === null || ++count > 4 ) { clearInterval(pingBackground); return; } firstContact(); }, 3000); })(); 'use strict'; var vAPI = Object.create(null); vAPI.maxthon = true; vAPI._runtime = external.mxGetRuntime(); vAPI.app = (function() { var extInfo = location.hash.slice(1).split(','); return { name: extInfo[0], version: extInfo[1], platform: 'Maxthon ' + external.mxVersion + ' (' + navigator.platform + ')' }; })(); vAPI.storage = { _mxStorage: vAPI._runtime.storage, get: function(key, callback) { var value = this._mxStorage.getConfig(key); callback(value === '' ? null : value); }, set: function(key, value) { return this._mxStorage.setConfig(key, value); }, remove: function(key) { this._mxStorage.setConfig(key, ''); } }; 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(request) { var listenerId = request.listenerId; return { msg: JSON.parse(request.message), origin: request.origin, postMessage: function(message) { vAPI._runtime.post(listenerId, JSON.stringify(message)); } }; }, listen: function(callback, name) { vAPI._runtime.listen(name || 'service', callback); } }; 'use strict'; var cachedPrefs; var updatePrefs = function(newPrefs, storedPrefs) { var xhr = new XMLHttpRequest; xhr.overrideMimeType('application/json;charset=utf-8'); xhr.open('GET', 'defaults.json', true); xhr.addEventListener('load', function() { var key; var defPrefs = JSON.parse(this.responseText); cachedPrefs = {}; for ( key in defPrefs ) { cachedPrefs[key] = storedPrefs[key] === void 0 ? defPrefs[key] : storedPrefs[key]; if ( newPrefs[key] === void 0 ) { continue; } if ( typeof newPrefs[key] !== typeof defPrefs[key] ) { continue; } if ( newPrefs[key] === defPrefs[key] ) { cachedPrefs[key] = defPrefs[key]; continue; } if ( typeof defPrefs[key] === 'object' && JSON.stringify(newPrefs[key]) === JSON.stringify(defPrefs[key]) ) { cachedPrefs[key] = defPrefs[key]; continue; } cachedPrefs[key] = newPrefs[key]; } // In order to initialize sooner on content side, Chrome reads the prefs // there (to avoid messaging), so we have to save all prefs if ( vAPI.chrome ) { vAPI.storage.set('cfg', JSON.stringify(cachedPrefs)); return; } var prefsToStore = {}; for ( key in defPrefs ) { if ( cachedPrefs[key] === defPrefs[key] ) { continue; } if ( typeof defPrefs[key] === 'object' ) { if ( JSON.stringify(cachedPrefs[key]) === JSON.stringify(defPrefs[key]) ) { continue; } } prefsToStore[key] = cachedPrefs[key]; } prefsToStore = JSON.stringify(prefsToStore); if ( prefsToStore === '{}' ) { vAPI.storage.remove('cfg'); } else if ( prefsToStore !== JSON.stringify(storedPrefs) ) { vAPI.storage.set('cfg', prefsToStore); } }); xhr.send(); }; vAPI.storage.get('cfg', function(cfg) { var storedPrefs; try { storedPrefs = JSON.parse(cfg || '{}'); } catch ( ex ) { storedPrefs = {}; } updatePrefs(storedPrefs, storedPrefs); }); 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': vAPI.storage.get('cfg', function(cfg) { updatePrefs(message.prefs, JSON.parse(cfg || '{}')); }); 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 'loadFile': var xhr = new XMLHttpRequest; xhr.overrideMimeType('text/plain; charset=x-user-defined'); xhr.open('GET', message.path, true); xhr.addEventListener('load', function() { channel.postMessage(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, i; var integer = 0; if ( position === void 0 || position < 0 ) { pos = this.pos; this.pos += bytes; } else { pos = position; } if ( this.littleEndian ) { i = bytes - 1; while ( i >= 0 ) { integer += this.readByte(pos + i) << i-- * 8; } } else { i = 0; while ( i < bytes ) { integer += this.readByte(pos + i++) << (bytes - i) * 8; } } return integer >>> 0; }; this.intToBytes = function(integer, numberOfBytes) { var i = numberOfBytes || 4; var bytes = []; while ( i-- ) { bytes.push(integer >> i * 8 & 0xff); } return String.fromCharCode.apply( null, this.littleEndian ? bytes.reverse() : bytes ); }; }; if ( !win.opera ) { // Solves utf8 problems win.btoa = function(b64str) { var c1, c2; var b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; var mod = b64str.length % 3; var l = b64str.length - mod; var pos = 0; var res = ''; while ( pos < l ) { c1 = b64str.charCodeAt(pos++) & 0xff; c2 = b64str.charCodeAt(pos++) & 0xff; res += b64chars[c1 >> 2]; res += b64chars[(c1 & 3) << 4 | c2 >> 4]; c1 = b64str.charCodeAt(pos++) & 0xff; res += b64chars[(c2 & 0x0f) << 2 | c1 >> 6]; res += b64chars[c1 & 0x3f]; } if ( mod === 0 ) { return res; } c1 = b64str.charCodeAt(pos++) & 0xff; res += b64chars[c1 >> 2]; if ( mod === 1 ) { res += b64chars[(c1 & 3) << 4]; res += '=='; } else { c2 = b64str.charCodeAt(pos++) & 0xff; res += b64chars[(c1 & 3) << 4 | c2 >> 4]; res += b64chars[(c2 & 0x0f) << 2]; res += '='; } return res; }; } var maxSize = 20 * 1024 * 1024; var xhr = new win.XMLHttpRequest; xhr.overrideMimeType('text/plain; charset=x-user-defined'); xhr.addEventListener('readystatechange', function() { if ( this.readyState === 2 ) { var contentLength = this.getResponseHeader('Content-Length'); if ( contentLength && contentLength > maxSize ) { this.abort(); errorHandler('Image is too large...'); return; } } if ( !this.responseText ) { return; } var i, chunkSize; if ( !this.imgType ) { // PNG or GIF or WEBP signature imgHead = /^(?:\x89(PNG)\r\n\x1a\n|(GIF)8[79]a|RIFF....(WEBP)VP8X)/; this.imgType = this.responseText.match(imgHead); // Seems like in some cases a character encoding is applied anyway, // however it's enough to check only the signature if ( !this.imgType ) { if ( this.responseText[1] === 'P' ) { chunkSize = 8; } else if ( this.responseText[0] === 'G' ) { chunkSize = 6; } else if ( this.responseText[0] === 'R' ) { chunkSize = 1; } if ( chunkSize ) { this.imgType = this.responseText.slice(0, chunkSize).split(''); for ( i = 0; i < this.imgType.length; ++i ) { this.imgType[i] = this.imgType[i].charCodeAt(0) & 0xff; } this.imgType = String.fromCharCode .apply(null, this.imgType) .match(imgHead); } } if ( !this.imgType ) { this.abort(); errorHandler('Not animated...'); return; } this.imgType = this.imgType[2] || this.imgType[1] || this.imgType[3]; } if ( this.readyState !== 4 ) { /* || this.status !== 200*/ return; } if ( this.responseText.length > maxSize ) { errorHandler('Image is too large...'); return; } var IHDR, chunkType; var frames = []; var bin = new BinaryTools(this.responseText); var animation = {}; 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 ( chunkType === 'acTL' ) { if ( frames.length ) { continue; } animation.numFrames = bin.readInt(4, bin.pos + 8); animation.numPlays = bin.readInt(4, bin.pos + 12); bin.pos += 20; } else if ( chunkType === 'fcTL' ) { bin.pos += 12; i = frames.length; frames.push({ width: bin.readInt(4), height: bin.readInt(4), xOffset: bin.readInt(4), yOffset: bin.readInt(4), delay: 1000 * bin.readInt(2) / (bin.readInt(2) || 100), disposeOp: bin.readInt(1), blendOp: bin.readInt(1), data: 'IDAT' }); if ( i === 0 && frames[i].disposeOp === 2 ) { frames[i].disposeOp = 1; } // Skip crc bin.pos += 4; // console.log(frames[frames.length - 1]); } else if ( chunkType === 'IDAT' || chunkType === 'fdAT' ) { if ( !animation.numFrames || animation.numFrames < 2 ) { break; // IDAT without acTL chunk should be ignored } else if ( chunkType === 'IDAT' && !frames.length ) { // console.log('PNG: ignoring IDAT from animation...'); bin.pos += bin.readInt(4, bin.pos) + 12; continue; } i = chunkType === 'fdAT' ? 4 : 0; // Read the length, also skip the sequence number from fdAT chunkSize = bin.readInt(4) - i; // Skip chunk type, // also the sequence number in case of the fdAT chunk type bin.pos += 4 + i; frames[frames.length - 1].data += bin.readString(chunkSize); // Skip crc bin.pos += 4; } else if ( frames.length ) { bin.pos += bin.readInt(4, bin.pos) + 12; } else { // Read the full chunk (length + chunk type + chunkdate + crc) imgHead += bin.readString(bin.readInt(4, bin.pos) + 12); } } } else if ( this.imgType === 'GIF' ) { // http://www.w3.org/Graphics/GIF/spec-gif89a.txt bin.littleEndian = true; bin.skipSubBlock = function() { do { this.pos += this.readInt(1, this.pos) + 1; if ( bin.pos >= bin.length ) { throw Error(this.imgType + ': end reached...'); } } while ( this.readInt(1, this.pos) !== 0x00 ); ++this.pos; }; // Skip signature bin.pos = 6; // Logical Screen Descriptor animation.width = bin.readInt(2); animation.height = bin.readInt(2); bin.packed = bin.readBits(1, 10); bin.packed = bin.packed[0] === '1' ? 3 * 1 << parseInt(bin.packed.slice(-3), 2) + 1 : 0; imgHead += bin.readString(3 + bin.packed); // Frame index i = 0; while ( bin.pos < bin.length ) { chunkType = bin.readString(1); // console.log("sentinel: " + chunkType); // Extension block (0x21, an exclamation point '!') // optional if ( chunkType === '!' ) { chunkType = bin.readInt(1); // console.log("ext_label: " + chunkType.toString(16)); // Plain Text Extension if ( chunkType === 0x01 ) { // No support for this, so skip bin.pos += 13; bin.skipSubBlock(); // Graphics Control Extension } else if ( chunkType === 0xf9 ) { bin.packed = bin.readBits(1, bin.pos + 1); frames.push({ delay: bin.readInt(2, bin.pos + 2) * 10 || 100, // -1 in order to match PNG's indexes, also treat 0 as 1 disposeOp: Math.max( 0, parseInt(bin.packed.slice(3, -2), 2) - 1 ), // sentinel + ext_label data: bin.readString(4, bin.pos - 2) // with zero delay + bin.intToBytes(0, 2) // transparent color index + block terminator + bin.readString(2, bin.pos + 4) }); bin.pos += 6; // Comment Block Extension } else if ( chunkType === 0xfe ) { bin.skipSubBlock(); // Application Block Extension } else if ( chunkType === 0xff ) { bin.pos += 12; bin.skipSubBlock(); // Try to skip anything else } else { bin.pos = bin.data.indexOf('\x00', bin.pos); if ( bin.pos === -1 ) { bin.pos = bin.length; } else { ++bin.pos; } } // Image (0x2C, a comma ',') } else if ( chunkType === ',' ) { if ( !frames[i] ) { frames.push({ delay: 100, disposeOp: 0, // sentinel, ext_label, block size, packed field, delay, // transparent color index, terminator data: '\x21\xf9\x04\x00\x00\x00\x00\x00' }); } frames[i].xOffset = bin.readInt(2); frames[i].yOffset = bin.readInt(2); bin._pos = bin.pos; frames[i].width = bin.readInt(2); frames[i].height = bin.readInt(2); bin.packed = bin.readBits(1); bin.pos += bin.packed[0] === '1' ? 3 * (1 << parseInt(bin.packed.slice(-3), 2) + 1) : 0; // LZW minimum code size ++bin.pos; bin.skipSubBlock(); frames[i]._data = [bin.pos - bin._pos, bin._pos]; ++i; // Trailer (0x3B, a semi-colon ';') or something else } else { break; } } } else if ( this.imgType === 'WEBP' ) { // https://developers.google.com/speed/webp/docs/riff_container bin.littleEndian = true; // WebP file header + VP8X and its chunk size bin.pos = 20; // VP8X flags bin.packed = bin.readBits(1); // Animation flag if ( bin.packed[6] === '0' ) { errorHandler(this.imgType + ': not animated...'); return; } // Reserved 24 bits bin.pos += 3; // Canvas width animation.width = bin.readInt(3) + 1; // Canvas height animation.height = bin.readInt(3) + 1; while ( bin.pos < bin.length ) { chunkType = bin.readString(4); if ( chunkType === 'ANIM' ) { // Skip Background Color: 32 bits + Loop Count: 16 bits // chunk size + chunk payload bin.pos += 4 + bin.readInt(4); animation.ANIM = true; continue; } if ( chunkType !== 'ANMF' ) { // Skip chunk bin.pos += 4 + bin.readInt(4); continue; } if ( !animation.ANIM ) { errorHandler(this.imgType + ': ANIM chunk not found!'); return; } i = frames.length; // Size of the Frame Data chunkSize = bin.readInt(4); // If the chunk size is odd, then a padding byte is added chunkSize += chunkSize & 1; // Remove the size of the ANMF properties listed below chunkSize -= 16; frames.push({ xOffset: bin.readInt(3) * 2, yOffset: bin.readInt(3) * 2, width: bin.readInt(3) + 1, height: bin.readInt(3) + 1, delay: bin.readInt(3), disposeOp: bin.readInt(1) & 1, data: '' }); bin._pos = bin.pos + chunkSize; while ( bin.pos < bin._pos ) { chunkType = bin.readString(4); chunkSize = bin.readInt(4); chunkSize += chunkSize & 1; // Should exist before the 'VP8 ' chunk only /* if ( chunkType === 'ALPH' ) { if ( bin.readString(4, bin.pos + chunkSize) === 'VP8 ' ) { // The whole ALPH chunk frames[i].data += bin.readString(8, bin.pos - 8); frames[i].data += bin.readString(chunkSize); } else { bin.pos += chunkSize; } } else */ if ( chunkType === 'VP8 ' || chunkType === 'VP8L' ) { // chunk type + chunk size + VP8? bitstream; frames[i].data += bin.readString(8, bin.pos - 8); frames[i].data += bin.readString(chunkSize); } else { bin.pos += chunkSize; } } // frames[i].data += bin.readString(chunkSize); } } if ( frames.length < 1 ) { errorHandler(this.imgType + ': not animated...'); return; } var generateImageSRC, wrap, speed, currentFrame; var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); // "new Image" doesn't work in Maxthon var img = document.createElement('img'); canvas.width = animation.width; canvas.height = animation.height; if ( this.imgType === 'PNG' ) { chunkSize = bin.intToBytes(13); var imgEnd = bin.readString(12, bin.length - 12); generateImageSRC = function() { var frm = frames[frames.idx]; var _IHDR = 'IHDR' + bin.intToBytes(frm.width) + bin.intToBytes(frm.height) + IHDR; _IHDR += bin.intToBytes(crc32(_IHDR)); return 'data:image/png;base64,' + win.btoa( '\x89PNG\r\n\x1a\n' + chunkSize + _IHDR + imgHead + bin.intToBytes(frm.data.length - 4) + frm.data + bin.intToBytes(crc32(frm.data)) + imgEnd ); }; } else if ( this.imgType === 'GIF' ) { chunkSize = bin.intToBytes(0, 2); chunkSize = ',' + chunkSize + chunkSize; generateImageSRC = function() { var frm = frames[frames.idx]; return 'data:image/gif;base64,' + win.btoa( 'GIF89a' + bin.intToBytes(frm.width, 2) + bin.intToBytes(frm.height, 2) + imgHead + frm.data + chunkSize + bin.readString(frm._data[0], frm._data[1]) + ';' ); }; } else if ( this.imgType === 'WEBP' ) { generateImageSRC = function() { var frm = frames[frames.idx]; return 'data:image/webp;base64,' + win.btoa( 'RIFF' + bin.intToBytes(frm.data.length + 4) + 'WEBP' + frm.data ); }; } var onImgLoad = function() { if ( drawFullFrame ) { var frame = frames[frames.idx]; var prev = frames[frames.idx - 1]; if ( prev ) { if ( prev.disposeOp === 1 ) { ctx.clearRect( prev.xOffset, prev.yOffset, prev.width, prev.height ); } else if ( prev.disposeOp === 2 ) { ctx.putImageData( this.prevDisposeData, prev.xOffset, prev.yOffset ); } } if ( frame.disposeOp === 2 ) { this.prevDisposeData = ctx.getImageData( frame.xOffset, frame.yOffset, frame.width, frame.height ); } // only for PNG if ( frame.blendOp === 0 ) { ctx.clearRect( frame.xOffset, frame.yOffset, frame.width, frame.height ); } ctx.drawImage( this, frame.xOffset, frame.yOffset ); } var c = canvas.cloneNode(false); if ( drawFullFrame ) { c.getContext('2d').putImageData( ctx.getImageData(0, 0, canvas.width, canvas.height), 0, 0 ); } else { c.width = this.width; c.height = this.height; c.getContext('2d').drawImage(this, 0, 0); } wrap.appendChild(c); this.removeAttribute('src'); c.style.display = 'inline-block'; if ( c.previousElementSibling ) { c.previousElementSibling.style.display = ''; } ++frames.idx; currentFrame.value = frames.idx; processNextFrame(); // eslint-disable-line }; var done = function() { wrap.current = 0; wrap.children[wrap.children.length - 1].style.display = ''; wrap.children[wrap.current].style.display = 'inline-block'; currentFrame.value = 1; var onWrapMouseUp = function(e) { if ( e.button !== 0 ) { return; } if ( e.ctrlKey ) { if ( e.target.toDataURL && speed.value < 1 ) { var canvasImg = document.createElement('img'); canvasImg.src = e.target.toDataURL(); this.replaceChild(canvasImg, e.target); wrap.step(null); } return; } this.stop(); if ( this.classList.contains('showall') ) { if ( e.target && e.target.parentNode === wrap ) { currentFrame.value = [].indexOf.call(wrap.childNodes, e.target) + 1; wrap.step(null); } this.addEventListener(vAPI.browser.wheel, this.wheeler); } else { this.removeEventListener(vAPI.browser.wheel, this.wheeler); } this.classList.toggle('showall'); }; wrap.wheeler = function(e) { wrap.step((e.deltaY || -e.wheelDelta) > 0); wrap.stop(); e.preventDefault(); e.stopImmediatePropagation(); }; wrap.animate = function() { clearTimeout(wrap.animationTimer); wrap.step(wrap.speedValue < 0); if ( wrap.speedValue ) { wrap.animationTimer = setTimeout( wrap.animate, frames[wrap.current].delay / Math.abs(wrap.speedValue) ); } }; wrap.stop = function() { clearTimeout(this.animationTimer); speed.value = 0; }; wrap.step = function(backward) { wrap.children[wrap.current].style.display = ''; if ( backward === null ) { wrap.current = Math.max( 1, Math.min( parseInt(currentFrame.value, 10) || 1, currentFrame.max ) ) - 1; } else if ( backward ) { --wrap.current; } else { ++wrap.current; } if ( wrap.current >= wrap.children.length ) { wrap.current = 0; } else if ( wrap.current < 0 ) { wrap.current = wrap.children.length - 1; } wrap.children[wrap.current].style.display = 'inline-block'; currentFrame.value = wrap.current + 1; currentFrame.nextElementSibling.value = currentFrame.value + ' / ' + frames.length; }; wrap.addEventListener('mouseup', onWrapMouseUp); wrap.addEventListener(vAPI.browser.wheel, wrap.wheeler); currentFrame.addEventListener(vAPI.browser.wheel, wrap.wheeler); currentFrame.addEventListener('input', function() { if ( parseFloat(speed.value, 10) !== 0 ) { wrap.stop(); } if ( wrap.classList.contains('showall') ) { onWrapMouseUp.call(wrap, {button: 0}); } wrap.step(null); }); speed.addEventListener('input', function() { wrap.speedValue = parseFloat(speed.value) || 0; if ( wrap.speedValue === 0 ) { wrap.stop(); wrap.addEventListener(vAPI.browser.wheel, wrap.wheeler); return; } wrap.classList.remove('showall'); wrap.removeEventListener(vAPI.browser.wheel, wrap.wheeler); wrap.animate(); }); }; var processNextFrame = function() { if ( frames.idx < frames.length ) { img.src = generateImageSRC(); frames[frames.idx].data = null; } else { img.removeEventListener('load', onImgLoad); img = null; done(); errorHandler(null); } }; img.addEventListener('load', onImgLoad); img.addEventListener('error', function() { wrap.textContent = xhr.imgType + ': frame (' + (frames.idx + 1) + ") couldn't be parsed!"; wrap.appendChild(this); }); wrap = document.body; wrap.className = 'frames'; wrap.textContent = ''; vAPI.buildNodes(wrap, [ {tag: 'a', attrs: { class: 'back', href: win.location.href }, text: '\u2190'}, ' ', {tag: 'input', attrs: { type: 'number', id: 'speed', style: 'width: 55px; text-align: center;', value: 0, step: 0.5, min: -10, max: 10 }}, 'x ', {tag: 'input', attrs: { type: 'range', id: 'current-frame', style: 'width: 500px; vertical-align: middle;', size: 6, value: 1, step: 1, min: 1 }}, ' ', {tag: 'output', attrs: { for: 'currentFrame' }, text: '1 / ' + frames.length}, ' ', {tag: 'div', attrs: {id: 'frames'}} ]); wrap = $('frames'); speed = $('speed'); currentFrame = $('current-frame'); currentFrame.max = frames.length; frames.idx = 0; processNextFrame(); }); xhr.addEventListener('error', function() { errorHandler('Failed to load!'); }); xhr.open('GET', win.location.href, true); xhr.send(); 'use strict'; var defaultPrefs; var inputChanges = Object.create(null); var $ = function(id) { return document.getElementById(id); }; var localizeNodes = function(nodes) { var i = nodes.length; while ( i-- ) { if ( nodes[i]._nodeLocalized ) { continue; } var els = nodes[i].querySelectorAll('[data-l10n]'); var l = els.length; while ( l-- ) { var l10nString = vAPI.l10n(els[l].dataset.l10n); var l10nAttr = els[l].dataset.l10nAttr; els[l].removeAttribute('data-l10n'); if ( !l10nAttr ) { vAPI.insertHTML(els[l], l10nString); continue; } if ( /^(title|placeholder)$/i.test(l10nAttr) ) { els[l][l10nAttr] = l10nString; } els[l].removeAttribute('data-l10n-attr'); } nodes[i]._nodeLocalized = true; } }; var changeColor = function(node, color, time) { clearTimeout(node.colorTransitionTimer); if ( typeof color !== 'string' ) { node.style.color = ''; delete node.colorTransitionTimer; return; } node.style.color = color; node.colorTransitionTimer = setTimeout(function() { changeColor(node); }, time || 2000); }; var fillOutput = function(e) { var node = e.target || e; var op = node.previousElementSibling; op.value = node.value; op.defaultValue = defaultPrefs[node.name]; }; var colorOnInput = function(node) { var target = node.type === 'input' ? this : node; var c = /^#([\da-f]{3}){1,2}$/i.test(target.value) ? target.value : '#ffffff'; if ( c.length === 4 ) { c = '#' + c[1] + c[1] + c[2] + c[2] + c[3] + c[3]; } target.previousElementSibling.value = c; }; var colorOnChange = function() { this.nextElementSibling.value = this.value; }; var setDefault = function(selector) { if ( !selector ) { return; } var nodeList = typeof selector === 'string' ? document.querySelectorAll(selector) : [selector]; [].forEach.call(nodeList, function(el) { if ( el.type === 'checkbox' ) { el.checked = el.defaultChecked; } else if ( el.type.lastIndexOf('select', 0) === 0 ) { var i = el.length; while ( i-- ) { if ( el[i].hasAttribute('selected') ) { el.selectedIndex = i; break; } } } else { el.value = el.defaultValue; if ( el.type === 'range' ) { fillOutput(el); } } }); }; var load = function(prefs) { var fields = document.querySelectorAll('form [name]'); var i = fields.length; while ( i-- ) { var field = fields[i]; var pref = field.name; if ( field.disabled || field.readOnly || defaultPrefs[pref] === void 0 ) { continue; } if ( field.type === 'checkbox' ) { field.defaultChecked = defaultPrefs[pref]; pref = !!(prefs[pref] === void 0 ? defaultPrefs : prefs)[pref]; field.checked = field.defChecked = pref; continue; } if ( pref === 'sendToHosts' ) { if ( !Array.isArray(prefs[pref]) ) { prefs[pref] = defaultPrefs[pref]; } field.rows = prefs[pref].length || 2; field.defaultValue = defaultPrefs[pref].join('\n'); prefs[pref] = prefs[pref].join('\n'); } else if ( field.type.lastIndexOf('select', 0) === 0 ) { /* eslint-disable */ [].some.call(field, function(el) { if ( el.value == defaultPrefs[pref] ) { el.defaultSelected = true; return true; } }); /* eslint-enable */ } else { field.defaultValue = defaultPrefs[pref]; } pref = (prefs[pref] === void 0 ? defaultPrefs : prefs)[pref]; field.value = field.defValue = pref; if ( field.type === 'range' ) { var m = field.previousElementSibling; if ( m && m.localName === 'output' ) { fillOutput(field); } m = m.previousElementSibling; if ( m && m.getAttribute('type') === 'color' ) { m.style.opacity = field.value; } field.addEventListener('change', fillOutput); } else if ( field.type === 'text' ) { if ( !field.previousElementSibling ) { continue; } if ( field.previousElementSibling.getAttribute('type') === 'color' ) { continue; } field.addEventListener('input', colorOnInput); colorOnInput(field); field.previousElementSibling.addEventListener('change', colorOnChange); } } }; var save = function() { var fields = document.querySelectorAll('form [name]'); var prefs = Object.create(null); for ( var i = 0; i < fields.length; ++i ) { var field = fields[i]; var pref = field.name; if ( field.disabled || field.readOnly || defaultPrefs[pref] === void 0 ) { continue; } if ( field.type === 'checkbox' ) { prefs[pref] = field.checked; } else if ( field.type === 'range' || field.type === 'number' || field.classList.contains('number') ) { prefs[pref] = parseFloat(field.value); if ( field.min ) { prefs[pref] = Math.max( field.min, Math.min(field.max, prefs[pref]) ); } if ( typeof prefs[pref] !== 'number' ) { prefs[pref] = parseFloat(field.defaultValue); } field.value = prefs[pref]; } else { if ( pref === 'sendToHosts' ) { // 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 ( !section._nodeLocalized ) { if ( hash === 'info' ) { 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'); } menu.activeLink = menu.querySelector('a[href="#' + hash + '"]'); if ( menu.activeLink ) { 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 ) { return; } if ( e.ctrlKey || e.altKey || e.metaKey || e.which < 47 ) { return; } e.preventDefault(); changeColor(e.target); var keys = { 96: '0', 97: '1', 98: '2', 99: '3', 100: '4', 101: '5', 102: '6', 103: '7', 104: '8', 105: '9', 106: '*', 107: '+', 109: '-', 110: '.', 111: '/', 186: ';', 187: '=', 188: ',', 189: '-', 190: '.', 191: '/', 192: '`', 219: '[', 220: '\\', 221: ']', 222: "'", 112: 'F1', 113: 'F2', 114: 'F3', 115: 'F4', 116: 'F5', 117: 'F6', 118: 'F7', 119: 'F8', 120: 'F9', 121: 'F10', 122: 'F11', 123: 'F12' }; var key = keys[e.which] || String.fromCharCode(e.which).toUpperCase(); keys = document.body.querySelectorAll('input[name^="key_"]'); for ( var i = 0; i < keys.length; ++i ) { if ( keys[i].value.toUpperCase() !== key ) { continue; } if ( e.target !== keys[i] ) { changeColor(e.target, 'red'); } return; } e.target.value = key; onFormChange(e); }); form.addEventListener('contextmenu', function(e) { e.stopPropagation(); var t = e.target; if ( t.classList.contains('checkbox') ) { t = t.previousElementSibling; } if ( !t.name ) { return; } if ( e.ctrlKey ) { e.preventDefault(); setDefault(t); onFormChange({target: t}); } }); form.addEventListener('change', onFormChange); var resetButton = $('button-reset'); resetButton.reset = function() { delete resetButton.pending; resetButton.style.color = '#000'; }; resetButton.addEventListener('click', function(e) { if ( e.button !== 0 ) { return; } if ( this.pending ) { clearTimeout(this.pending); this.nextElementSibling.style.color = '#e03c00'; inputChanges.formReset = true; if ( e.ctrlKey ) { e.preventDefault(); var sec = (location.hash || '#general') + '-sec '; setDefault(sec + 'input,' + sec + 'select,' + sec + 'textarea'); this.style.color = 'lime'; } else { this.style.color = 'green'; } this.pending = setTimeout(this.reset, 2000); return; } this.style.color = 'orange'; this.pending = setTimeout(this.reset, 2000); e.preventDefault(); }); $('button-save').addEventListener('click', function(e) { e.preventDefault(); if ( e.button !== 0 ) { return; } save(); changeColor(resetButton); changeColor(this, 'green'); }); form.querySelector('.op-buttons').addEventListener('mousedown', function(e) { e.preventDefault(); }); vAPI.messaging.send({cmd: 'loadPrefs', getAppInfo: true}, function(data) { $('app-name').textContent = data.app.name; $('app-version').textContent = data.app.version; $('platform-info').textContent = data.app.platform; document.title = ':: ' + data.app.name + ' ::'; 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(); }); }); [lang] appDescriptionShort=Vylepšuje práci s obrázky a videi ve vašem prohlížeči. buttonReset=Výchozí nastavení buttonSave=Uložit centerContent=Zarovnat na střed customCss=Vlastní styl (CSS) customCssTextareaPh="Zde můžete změnit barvu pozadí stránky nebo obrázku, rám, stín, chování posuvníků, skrýt postranní panel...\nPro zobrazení příkladů přejeďte kurzorem přes otazník vlevo. Přesné kódy barev získáte pomocí tlačítka pro výběr barev výše." customCssTip="body {\n background: #f3f3f5; /* Změní pozadí stránky a obrázku (je-li průhledný). Lze použít všechny platné CSS hodnoty (color, url(), gradient...). */\n overflow: hidden; /* Skryje posuvníky. */\n}\n\n#media {\n background: #eef; /* Pozadí obrázku, je-li průhledný. */\n border: 10px solid white; /* Rám obrázku. */\n box-shadow: 0 0 10px grey; /* Stín pod obrázkem. */\n cursor: default !important; /* Vynutí výchozí kurzor (tzn. nezmění se na ručičku či lupu). */\n}\n\n.mask {\n color: rgba(0, 0, 0, .4); /* Barva krytí v režimu ručního zvětšení. */\n}\n\n#menu {\n display: none; /* Vypne zobrazování postranního panelu v levém horní rohu. */\n}\n" defaultMode=Výchozí přiblížení disabled=zakázáno favicon=Vlastní ikona faviconTip="Toto vám umožňuje nastavit vlastní ikonu, která se zobrazí vedle názvu panelu v prohlížeči.\nChcete-li jako ikonu použít obrázek samotný, použijte proměnnou %url." infoTranslations=Překlady longpressActionFitImage=roztáhnout na výšku/šířku longpressLeft=Akce při dlouhém stisku levého tlačítka myši longpressRight=Akce při dlouhém stisku pravého tlačítka myši mediaAttributesTip="Lze použít tyto atributy:\nautoplay - přehrát video automaticky\nloop - přehrávat dokola\ncontrols - zobrazit ovládací prvky\nmuted - vypnout zvuk\nvolume=0-100 - výchozí hlasitost (v procentech)" mediaInfo=Vlastnosti obrázku mediaInfoTip="V titulku stránky (v panelu prohlížeče) lze zobrazit tyto vlastnosti obrázku:\n%ow - původní šířka obrázku\n%oh - původní výška obrázku\n%ratio - poměr stran (šířka / výška)\n%w - současná šířka\n%h - současná výška\n%perc - procento zvětšení\n%url - úplná URL adresa\n%name - název souboru" minUpscale=Zvětšit malé obrázky minUpscaleTip="Ve výchozím nastavení nebudou malé obrázky automaticky zvětšovány. Přeje-li si to, použijte tuto volbu.\nObrázky, které jsou větší než daný počet procent šířky nebo výšky okna prohlížeče (záleží na předchozí volbě) budou automaticky roztaženy." modeAutoFit=přizpůsobit automaticky modeBestFit=roztáhnout automaticky modeNatural=původní velikost navGeneral=Obecné navInfo=O doplňku opener=Otevřít obrázek ze stránky openerBoth=obojí openerCtrlAltClick=Ctrl + Alt + pravé tlačítko openerRightLong=dlouhý stisk pravého tlačítka phClickForExample=kliknutím zobrazíte příklady... scCycleModes=Přepínat mezi režimy zvětšení: původní velikost, roztáhnout na šířku a roztáhnout na výšku scDragndrop=Držte Ctrl nebo Alt nebo začněte v pravé části obrázku, chcete-li obrázek přetáhnout jinam (např. mimo okno prohlížeče) scFitToHeight=Roztáhnout na výšku scFitToWidth=Roztáhnout na šířku scFlipHorizontal=Překlopit vodorovně scFlipVertical=Překlopit svisle scFloatMenu=Přesunutím kurzoru do levého horního rohu stránky vyvoláte postranní panel scFreeZoom=Shift + výběr myší pro vyvolání režimu ručního zvětšení (pro posunutí výběru držte Ctrl) scHorizontalScroll=Pro vodorovné posouvání obrázku kolečkem myši přesuňte kurzor do levé dolní části obrázku scModeContain=Automaticky scModeNatural=Skutečná velikost scReset=Esc obnoví obrázek do původního stavu (pokud byl např. zvětšen, otočen nebo převrácen) nebo ukončí režim ručního zvětšení scRotateLeft=Otočit vlevo scRotateRight=Otočit vpravo scZoom=Přiblížit / oddálit sendTo=Odeslat obrázek do... shortcuts=Klávesové zkratky wheelZoom=Použít kolečko myši jako lupu [lang] buttonReset=Επαναφορά buttonSave=Αποθήκευση customCss=Προσαρμοσμένο στυλ defaultMode=Αρχικό μεγέθος disabled=απενεργοποιημένο favicon=Προσαρμοσμένο εικονίδιο faviconTip="Η επιλογή αυτή ορίζει ένα εικονίδιο καρτέλας για την ανοιγμένη εικόνα.\nΗ διεύθυνση της εικόνας μπορεί να χρησιμοποιηθεί και ως μια μεταβλητή: %url" infoTranslations=Μεταφράσεις longpressActionFitImage=προσαρμογή στο πλάτος/ύψος longpressLeft=Λειτουργία παρατετημένου πατήματος αριστερού κουμπιού longpressRight=Λειτουργία παρατετημένου πατήματος δεξιού κουμπιού mediaInfo=Πληροφορίες εικόνας minUpscale=Μεγέθυνση μικρών εικόνων minUpscaleTip="Μικρές εικόνες δεν μεγεθύνονται. Αυτή η επιλογή τις αναγκάζει να μεγεθυνθούν.\nΗ τιμή είναι σε ποσοστό και μεγεθύνει τις εικόνες που είναι μεγαλύτερες από το επιλεγμένο ποσοστό του ύψους ή του πλάτους της οθόνης." modeAutoFit=αυτόματη προσαρμογή modeBestFit=βέλτιστη προσαρμογή modeNatural=φυσικό μέγεθος navInfo=Πληροφορίες scCycleModes=Εναλαγή μεταξύ μεγεθών: φυσικό, προσαρμογή στο πλάτος, προσαρμογή στο ύψος scFitToHeight=Προσρμογή στο ύψος scFitToWidth=Προσρμογή στο πλάτος scFlipHorizontal=Οριζόντια αναστροφή scFlipVertical=Κάθετη αναστροφή scFreeZoom=Shift + μεταφορά στην εικόνα για ελεύθερη μεγέθυνση, κρατήστε το Ctrl για να μετακινήσετε την επιλογή scModeContain=Αυτόματη προσαρμογή scModeNatural=Φυσικό μέγεθος scReset=To Esc θα επαναφέρει την εικόνα στην αρχική της μορφή ή θα κλείσει την ελεύθερη μεγέθυνση scRotateLeft=Περιστροφή αριστερά scRotateRight=Περιστροφή δεξιά sendTo=Αποστολή εικόνας προς... shortcuts=Συντομεύσεις wheelZoom=Μεγεύθυνση με τη ροδέλα του ποντικιού [lang] appDescriptionShort=Additional functionality for the browser's default image and video viewer. buttonReset=Default buttonSave=Save centerContent=Center content customCss=Custom style (CSS) customCssTextareaPh="Change the background color, image border/shadow, and hide the scrollbars or the floating menu... \nHover the question mark to see examples, use the color picker above for getting color codes." customCssTip="body {\n background: #f3f3f5; /* Any valid background property (color, url(), gradient...). */\n overflow: hidden; /* Hides the scrollbars. To show them, change \"hidden\" to \"auto\". */\n}\n\n#media {\n background: #eef; /* Different background for the image. */\n border: 10px solid white; /* Image border. */\n box-shadow: 0 0 10px grey; /* Shadow of the image. */\n cursor: default !important; /* Don't allow the mouse cursor to change. */\n}\n\n.mask {\n color: rgba(0, 0, 0, .4); /* Color of the free-zoom mask. */\n}\n\n#menu {\n display: none; /* Disable the floating menu. */\n}\n" defaultMode=Initial sizing mode disabled=disabled favicon=Custom favicon faviconTip="This option allows to set a custom tab-icon for the opened image.\nThe address of the image can be used as a variable: %url" infoTranslations=Translations longpressActionFitImage=fit to width/height longpressActionWheelZoom=toggle wheel zooming longpressLeft=Left long-press action longpressRight=Right long-press action mediaAttributes=Media attributes mediaAttributesTip="Acceptable attributes\nautoplay - video starts automatically\nloop - repeat the play\ncontrols - show player controls\nmuted - mute sound\nvolume=0-100 - default volume (%)" mediaInfo=Image informations mediaInfoTip="Display custom information in the title of the tab. It may contain the following variables:\n%ow - original width\n%oh - original height\n%ratio - current width / current height\n%w - current width\n%h - current height\n%perc - percent of the original size\n%url - full URL\n%name - filename" minUpscale=Enlarge small images minUpscaleTip="Normally, smaller images won't be upscaled to the view-port. This option forces them to do so.\nThe value is given in percent, and tells the script to enlarge those images that are larger than the given percent of view-port's width or height (it depends on the previous option)." modeAutoFit=contain modeBestFit=best fit modeNatural=natural size navGeneral=General navInfo=Info opener=Open images from regular web-pages openerBoth=both openerCtrlAltClick=Ctrl + Alt + right click openerRightLong=right long-press phClickForExample=click for examples... scChangeVolume=Up / Down Increase/decrease the volume scCycleModes=Cycle through sizing modes: natural, fit to width, fit to height scDragndrop=Hold Ctrl or Alt to allow drag-and-drop, or drag from the right edge of the image, if that fits into the window scFitToHeight=Fit to height scFitToWidth=Fit to width scFlipHorizontal=Flip horizontal scFlipVertical=Flip vertical scFloatMenu=Move the cursor to the top left edge of the page to show the menu scFreeZoom=Shift + drag on the image to use free-zoom, hold Ctrl to move the selection scHorizontalScroll=To scroll the image horizontally, use the mouse wheel over the left bottom edge scImgBg=Cycle through image backgrounds: default, black, white, check, or hold Shift for custom value scModeContain=Auto fit scModeNatural=Natural size scPixelate=Pixelate image scReset=Esc will reset the image to its original form, or quits from free-zoom scRotateLeft=Rotate left scRotateRight=Rotate right scTogglePlay=Space Toggle play/pause scWheelZoom=Toggle wheel zooming scZoom=Zoom in / out sendTo=Send image to... shortcuts=Shortcuts wheelZoom=Zoom with mouse wheel [lang] appDescriptionShort=Funciones adicionales para el visor de imágenes y vídeo del navegador. buttonReset=Predeterminado buttonSave=Guardar centerContent=Centrar el contenido customCss=Estilo personalizado (CSS) customCssTextareaPh="Cambia el color de fondo, bordes/sombras de la imagen, y esconde las barras de desplazamiento o el menú flotante.\nColoca el cursor sobre el signo de interrogación a la izquierda para ver ejemplos. Utiliza el selector de color (arriba a la derecha) para obtener códigos de color." customCssTip="body {\n background: #f3f3f5; /* Cualquier atributo válido para background (color, url(), gradient...). */\n overflow: hidden; /* Oculta las barras de desplazamiento. Para mostrarlas, cambia \"hidden\" por \"auto\". */\n}\n\n#media {\n background: #eef; /* Cambia el fondo de la imagen. */\n border: 10px solid white; /* Borde de la imagen. */\n box-shadow: 0 0 10px grey; /* Sombra de la imagen. */\n cursor: default !important; /* No permite que el puntero cambie. */\n}\n\n.mask {\n color: rgba(0, 0, 0, .4); /* Color para el modo de ampliación de selección. */\n}\n\n#menu {\n display: none; /* Deshabilita el menú flotante. */\n}\n" defaultMode=Modo inicial de escalado disabled=deshabilitado favicon=Icono personalizado faviconTip="Esta opción permite establecer un favicono personalizado para las pestañas con imágenes abiertas.\nLa dirección de la imagen puede ser usada como variable: %url" infoTranslations=Traducciones longpressActionFitImage=ajustar a la anchura/altura longpressLeft=Acción para una pulsación larga con el botón izquierdo longpressRight=Acción para una pulsación larga con el botón derecho mediaAttributes=Atributos multimedia mediaAttributesTip="Atributos aceptados\nautoplay - comenzar reproducción automáticamente\nloop - repetir la reproducción\ncontrols - mostrar los controles del reproductor\nmuted - sin sonido\nvolume=0-100 - volumen por defecto (porcentaje)" mediaInfo=Información de la imagen mediaInfoTip="Muestra información sobre el contenido en el título de la pestaña. Puede contener las siguientes variables:\n%ow - anchura original\n%oh - altura original\n%ratio - anchura actual / altura actual\n%w - anchura actual\n%h - altura actual\n%perc - porcentaje del tamaño original\n%url - dirección URL\n%name - nombre del archivo" minUpscale=Ampliar imágenes pequeñas minUpscaleTip="Por defecto, las imágenes pequeñas no serán ampliadas para encajar en la ventana de visualización. Esta opción las fuerza a hacerlo.\nEl valor esta dado en porcentaje, e indica a la extensión que amplié las imágenes que sean mayores al porcentaje en anchura o altura de la ventana de visualización (esto depende de la opción anterior).\n Ejemplo: si el valor esta fijado en 20%, y una imagen ocupa el 30% de la ventana de visualización, será ampliada de acuerdo a la opción anterior (Modo inicial de escalado)." modeAutoFit=ajustar modeBestFit=mejor ajuste modeNatural=tamaño original navInfo=Información opener=Abrir imágenes desde páginas web openerBoth=ambas openerCtrlAltClick=Ctrl + Alt + clic derecho openerRightLong=una pulsación larga con el botón derecho phClickForExample=haz clic para mostrar ejemplos... scChangeVolume=Arriba / Abajo Aumentar/disminuir volumen scCycleModes=Cambiar entre los modos de escalado: tamaño original, ajustar a la anchura, ajustar a la altura scDragndrop=Mantén presionado Ctrl o Alt para permitir arrastrar y soltar, o arrastra desde el borde derecho de la imagen (si cabe en la ventana) scFitToHeight=Ajustar a lo alto scFitToWidth=Ajustar a lo ancho scFlipHorizontal=Voltear horizontalmente scFlipVertical=Voltear verticalmente scFloatMenu=Mueve el cursor a la esquina superior izquierda de la pantalla para mostrar el menú scFreeZoom=Shift + arrastrar sobre la imagen para usar el modo de ampliación de selección, mantén presionado Ctrl (sin soltar Shift) para mover la selección scHorizontalScroll=Para desplazar la imagen horizontalmente, utiliza la rueda del ratón sobre el borde inferior izquierdo scModeContain=Ajuste automático scModeNatural=Tamaño original scReset=Esc devolverá la imagen a su forma original, o saldrá del modo de ampliación de selección scRotateLeft=Girar a la izquierda scRotateRight=Girar a la derecha scTogglePlay=Barra espaciadora Alterna entre reproducción/pausa scZoom=Acercar/alejar la imagen sendTo=Enviar imagen a... shortcuts=Atajos wheelZoom=Ampliar (zoom) con la rueda del ratón [lang] buttonReset=Palauta oletukset buttonSave=Tallenna defaultMode=Oletuskoko disabled=poissa käytöstä favicon=Oma kuvake longpressActionFitImage=sovita leveyteen tai korkeuteen longpressLeft=Ykköspainikkeen pitkän painalluksen toiminto longpressRight=Kakkospainikkeen pitkän painalluksen toiminto mediaInfo=Kuvan tiedot minUpscale=Suurenna pieniä kuvia (%) minUpscaleTip="Tavallisesti pieniä kuvia ei skaalata näkymäalueeseen, mutta tämä asetus pakottaa sen päälle.\nArvo annetaan prosentteina, ja se saa skriptin suurentamaan kuvia, jotka ovat suurempia kuin annettu prosenttiosuus näkymäalueen leveydestä tai korkeudesta (riippuen edellisestä asetuksesta)." modeAutoFit=automaattinen sovitus modeBestFit=paras sovitus modeNatural=luonnollinen koko navInfo=Tietoja phClickForExample=klikkaa nähdäksesi esimerkkejä... scCycleModes=Siirry suurennustilojen välillä: luonnollinen koko, sovita leveyteen, sovita korkeuteen scFitToHeight=Sovita korkeuteen scFitToWidth=Sovita leveyteen scFlipHorizontal=Käännä pystysuunnassa scFlipVertical=Käännä vaakasuunnassa scFreeZoom=Pidä Vaihtoa pohjassa ja vedä kuvan päällä käyttääksesi FreeZoomia, pidä Ctrl:ia pohjassa siirtääksesi valittua aluetta scModeContain=Automaattinen sovitus scModeNatural=Luonnollinen koko scReset=Esc palauttaa kuvan alkuperäiseen tilaan tai poistuu FreeZoom-tilasta scRotateLeft=Kierrä vasemmalle scRotateRight=Kierrä oikealle scZoom=Suurenna / pienennä sendTo=Lähetä kuvan osoite... shortcuts=Näppäinoikotiet wheelZoom=Suurennus hiiren rullalla [lang] appDescriptionShort=Des fonctionnalités additionnelles pour l’affichage des images et des vidéos de votre navigateur. buttonReset=Par défaut buttonSave=Sauvegarder centerContent=Centrer le contenu customCss=Style personnalisé (CSS) defaultMode=Redimensionnement disabled=désactivé favicon=Favicon personnalisé faviconTip="Cette option permet de choisir un icône personnalisé pour l'onglet de l'image ouverte.\nL'adresse de l'image peut être utilisée comme une variable : %url" infoTranslations=Traductions longpressActionFitImage=adapter à la largeur/hauteur longpressLeft=Clic gauche prolongé longpressRight=Clic droit prolongé mediaAttributesTip="Options possibles\nautoplay - la vidéo se lance automatiquement\nloop - répéter la vidéo\ncontrols - montrer les boutons du lecteur\nmuted - rendre muet\nvolume=0-100 - volume par défaut (en pourcentage)" mediaInfo=Détails de l'image minUpscale=Agrandir les petites images minUpscaleTip="En temps normal, les petites images ne sont pas élargies à la taille de la fenêtre. Cette option les y force.\nLa valeur est un pourcentage, et indique au script d'élargir les images plus grandes qu'un certain pourcentage de la hauteur ou de la largeur de la fenêtre (en fonction de l'option choisie précédemment)." modeAutoFit=réduire modeBestFit=taille optimale modeNatural=taille initiale navInfo=Infos opener=Ouvre les images des pages web classiques openerBoth=les deux openerCtrlAltClick=Ctrl + Alt + clic droit openerRightLong=clic droit prolongé phClickForExample=cliquez pour avoir un exemple... scCycleModes=Faire défiler les différents modes : taille initiale, adapter à la largeur, adapter à la hauteur scFitToHeight=Adapter à la hauteur scFitToWidth=Adapter à la largeur scFlipHorizontal=Inverser horizontalement scFlipVertical=Inverser verticalement scFloatMenu=Déplacez le curseur en haut à gauche de la page pour afficher le menu scFreeZoom=Maj + glisser sur l'image pour utiliser le zoom libre, maintenir Ctrl pour déplacer la sélection scHorizontalScroll=Pour faire défiler l'image horizontalement, utilisez la molette de la souris en bas à gauche scModeContain=Redimensionnement automatique scModeNatural=Taille initiale scReset=Échap ramènera l'image à sa taille initiale, ou sortira du zoom libre scRotateLeft=Rotation vers la gauche scRotateRight=Rotation vers la droite scZoom=Zoom avant / arrière sendTo=Envoyer l'image vers... shortcuts=Raccourcis wheelZoom=Zoomer avec la molette [lang] appDescriptionShort=A beépített kép- illetve videónéző funkcióit bővíti. buttonReset=Alap buttonSave=Mentés centerContent=Tartalom középre helyezése customCss=Egyedi stílus (CSS) customCssTextareaPh="Itt lehetseéges a háttér színének, kép keretének/árnyékának, stb. beállítása, illetve a görgősávok és a lebegő menü elrejtése.\nPéldákért vidd az egérkurzort a kérdőjel fölé, a színkódokhoz pedig használd a fenti színválasztót." customCssTip="body {\n background: #f3f3f5; /* Bármilyen elfogadott background érték (szín, url(), színátmenet...). */\n overflow: hidden; /* Elrejti a görgősávot. \"hidden\" változtatása \"auto\"-ra a megjelenítésükhöz. */\n}\n\n#media {\n background: #eef; /* Más háttér kizárólag a képnek. */\n border: 10px solid white; /* Egyéni képkeret. */\n box-shadow: 0 0 10px grey; /* Kép körüli árnyék. */\n cursor: default !important; /* Az egérkurzor változatlan marad ezzel az értékkel. */\n}\n\n.mask {\n color: rgba(0, 0, 0, .4); /* A szabad méretezés mask színe. */\n}\n\n#menu {\n display: none; /* A lebegő menü elrejtése. */\n}\n" defaultMode=Alap méretezés disabled=kikapcsolva favicon=Egyéni ikon a fülön faviconTip=A kép címe használható változóként a megadott értékben: %url infoTranslations=Fordítások longpressActionFitImage=szélességhez/magassághoz méretez longpressActionWheelZoom=egérgörgővel való nagyítás ki/bekapcsolása longpressLeft=Bal hosszan-tartás funkciója longpressRight=Jobb hosszan-tartás funkciója mediaAttributes=Média attribútumok mediaAttributesTip="Használható attribútumok\nautoplay - automatikus indítás\nloop - lejátszás ismétlése\ncontrols - lejátszógombok megjelenítése\nmuted - hang némítása\nvolume=0-100 - alapértelmezett hangerő (%)" mediaInfo=Képinformációk mediaInfoTip="Egyéni adatok megjelenítése a fül címében, a következő változók felhaszanálásával:\n%ow - eredeti szélesség\n%oh - eredeti magasság\n%ratio - jelenlegi szélesség és magasság aránya\n%w - jelenlegi szélesség\n%h - jelenlegi magasság\n%perc - átméretezés százalékban\n%url - teljes cím\n%name - fájl neve" minUpscale=Kis képek nagyítása minUpscaleTip="A kisebb képek alapból nem méreteződnek az ablakhoz. Ez a beállítás az ellenkezőjére kényszeríti őket.\nAzok a képek méreteződnek fel, amelyek méretei nagyobbak, mint a százalékban megadott ablak szélessége vagy magassága (az előző beállítástól függ)." modeAutoFit=ablakhoz méretez modeBestFit=illeszkedés az ablakhoz modeNatural=eredeti méret navGeneral=Beállítások navInfo=Infó opener=Képek megnyitása normál web-oldalkról openerBoth=mindkettő openerCtrlAltClick=Ctrl + Alt + jobb klikk openerRightLong=jobb klikk hosszan-tartva phClickForExample=kattints példákért... scChangeVolume=Fel / Le Hangerő növelése/csökkentése scCycleModes=Méretezések közti váltás: eredeti, szélességhez-, magassághoz méretez scDragndrop=Ctrl vagy Alt nyomva-tartásával vonszolható a kép, vagy ha belefér a nézetablakba, akkor a jobb szélénél fogva scFitToHeight=Magassághoz méretez scFitToWidth=Szélességhez méretez scFlipHorizontal=Vízszintes tükrözés scFlipVertical=Függőleges tükrözés scFloatMenu=A menü megjelenítéséhez mozgasd az egérkurzort az oldal bel felső szélére scFreeZoom=Shift + vonszolás nagyít a kijelölt részre, Ctrl tartásával a kijelölés mozgatható scHorizontalScroll=A kép vízszintes mozgatása az oldal bal also élén való görgetéssel lehetséges. scImgBg=Kép hátterének váltogatása: alap, fekete, fehér, sakkminta, vagy a Shift lenyomásával egyéni érték megadása scModeContain=Ablakhoz méretez scModeNatural=Eredeti méret scPixelate=Pixeles kép scReset=Esc a képet az eredeti állapotára állítja, vagy kilép a szabad méretezésből scRotateLeft=Forgatás jobbra scRotateRight=Forgatás balra scTogglePlay=Space Médiafájlok lejátszása/leállítása scWheelZoom=Egérgörgővel való nagyítás ki/bekapcsolása scZoom=Nagyítás / kicsinyítés sendTo=Kép küldése... shortcuts=Billentyűparancsok wheelZoom=Nagyítás görgetéssel [lang] appDescriptionShort=브라우저의 기본 이미지와 비디오 뷰어에 여러 기능을 추가해줍니다. buttonReset=기본 buttonSave=저장 centerContent=내용 가운데 정렬 customCss=커스텀 스타일 (CSS) customCssTextareaPh="배경 색 바꾸기, 이미지 테두리 / 그림자, 스크롤바 숨기기와 떠 있는 메뉴 등...\n위 색상 선택기를 사용하여 색상 코드를 얻을 수 있습니다. 예시를 보려면 물음표에 커서를 올리세요." customCssTip="body {\n background: #f3f3f5; /* 아무 유효한 배경 속성 (color, url(), gradient...) */\n overflow: hidden; /* 스크롤 바를 숨깁니다. 보이기 위해서는, \"hidden\"을 \"auto\"로 바꾸세요. */\n}\n\n#media {\n background: #eef; /* 이미지를 위한 배경 */\n border: 10px solid white; /* 이미지 테두리 */\n box-shadow: 0 0 10px grey; /* 이미지 그림자 */\n cursor: default !important; /* 마우스 커서의 모양이 변하지 않게 합니다. */\n}\n\n.mask {\n color: rgba(0, 0, 0, .4); /* 자유 확대 / 축소 마스크의 색상 */\n}\n\n#menu {\n display: none; /* 떠 있는 메뉴를 비활성화 */\n}\n" defaultMode=초기 크기 조절 모드 disabled=비활성화됨 favicon=커스텀 파비콘 faviconTip="이 옵션으로 이미지가 열린 탭의 아이콘을 바꿀 수 있습니다.\n이미지 주소가 변수로서 쓰일 수 있습니다:\n%url" infoTranslations=번역 longpressActionFitImage=폭/높이에 맞춤 longpressLeft=왼쪽 길게 누르기 작동 longpressRight=오른쪽 길게 누르기 작동 mediaAttributesTip="사용 가능한 속성\n자동 재생 - 비디오가 자동으로 시작됨\n반복 재생 - 비디오를 반복하여 재생\n컨트롤 - 플레이어 컨트롤 표시\n조용히 - 소리 끄기\n볼륨=0-100 - 기본 볼륨 (퍼센트)" mediaInfo=이미지 정보 mediaInfoTip="커스텀 정보를 탭의 제목에 표시합니다. 아래의 변수를 포함할 수 있습니다:\n%ow - 실제 폭\n%oh - 실제 높이\n%ratio - 현재 폭 / 현재 높이\n%w - 현재 폭\n%h - 현재 높이\n%perc - 실제 크기에 대한 퍼센트\n%url - 전체 URL\n%name - 파일명" minUpscale=작은 이미지를 확대 minUpscaleTip="보통 작은 이미지는 표시 영역에 맞춰 확대되지 않지만 이 옵션은 이것을 강제합니다.\n 이 값은 퍼센트로 되어 있습니다. 이전 옵션에 따라 표시 영역의 폭이나 높이의 퍼센트보다 큰 이미지는 표시 영역에 맞춰 확대됩니다." modeAutoFit=포함 modeBestFit=최적 modeNatural=자연스럽게 navGeneral=기본 navInfo=정보 opener=일반 웹 페이지에서 이미지 열기 openerBoth=둘 다 openerCtrlAltClick=Ctrl + Alt + 오른쪽 클릭 openerRightLong=오른쪽 길게 누르기 phClickForExample=예시를 보려면 클릭... scCycleModes=크기 조절 모드를 차례로 순환: 자연스럽게, 폭 맞춤, 높이 맞춤 scDragndrop=끌어서 놓기를 허용하려면 Ctrl 또는 Alt를 누르고 있거나, 창과 맞다면 이미지의 오른쪽 가장자리에서 끌면 됩니다 scFitToHeight=높이 맞춤 scFitToWidth=폭 맞춤 scFlipHorizontal=위아래 뒤집기 scFlipVertical=좌우 뒤집기 scFloatMenu=메뉴를 표시하려면 커서를 페이지 왼쪽 위 모서리로 이동하세요 scFreeZoom=이미지 위에서 Shift + 끌기를 하여 자유 확대 / 축소를 하고, Ctrl을 누른 상태에서는 선택 영역을 이동할 수 있습니다 scHorizontalScroll=큰 이미지를 좌우로 움직이려면 페이지 왼쪽 아래 모서리에서 마우스 휠을 사용하면 됩니다 scModeContain=자동 맞춤 scModeNatural=자연스러운 크기 scReset=Esc는 이미지를 원래 모습으로 되돌리거나, 자유 확대 / 축소를 취소합니다 scRotateLeft=시계 반대 방향 회전 scRotateRight=시계 방향 회전 scZoom=확대 / 축소 sendTo=이미지를 다음으로 보내기... shortcuts=바로가기 wheelZoom=마우스 휠로 확대 / 축소 [lang] buttonReset=Reset buttonSave=Opslaan customCss=Aangepaste stijl (CSS) defaultMode=Oorspronkelijke pas-modus disabled=uit favicon=Aangepaste favicon faviconTip="Deze optie maakt het mogelijk om een aangepaste tab-icoon te gebruiken voor de geopende afbeelding.\nHet adres van de afbeelding kan gebruikt worden als variabele: %url" infoTranslations=Vertalingen longpressActionFitImage=breedte/hoogte passend maken longpressLeft=Linker lange druk aktie longpressRight=Rechter lange druk aktie mediaInfo=Afbeeldings informatie minUpscale=Kleine afbeeldingen vergroten minUpscaleTip="Normaal gesproken worden kleinere afbeeldingen niet vergroot. Deze optie dwingt afbeeldingen te vergroten.\nDe waarde is in procenten, en vertelt het script om afbeeldingen die groter zijn de gegeven procenten van de breedte of hoogte van de kijker te vergroten (afhankelijk van de vorige optie)." modeAutoFit=bevatten modeBestFit=best afstemmen modeNatural=natuurlijk formaat phClickForExample=klikken voor voorbeelden... scCycleModes=Door sizing modi wisselen: normaal, breedte passend maken, hoogte passend maken scFitToHeight=Hoogte passend maken scFitToWidth=Breedte passend maken scFlipHorizontal=Horizontaal omdraaien scFlipVertical=Verticaal omdraaien scFreeZoom=Shift + Sleep de afbeelding om free-zoom te gebruiken, Ctrl ingedrukt houden om de selectie te verplaatsen scModeContain=Automatisch passen scModeNatural=Normale grootte scReset=Esc herstelt de afbeelding naar origineel formaat, of verlaat de vrije-zoom scRotateLeft=Links roteren scRotateRight=Rechts roteren scZoom=In-/uitzoomen sendTo=Afbeelding sturen naar... shortcuts=Snelkoppelingen wheelZoom=Zoomen met muiswiel [lang] appDescriptionShort=Rozszerzenie standardowej przeglądarki obrazów i filmów o nowe funkcje. buttonReset=Resetuj buttonSave=Zapisz centerContent=Wyśrodkuj customCss=Własne style (CSS) customCssTextareaPh="Pozwala zmienić kolor tła, obramowanie i cień dla obrazka i ukryć paski przewijania, lub menu z dodatkowymi funkcjami.\nNajedź na znak zapytania by zobaczyć przykładowy kod. Użyj pipety kolorów powyżej, by znaleźć kod wybranego koloru." customCssTip="body {\n background: #f3f3f5; /* Dowolna deklaracja tła zgodna z CSS (color, url(), gradient...). */\n overflow: hidden; /* Ukrywa paski przewijania. Aby je przywrócić, zmień \"hidden\" na \"auto\". */\n}\n\n#media {\n background: #eef; /* Inne tło dla obrazka. */\n border: 10px solid white; /* Obramowanie obrazka. */\n box-shadow: 0 0 10px grey; /* Cień obrazka. */\n cursor: default !important; /* Nie pozwala na zmianę wyglądu kursora. */\n}\n\n.mask {\n color: rgba(0, 0, 0, .4); /* Kolor maski w trybie powiększania wybranego obszaru. */\n}\n\n#menu {\n display: none; /* Wyłącza menu z dodatkowymi funkcjami. */\n}\n" defaultMode=Skalowanie obrazów disabled=brak favicon=Własna ikona pliku faviconTip="Zmienia ikonę pliku w pasku tytułu (domyślnie przeglądarka używa obrazka jako ikony).\nAdres obrazka można wprowadzić za pomocą zmiennej: %url" infoTranslations=Tłumaczenia longpressActionFitImage=zmieść w oknie longpressLeft=Funkcja dla przytrzymania lewego przycisku longpressRight=Funkcja dla przytrzymania prawego przycisku mediaAttributesTip="Dopuszczalne parametry:\nautoplay - film jest odtwarzany automatycznie\nloop - odtwórz ponownie po zakończeniu\ncontrols - pokazuj przyciski kontrolne odtwarzacza\nmuted - wycisz film\nvolume=0-100 - domyślna głośność (wyrażona w procentach)" mediaInfo=Informacje o obrazku mediaInfoTip="Wyświetlaj wybrane informacje o pliku w tytule karty przeglądarki. Lista możliwych opcji:\n%ow - rzeczywista szerokość\n%oh - rzeczywista wysokość\n%ratio - aktualna szerokość / aktualna wysokość\n%w - aktualna szerokość\n%h - aktualna wysokość\n%perc - procent powiększenia\n%url - pełny adres pliku\n%name - nazwa pliku" minUpscale=Powiększanie małych obrazków minUpscaleTip="Domyślnie małe obrazki nie są powiększane do rozmiarów okna. Ta funkcja wymusza ich skalowanie.\nFunkcja ta powoduje powiększenie tych obrazków, których wymiary przekraczają określony procent wysokości lub szerokości okna (w zależności od ustawień poprzedniej funkcji)." modeAutoFit=zmieść na ekranie modeBestFit=automatyczne dopasowanie modeNatural=rzeczywisty wymiar navGeneral=Ogólne opener=Otwieraj zwykłe obrazki na stronach openerBoth=obydwa openerCtrlAltClick=Ctrl + Alt + prawy przycisk myszy openerRightLong=przytrzymując prawy klawisz myszy phClickForExample=kliknij, by zobaczyć przykłady... scCycleModes=Przełącza tryby powiększenia: rzeczywiste wymiary, zmieść w poziomie, zmieść w pionie scDragndrop=Przytrzymaj Ctrl lub Alt by włączyć tryb przeciągania i upuszczania, lub przeciągnij z prawej strony obrazka, jeśli mieści się w oknie przeglądarki scFitToHeight=Dopasuj do wysokości scFitToWidth=Dopasuj do szerokości scFlipHorizontal=Odbij w poziomie scFlipVertical=Odbij w pionie scFloatMenu=Najedź na lewy górny róg strony by zobaczyć menu scFreeZoom=Przeciągnij z Shiftem na obrazku, by aktywować powiększanie obszarowe. Przytrzymaj Ctrl aby przesunąć zaznaczenie scHorizontalScroll=Aby przewijać obrazek w poziomie, użyj kółka myszy w lewym dolnym rogu strony scModeContain=Auto dopasowanie scModeNatural=Rzeczywisty wymiar scReset=Esc przywraca domyślne ustawienia obrazka lub opuszcza tryb powiększania wybranego obszaru scRotateLeft=Obróć w lewo scRotateRight=Obróć w prawo scZoom=Powiększ / Pomniejsz sendTo=Wyślij obrazek do... shortcuts=Skróty wheelZoom=Powiększaj za pomocą kółka myszki [lang] buttonReset=Padrão buttonSave=Salvar customCss=Estilo de CSS personalizado defaultMode=Tamanho de exibição disabled=desativado favicon=Ícone personalizado faviconTip="Esta opção possibilita adicionar um ícone personalizado à imagem aberta.\nO endereço da imagem pode ser usado como variável: %url" infoTranslations=Traduções longpressActionFitImage=caber na altura/largura longpressLeft=Clique longo com o botão esquerdo do mouse longpressRight=Clique longo com o botão direito do mouse mediaInfo=Informações da imagem. minUpscale=Aumentar imagens pequenas minUpscaleTip="Geralmente imagens pequenas não são exibidas em grande parte da tela. Esta função força que elas sejam.\nO valor é dado em porcentagem, e informa ao script para deixa-las de acordo com os dados de altura e largura fornecidos (isso depende das opções selecionadas)." modeAutoFit=redimensionar à tela modeBestFit=redimensionar da melhor forma modeNatural=tamanho original navInfo=Dados phClickForExample=clique para ver exemplos... scCycleModes=Trocar entre os modos: tamanho original, caber na altura, caber na largura scFitToHeight=Dimensionar à altura scFitToWidth=Dimensionar à largura scFlipHorizontal=Virar à horizontal scFlipVertical=Virar à vertical scFreeZoom=Shift + arrastrar em cima da imagem para usar o modo de ampliação de seleção, mantenha pressionado Ctrl (sem soltar Shift) para mover a seleção scModeContain=Dimensionar automaticamente scModeNatural=Tamanho original scReset=Esc voltará a imagem à sua forma normal, ou sairá do zoom-livre scRotateLeft=Rodar à esquerda scRotateRight=Rodar à direita scZoom=Zoom mais/menos sendTo=Enviar imagem para... shortcuts=Atalhos do teclado wheelZoom=Fazer zoom ao rodar roda do mouse [lang] appDescriptionShort=Дополнительная функциональность при просмотре изображений и видео в браузере. buttonReset=По умолчанию buttonSave=Сохранить centerContent=Центрировать содержимое customCss=Пользовательский стиль (CSS) customCssTextareaPh="Можно изменять цвета фона, границу/тень изображения, скрывать полосы прокрутки или всплывающее меню...\nНаведите курсор на вопросительный знак, чтобы увидеть примеры, используйте палитру цветов выше для получения кодов цвета." customCssTip="body {\n background: #f3f3f5; /* Любое допустимое свойство фона (color, url(), gradient...). */\n overflow: hidden; /* Скрыть полосы прокрутки. Чтобы показать их, измените \"hidden\" на \"auto\". */\n}\n\n#media {\n background: #eef; /* Различный фон для изображения. */\n border: 10px solid white; /* Граница изображения. */\n box-shadow: 0 0 10px grey; /* Тень изображения. */\n cursor: default !important; /* Запретить изменение курсора. */\n}\n\n.mask {\n color: rgba(0, 0, 0, .4); /* Цвет маски свободного масштабирования. */\n}\n\n#menu {\n display: none; /* Отключить всплывающее меню. */\n}\n" defaultMode=Размер по умолчанию disabled=отключено favicon=Пользовательская иконка faviconTip="Этот параметр позволяет назначить произвольную иконку для вкладки с открытым изображением.\nАдрес изображения можно использовать как переменную: %url" infoTranslations=Переводы longpressActionFitImage=подогнать по ширине/высоте longpressActionWheelZoom=переключить масштабирование колесом longpressLeft=Действие длительного нажатия левой кнопкой мыши longpressRight=Действие длительного нажатия правой кнопкой мыши mediaAttributes=Атрибуты медиа mediaAttributesTip="Допустимые атрибуты\nautoplay - видео начинается автоматически\nloop - повторить воспроизведение\ncontrols - показывать элементы управления плейером\nmuted - отключение звука\nvolume=0-100 - уровень громкости по умолчанию (процент)" mediaInfo=Информация об изображении mediaInfoTip="Отображение пользовательской информации в заголовке вкладки. Она может содержать следующие переменные:\n%ow - оригинальная ширина\n%oh - оригинальная высота\n%ratio - текущая ширина / текущая высота\n%w - текущая ширина\n%h - текущая высота\n%perc - процент от оригинального размера\n%url - полный URL\n%name - имя файла" minUpscale=Увеличивать маленькие изображения minUpscaleTip="Как правило, небольшие изображения не увеличиваются до размеров области просмотра при масштабировании. Этот параметр заставит их это делать.\nЗначение задаётся в процентах, скрипт увеличит те изображения, размер которых больше данного процента от ширины или высоты области просмотра (в зависимости от предыдущей настройки)." modeAutoFit=вписать modeBestFit=наилучшее заполнение modeNatural=оригинальный размер navGeneral=Настройки navInfo=Инфо opener=Открытие изображений c обычных веб-страниц openerBoth=оба openerCtrlAltClick=Ctrl + Alt + правая кнопка мыши openerRightLong=длительное нажатие правой кнопки мыши phClickForExample=посмотреть примеры... scChangeVolume=Вверх / Вниз Увеличить/уменьшить громкость scCycleModes=Переключить между режимами: оригинальный, подгон по ширине, подгон по высоте scDragndrop=Зажмите Ctrl или Alt, чтобы позволить drag-and-drop, или протяните от правого края изображения, если оно вписано в окно scFitToHeight=Подогнать по высоте scFitToWidth=Подогнать по ширине scFlipHorizontal=Отразить по горизонтали scFlipVertical=Отразить по вертикали scFloatMenu=Подведите курсор к верхнему левому краю страницы, чтобы показать меню scFreeZoom=Зажать Shift + левую кнопку мыши на изображении для свободного масштабирования, дополнительно зажать Ctrl для перемещения выделения scHorizontalScroll=Для прокрутки изображения по горизонтали используйте колёсико мыши над левым нижним краем scImgBg=Переключать фон изображений: по умолчанию, чёрный, белый, шахматная доска; либо удерживайте Shift для установки пользовательского значения scModeContain=Вписать scModeNatural=Оригинальный размер scPixelate=Пикселизировать изображение scReset=Esc возвращает изображение к первоначальному виду или выходит из режима свободного масштабирования. scRotateLeft=Повернуть влево scRotateRight=Повернуть вправо scTogglePlay=Пробел Переключить воспроизведение/пауза scWheelZoom=Переключить масштабирование колесом scZoom=Увеличить / уменьшить sendTo=Отправить изображение в... shortcuts=Сочетания клавиш wheelZoom=Масштабировать колесом мыши [lang] appDescriptionShort=Extra funktionalitet till webbläsarens egen bildvisare och videospelare. buttonReset=Nollställ buttonSave=Spara centerContent=Centrera innehållet customCss=Egen stilmall (CSS) customCssTextareaPh="Byt bakgrundsfärgen, ändra bilden skugga och ram, dölj skrollisterna och de flytande menyerna...\nMed musen över frågetecknet, kan du se fler exempel. Använd färgpaletten ovan för att få färghexkoder." customCssTip="body {\n background: #f3f3f5; /* Välj en acceptabel bakgrundsegenskap (color, url(), gradient, etc.). */\n overflow: hidden; /* Döljer skrollisterna. För att visa dem, byt från \"hidden\" till \"auto\". */\n}\n\n# media {\n background: #eef; /* Annan bakgrundsfärg för bilden. */\n border: 10px solid white; /* Bildram. */\n box-shadow: 0 0 10px grey; /* Bildskugga. */\n cursor: default !important; /* Tillåter inte muspekaren att ändras. */\n}\n\n.mask {\n color: rgba(0, 0, 0, .4); /* Färg för fri-zoommasken. */\n}\n\n#menu {\n display: none; /* Tillåt inte flytande menyer. */\n}\n" defaultMode=Initalstorlek disabled=avstängt favicon=Egen adressikon faviconTip="Med denna inställning, ställer du in egen adressikon för de öppnade bilderna.\nBildens adress kan användas med variabeln %url" infoTranslations=Översättningar longpressActionFitImage=passa till höjd eller bredd longpressActionWheelZoom=skifta skrollhjulszoomning longpressLeft=Handling vid långvarig vänsterklick longpressRight=Handling vid långvarig högerklick mediaAttributes=Medieattribut mediaAttributesTip="Accepterade attribut\nautoplay - starta videon automatiskt\nloop - loopa uppspelning\ncontrols - visa kontroller\nmuted - tysta videon\nvolume=0-100 - standardvolym i procent" mediaInfo=Bildinformation mediaInfoTip="Visa egenanpassad information i flikens titelfält. Den kan innehålla följande variabler:\n%ow - originalbredd\n%oh - originalhöjd\n%ratio - förhållande mellan nuvarande bredd och höjd\n%w - nuvarande bredd\n%h - nuvarande höjd\n%perc - procent av originalstorleken\n%url - hela adressen\n%name - filnamnet" minUpscale=Förstora små bilder minUpscaleTip="Normalt burkar små bilder inte skalas upp i bildvyn. Detta tvingar små bilder att växa.\nVärdet är givet i procent och anger gränsen för hur små bilderna är i förhållande till bildvyns storlek." modeAutoFit=fyll modeBestFit=optimal anpassning modeNatural=naturlig storlek navGeneral=Generellt navInfo=Information opener=Öppna bilder från vanliga webbplatser openerBoth=både och openerCtrlAltClick=Ctrl + Alt + högerklick openerRightLong=långvarig högerklick phClickForExample=klicka för exempel... scChangeVolume=Upp eller ned för att höja eller sänka volymen scCycleModes=Bläddra igenom storlekslägen: naturlig, passa till bredd, passa till höjd scDragndrop=Håll Ctrl eller AltSkift + dra i bilden för att använda fri zoomning; håll Ctrl för att flytta valet scHorizontalScroll=För att skrolla bilden horisontellt: använd skrollhjulet vid nedre vänstra kanten scImgBg=Bläddra igenom bildbakgrunder: default, black, white, check eller håll Skift för egna värden scModeContain=Autoanpassning scModeNatural=Naturlig storlek scPixelate=Pixelera bild scReset=Esc kommer nollställa bilden eller avsluta zoomläget scRotateLeft=Rotera åt vänster scRotateRight=Rotera åt höger scTogglePlay=Blanksteg för att växla mellan spela och pausa scWheelZoom=Skifta skrollhjulszoomning scZoom=Zooma in eller ut sendTo=Skicka bilden till... shortcuts=Genvägar wheelZoom=Zooma med skrollhjulet [lang] buttonReset=Varsayılan buttonSave=Kaydet defaultMode=İlk boyutlandırma modu disabled=devre dışı favicon=Özel favicon mediaInfo=Resim bilgileri minUpscale=Küçük resimleri büyüt modeAutoFit=sığdır navInfo=Bilgi phClickForExample=örnekler için tıkla... scFitToHeight=Yüksekliğe sığdır scFitToWidth=Genişliğe sığdır scFlipVertical=Dikey çevir scModeNatural=Orijinal boyutlar scRotateRight=Sağa döndür shortcuts=Kısayollar wheelZoom=Fare tekeriyle yakınlaştır [lang] buttonReset=Дефолні налаштування buttonSave=Зберегти customCss=Стиль (CSS) defaultMode=Розмір за замовчуванням disabled=відключено favicon=Іконка faviconTip="Цей параметр дозволяє призначити довільну іконку для вкладки з відкритим зображенням.\nАдреса зображення можна використовувати як змінну: %url" infoTranslations=Переклади longpressActionFitImage=підігнати по ширині / висоті longpressLeft=Дія тривалого натискання лівою кнопкою миші longpressRight=Дія тривалого натискання правою кнопкою миші mediaInfo=Інформація про зображення minUpscale=Збільшувати маленькі зображення minUpscaleTip="Як правило, невеликі зображення не збільшуються до розмірів області перегляду при масштабування. Цей параметр змусить їх це робити.\nЗначення задається у відсотках, скрипт збільшить ті зображення, розмір яких більше даного відсотка від ширини або висоти області перегляду (залежно від попередньої настройки)." modeAutoFit=вписати modeBestFit=найкраще заповнення modeNatural=оригінальний розмір navInfo=Інфо phClickForExample=Дивитить приклади... scCycleModes=Переключити між режимами: оригінальний, підгін по ширині, підгін по висоті scFitToHeight=Підігнати по висоті scFitToWidth=Підігнати по ширині scFlipHorizontal=Відобразити по горизонталі scFlipVertical=Відобразити по вертикалі scFreeZoom=Зажати Shift + ліву кнопку миші на зображенні для вільного масштабування, додатково затиснути Ctrl для переміщення виділення scModeContain=Вписати scModeNatural=Оригінальний розмір scReset=Esc повертає зображення до первісного вигляду або виходить з режиму вільного масштабування. scRotateLeft=Повернути вліво scRotateRight=Повернути вправо scZoom=Збільшити / зменшити sendTo=Надіслати зображення в... shortcuts=Поєднання клавіш wheelZoom=Масштабувати колесом миші [lang] buttonReset=重置 buttonSave=保存 customCss=自定义样式 (CSS) defaultMode=图片默认显示模式 disabled=禁用 favicon=自定义 favicon faviconTip="该选项用于为打开的图片设置一个自定义的标签页图标。\n图片地址可使用以下变量:%url" infoTranslations=翻译 longpressActionFitImage=适应宽度/高度 longpressLeft=鼠标左键长按时的操作 longpressRight=鼠标右键长按时的操作 mediaInfo=图片信息 minUpscale=放大小图片 minUpscaleTip="通常小图片不会被放大到视图窗口(view-port)那么大,而该选项可以强制放大这些小图片。\n该选项值表示视图窗口宽度和高度值(这由前一个选项来决定)的百分比,用于告知脚本凡是大于该百分比的图片都强制放大。" modeAutoFit=嵌入查看器 modeBestFit=最佳适应方式 modeNatural=原始尺寸 navInfo=信息 phClickForExample=点击查看样例... scCycleModes=在原始大小,适应宽度和适应高度三种显示模式中切换 scFitToHeight=适应高度 scFitToWidth=适应宽度 scFlipHorizontal=水平翻转 scFlipVertical=垂直翻转 scFreeZoom=Shift + 拖动 图片进入自由缩放模式,按住 Ctrl 时可移动选区 scModeContain=自动适应 scModeNatural=原始尺寸 scReset=Esc 键可重置图片为原始显示方式,或退出自由缩放模式 scRotateLeft=向左旋转 scRotateRight=向右旋转 scZoom=缩小 / 放大 sendTo=发送图片到... shortcuts=快捷键 wheelZoom=使用鼠标滚轮缩放 [lang] buttonReset=預設 buttonSave=儲存 defaultMode=初始尺寸模式 disabled=停用 favicon=自訂網站圖標 longpressActionFitImage=符合寬度/高度 longpressLeft=左鍵長按動作 longpressRight=右鍵長按動作 mediaInfo=影像資訊 minUpscale=放大小圖片 modeAutoFit=自動縮放 modeBestFit=適合圖片 modeNatural=原始大小 navInfo=相關訊息 phClickForExample=點擊以做為範例... scFitToHeight=適合高度 scFitToWidth=適合寬度 scFlipVertical=垂直翻轉 scModeNatural=原始大小 scRotateRight=向右旋轉 shortcuts=快捷鍵 wheelZoom=以滑鼠滾輪縮放 {"_":"en","cs":{"name":"Czech (čeština)","translators":[{"email":"jaramat(at)email(dot)cz","name":"jaramat","realname":"Jaroslav Matura"}]},"el":{"name":"Greek (Ελληνικά)","translators":[{"email":"farow(dot)the(dot)time(dot)traveler(at)gmail(dot)com","name":"Farow"}]},"en":{"name":"English","translators":[{"email":"deathamns(at)gmail(dot)com","name":"Deathamns"}]},"es":{"name":"Spanish (español)","translators":[{"email":"nightroad(at)mail(dot)com","name":"DurianZheitk","realname":"Javier Vera"},{"name":"alm","realname":"A LM"}]},"fi":{"name":"Finnish (suomi)","translators":[{"email":"opeeera(at)myopera(dot)com","name":"Opeeera"}]},"fr":{"name":"French (français)","translators":[{"email":"tmnath2(at)gmail(dot)com","name":"Tmnath"}]},"hu":{"name":"Hungarian (magyar)","translators":[{"email":"deathamns(at)gmail(dot)com","name":"Deathamns"}]},"ko":{"name":"Korean (한국어)","translators":[{"email":"yut951121(at)gmail(dot)com","name":"QbsidianH20","realname":"유태종"}]},"nl":{"name":"Dutch (Nederlands)","translators":[{"email":"kackar(at)outlook(dot)com","name":"Kaçkar"}]},"pl":{"name":"Polish (polski)","translators":[{"name":"pafflick","realname":"Paweł Pawlak","web":"http://www.pafflick.com/"}]},"pt-BR":{"name":"Portuguese (Brazil) (português (Brasil))","translators":[{"email":"romulo(at)brazilmail(dot)com","realname":"Rômulo Godoi"}]},"ru":{"name":"Russian (русский)","translators":[{"email":"rodny0(at)gmail(dot)com","name":"Rodny"}]},"sv":{"name":"Swedish (svenska)","translators":[{"email":"johanohlin(at)gmx(dot)com","name":"Jojan","realname":"Johan Öhlin"}]},"tr":{"name":"Turkish (Türkçe)","translators":[{"email":"sanerapaydin86(at)gmail(dot)com","realname":"Saner Apaydın"}]},"uk":{"name":"Ukrainian (українська)","translators":[{"email":"simofon(at)yandex(dot)ru","name":"Simofon"}]},"zh-CN":{"name":"Chinese (Simplified Han) (中文(简体中文))","translators":[{"email":"wlq105556(at)gmail(dot)com","name":"fang5566"}]},"zh-TW":{"name":"Chinese (Traditional Han) (中文 (繁體中文))","translators":[{"email":"tingyang(at)gmail(dot)com","name":"TYKuo"}]}}
0%

  • + / -

Icons

Extension icon by esk6a
Menu icons by Egor Rumyantsev, Freepik, Icomoon @ www.flaticon.com