From 566b4683272647abeb642bc3d4d5818cdffdafca Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Tue, 12 Feb 2013 03:29:16 +0100 Subject: [PATCH] Some QR fixes. Use notifications for QR errors and successes! Close #562. Add an entry to open the QR in the Header's menu. --- 4chan_x.user.js | 83 ++++++++++++++++++++++++++------------------- lib/$.coffee | 4 +-- src/features.coffee | 62 ++++++++++++++++++--------------- 3 files changed, 86 insertions(+), 63 deletions(-) diff --git a/4chan_x.user.js b/4chan_x.user.js index d014af2bf..594fb6377 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -778,8 +778,12 @@ el.removeEventListener(event, handler, false); } }, - event: function(event, detail) { - return d.dispatchEvent(new CustomEvent(event, { + event: function(event, detail, root) { + if (root == null) { + root = d; + } + return root.dispatchEvent(new CustomEvent(event, { + bubbles: true, detail: detail })); }, @@ -1005,7 +1009,9 @@ }; Notification.prototype.close = function() { - return $.rm(this.el); + if (this.el.parentNode) { + return $.rm(this.el); + } }; return Notification; @@ -1818,12 +1824,22 @@ QR = { init: function() { + var link; if (!Conf['Quick Reply']) { return; } if (Conf['Hide Original Post Form']) { Main.css += "#postForm, .postingMode {\n display: none;\n}"; } + link = $.el('a', { + textContent: 'Open the QR', + href: 'javascript:;' + }); + $.on(link, 'click', QR.open); + $.event('AddMenuEntry', { + type: 'header', + el: link + }); Post.prototype.callbacks.push({ name: 'Quick Reply', cb: this.node @@ -1885,23 +1901,27 @@ }, error: function(err) { var el; - el = $('.warning', QR.el); - if (typeof err === 'string') { - el.textContent = err; - } else { - el.innerHTML = null; - $.add(el, err); - } QR.open(); + if (typeof err === 'string') { + el = $.tn(err); + } else { + el = err; + el.removeAttribute('style'); + } if (QR.captcha.isEnabled && /captcha|verification/i.test(el.textContent)) { $('[autocomplete]', QR.el).focus(); } if (d.hidden) { - return alert(el.textContent); + alert(el.textContent); } + return QR.lastNotification = new Notification('warning', el); }, cleanError: function() { - return $('.warning', QR.el).textContent = null; + var _ref; + if ((_ref = QR.lastNotification) != null) { + _ref.close(); + } + return delete QR.lastNotification; }, status: function(data) { var disabled, input, value; @@ -2064,7 +2084,7 @@ range = caretPos + text.length; ta.setSelectionRange(range, range); ta.focus(); - return $.event(ta, new Event('input')); + return ta.dispatchEvent(new Event('input')); }, characterCount: function() { var count, counter; @@ -2439,7 +2459,6 @@
\
\ \ -
\ '); if (Conf['Remember QR size'] && $.engine === 'gecko') { $.on(ta = $('textarea', QR.el), 'mouseup', function() { @@ -2510,7 +2529,6 @@ $.on(spoiler.firstChild, 'change', function() { return $('input', QR.selected.el).click(); }); - $.on($('.warning', QR.el), 'click', QR.cleanError); new QR.reply().select(); _ref1 = ['name', 'email', 'sub', 'com']; for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { @@ -2528,9 +2546,7 @@ QR.cooldown.init(); QR.captcha.init(); $.add(d.body, QR.el); - return $.event(QR.el, new CustomEvent('QRDialogCreation', { - bubbles: true - })); + return $.event(new CustomEvent('QRDialogCreation', null, QR.el)); }, submit: function(e) { var callbacks, captcha, captchas, challenge, err, filetag, m, opts, post, reply, response, textOnly, threadID, _ref; @@ -2651,19 +2667,19 @@ return QR.ajax = $.ajax($.id('postForm').parentNode.action, callbacks, opts); }, response: function(html) { - var ban, board, err, persona, postID, reply, threadID, _, _ref, _ref1; - doc = d.implementation.createHTMLDocument(''); - doc.documentElement.innerHTML = html; - if (ban = $('.banType', doc)) { - board = $('.board', doc).innerHTML; + var ban, board, err, h1, persona, postID, reply, threadID, tmpDoc, _, _ref, _ref1; + tmpDoc = d.implementation.createHTMLDocument(''); + tmpDoc.documentElement.innerHTML = html; + if (ban = $('.banType', tmpDoc)) { + board = $('.board', tmpDoc).innerHTML; err = $.el('span', { - innerHTML: ban.textContent.toLowerCase() === 'banned' ? ("You are banned on " + board + "! ;_;
") + "Click here to see the reason." : ("You were issued a warning on " + board + " as " + ($('.nameBlock', doc).innerHTML) + ".
") + ("Reason: " + ($('.reason', doc).innerHTML)) + innerHTML: ban.textContent.toLowerCase() === 'banned' ? ("You are banned on " + board + "! ;_;
") + "Click here to see the reason." : ("You were issued a warning on " + board + " as " + ($('.nameBlock', tmpDoc).innerHTML) + ".
") + ("Reason: " + ($('.reason', tmpDoc).innerHTML)) }); - } else if (err = doc.getElementById('errmsg')) { + } else if (err = tmpDoc.getElementById('errmsg')) { if ((_ref = $('a', err)) != null) { _ref.target = '_blank'; } - } else if (doc.title !== 'Post successful!') { + } else if (tmpDoc.title !== 'Post successful!') { err = 'Connection error with sys.4chan.org.'; } if (err) { @@ -2682,6 +2698,8 @@ QR.error(err); return; } + h1 = $('h1', tmpDoc); + QR.lastNotification = new Notification('success', h1.textContent, 5); reply = QR.replies[0]; persona = $.get('QR.persona', {}); persona = { @@ -2690,14 +2708,11 @@ sub: Conf['Remember Subject'] ? reply.sub : null }; $.set('QR.persona', persona); - _ref1 = doc.body.lastChild.textContent.match(/thread:(\d+),no:(\d+)/), _ = _ref1[0], threadID = _ref1[1], postID = _ref1[2]; - $.event(QR.el, new CustomEvent('QRPostSuccessful', { - bubbles: true, - detail: { - threadID: threadID, - postID: postID - } - })); + _ref1 = h1.nextSibling.textContent.match(/thread:(\d+),no:(\d+)/), _ = _ref1[0], threadID = _ref1[1], postID = _ref1[2]; + $.event(new CustomEvent('QRPostSuccessful', { + threadID: threadID, + postID: postID + }, QR.el)); QR.cooldown.set({ post: reply, isReply: threadID !== '0' diff --git a/lib/$.coffee b/lib/$.coffee index 16c3df932..e2c9cb9bb 100644 --- a/lib/$.coffee +++ b/lib/$.coffee @@ -130,8 +130,8 @@ $.extend $, for event in events.split ' ' el.removeEventListener event, handler, false return - event: (event, detail) -> - d.dispatchEvent new CustomEvent event, {detail} + event: (event, detail, root=d) -> + root.dispatchEvent new CustomEvent event, {bubbles: true, detail} open: (url) -> (GM_openInTab or window.open) url, '_blank' hidden: -> diff --git a/src/features.coffee b/src/features.coffee index b66c2431e..8a915c96b 100644 --- a/src/features.coffee +++ b/src/features.coffee @@ -95,7 +95,7 @@ class Notification @type = type close: -> - $.rm @el + $.rm @el if @el.parentNode Settings = init: -> @@ -771,6 +771,14 @@ QR = } """ + link = $.el 'a', + textContent: 'Open the QR' + href: 'javascript:;' + $.on link, 'click', QR.open + $.event 'AddMenuEntry', + type: 'header' + el: link + Post::callbacks.push name: 'Quick Reply' cb: @node @@ -818,19 +826,20 @@ QR = @checked and QR.hide() or QR.unhide() error: (err) -> - el = $ '.warning', QR.el - if typeof err is 'string' - el.textContent = err - else - el.innerHTML = null - $.add el, err QR.open() + if typeof err is 'string' + el = $.tn err + else + el = err + el.removeAttribute 'style' if QR.captcha.isEnabled and /captcha|verification/i.test el.textContent # Focus the captcha input on captcha error. $('[autocomplete]', QR.el).focus() alert el.textContent if d.hidden + QR.lastNotification = new Notification 'warning', el cleanError: -> - $('.warning', QR.el).textContent = null + QR.lastNotification?.close() + delete QR.lastNotification status: (data={}) -> return unless QR.el @@ -978,7 +987,7 @@ QR = ta.focus() # Fire the 'input' event - $.event ta, new Event 'input' + ta.dispatchEvent new Event 'input' characterCount: -> counter = QR.charaCounter @@ -1262,7 +1271,6 @@ QR =
-
' if Conf['Remember QR size'] and $.engine is 'gecko' @@ -1320,7 +1328,6 @@ QR = $.on fileInput, 'change', QR.fileInput $.on fileInput, 'click', (e) -> if e.shiftKey then QR.selected.rmFile() or e.preventDefault() $.on spoiler.firstChild, 'change', -> $('input', QR.selected.el).click() - $.on $('.warning', QR.el), 'click', QR.cleanError new QR.reply().select() # save selected reply's data @@ -1341,8 +1348,7 @@ QR = # Create a custom event when the QR dialog is first initialized. # Use it to extend the QR's functionalities, or for XTRM RICE. - $.event QR.el, new CustomEvent 'QRDialogCreation', - bubbles: true + $.event new CustomEvent 'QRDialogCreation', null, QR.el submit: (e) -> e?.preventDefault() @@ -1453,20 +1459,20 @@ QR = QR.ajax = $.ajax $.id('postForm').parentNode.action, callbacks, opts response: (html) -> - doc = d.implementation.createHTMLDocument '' - doc.documentElement.innerHTML = html - if ban = $ '.banType', doc # banned/warning - board = $('.board', doc).innerHTML + tmpDoc = d.implementation.createHTMLDocument '' + tmpDoc.documentElement.innerHTML = html + if ban = $ '.banType', tmpDoc # banned/warning + board = $('.board', tmpDoc).innerHTML err = $.el 'span', innerHTML: if ban.textContent.toLowerCase() is 'banned' "You are banned on #{board}! ;_;
" + "Click here to see the reason." else - "You were issued a warning on #{board} as #{$('.nameBlock', doc).innerHTML}.
" + - "Reason: #{$('.reason', doc).innerHTML}" - else if err = doc.getElementById 'errmsg' # error! + "You were issued a warning on #{board} as #{$('.nameBlock', tmpDoc).innerHTML}.
" + + "Reason: #{$('.reason', tmpDoc).innerHTML}" + else if err = tmpDoc.getElementById 'errmsg' # error! $('a', err)?.target = '_blank' # duplicate image link - else if doc.title isnt 'Post successful!' + else if tmpDoc.title isnt 'Post successful!' err = 'Connection error with sys.4chan.org.' if err @@ -1493,6 +1499,9 @@ QR = QR.error err return + h1 = $ 'h1', tmpDoc + QR.lastNotification = new Notification 'success', h1.textContent, 5 + reply = QR.replies[0] persona = $.get 'QR.persona', {} @@ -1502,14 +1511,13 @@ QR = sub: if Conf['Remember Subject'] then reply.sub else null $.set 'QR.persona', persona - [_, threadID, postID] = doc.body.lastChild.textContent.match /thread:(\d+),no:(\d+)/ + [_, threadID, postID] = h1.nextSibling.textContent.match /thread:(\d+),no:(\d+)/ # Post/upload confirmed as successful. - $.event QR.el, new CustomEvent 'QRPostSuccessful', - bubbles: true - detail: - threadID: threadID - postID: postID + $.event new CustomEvent 'QRPostSuccessful', { + threadID + postID + }, QR.el QR.cooldown.set post: reply