##// END OF EJS Templates
Do not close images from refpopups when the popup is removed
neko259 -
r1474:378f92ac default
parent child Browse files
Show More
@@ -1,202 +1,201 b''
1 /*
1 /*
2 @licstart The following is the entire license notice for the
2 @licstart The following is the entire license notice for the
3 JavaScript code in this page.
3 JavaScript code in this page.
4
4
5
5
6 Copyright (C) 2013 neko259
6 Copyright (C) 2013 neko259
7
7
8 The JavaScript code in this page is free software: you can
8 The JavaScript code in this page is free software: you can
9 redistribute it and/or modify it under the terms of the GNU
9 redistribute it and/or modify it under the terms of the GNU
10 General Public License (GNU GPL) as published by the Free Software
10 General Public License (GNU GPL) as published by the Free Software
11 Foundation, either version 3 of the License, or (at your option)
11 Foundation, either version 3 of the License, or (at your option)
12 any later version. The code is distributed WITHOUT ANY WARRANTY;
12 any later version. The code is distributed WITHOUT ANY WARRANTY;
13 without even the implied warranty of MERCHANTABILITY or FITNESS
13 without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
14 FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
15
15
16 As additional permission under GNU GPL version 3 section 7, you
16 As additional permission under GNU GPL version 3 section 7, you
17 may distribute non-source (e.g., minimized or compacted) forms of
17 may distribute non-source (e.g., minimized or compacted) forms of
18 that code without the copy of the GNU GPL normally required by
18 that code without the copy of the GNU GPL normally required by
19 section 4, provided you include this license notice and a URL
19 section 4, provided you include this license notice and a URL
20 through which recipients can access the Corresponding Source.
20 through which recipients can access the Corresponding Source.
21
21
22 @licend The above is the entire license notice
22 @licend The above is the entire license notice
23 for the JavaScript code in this page.
23 for the JavaScript code in this page.
24 */
24 */
25
25
26 var IMAGE_POPUP_MARGIN = 10;
26 var IMAGE_POPUP_MARGIN = 10;
27
27
28
28
29 var IMAGE_VIEWERS = [
29 var IMAGE_VIEWERS = [
30 ['simple', new SimpleImageViewer()],
30 ['simple', new SimpleImageViewer()],
31 ['popup', new PopupImageViewer()]
31 ['popup', new PopupImageViewer()]
32 ];
32 ];
33
33
34 var FULL_IMG_CLASS = 'post-image-full';
34 var FULL_IMG_CLASS = 'post-image-full';
35
35
36 var ATTR_SCALE = 'scale';
36 var ATTR_SCALE = 'scale';
37
37
38
38
39 // Init image viewer
39 // Init image viewer
40 var viewerName = $('body').attr('data-image-viewer');
40 var viewerName = $('body').attr('data-image-viewer');
41 var viewer = ImageViewer();
41 var viewer = ImageViewer();
42 for (var i = 0; i < IMAGE_VIEWERS.length; i++) {
42 for (var i = 0; i < IMAGE_VIEWERS.length; i++) {
43 var item = IMAGE_VIEWERS[i];
43 var item = IMAGE_VIEWERS[i];
44 if (item[0] === viewerName) {
44 if (item[0] === viewerName) {
45 viewer = item[1];
45 viewer = item[1];
46 break;
46 break;
47 }
47 }
48 }
48 }
49
49
50
50
51 function getFullImageWidth(previewImage) {
51 function getFullImageWidth(previewImage) {
52 var full_img_w = previewImage.attr('data-width');
52 var full_img_w = previewImage.attr('data-width');
53 if (full_img_w == null) {
53 if (full_img_w == null) {
54 full_img_w = previewImage[0].naturalWidth;
54 full_img_w = previewImage[0].naturalWidth;
55 }
55 }
56
56
57 return full_img_w;
57 return full_img_w;
58 }
58 }
59
59
60 function getFullImageHeight(previewImage) {
60 function getFullImageHeight(previewImage) {
61 var full_img_h = previewImage.attr('data-height');
61 var full_img_h = previewImage.attr('data-height');
62 if (full_img_h == null) {
62 if (full_img_h == null) {
63 full_img_h = previewImage[0].naturalHeight;
63 full_img_h = previewImage[0].naturalHeight;
64 }
64 }
65
65
66 return full_img_h;
66 return full_img_h;
67 }
67 }
68
68
69
69
70 function ImageViewer() {}
70 function ImageViewer() {}
71 ImageViewer.prototype.view = function (post) {};
71 ImageViewer.prototype.view = function (post) {};
72
72
73 function SimpleImageViewer() {}
73 function SimpleImageViewer() {}
74 SimpleImageViewer.prototype.view = function (post) {
74 SimpleImageViewer.prototype.view = function (post) {
75 var images = post.find('img');
75 var images = post.find('img');
76 images.toggle();
76 images.toggle();
77
77
78 // When we first enlarge an image, a full image needs to be created
78 // When we first enlarge an image, a full image needs to be created
79 if (images.length == 1) {
79 if (images.length == 1) {
80 var thumb = images.first();
80 var thumb = images.first();
81
81
82 var width = getFullImageWidth(thumb);
82 var width = getFullImageWidth(thumb);
83 var height = getFullImageHeight(thumb);
83 var height = getFullImageHeight(thumb);
84
84
85 if (width == null || height == null) {
85 if (width == null || height == null) {
86 width = '100%';
86 width = '100%';
87 height = '100%';
87 height = '100%';
88 }
88 }
89
89
90 var parent = images.first().parent();
90 var parent = images.first().parent();
91 var link = parent.attr('href');
91 var link = parent.attr('href');
92
92
93 var fullImg = $('<img />')
93 var fullImg = $('<img />')
94 .addClass(FULL_IMG_CLASS)
94 .addClass(FULL_IMG_CLASS)
95 .attr('src', link)
95 .attr('src', link)
96 .attr('width', width)
96 .attr('width', width)
97 .attr('height', height);
97 .attr('height', height);
98
98
99 parent.append(fullImg);
99 parent.append(fullImg);
100 }
100 }
101 };
101 };
102
102
103 function PopupImageViewer() {}
103 function PopupImageViewer() {}
104 PopupImageViewer.prototype.view = function (post) {
104 PopupImageViewer.prototype.view = function (post) {
105 var el = post;
105 var el = post;
106 var thumb_id = 'full' + el.find('img').attr('alt');
106 var thumb_id = 'full' + el.find('img').attr('alt');
107
107
108 var existingPopups = $('#' + thumb_id);
108 var existingPopups = $('#' + thumb_id);
109 if (!existingPopups.length) {
109 if (!existingPopups.length) {
110 var imgElement = el.find('img');
110 var imgElement = el.find('img');
111
111
112 var full_img_w = getFullImageWidth(imgElement);
112 var full_img_w = getFullImageWidth(imgElement);
113 var full_img_h = getFullImageHeight(imgElement);
113 var full_img_h = getFullImageHeight(imgElement);
114
114
115 var win = $(window);
115 var win = $(window);
116
116
117 var win_w = win.width();
117 var win_w = win.width();
118 var win_h = win.height();
118 var win_h = win.height();
119
119
120 // New image size
120 // New image size
121 var w_scale = 1;
121 var w_scale = 1;
122 var h_scale = 1;
122 var h_scale = 1;
123
123
124 var freeWidth = win_w - 2 * IMAGE_POPUP_MARGIN;
124 var freeWidth = win_w - 2 * IMAGE_POPUP_MARGIN;
125 var freeHeight = win_h - 2 * IMAGE_POPUP_MARGIN;
125 var freeHeight = win_h - 2 * IMAGE_POPUP_MARGIN;
126
126
127 if (full_img_w > freeWidth) {
127 if (full_img_w > freeWidth) {
128 w_scale = full_img_w / freeWidth;
128 w_scale = full_img_w / freeWidth;
129 }
129 }
130 if (full_img_h > freeHeight) {
130 if (full_img_h > freeHeight) {
131 h_scale = full_img_h / freeHeight;
131 h_scale = full_img_h / freeHeight;
132 }
132 }
133
133
134 var scale = Math.max(w_scale, h_scale)
134 var scale = Math.max(w_scale, h_scale)
135 var img_w = full_img_w / scale;
135 var img_w = full_img_w / scale;
136 var img_h = full_img_h / scale;
136 var img_h = full_img_h / scale;
137
137
138 var postNode = $(el);
138 var postNode = $(el);
139
139
140 var img_pv = new Image();
140 var img_pv = new Image();
141 var newImage = $(img_pv);
141 var newImage = $(img_pv);
142 newImage.addClass('img-full')
142 newImage.addClass('img-full')
143 .attr('id', thumb_id)
143 .attr('id', thumb_id)
144 .attr('src', postNode.attr('href'))
144 .attr('src', postNode.attr('href'))
145 .attr(ATTR_SCALE, scale)
145 .attr(ATTR_SCALE, scale)
146 .css({
146 .css({
147 'width': img_w,
147 'width': img_w,
148 'height': img_h,
148 'height': img_h,
149 'left': (win_w - img_w) / 2,
149 'left': (win_w - img_w) / 2,
150 'top': ((win_h - img_h) / 2)
150 'top': ((win_h - img_h) / 2)
151 })
151 })
152 .appendTo(postNode)
152 //scaling preview
153 //scaling preview
153 .mousewheel(function(event, delta) {
154 .mousewheel(function(event, delta) {
154 var cx = event.originalEvent.clientX;
155 var cx = event.originalEvent.clientX;
155 var cy = event.originalEvent.clientY;
156 var cy = event.originalEvent.clientY;
157
156
158 var scale = newImage.attr(ATTR_SCALE) / (delta > 0 ? 1.25 : 0.8);
157 var scale = newImage.attr(ATTR_SCALE) / (delta > 0 ? 1.25 : 0.8);
159
158
160 var oldWidth = newImage.width();
159 var oldWidth = newImage.width();
161 var oldHeight = newImage.height();
160 var oldHeight = newImage.height();
162
161
163 var newIW = full_img_w / scale;
162 var newIW = full_img_w / scale;
164 var newIH = full_img_h / scale;
163 var newIH = full_img_h / scale;
165
164
166 newImage.width(newIW);
165 newImage.width(newIW);
167 newImage.height(newIH);
166 newImage.height(newIH);
168 newImage.attr(ATTR_SCALE, scale);
167 newImage.attr(ATTR_SCALE, scale);
169
168
170 // Set position
169 // Set position
171 var oldPosition = newImage.position();
170 var oldPosition = newImage.position();
172 newImage.css({
171 newImage.css({
173 left: parseInt(cx - (newIW/oldWidth) * (cx - parseInt(oldPosition.left, 10)), 10),
172 left: parseInt(cx - (newIW/oldWidth) * (cx - parseInt(oldPosition.left, 10)), 10),
174 top: parseInt(cy - (newIH/oldHeight) * (cy - parseInt(oldPosition.top, 10)), 10)
173 top: parseInt(cy - (newIH/oldHeight) * (cy - parseInt(oldPosition.top, 10)), 10)
175 });
174 });
176
175
177 return false;
176 return false;
178 }
177 })
179 )
180 .draggable({
178 .draggable({
181 addClasses: false,
179 addClasses: false,
182 stack: '.img-full'
180 stack: '.img-full'
183 });
181 })
182 .appendTo($('body'));
184 } else {
183 } else {
185 existingPopups.remove();
184 existingPopups.remove();
186 }
185 }
187 };
186 };
188
187
189 function addImgPreview() {
188 function addImgPreview() {
190 //keybind
189 //keybind
191 $(document).on('keyup.removepic', function(e) {
190 $(document).on('keyup.removepic', function(e) {
192 if(e.which === 27) {
191 if(e.which === 27) {
193 $('.img-full').remove();
192 $('.img-full').remove();
194 }
193 }
195 });
194 });
196
195
197 $('body').on('click', '.thumb', function() {
196 $('body').on('click', '.thumb', function() {
198 viewer.view($(this));
197 viewer.view($(this));
199
198
200 return false;
199 return false;
201 });
200 });
202 }
201 }
@@ -1,122 +1,132 b''
1 var LOADING_MSG = "<div class=\"post\">" + gettext('Loading...') + "</div>";
2
1 function $X(path, root) {
3 function $X(path, root) {
2 return document.evaluate(path, root || document, null, 6, null);
4 return document.evaluate(path, root || document, null, 6, null);
3 }
5 }
4 function $x(path, root) {
6 function $x(path, root) {
5 return document.evaluate(path, root || document, null, 8, null).singleNodeValue;
7 return document.evaluate(path, root || document, null, 8, null).singleNodeValue;
6 }
8 }
7
9
8 function $del(el) {
10 function $del(el) {
9 if(el) el.parentNode.removeChild(el);
11 if(el) el.parentNode.removeChild(el);
10 }
12 }
11
13
12 function $each(list, fn) {
14 function $each(list, fn) {
13 if(!list) return;
15 if(!list) return;
14 var i = list.snapshotLength;
16 var i = list.snapshotLength;
15 if(i > 0) while(i--) fn(list.snapshotItem(i), i);
17 if(i > 0) while(i--) fn(list.snapshotItem(i), i);
16 }
18 }
17
19
18 function mkPreview(cln, html) {
20 function mkPreview(cln, html) {
19 cln.innerHTML = html;
21 cln.innerHTML = html;
20
22
21 addScriptsToPost($(cln));
23 addScriptsToPost($(cln));
22 }
24 }
23
25
24 function isElementInViewport (el) {
26 function isElementInViewport (el) {
25 //special bonus for those using jQuery
27 //special bonus for those using jQuery
26 if (typeof jQuery === "function" && el instanceof jQuery) {
28 if (typeof jQuery === "function" && el instanceof jQuery) {
27 el = el[0];
29 el = el[0];
28 }
30 }
29
31
30 var rect = el.getBoundingClientRect();
32 var rect = el.getBoundingClientRect();
31
33
32 return (
34 return (
33 rect.top >= 0 &&
35 rect.top >= 0 &&
34 rect.left >= 0 &&
36 rect.left >= 0 &&
35 rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */
37 rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */
36 rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */
38 rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */
37 );
39 );
38 }
40 }
39
41
40 function addRefLinkPreview(node) {
42 function addRefLinkPreview(node) {
41 $each($X('.//a[starts-with(text(),">>")]', node || document), function(link) {
43 $each($X('.//a[starts-with(text(),">>")]', node || document), function(link) {
42 link.addEventListener('mouseover', showPostPreview, false);
44 link.addEventListener('mouseover', showPostPreview, false);
43 link.addEventListener('mouseout', delPostPreview, false);
45 link.addEventListener('mouseout', delPostPreview, false);
44 });
46 });
45 }
47 }
46
48
47 function showPostPreview(e) {
49 function showPostPreview(e) {
48 var doc = document;
50 var doc = document;
49
51
50 var reflink = $(this);
52 var reflink = $(this);
51 var pNum = reflink.text().match(/\d+/);
53 var pNum = reflink.text().match(/\d+/);
52
54
53 if (pNum == null || pNum.length == 0) {
55 if (pNum == null || pNum.length == 0) {
54 return;
56 return;
55 }
57 }
56
58
57 var post = $('#' + pNum);
59 var post = $('#' + pNum);
58 if (post.length > 0 && isElementInViewport(post)) {
60 if (post.length > 0 && isElementInViewport(post)) {
61 // If post is on the same page and visible, just highlight it
59 post.addClass('highlight');
62 post.addClass('highlight');
60 } else {
63 } else {
61 var x = reflink.offset().left;
64 var x = reflink.offset().left;
62 var y = reflink.offset().top;
65 var y = reflink.offset().top;
63
66
64 var cln = doc.createElement('div');
67 var cln = doc.createElement('div');
65 cln.id = 'pstprev_' + pNum;
68 cln.id = 'pstprev_' + pNum;
66 cln.className = 'post_preview';
69 cln.className = 'post_preview';
67
70
68 // var newX = x < doc.body.clientWidth/2 ? 'left:' + x : 'right:' + parseInt(doc.body.clientWidth - x - reflink.width());
69 // var newY = y < doc.body.clientHeight/2 ? 'top:' + y : 'bottom:' + parseInt(doc.body.clientHeight - y - reflink.height());
70 cln.style.cssText = 'left:' + x + 'px; top:' + y + 'px';
71 cln.style.cssText = 'left:' + x + 'px; top:' + y + 'px';
71
72
72 cln.addEventListener('mouseout', delPostPreview, false);
73 cln.addEventListener('mouseout', delPostPreview, false);
73
74
74 cln.innerHTML = "<div class=\"post\">" + gettext('Loading...') + "</div>";
75 cln.innerHTML = LOADING_MSG;
75
76
76 if(post.length > 0) {
77 if (post.length > 0) {
77 var postdata = post.clone().wrap("<div/>").parent().html();
78 // If post is on the same page but not visible, generate preview from it
79 var postClone = post.clone();
80 postClone.removeAttr('style');
81 var postdata = postClone.wrap("<div/>").parent().html();
78
82
79 mkPreview(cln, postdata);
83 mkPreview(cln, postdata);
80 } else {
84 } else {
85 // If post is from other page, load it
81 $.ajax({
86 $.ajax({
82 url: '/api/post/' + pNum + '/?truncated'
87 url: '/api/post/' + pNum + '/?truncated'
83 })
88 })
84 .success(function(data) {
89 .success(function(data) {
85 var postdata = $(data).wrap("<div/>").parent().html();
90 var postdata = $(data).wrap("<div/>").parent().html();
86
87 //make preview
88 mkPreview(cln, postdata);
89
91
90 })
92 //make preview
91 .error(function() {
93 mkPreview(cln, postdata);
92 cln.innerHTML = "<div class=\"post\">"
94 })
93 + gettext('Post not found') + "</div>";
95 .error(function() {
94 });
96 cln.innerHTML = "<div class=\"post\">"
97 + gettext('Post not found') + "</div>";
98 });
95 }
99 }
96
100
97 $del(doc.getElementById(cln.id));
101 $del(doc.getElementById(cln.id));
98
102
99 //add preview
103 //add preview
100 $(cln).fadeIn(200);
104 $(cln).fadeIn(200);
101 $('body').append(cln);
105 $('body').append(cln);
102 }
106 }
103 }
107 }
104
108
105 function delPostPreview(e) {
109 function delPostPreview(e) {
106 var el = $x('ancestor-or-self::*[starts-with(@id,"pstprev")]', e.relatedTarget);
110 var el = $x('ancestor-or-self::*[starts-with(@id,"pstprev")]', e.relatedTarget);
107 if(!el) {
111 if(!el) {
108 $each($X('.//div[starts-with(@id,"pstprev")]'), function(clone) {
112 $each($X('.//div[starts-with(@id,"pstprev")]'), function(clone) {
109 $del(clone)
113 $del(clone)
110 });
114 });
111 } else {
115 } else {
112 while(el.nextSibling) $del(el.nextSibling);
116 while (el.nextSibling) {
117 if (el.nextSibling.className.startsWith('pstprev')) {
118 $del(el.nextSibling);
119 } else {
120 break;
121 }
122 }
113 }
123 }
114
124
115 $('.highlight').removeClass('highlight');
125 $('.highlight').removeClass('highlight');
116 }
126 }
117
127
118 function addPreview() {
128 function addPreview() {
119 $('.post').find('a').each(function() {
129 $('.post').find('a').each(function() {
120 showPostPreview($(this));
130 showPostPreview($(this));
121 });
131 });
122 }
132 }
General Comments 0
You need to be logged in to leave comments. Login now