Automatically reposition a quote preview or image hover once the content is loaded. Close #237.

This commit is contained in:
Nicolas Stepien 2013-02-14 12:13:24 +01:00
parent cd7926d45b
commit bbb455c0c5
3 changed files with 77 additions and 43 deletions

View File

@ -521,19 +521,33 @@
} }
return localStorage.setItem("" + g.NAMESPACE + this.id + ".position", this.style.cssText); return localStorage.setItem("" + g.NAMESPACE + this.id + ".position", this.style.cssText);
}; };
hoverstart = function(root, el, events, cb) { hoverstart = function(_arg) {
var event, o, _i, _len, _ref; var asap, asapTest, cb, el, event, events, initialEvent, o, root, _i, _len, _ref;
root = _arg.root, el = _arg.el, initialEvent = _arg.initialEvent, events = _arg.events, asapTest = _arg.asapTest, cb = _arg.cb;
o = { o = {
root: root, root: root,
el: el, el: el,
style: el.style, style: el.style,
cb: cb, cb: cb,
events: events.split(' '), events: events.split(' '),
mousemove: function(e) {
return initialEvent = e;
},
clientHeight: doc.clientHeight, clientHeight: doc.clientHeight,
clientWidth: doc.clientWidth clientWidth: doc.clientWidth
}; };
o.hover = hover.bind(o); o.hover = hover.bind(o);
o.hoverend = hoverend.bind(o); o.hoverend = hoverend.bind(o);
root.addEventListener('mousemove', o.mousemove, false);
asap = function() {
if (asapTest()) {
root.removeEventListener('mousemove', o.mousemove, false);
return o.hover(initialEvent);
} else {
return o.timeout = setTimeout(asap, 25);
}
};
asap();
_ref = o.events; _ref = o.events;
for (_i = 0, _len = _ref.length; _i < _len; _i++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
event = _ref[_i]; event = _ref[_i];
@ -568,6 +582,8 @@
this.root.removeEventListener(event, this.hoverend, false); this.root.removeEventListener(event, this.hoverend, false);
} }
this.root.removeEventListener('mousemove', this.hover, false); this.root.removeEventListener('mousemove', this.hover, false);
this.root.removeEventListener('mousemove', this.mousemove, false);
clearTimeout(this.timeout);
if (this.cb) { if (this.cb) {
return this.cb.call(this); return this.cb.call(this);
} }
@ -2923,7 +2939,16 @@
}); });
$.add(d.body, qp); $.add(d.body, qp);
Get.postClone(board, threadID, postID, qp, Get.contextFromLink(this)); Get.postClone(board, threadID, postID, qp, Get.contextFromLink(this));
UI.hover(this, qp, 'mouseout click', QuotePreview.mouseout); UI.hover({
root: this,
el: qp,
initialEvent: e,
events: 'mouseout click',
cb: QuotePreview.mouseout,
asapTest: function() {
return qp.firstElementChild;
}
});
if (!(origin = g.posts["" + board + "." + postID])) { if (!(origin = g.posts["" + board + "." + postID])) {
return; return;
} }
@ -3725,35 +3750,28 @@
} }
return $.on(this.file.thumb, 'mouseover', ImageHover.mouseover); return $.on(this.file.thumb, 'mouseover', ImageHover.mouseover);
}, },
mouseover: function() { mouseover: function(e) {
var el, var el;
_this = this;
el = $.el('img', { el = $.el('img', {
id: 'ihover', id: 'ihover',
src: this.parentNode.href src: this.parentNode.href
}); });
$.add(d.body, el); $.add(d.body, el);
$.on(el, 'load', function() { UI.hover({
return ImageHover.load(_this, el); root: this,
el: el,
initialEvent: e,
events: 'mouseout',
asapTest: function() {
return el.naturalHeight;
}
}); });
$.on(el, 'error', ImageHover.error); return $.on(el, 'error', ImageHover.error);
return UI.hover(this, el, 'mouseout');
},
load: function(root, el) {
var e, style;
if (!el.parentNode) {
return;
}
style = el.style;
e = new Event('mousemove');
e.clientX = -45 + parseInt(style.left);
e.clientY = 120 + parseInt(style.top);
return root.dispatchEvent(e);
}, },
error: function() { error: function() {
var URL, src, timeoutID, var URL, src, timeoutID,
_this = this; _this = this;
if (!this.parentNode) { if (!doc.contains(this)) {
return; return;
} }
src = this.src.split('/'); src = this.src.split('/');
@ -3830,7 +3848,7 @@
input = _ref1[_i]; input = _ref1[_i];
if (input.type === 'checkbox') { if (input.type === 'checkbox') {
$.on(input, 'click', this.cb.checkbox.bind(this)); $.on(input, 'click', this.cb.checkbox.bind(this));
input.dispatchEvent(new Event('click')); $.event('click', null, input);
} }
switch (input.name) { switch (input.name) {
case 'Scroll BG': case 'Scroll BG':
@ -3842,7 +3860,7 @@
break; break;
case 'Interval': case 'Interval':
$.on(input, 'change', this.cb.interval.bind(this)); $.on(input, 'change', this.cb.interval.bind(this));
input.dispatchEvent(new Event('change')); $.event('change', null, input);
break; break;
case 'Update Now': case 'Update Now':
$.on(input, 'click', this.update.bind(this)); $.on(input, 'click', this.update.bind(this));

View File

@ -286,18 +286,30 @@ UI = (->
d.removeEventListener 'mouseup', @up, false d.removeEventListener 'mouseup', @up, false
localStorage.setItem "#{g.NAMESPACE}#{@id}.position", @style.cssText localStorage.setItem "#{g.NAMESPACE}#{@id}.position", @style.cssText
hoverstart = (root, el, events, cb) -> hoverstart = ({root, el, initialEvent, events, asapTest, cb}) ->
o = { o = {
root: root root: root
el: el el: el
style: el.style style: el.style
cb: cb cb: cb
events: events.split ' ' events: events.split ' '
mousemove: (e) -> initialEvent = e
clientHeight: doc.clientHeight clientHeight: doc.clientHeight
clientWidth: doc.clientWidth clientWidth: doc.clientWidth
} }
o.hover = hover.bind o o.hover = hover.bind o
o.hoverend = hoverend.bind o o.hoverend = hoverend.bind o
# Set position once content is loaded.
root.addEventListener 'mousemove', o.mousemove, false
asap = ->
if asapTest()
root.removeEventListener 'mousemove', o.mousemove, false
o.hover initialEvent
else
o.timeout = setTimeout asap, 25
asap()
for event in o.events for event in o.events
root.addEventListener event, o.hoverend, false root.addEventListener event, o.hoverend, false
root.addEventListener 'mousemove', o.hover, false root.addEventListener 'mousemove', o.hover, false
@ -328,8 +340,10 @@ UI = (->
hoverend = -> hoverend = ->
@el.parentNode.removeChild @el @el.parentNode.removeChild @el
for event in @events for event in @events
@root.removeEventListener event, @hoverend, false @root.removeEventListener event, @hoverend, false
@root.removeEventListener 'mousemove', @hover, false @root.removeEventListener 'mousemove', @hover, false
@root.removeEventListener 'mousemove', @mousemove, false
clearTimeout @timeout
@cb.call @ if @cb @cb.call @ if @cb

View File

@ -1765,7 +1765,13 @@ QuotePreview =
$.add d.body, qp $.add d.body, qp
Get.postClone board, threadID, postID, qp, Get.contextFromLink @ Get.postClone board, threadID, postID, qp, Get.contextFromLink @
UI.hover @, qp, 'mouseout click', QuotePreview.mouseout UI.hover
root: @
el: qp
initialEvent: e
events: 'mouseout click'
cb: QuotePreview.mouseout
asapTest: -> qp.firstElementChild
return unless origin = g.posts["#{board}.#{postID}"] return unless origin = g.posts["#{board}.#{postID}"]
@ -2172,7 +2178,7 @@ ImageExpand =
thumb.hidden = true thumb.hidden = true
$.addClass post.nodes.root, 'expanded-image' $.addClass post.nodes.root, 'expanded-image'
if img = $ '.full-image', thumb.parentNode if img = $ '.full-image', thumb.parentNode
# Expand already loaded picture # Expand already loaded picture.
img.hidden = false img.hidden = false
return return
img = $.el 'img', img = $.el 'img',
@ -2299,24 +2305,20 @@ ImageHover =
node: -> node: ->
return unless @file?.isImage return unless @file?.isImage
$.on @file.thumb, 'mouseover', ImageHover.mouseover $.on @file.thumb, 'mouseover', ImageHover.mouseover
mouseover: -> mouseover: (e) ->
el = $.el 'img' el = $.el 'img'
id: 'ihover' id: 'ihover'
src: @parentNode.href src: @parentNode.href
$.add d.body, el $.add d.body, el
$.on el, 'load', => ImageHover.load @, el UI.hover
root: @
el: el
initialEvent: e
events: 'mouseout'
asapTest: -> el.naturalHeight
$.on el, 'error', ImageHover.error $.on el, 'error', ImageHover.error
UI.hover @, el, 'mouseout'
load: (root, el) ->
return unless el.parentNode
# 'Fake' mousemove event by giving required values.
{style} = el
e = new Event 'mousemove'
e.clientX = - 45 + parseInt style.left
e.clientY = 120 + parseInt style.top
root.dispatchEvent e
error: -> error: ->
return unless @parentNode return unless doc.contains @
src = @src.split '/' src = @src.split '/'
unless src[2] is 'images.4chan.org' and URL = Redirect.image src[3], src[5] unless src[2] is 'images.4chan.org' and URL = Redirect.image src[3], src[5]
return if g.DEAD return if g.DEAD
@ -2373,7 +2375,7 @@ ThreadUpdater =
for input in $$ 'input', dialog for input in $$ 'input', dialog
if input.type is 'checkbox' if input.type is 'checkbox'
$.on input, 'click', @cb.checkbox.bind @ $.on input, 'click', @cb.checkbox.bind @
input.dispatchEvent new Event 'click' $.event 'click', null, input
switch input.name switch input.name
when 'Scroll BG' when 'Scroll BG'
$.on input, 'click', @cb.scrollBG.bind @ $.on input, 'click', @cb.scrollBG.bind @
@ -2382,7 +2384,7 @@ ThreadUpdater =
$.on input, 'click', @cb.autoUpdate.bind @ $.on input, 'click', @cb.autoUpdate.bind @
when 'Interval' when 'Interval'
$.on input, 'change', @cb.interval.bind @ $.on input, 'change', @cb.interval.bind @
input.dispatchEvent new Event 'change' $.event 'change', null, input
when 'Update Now' when 'Update Now'
$.on input, 'click', @update.bind @ $.on input, 'click', @update.bind @