From 3583ffaefd0d07337f9f50e00683a14fe9966b2b Mon Sep 17 00:00:00 2001 From: ccd0 Date: Wed, 2 Apr 2014 18:04:58 -0700 Subject: [PATCH] compile after merge --- LICENSE | 2 +- builds/4chan-X.user.js | 710 +++-------------------------------------- builds/crx/script.js | 710 +++-------------------------------------- 3 files changed, 79 insertions(+), 1343 deletions(-) diff --git a/LICENSE b/LICENSE index 9c4c72ac9..160826428 100755 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ /* -* 4chan X - Version 1.4.1 - 2014-03-31 +* 4chan X - Version 1.4.1 - 2014-04-02 * * Licensed under the MIT license. * https://github.com/Spittie/4chan-x/blob/master/LICENSE diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index 2dd0ec282..24025db5f 100644 --- a/builds/4chan-X.user.js +++ b/builds/4chan-X.user.js @@ -24,7 +24,7 @@ // ==/UserScript== /* -* 4chan X - Version 1.4.1 - 2014-03-31 +* 4chan X - Version 1.4.1 - 2014-04-02 * * Licensed under the MIT license. * https://github.com/Spittie/4chan-x/blob/master/LICENSE @@ -6319,6 +6319,10 @@ onload: QR.response, onerror: function(err, url, line) { delete QR.req; + if (QR.captcha.isEnabled) { + QR.captcha.destroy(); + QR.captcha.setup(); + } post.unlock(); QR.cooldown.auto = false; QR.status(); @@ -6351,9 +6355,12 @@ return QR.status(); }, response: function() { - var URL, ban, board, captchasCount, err, h1, isReply, m, notif, post, postID, postsCount, req, resDoc, threadID, _, _ref, _ref1; + var URL, ban, board, err, h1, isReply, m, post, postID, postsCount, req, resDoc, threadID, _, _ref, _ref1; req = QR.req; delete QR.req; + if (QR.captcha.isEnabled) { + QR.captcha.destroy(); + } post = QR.posts[0]; post.unlock(); resDoc = req.response; @@ -6378,12 +6385,12 @@ } else if (/expired/i.test(err.textContent)) { err = 'This CAPTCHA is no longer valid because it has expired.'; } - QR.cooldown.auto = QR.captcha.isEnabled ? !!QR.captcha.captchas.length : err === 'Connection error with sys.4chan.org.' ? true : false; + QR.cooldown.auto = false; QR.cooldown.set({ delay: 2 }); } else if (err.textContent && (m = err.textContent.match(/wait\s+(\d+)\s+second/i))) { - QR.cooldown.auto = QR.captcha.isEnabled ? !!QR.captcha.captchas.length : true; + QR.cooldown.auto = !QR.captcha.isEnabled; QR.cooldown.set({ delay: m[1] }); @@ -6422,22 +6429,6 @@ }); postsCount = QR.posts.length - 1; QR.cooldown.auto = postsCount && isReply; - if (QR.cooldown.auto && QR.captcha.isEnabled && (captchasCount = QR.captcha.captchas.length) < 3 && captchasCount < postsCount) { - notif = new Notification('Quick reply warning', { - body: "You are running low on cached captchas. Cache count: " + captchasCount + ".", - icon: Favicon.logo - }); - notif.onclick = function() { - QR.open(); - QR.captcha.nodes.input.focus(); - return window.focus(); - }; - notif.onshow = function() { - return setTimeout(function() { - return notif.close(); - }, 7 * $.SECOND); - }; - } if (!(Conf['Persistent QR'] || QR.cooldown.auto)) { QR.close(); } else { @@ -6473,12 +6464,11 @@ QR.captcha = { init: function() { - var container, imgContainer, input; + var imgContainer, input; if (d.cookie.indexOf('pass_enabled=1') >= 0) { return; } - container = $.id('captchaContainer'); - if (!(this.isEnabled = !!container)) { + if (!(this.isEnabled = !!$.id('captchaContainer'))) { return; } if (Conf['Auto-load captcha']) { @@ -6487,13 +6477,11 @@ imgContainer = $.el('div', { className: 'captcha-img', title: 'Reload reCAPTCHA', - innerHTML: '', - hidden: true + innerHTML: '' }); input = $.el('input', { className: 'captcha-input field', title: 'Verification', - placeholder: 'Focus to load reCAPTCHA', autocomplete: 'off', spellcheck: false, tabIndex: 45 @@ -6502,44 +6490,41 @@ img: imgContainer.firstChild, input: input }; - $.on(input, 'focus', this.setup); $.on(input, 'blur', QR.focusout); $.on(input, 'focus', QR.focusin); $.addClass(QR.nodes.el, 'has-captcha'); $.after(QR.nodes.com.parentNode, [imgContainer, input]); + this.beforeSetup(); + return this.afterSetup(); + }, + beforeSetup: function() { + var img, input, _ref; + _ref = this.nodes, img = _ref.img, input = _ref.input; + img.parentNode.hidden = true; + input.value = ''; + input.placeholder = 'Focus to load reCAPTCHA'; + $.on(input, 'focus', this.setup); this.setupObserver = new MutationObserver(this.afterSetup); - this.setupObserver.observe(container, { + return this.setupObserver.observe($.id('captchaContainer'), { childList: true }); - return this.afterSetup(); }, setup: function() { return $.globalEval('loadRecaptcha()'); }, afterSetup: function() { - var challenge, img, input, setLifetime, _ref; + var challenge, img, input, _ref; if (!(challenge = $.id('recaptcha_challenge_field_holder'))) { return; } QR.captcha.setupObserver.disconnect(); delete QR.captcha.setupObserver; - setLifetime = function(e) { - return QR.captcha.lifetime = e.detail; - }; - $.on(window, 'captcha:timeout', setLifetime); - $.globalEval('window.dispatchEvent(new CustomEvent("captcha:timeout", {detail: RecaptchaState.timeout}))'); - $.off(window, 'captcha:timeout', setLifetime); _ref = QR.captcha.nodes, img = _ref.img, input = _ref.input; img.parentNode.hidden = false; + input.placeholder = 'Verification'; $.off(input, 'focus', QR.captcha.setup); $.on(input, 'keydown', QR.captcha.keydown.bind(QR.captcha)); $.on(img.parentNode, 'click', QR.captcha.reload.bind(QR.captcha)); - $.get('captchas', [], function(_arg) { - var captchas; - captchas = _arg.captchas; - return QR.captcha.sync(captchas); - }); - $.sync('captchas', QR.captcha.sync); QR.captcha.nodes.challenge = challenge; new MutationObserver(QR.captcha.load.bind(QR.captcha)).observe(challenge, { childList: true, @@ -6548,94 +6533,31 @@ }); return QR.captcha.load(); }, - sync: function(captchas) { - QR.captcha.captchas = captchas; - return QR.captcha.count(); + destroy: function() { + $.globalEval('Recaptcha.destroy()'); + return this.beforeSetup(); }, getOne: function() { - var captcha, challenge, response; - this.clear(); - if (captcha = this.captchas.shift()) { - challenge = captcha.challenge, response = captcha.response; - this.count(); - $.set('captchas', this.captchas); - } else { - challenge = this.nodes.img.alt; - if (response = this.nodes.input.value) { - this.reload(); - } - } - if (response) { - response = response.trim(); - if (!/\s/.test(response)) { - response = "" + response + " " + response; - } + var challenge, response; + challenge = this.nodes.img.alt; + response = this.nodes.input.value.trim(); + if (response && !/\s/.test(response)) { + response = "" + response + " " + response; } return { challenge: challenge, response: response }; }, - save: function() { - var response; - if (!(response = this.nodes.input.value.trim())) { - return; - } - this.captchas.push({ - challenge: this.nodes.img.alt, - response: response, - timeout: this.timeout - }); - this.count(); - this.reload(); - return $.set('captchas', this.captchas); - }, - clear: function() { - var captcha, i, now, _i, _len, _ref; - if (!this.captchas.length) { - return; - } - now = Date.now(); - _ref = this.captchas; - for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { - captcha = _ref[i]; - if (captcha.timeout > now) { - break; - } - } - if (!i) { - return; - } - this.captchas = this.captchas.slice(i); - this.count(); - return $.set('captchas', this.captchas); - }, load: function() { var challenge; if (!this.nodes.challenge.firstChild) { return; } - this.timeout = Date.now() + this.lifetime * $.SECOND - $.MINUTE; challenge = this.nodes.challenge.firstChild.value; this.nodes.img.alt = challenge; this.nodes.img.src = "//www.google.com/recaptcha/api/image?c=" + challenge; - this.nodes.input.value = null; - return this.clear(); - }, - count: function() { - var count; - count = this.captchas ? this.captchas.length : 0; - this.nodes.input.placeholder = (function() { - switch (count) { - case 0: - return 'Verification (Shift + Enter to cache)'; - case 1: - return 'Verification (1 cached captcha)'; - default: - return "Verification (" + count + " cached captchas)"; - } - })(); - return this.nodes.input.alt = count; + return this.nodes.input.value = null; }, reload: function(focus) { $.globalEval('Recaptcha.reload("t")'); @@ -6646,8 +6568,6 @@ keydown: function(e) { if (e.keyCode === 8 && !this.nodes.input.value) { this.reload(); - } else if (e.keyCode === 13 && e.shiftKey) { - this.save(); } else { return; } @@ -6983,6 +6903,9 @@ node.disabled = lock; } } + if (QR.captcha.isEnabled) { + QR.captcha.nodes.input.disabled = lock; + } this.nodes.rm.style.visibility = lock ? 'hidden' : ''; (lock ? $.off : $.on)(QR.nodes.filename.previousElementSibling, 'click', QR.openFileInput); this.nodes.spoiler.disabled = lock; @@ -8647,561 +8570,6 @@ ] }; - Linkify = { - init: function() { - var type, _i, _len, _ref; - if (g.VIEW === 'catalog' || !Conf['Linkify']) { - return; - } - this.regString = /((https?|mailto|git|magnet|ftp|irc):([a-z\d%\/])|[-a-z\d]+[.](aero|asia|biz|cat|com|coop|info|int|jobs|mobi|museum|name|net|org|post|pro|tel|travel|xxx|edu|gov|mil|[a-z]{2})(\/|(?!.))|[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}|[-\w\d.@]+@[a-z\d.-]+\.[a-z\d])/i; - this.types = {}; - _ref = this.ordered_types; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - type = _ref[_i]; - this.types[type.key] = type; - } - if (Conf['Comment Expansion']) { - ExpandComment.callbacks.push(this.node); - } - if (Conf['Title Link']) { - $.sync('CachedTitles', Linkify.titleSync); - } - return Post.callbacks.push({ - name: 'Linkify', - cb: this.node - }); - }, - node: function() { - var data, el, end, endNode, i, index, items, length, link, links, node, result, saved, snapshot, space, test, word, _i, _len, _ref; - if (this.isClone) { - if (Conf['Embedding']) { - i = 0; - items = $$('.embed', this.nodes.comment); - while (el = items[i++]) { - $.on(el, 'click', Linkify.cb.toggle); - if ($.hasClass(el, 'embedded')) { - Linkify.cb.toggle.call(el); - } - } - } - return; - } - test = /[^\s'"]+/g; - space = /[\s'"]/; - snapshot = $.X('.//br|.//text()', this.nodes.comment); - i = 0; - links = []; - while (node = snapshot.snapshotItem(i++)) { - data = node.data; - if (node.parentElement.nodeName === "A" || !data) { - continue; - } - while (result = test.exec(data)) { - index = result.index; - endNode = node; - word = result[0]; - if ((length = index + word.length) === data.length) { - test.lastIndex = 0; - while ((saved = snapshot.snapshotItem(i++))) { - if (saved.nodeName === 'BR') { - break; - } - endNode = saved; - data = saved.data; - word += data; - length = data.length; - if (end = space.exec(data)) { - test.lastIndex = length = end.index; - i--; - break; - } - } - } - if (Linkify.regString.exec(word)) { - links.push(Linkify.makeRange(node, endNode, index, length)); - } - if (!(test.lastIndex && node === endNode)) { - break; - } - } - } - _ref = links.reverse(); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - link = _ref[_i]; - this.nodes.links.push(Linkify.makeLink(link, this)); - link.detach(); - } - if (!(Conf['Embedding'] || Conf['Link Title'])) { - return; - } - links = this.nodes.links; - i = 0; - while (link = links[i++]) { - if (data = Linkify.services(link)) { - if (Conf['Embedding']) { - Linkify.embed(data); - } - if (Conf['Link Title']) { - Linkify.title(data); - } - } - } - }, - makeRange: function(startNode, endNode, startOffset, endOffset) { - var range; - range = document.createRange(); - range.setStart(startNode, startOffset); - range.setEnd(endNode, endOffset); - return range; - }, - makeLink: function(range) { - var a, char, i, text; - text = range.toString(); - i = 0; - while (/[(\[{<>]/.test(text.charAt(i))) { - i++; - } - if (i) { - text = text.slice(i); - while (range.startOffset + i >= range.startContainer.data.length) { - i--; - } - if (i) { - range.setStart(range.startContainer, range.startOffset + i); - } - } - i = 0; - while (/[)\]}>.,]/.test(char = text.charAt(text.length - (1 + i)))) { - if (!(/[.,]/.test(char) || (text.match(/[()\[\]{}<>]/g)).length % 2)) { - break; - } - i++; - } - if (i) { - text = text.slice(0, -i); - while (range.endOffset - i < 0) { - i--; - } - if (i) { - range.setEnd(range.endContainer, range.endOffset - i); - } - } - if (!/(https?|mailto|git|magnet|ftp|irc):/.test(text)) { - text = (/@/.test(text) ? 'mailto:' : 'http://') + text; - } - a = $.el('a', { - className: 'linkify', - rel: 'nofollow noreferrer', - target: '_blank', - href: text - }); - $.add(a, range.extractContents()); - range.insertNode(a); - return a; - }, - services: function(link) { - var href, match, type, _i, _len, _ref; - href = link.href; - _ref = Linkify.ordered_types; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - type = _ref[_i]; - if (!(match = type.regExp.exec(href))) { - continue; - } - if (type.dummy) { - return; - } - return [type.key, match[1], match[2], link]; - } - }, - embed: function(data) { - var embed, href, key, link, name, options, uid, value, _ref; - key = data[0], uid = data[1], options = data[2], link = data[3]; - href = link.href; - embed = $.el('a', { - className: 'embedder', - href: 'javascript:;', - textContent: '(embed)' - }); - _ref = { - key: key, - href: href, - uid: uid, - options: options - }; - for (name in _ref) { - value = _ref[name]; - embed.dataset[name] = value; - } - embed.dataset.nodedata = link.innerHTML; - $.addClass(link, "" + embed.dataset.key); - $.on(embed, 'click', Linkify.cb.toggle); - $.after(link, [$.tn(' '), embed]); - if (Conf['Auto-embed']) { - Linkify.cb.toggle.call(embed); - } - data.push(embed); - }, - title: function(data) { - var embed, err, key, link, options, service, title, titles, uid; - key = data[0], uid = data[1], options = data[2], link = data[3], embed = data[4]; - if (!(service = Linkify.types[key].title)) { - return; - } - titles = Conf['CachedTitles']; - if (title = titles[uid]) { - if (link) { - link.textContent = title[0]; - } - if (Conf['Embedding']) { - return embed.dataset.title = title[0]; - } - } else { - try { - $.cache(service.api(uid), function() { - return title = Linkify.cb.title(this, data); - }, { - responseType: 'json' - }); - } catch (_error) { - err = _error; - if (link) { - link.innerHTML = "[" + key + "] Title Link Blocked (are you using NoScript?)"; - } - return; - } - if (title) { - titles[uid] = [title, Date.now()]; - return $.set('CachedTitles', titles); - } - } - }, - titleSync: function(value) { - return Conf['CachedTitles'] = value; - }, - cb: { - toggle: function() { - var string, _ref; - _ref = $.hasClass(this, "embedded") ? ['unembed', '(embed)'] : ['embed', '(unembed)'], string = _ref[0], this.textContent = _ref[1]; - $.replace(this.previousElementSibling, Linkify.cb[string](this)); - return $.toggleClass(this, 'embedded'); - }, - embed: function(a) { - var el, style, type; - el = (type = Linkify.types[a.dataset.key]).el(a); - el.style.cssText = (style = type.style) ? style : "border: 0; width: 640px; height: 390px"; - return el; - }, - unembed: function(a) { - var el; - el = $.el('a', { - rel: 'nofollow noreferrer', - target: 'blank', - className: 'linkify', - href: a.dataset.href, - innerHTML: a.dataset.title || a.dataset.nodedata - }); - $.addClass(el, a.dataset.key); - return el; - }, - title: function(response, data) { - var embed, key, link, options, service, text, uid; - key = data[0], uid = data[1], options = data[2], link = data[3], embed = data[4]; - service = Linkify.types[key].title; - switch (response.status) { - case 200: - case 304: - text = "" + (service.text(response.response)); - if (Conf['Embedding']) { - embed.dataset.title = text; - } - break; - case 404: - text = "[" + key + "] Not Found"; - break; - case 403: - text = "[" + key + "] Forbidden or Private"; - break; - default: - text = "[" + key + "] " + this.status + "'d"; - } - if (link) { - return link.textContent = text; - } - } - }, - ordered_types: [ - { - key: 'audio', - regExp: /(.*\.(mp3|ogg|wav))$/, - el: function(a) { - return $.el('audio', { - controls: 'controls', - preload: 'auto', - src: a.dataset.uid - }); - } - }, { - key: 'gist', - regExp: /.*(?:gist.github.com.*\/)([^\/][^\/]*)$/, - el: function(a) { - var div; - return div = $.el('iframe', { - src: "http://www.purplegene.com/script?url=https://gist.github.com/" + a.dataset.uid + ".js" - }); - }, - title: { - api: function(uid) { - return "https://api.github.com/gists/" + uid; - }, - text: function(_arg) { - var file, files; - files = _arg.files; - for (file in files) { - if (files.hasOwnProperty(file)) { - return file; - } - } - } - } - }, { - key: 'image', - regExp: /(http|www).*\.(gif|png|jpg|jpeg|bmp)$/, - style: 'border: 0; width: auto; height: auto;', - el: function(a) { - return $.el('div', { - innerHTML: "" - }); - } - }, { - key: 'InstallGentoo', - regExp: /.*(?:paste.installgentoo.com\/view\/)([0-9a-z_]+)/, - el: function(a) { - return $.el('iframe', { - src: "http://paste.installgentoo.com/view/embed/" + a.dataset.uid - }); - } - }, { - key: 'Twitter', - regExp: /.*twitter.com\/(.+\/status\/\d+)/, - el: function(a) { - return $.el('iframe', { - src: "https://twitframe.com/show?url=https://twitter.com/" + a.dataset.uid - }); - } - }, { - key: 'LiveLeak', - regExp: /.*(?:liveleak.com\/view.+i=)([0-9a-z_]+)/, - el: function(a) { - var el; - el = $.el('iframe', { - width: "640", - height: "360", - src: "http://www.liveleak.com/ll_embed?i=" + a.dataset.uid, - frameborder: "0" - }); - el.setAttribute("allowfullscreen", "true"); - return el; - } - }, { - key: 'MediaCrush', - regExp: /.*(?:mediacru.sh\/)([0-9a-z_]+)/i, - style: 'border: 0;', - el: function(a) { - var el; - el = $.el('div'); - $.cache("https://mediacru.sh/" + a.dataset.uid + ".json", function() { - var embed, file, files, status, type, _i, _j, _len, _len1, _ref; - status = this.status; - if (status !== 200 && status !== 304) { - return div.innerHTML = "ERROR " + status; - } - files = this.response.files; - _ref = ['video/mp4', 'video/ogv', 'image/svg+xml', 'image/png', 'image/gif', 'image/jpeg', 'image/svg', 'audio/mpeg']; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - type = _ref[_i]; - for (_j = 0, _len1 = files.length; _j < _len1; _j++) { - file = files[_j]; - if (file.type === type) { - embed = file; - break; - } - } - if (embed) { - break; - } - } - if (!embed) { - return div.innerHTML = "ERROR: Not a valid filetype"; - } - return el.innerHTML = (function() { - switch (embed.type) { - case 'video/mp4': - case 'video/ogv': - return ""; - case 'image/png': - case 'image/gif': - case 'image/jpeg': - return ""; - case 'image/svg': - case 'image/svg+xml': - return ""; - case 'audio/mpeg': - return ""; - default: - return "ERROR: No valid filetype."; - } - })(); - }); - return el; - } - }, { - key: 'pastebin', - regExp: /.*(?:pastebin.com\/(?!u\/))([^#\&\?]*).*/, - el: function(a) { - var div; - return div = $.el('iframe', { - src: "http://pastebin.com/embed_iframe.php?i=" + a.dataset.uid - }); - } - }, { - key: 'gfycat', - regExp: /.*gfycat.com\/(?:iframe\/)?(\S*)/, - el: function(a) { - var div; - return div = $.el('iframe', { - src: "http://gfycat.com/iframe/" + a.dataset.uid - }); - } - }, { - key: 'SoundCloud', - regExp: /.*(?:soundcloud.com\/|snd.sc\/)([^#\&\?]*).*/, - style: 'height: auto; width: 500px; display: inline-block;', - el: function(a) { - var div; - div = $.el('div', { - className: "soundcloud", - name: "soundcloud" - }); - $.ajax("//soundcloud.com/oembed?show_artwork=false&&maxwidth=500px&show_comments=false&format=json&url=https://www.soundcloud.com/" + a.dataset.uid, { - onloadend: function() { - return div.innerHTML = JSON.parse(this.responseText).html; - } - }, false); - return div; - }, - title: { - api: function(uid) { - return "//soundcloud.com/oembed?show_artwork=false&&maxwidth=500px&show_comments=false&format=json&url=https://www.soundcloud.com/" + uid; - }, - text: function(_) { - return _.title; - } - } - }, { - key: 'StrawPoll', - regExp: /strawpoll\.me\/(?:embed_\d+\/)?(\d+)/, - style: 'border: 0; width: 600px; height: 406px;', - el: function(a) { - return $.el('iframe', { - src: "http://strawpoll.me/embed_1/" + a.dataset.uid - }); - } - }, { - key: 'TwitchTV', - regExp: /.*(?:twitch.tv\/)([^#\&\?]*).*/, - style: "border: none; width: 640px; height: 360px;", - el: function(a) { - var channel, chapter, result, _; - if (result = /(\w+)\/(?:[a-z]\/)?(\d+)/i.exec(a.dataset.uid)) { - _ = result[0], channel = result[1], chapter = result[2]; - return $.el('object', { - data: 'http://www.twitch.tv/widgets/archive_embed_player.swf', - innerHTML: "\n" - }); - } else { - channel = (/(\w+)/.exec(a.dataset.uid))[0]; - return $.el('object', { - data: "http://www.twitch.tv/widgets/live_embed_player.swf?channel=" + channel, - innerHTML: "\n\n" - }); - } - } - }, { - key: 'Vocaroo', - regExp: /.*(?:vocaroo.com\/)([^#\&\?]*).*/, - style: 'border: 0; width: 150px; height: 45px;', - el: function(a) { - return $.el('object', { - innerHTML: "" - }); - } - }, { - key: 'Vimeo', - regExp: /.*(?:vimeo.com\/)([^#\&\?]*).*/, - el: function(a) { - return $.el('iframe', { - src: "//player.vimeo.com/video/" + a.dataset.uid + "?wmode=opaque" - }); - }, - title: { - api: function(uid) { - return "https://vimeo.com/api/oembed.json?url=http://vimeo.com/" + uid; - }, - text: function(_) { - return _.title; - } - } - }, { - key: 'Vine', - regExp: /.*(?:vine.co\/)([^#\&\?]*).*/, - style: 'border: none; width: 500px; height: 500px;', - el: function(a) { - return $.el('iframe', { - src: "https://vine.co/" + a.dataset.uid + "/card" - }); - } - }, { - key: 'YouTube', - regExp: /.*(?:youtu.be\/|youtube.*v=|youtube.*\/embed\/|youtube.*\/v\/|youtube.*videos\/)([^#\&\?]*)\??(t\=.*)?/, - el: function(a) { - var el; - el = $.el('iframe', { - src: "//www.youtube.com/embed/" + a.dataset.uid + (a.dataset.option ? '#' + a.dataset.option : '') + "?wmode=opaque" - }); - el.setAttribute("allowfullscreen", "true"); - return el; - }, - title: { - api: function(uid) { - return "https://gdata.youtube.com/feeds/api/videos/" + uid + "?alt=json&fields=title/text(),yt:noembed,app:control/yt:state/@reasonCode"; - }, - text: function(data) { - return data.entry.title.$t; - } - } - }, { - key: 'Loopvid', - regExp: /.*loopvid.appspot.com\/.*/, - dummy: true - }, { - key: 'MediaFire', - regExp: /.*mediafire.com\/.*/, - dummy: true - }, { - key: 'video', - regExp: /(.*\.(ogv|webm|mp4))$/, - el: function(a) { - return $.el('video', { - controls: 'controls', - preload: 'auto', - src: a.dataset.uid - }); - } - } - ] - }; - ArchiveLink = { init: function() { var div, entry, type, _i, _len, _ref; diff --git a/builds/crx/script.js b/builds/crx/script.js index 5c559af45..24a3a3798 100644 --- a/builds/crx/script.js +++ b/builds/crx/script.js @@ -1,6 +1,6 @@ // Generated by CoffeeScript /* -* 4chan X - Version 1.4.1 - 2014-03-31 +* 4chan X - Version 1.4.1 - 2014-04-02 * * Licensed under the MIT license. * https://github.com/Spittie/4chan-x/blob/master/LICENSE @@ -6344,6 +6344,10 @@ onload: QR.response, onerror: function(err, url, line) { delete QR.req; + if (QR.captcha.isEnabled) { + QR.captcha.destroy(); + QR.captcha.setup(); + } post.unlock(); QR.cooldown.auto = false; QR.status(); @@ -6376,9 +6380,12 @@ return QR.status(); }, response: function() { - var URL, ban, board, captchasCount, err, h1, isReply, m, notif, post, postID, postsCount, req, resDoc, threadID, _, _ref, _ref1; + var URL, ban, board, err, h1, isReply, m, post, postID, postsCount, req, resDoc, threadID, _, _ref, _ref1; req = QR.req; delete QR.req; + if (QR.captcha.isEnabled) { + QR.captcha.destroy(); + } post = QR.posts[0]; post.unlock(); resDoc = req.response; @@ -6403,12 +6410,12 @@ } else if (/expired/i.test(err.textContent)) { err = 'This CAPTCHA is no longer valid because it has expired.'; } - QR.cooldown.auto = QR.captcha.isEnabled ? !!QR.captcha.captchas.length : err === 'Connection error with sys.4chan.org.' ? true : false; + QR.cooldown.auto = false; QR.cooldown.set({ delay: 2 }); } else if (err.textContent && (m = err.textContent.match(/wait\s+(\d+)\s+second/i))) { - QR.cooldown.auto = QR.captcha.isEnabled ? !!QR.captcha.captchas.length : true; + QR.cooldown.auto = !QR.captcha.isEnabled; QR.cooldown.set({ delay: m[1] }); @@ -6447,22 +6454,6 @@ }); postsCount = QR.posts.length - 1; QR.cooldown.auto = postsCount && isReply; - if (QR.cooldown.auto && QR.captcha.isEnabled && (captchasCount = QR.captcha.captchas.length) < 3 && captchasCount < postsCount) { - notif = new Notification('Quick reply warning', { - body: "You are running low on cached captchas. Cache count: " + captchasCount + ".", - icon: Favicon.logo - }); - notif.onclick = function() { - QR.open(); - QR.captcha.nodes.input.focus(); - return window.focus(); - }; - notif.onshow = function() { - return setTimeout(function() { - return notif.close(); - }, 7 * $.SECOND); - }; - } if (!(Conf['Persistent QR'] || QR.cooldown.auto)) { QR.close(); } else { @@ -6498,12 +6489,11 @@ QR.captcha = { init: function() { - var container, imgContainer, input; + var imgContainer, input; if (d.cookie.indexOf('pass_enabled=1') >= 0) { return; } - container = $.id('captchaContainer'); - if (!(this.isEnabled = !!container)) { + if (!(this.isEnabled = !!$.id('captchaContainer'))) { return; } if (Conf['Auto-load captcha']) { @@ -6512,13 +6502,11 @@ imgContainer = $.el('div', { className: 'captcha-img', title: 'Reload reCAPTCHA', - innerHTML: '', - hidden: true + innerHTML: '' }); input = $.el('input', { className: 'captcha-input field', title: 'Verification', - placeholder: 'Focus to load reCAPTCHA', autocomplete: 'off', spellcheck: false, tabIndex: 45 @@ -6527,44 +6515,41 @@ img: imgContainer.firstChild, input: input }; - $.on(input, 'focus', this.setup); $.on(input, 'blur', QR.focusout); $.on(input, 'focus', QR.focusin); $.addClass(QR.nodes.el, 'has-captcha'); $.after(QR.nodes.com.parentNode, [imgContainer, input]); + this.beforeSetup(); + return this.afterSetup(); + }, + beforeSetup: function() { + var img, input, _ref; + _ref = this.nodes, img = _ref.img, input = _ref.input; + img.parentNode.hidden = true; + input.value = ''; + input.placeholder = 'Focus to load reCAPTCHA'; + $.on(input, 'focus', this.setup); this.setupObserver = new MutationObserver(this.afterSetup); - this.setupObserver.observe(container, { + return this.setupObserver.observe($.id('captchaContainer'), { childList: true }); - return this.afterSetup(); }, setup: function() { return $.globalEval('loadRecaptcha()'); }, afterSetup: function() { - var challenge, img, input, setLifetime, _ref; + var challenge, img, input, _ref; if (!(challenge = $.id('recaptcha_challenge_field_holder'))) { return; } QR.captcha.setupObserver.disconnect(); delete QR.captcha.setupObserver; - setLifetime = function(e) { - return QR.captcha.lifetime = e.detail; - }; - $.on(window, 'captcha:timeout', setLifetime); - $.globalEval('window.dispatchEvent(new CustomEvent("captcha:timeout", {detail: RecaptchaState.timeout}))'); - $.off(window, 'captcha:timeout', setLifetime); _ref = QR.captcha.nodes, img = _ref.img, input = _ref.input; img.parentNode.hidden = false; + input.placeholder = 'Verification'; $.off(input, 'focus', QR.captcha.setup); $.on(input, 'keydown', QR.captcha.keydown.bind(QR.captcha)); $.on(img.parentNode, 'click', QR.captcha.reload.bind(QR.captcha)); - $.get('captchas', [], function(_arg) { - var captchas; - captchas = _arg.captchas; - return QR.captcha.sync(captchas); - }); - $.sync('captchas', QR.captcha.sync); QR.captcha.nodes.challenge = challenge; new MutationObserver(QR.captcha.load.bind(QR.captcha)).observe(challenge, { childList: true, @@ -6573,94 +6558,31 @@ }); return QR.captcha.load(); }, - sync: function(captchas) { - QR.captcha.captchas = captchas; - return QR.captcha.count(); + destroy: function() { + $.globalEval('Recaptcha.destroy()'); + return this.beforeSetup(); }, getOne: function() { - var captcha, challenge, response; - this.clear(); - if (captcha = this.captchas.shift()) { - challenge = captcha.challenge, response = captcha.response; - this.count(); - $.set('captchas', this.captchas); - } else { - challenge = this.nodes.img.alt; - if (response = this.nodes.input.value) { - this.reload(); - } - } - if (response) { - response = response.trim(); - if (!/\s/.test(response)) { - response = "" + response + " " + response; - } + var challenge, response; + challenge = this.nodes.img.alt; + response = this.nodes.input.value.trim(); + if (response && !/\s/.test(response)) { + response = "" + response + " " + response; } return { challenge: challenge, response: response }; }, - save: function() { - var response; - if (!(response = this.nodes.input.value.trim())) { - return; - } - this.captchas.push({ - challenge: this.nodes.img.alt, - response: response, - timeout: this.timeout - }); - this.count(); - this.reload(); - return $.set('captchas', this.captchas); - }, - clear: function() { - var captcha, i, now, _i, _len, _ref; - if (!this.captchas.length) { - return; - } - now = Date.now(); - _ref = this.captchas; - for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { - captcha = _ref[i]; - if (captcha.timeout > now) { - break; - } - } - if (!i) { - return; - } - this.captchas = this.captchas.slice(i); - this.count(); - return $.set('captchas', this.captchas); - }, load: function() { var challenge; if (!this.nodes.challenge.firstChild) { return; } - this.timeout = Date.now() + this.lifetime * $.SECOND - $.MINUTE; challenge = this.nodes.challenge.firstChild.value; this.nodes.img.alt = challenge; this.nodes.img.src = "//www.google.com/recaptcha/api/image?c=" + challenge; - this.nodes.input.value = null; - return this.clear(); - }, - count: function() { - var count; - count = this.captchas ? this.captchas.length : 0; - this.nodes.input.placeholder = (function() { - switch (count) { - case 0: - return 'Verification (Shift + Enter to cache)'; - case 1: - return 'Verification (1 cached captcha)'; - default: - return "Verification (" + count + " cached captchas)"; - } - })(); - return this.nodes.input.alt = count; + return this.nodes.input.value = null; }, reload: function(focus) { $.globalEval('Recaptcha.reload("t")'); @@ -6671,8 +6593,6 @@ keydown: function(e) { if (e.keyCode === 8 && !this.nodes.input.value) { this.reload(); - } else if (e.keyCode === 13 && e.shiftKey) { - this.save(); } else { return; } @@ -7002,6 +6922,9 @@ node.disabled = lock; } } + if (QR.captcha.isEnabled) { + QR.captcha.nodes.input.disabled = lock; + } this.nodes.rm.style.visibility = lock ? 'hidden' : ''; (lock ? $.off : $.on)(QR.nodes.filename.previousElementSibling, 'click', QR.openFileInput); this.nodes.spoiler.disabled = lock; @@ -8644,561 +8567,6 @@ ] }; - Linkify = { - init: function() { - var type, _i, _len, _ref; - if (g.VIEW === 'catalog' || !Conf['Linkify']) { - return; - } - this.regString = /((https?|mailto|git|magnet|ftp|irc):([a-z\d%\/])|[-a-z\d]+[.](aero|asia|biz|cat|com|coop|info|int|jobs|mobi|museum|name|net|org|post|pro|tel|travel|xxx|edu|gov|mil|[a-z]{2})(\/|(?!.))|[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}|[-\w\d.@]+@[a-z\d.-]+\.[a-z\d])/i; - this.types = {}; - _ref = this.ordered_types; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - type = _ref[_i]; - this.types[type.key] = type; - } - if (Conf['Comment Expansion']) { - ExpandComment.callbacks.push(this.node); - } - if (Conf['Title Link']) { - $.sync('CachedTitles', Linkify.titleSync); - } - return Post.callbacks.push({ - name: 'Linkify', - cb: this.node - }); - }, - node: function() { - var data, el, end, endNode, i, index, items, length, link, links, node, result, saved, snapshot, space, test, word, _i, _len, _ref; - if (this.isClone) { - if (Conf['Embedding']) { - i = 0; - items = $$('.embed', this.nodes.comment); - while (el = items[i++]) { - $.on(el, 'click', Linkify.cb.toggle); - if ($.hasClass(el, 'embedded')) { - Linkify.cb.toggle.call(el); - } - } - } - return; - } - test = /[^\s'"]+/g; - space = /[\s'"]/; - snapshot = $.X('.//br|.//text()', this.nodes.comment); - i = 0; - links = []; - while (node = snapshot.snapshotItem(i++)) { - data = node.data; - if (node.parentElement.nodeName === "A" || !data) { - continue; - } - while (result = test.exec(data)) { - index = result.index; - endNode = node; - word = result[0]; - if ((length = index + word.length) === data.length) { - test.lastIndex = 0; - while ((saved = snapshot.snapshotItem(i++))) { - if (saved.nodeName === 'BR') { - break; - } - endNode = saved; - data = saved.data; - word += data; - length = data.length; - if (end = space.exec(data)) { - test.lastIndex = length = end.index; - i--; - break; - } - } - } - if (Linkify.regString.exec(word)) { - links.push(Linkify.makeRange(node, endNode, index, length)); - } - if (!(test.lastIndex && node === endNode)) { - break; - } - } - } - _ref = links.reverse(); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - link = _ref[_i]; - this.nodes.links.push(Linkify.makeLink(link, this)); - link.detach(); - } - if (!(Conf['Embedding'] || Conf['Link Title'])) { - return; - } - links = this.nodes.links; - i = 0; - while (link = links[i++]) { - if (data = Linkify.services(link)) { - if (Conf['Embedding']) { - Linkify.embed(data); - } - if (Conf['Link Title']) { - Linkify.title(data); - } - } - } - }, - makeRange: function(startNode, endNode, startOffset, endOffset) { - var range; - range = document.createRange(); - range.setStart(startNode, startOffset); - range.setEnd(endNode, endOffset); - return range; - }, - makeLink: function(range) { - var a, char, i, text; - text = range.toString(); - i = 0; - while (/[(\[{<>]/.test(text.charAt(i))) { - i++; - } - if (i) { - text = text.slice(i); - while (range.startOffset + i >= range.startContainer.data.length) { - i--; - } - if (i) { - range.setStart(range.startContainer, range.startOffset + i); - } - } - i = 0; - while (/[)\]}>.,]/.test(char = text.charAt(text.length - (1 + i)))) { - if (!(/[.,]/.test(char) || (text.match(/[()\[\]{}<>]/g)).length % 2)) { - break; - } - i++; - } - if (i) { - text = text.slice(0, -i); - while (range.endOffset - i < 0) { - i--; - } - if (i) { - range.setEnd(range.endContainer, range.endOffset - i); - } - } - if (!/(https?|mailto|git|magnet|ftp|irc):/.test(text)) { - text = (/@/.test(text) ? 'mailto:' : 'http://') + text; - } - a = $.el('a', { - className: 'linkify', - rel: 'nofollow noreferrer', - target: '_blank', - href: text - }); - $.add(a, range.extractContents()); - range.insertNode(a); - return a; - }, - services: function(link) { - var href, match, type, _i, _len, _ref; - href = link.href; - _ref = Linkify.ordered_types; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - type = _ref[_i]; - if (!(match = type.regExp.exec(href))) { - continue; - } - if (type.dummy) { - return; - } - return [type.key, match[1], match[2], link]; - } - }, - embed: function(data) { - var embed, href, key, link, name, options, uid, value, _ref; - key = data[0], uid = data[1], options = data[2], link = data[3]; - href = link.href; - embed = $.el('a', { - className: 'embedder', - href: 'javascript:;', - textContent: '(embed)' - }); - _ref = { - key: key, - href: href, - uid: uid, - options: options - }; - for (name in _ref) { - value = _ref[name]; - embed.dataset[name] = value; - } - embed.dataset.nodedata = link.innerHTML; - $.addClass(link, "" + embed.dataset.key); - $.on(embed, 'click', Linkify.cb.toggle); - $.after(link, [$.tn(' '), embed]); - if (Conf['Auto-embed']) { - Linkify.cb.toggle.call(embed); - } - data.push(embed); - }, - title: function(data) { - var embed, err, key, link, options, service, title, titles, uid; - key = data[0], uid = data[1], options = data[2], link = data[3], embed = data[4]; - if (!(service = Linkify.types[key].title)) { - return; - } - titles = Conf['CachedTitles']; - if (title = titles[uid]) { - if (link) { - link.textContent = title[0]; - } - if (Conf['Embedding']) { - return embed.dataset.title = title[0]; - } - } else { - try { - $.cache(service.api(uid), function() { - return title = Linkify.cb.title(this, data); - }, { - responseType: 'json' - }); - } catch (_error) { - err = _error; - if (link) { - link.innerHTML = "[" + key + "] Title Link Blocked (are you using NoScript?)"; - } - return; - } - if (title) { - titles[uid] = [title, Date.now()]; - return $.set('CachedTitles', titles); - } - } - }, - titleSync: function(value) { - return Conf['CachedTitles'] = value; - }, - cb: { - toggle: function() { - var string, _ref; - _ref = $.hasClass(this, "embedded") ? ['unembed', '(embed)'] : ['embed', '(unembed)'], string = _ref[0], this.textContent = _ref[1]; - $.replace(this.previousElementSibling, Linkify.cb[string](this)); - return $.toggleClass(this, 'embedded'); - }, - embed: function(a) { - var el, style, type; - el = (type = Linkify.types[a.dataset.key]).el(a); - el.style.cssText = (style = type.style) ? style : "border: 0; width: 640px; height: 390px"; - return el; - }, - unembed: function(a) { - var el; - el = $.el('a', { - rel: 'nofollow noreferrer', - target: 'blank', - className: 'linkify', - href: a.dataset.href, - innerHTML: a.dataset.title || a.dataset.nodedata - }); - $.addClass(el, a.dataset.key); - return el; - }, - title: function(response, data) { - var embed, key, link, options, service, text, uid; - key = data[0], uid = data[1], options = data[2], link = data[3], embed = data[4]; - service = Linkify.types[key].title; - switch (response.status) { - case 200: - case 304: - text = "" + (service.text(response.response)); - if (Conf['Embedding']) { - embed.dataset.title = text; - } - break; - case 404: - text = "[" + key + "] Not Found"; - break; - case 403: - text = "[" + key + "] Forbidden or Private"; - break; - default: - text = "[" + key + "] " + this.status + "'d"; - } - if (link) { - return link.textContent = text; - } - } - }, - ordered_types: [ - { - key: 'audio', - regExp: /(.*\.(mp3|ogg|wav))$/, - el: function(a) { - return $.el('audio', { - controls: 'controls', - preload: 'auto', - src: a.dataset.uid - }); - } - }, { - key: 'gist', - regExp: /.*(?:gist.github.com.*\/)([^\/][^\/]*)$/, - el: function(a) { - var div; - return div = $.el('iframe', { - src: "http://www.purplegene.com/script?url=https://gist.github.com/" + a.dataset.uid + ".js" - }); - }, - title: { - api: function(uid) { - return "https://api.github.com/gists/" + uid; - }, - text: function(_arg) { - var file, files; - files = _arg.files; - for (file in files) { - if (files.hasOwnProperty(file)) { - return file; - } - } - } - } - }, { - key: 'image', - regExp: /(http|www).*\.(gif|png|jpg|jpeg|bmp)$/, - style: 'border: 0; width: auto; height: auto;', - el: function(a) { - return $.el('div', { - innerHTML: "" - }); - } - }, { - key: 'InstallGentoo', - regExp: /.*(?:paste.installgentoo.com\/view\/)([0-9a-z_]+)/, - el: function(a) { - return $.el('iframe', { - src: "http://paste.installgentoo.com/view/embed/" + a.dataset.uid - }); - } - }, { - key: 'Twitter', - regExp: /.*twitter.com\/(.+\/status\/\d+)/, - el: function(a) { - return $.el('iframe', { - src: "https://twitframe.com/show?url=https://twitter.com/" + a.dataset.uid - }); - } - }, { - key: 'LiveLeak', - regExp: /.*(?:liveleak.com\/view.+i=)([0-9a-z_]+)/, - el: function(a) { - var el; - el = $.el('iframe', { - width: "640", - height: "360", - src: "http://www.liveleak.com/ll_embed?i=" + a.dataset.uid, - frameborder: "0" - }); - el.setAttribute("allowfullscreen", "true"); - return el; - } - }, { - key: 'MediaCrush', - regExp: /.*(?:mediacru.sh\/)([0-9a-z_]+)/i, - style: 'border: 0;', - el: function(a) { - var el; - el = $.el('div'); - $.cache("https://mediacru.sh/" + a.dataset.uid + ".json", function() { - var embed, file, files, status, type, _i, _j, _len, _len1, _ref; - status = this.status; - if (status !== 200 && status !== 304) { - return div.innerHTML = "ERROR " + status; - } - files = this.response.files; - _ref = ['video/mp4', 'video/ogv', 'image/svg+xml', 'image/png', 'image/gif', 'image/jpeg', 'image/svg', 'audio/mpeg']; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - type = _ref[_i]; - for (_j = 0, _len1 = files.length; _j < _len1; _j++) { - file = files[_j]; - if (file.type === type) { - embed = file; - break; - } - } - if (embed) { - break; - } - } - if (!embed) { - return div.innerHTML = "ERROR: Not a valid filetype"; - } - return el.innerHTML = (function() { - switch (embed.type) { - case 'video/mp4': - case 'video/ogv': - return ""; - case 'image/png': - case 'image/gif': - case 'image/jpeg': - return ""; - case 'image/svg': - case 'image/svg+xml': - return ""; - case 'audio/mpeg': - return ""; - default: - return "ERROR: No valid filetype."; - } - })(); - }); - return el; - } - }, { - key: 'pastebin', - regExp: /.*(?:pastebin.com\/(?!u\/))([^#\&\?]*).*/, - el: function(a) { - var div; - return div = $.el('iframe', { - src: "http://pastebin.com/embed_iframe.php?i=" + a.dataset.uid - }); - } - }, { - key: 'gfycat', - regExp: /.*gfycat.com\/(?:iframe\/)?(\S*)/, - el: function(a) { - var div; - return div = $.el('iframe', { - src: "http://gfycat.com/iframe/" + a.dataset.uid - }); - } - }, { - key: 'SoundCloud', - regExp: /.*(?:soundcloud.com\/|snd.sc\/)([^#\&\?]*).*/, - style: 'height: auto; width: 500px; display: inline-block;', - el: function(a) { - var div; - div = $.el('div', { - className: "soundcloud", - name: "soundcloud" - }); - $.ajax("//soundcloud.com/oembed?show_artwork=false&&maxwidth=500px&show_comments=false&format=json&url=https://www.soundcloud.com/" + a.dataset.uid, { - onloadend: function() { - return div.innerHTML = JSON.parse(this.responseText).html; - } - }, false); - return div; - }, - title: { - api: function(uid) { - return "//soundcloud.com/oembed?show_artwork=false&&maxwidth=500px&show_comments=false&format=json&url=https://www.soundcloud.com/" + uid; - }, - text: function(_) { - return _.title; - } - } - }, { - key: 'StrawPoll', - regExp: /strawpoll\.me\/(?:embed_\d+\/)?(\d+)/, - style: 'border: 0; width: 600px; height: 406px;', - el: function(a) { - return $.el('iframe', { - src: "http://strawpoll.me/embed_1/" + a.dataset.uid - }); - } - }, { - key: 'TwitchTV', - regExp: /.*(?:twitch.tv\/)([^#\&\?]*).*/, - style: "border: none; width: 640px; height: 360px;", - el: function(a) { - var channel, chapter, result, _; - if (result = /(\w+)\/(?:[a-z]\/)?(\d+)/i.exec(a.dataset.uid)) { - _ = result[0], channel = result[1], chapter = result[2]; - return $.el('object', { - data: 'http://www.twitch.tv/widgets/archive_embed_player.swf', - innerHTML: "\n" - }); - } else { - channel = (/(\w+)/.exec(a.dataset.uid))[0]; - return $.el('object', { - data: "http://www.twitch.tv/widgets/live_embed_player.swf?channel=" + channel, - innerHTML: "\n\n" - }); - } - } - }, { - key: 'Vocaroo', - regExp: /.*(?:vocaroo.com\/)([^#\&\?]*).*/, - style: 'border: 0; width: 150px; height: 45px;', - el: function(a) { - return $.el('object', { - innerHTML: "" - }); - } - }, { - key: 'Vimeo', - regExp: /.*(?:vimeo.com\/)([^#\&\?]*).*/, - el: function(a) { - return $.el('iframe', { - src: "//player.vimeo.com/video/" + a.dataset.uid + "?wmode=opaque" - }); - }, - title: { - api: function(uid) { - return "https://vimeo.com/api/oembed.json?url=http://vimeo.com/" + uid; - }, - text: function(_) { - return _.title; - } - } - }, { - key: 'Vine', - regExp: /.*(?:vine.co\/)([^#\&\?]*).*/, - style: 'border: none; width: 500px; height: 500px;', - el: function(a) { - return $.el('iframe', { - src: "https://vine.co/" + a.dataset.uid + "/card" - }); - } - }, { - key: 'YouTube', - regExp: /.*(?:youtu.be\/|youtube.*v=|youtube.*\/embed\/|youtube.*\/v\/|youtube.*videos\/)([^#\&\?]*)\??(t\=.*)?/, - el: function(a) { - var el; - el = $.el('iframe', { - src: "//www.youtube.com/embed/" + a.dataset.uid + (a.dataset.option ? '#' + a.dataset.option : '') + "?wmode=opaque" - }); - el.setAttribute("allowfullscreen", "true"); - return el; - }, - title: { - api: function(uid) { - return "https://gdata.youtube.com/feeds/api/videos/" + uid + "?alt=json&fields=title/text(),yt:noembed,app:control/yt:state/@reasonCode"; - }, - text: function(data) { - return data.entry.title.$t; - } - } - }, { - key: 'Loopvid', - regExp: /.*loopvid.appspot.com\/.*/, - dummy: true - }, { - key: 'MediaFire', - regExp: /.*mediafire.com\/.*/, - dummy: true - }, { - key: 'video', - regExp: /(.*\.(ogv|webm|mp4))$/, - el: function(a) { - return $.el('video', { - controls: 'controls', - preload: 'auto', - src: a.dataset.uid - }); - } - } - ] - }; - ArchiveLink = { init: function() { var div, entry, type, _i, _len, _ref;