blob: 5fe494dde3af5ffc067c7c529cd8e288878a197a [file] [log] [blame]
avm9996304def3e2016-11-27 22:53:05 +01001// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4var page = {
5 startX: 150,
6 startY: 150,
7 endX: 400,
8 endY: 300,
9 moveX: 0,
10 moveY: 0,
11 pageWidth: 0,
12 pageHeight: 0,
13 visibleWidth: 0,
14 visibleHeight: 0,
15 dragging: false,
16 moving: false,
17 resizing: false,
18 isMouseDown: false,
19 scrollXCount: 0,
20 scrollYCount: 0,
21 scrollX: 0,
22 scrollY: 0,
23 captureWidth: 0,
24 captureHeight: 0,
25 isSelectionAreaTurnOn: false,
26 fixedElements_ : [],
27 marginTop: 0,
28 marginLeft: 0,
29 modifiedBottomRightFixedElements: [],
30 originalViewPortWidth: document.documentElement.clientWidth,
31 defaultScrollBarWidth: 17, // Default scroll bar width on windows platform.
32
33 hookBodyScrollValue: function(needHook) {
34 document.documentElement.setAttribute(
35 "__screen_capture_need_hook_scroll_value__", needHook);
36 var event = document.createEvent('Event');
37 event.initEvent('__screen_capture_check_hook_status_event__', true, true);
38 document.documentElement.dispatchEvent(event);
39 },
40
41 /**
42 * Determine if the page scrolled to bottom or right.
43 */
44 isScrollToPageEnd: function(coordinate) {
45 var body = document.body;
46 var docElement = document.documentElement;
47 if (coordinate == 'x')
48 return docElement.clientWidth + body.scrollLeft == body.scrollWidth;
49 else if (coordinate == 'y')
50 return docElement.clientHeight + body.scrollTop == body.scrollHeight;
51 },
52
53 /**
54 * Detect if the view port is located to the corner of page.
55 */
56 detectPagePosition: function() {
57 var body = document.body;
58 var pageScrollTop = body.scrollTop;
59 var pageScrollLeft = body.scrollLeft;
60 if (pageScrollTop == 0 && pageScrollLeft == 0) {
61 return 'top_left';
62 } else if (pageScrollTop == 0 && this.isScrollToPageEnd('x')) {
63 return 'top_right';
64 } else if (this.isScrollToPageEnd('y') && pageScrollLeft == 0) {
65 return 'bottom_left';
66 } else if (this.isScrollToPageEnd('y') && this.isScrollToPageEnd('x')) {
67 return 'bottom_right';
68 }
69 return null;
70 },
71
72 /**
73 * Detect fixed-positioned element's position in the view port.
74 * @param {Element} elem
75 * @return {String|Object} Return position of the element in the view port:
76 * top_left, top_right, bottom_left, bottom_right, or null.
77 */
78 detectCapturePositionOfFixedElement: function(elem) {
79 var docElement = document.documentElement;
80 var viewPortWidth = docElement.clientWidth;
81 var viewPortHeight = docElement.clientHeight;
82 var offsetWidth = elem.offsetWidth;
83 var offsetHeight = elem.offsetHeight;
84 var offsetTop = elem.offsetTop;
85 var offsetLeft = elem.offsetLeft;
86 var result = [];
87
88 // Compare distance between element and the edge of view port to determine
89 // the capture position of element.
90 if (offsetTop <= viewPortHeight - offsetTop - offsetHeight) {
91 result.push('top');
92 } else if (offsetTop < viewPortHeight) {
93 result.push('bottom');
94 }
95 if (offsetLeft <= viewPortWidth - offsetLeft - offsetWidth) {
96 result.push('left');
97 } else if (offsetLeft < viewPortWidth) {
98 result.push('right');
99 }
100
101 // If the element is out of view port, then ignore.
102 if (result.length != 2)
103 return null;
104 return result.join('_');
105 },
106
107 restoreFixedElements: function() {
108 this.fixedElements_.forEach(function(element) {
109 element[1].style.visibility = 'visible';
110 });
111 this.fixedElements_ = [];
112 },
113
114 /**
115 * Iterate DOM tree and cache visible fixed-position elements.
116 */
117 cacheVisibleFixedPositionedElements: function() {
118 var nodeIterator = document.createNodeIterator(
119 document.documentElement,
120 NodeFilter.SHOW_ELEMENT,
121 null,
122 false
123 );
124 var currentNode;
125 while (currentNode = nodeIterator.nextNode()) {
126 var nodeComputedStyle =
127 document.defaultView.getComputedStyle(currentNode, "");
128 // Skip nodes which don't have computeStyle or are invisible.
129 if (!nodeComputedStyle)
130 continue;
131 if (nodeComputedStyle.position == "fixed" &&
132 nodeComputedStyle.display != 'none' &&
133 nodeComputedStyle.visibility != 'hidden') {
134 var position =
135 this.detectCapturePositionOfFixedElement(currentNode);
136 if (position)
137 this.fixedElements_.push([position, currentNode]);
138 }
139 }
140 },
141
142 // Handle fixed-position elements for capture.
143 handleFixedElements: function(capturePosition) {
144 var docElement = document.documentElement;
145 var body = document.body;
146
147 // If page has no scroll bar, then return directly.
148 if (docElement.clientHeight == body.scrollHeight &&
149 docElement.clientWidth == body.scrollWidth)
150 return;
151
152 if (!this.fixedElements_.length) {
153 this.cacheVisibleFixedPositionedElements();
154 }
155
156 this.fixedElements_.forEach(function(element) {
157 if (element[0] == capturePosition)
158 element[1].style.visibility = 'visible';
159 else
160 element[1].style.visibility = 'hidden';
161 });
162 },
163
164 handleSecondToLastCapture: function() {
165 var docElement = document.documentElement;
166 var body = document.body;
167 var bottomPositionElements = [];
168 var rightPositionElements = [];
169 var that = this;
170 this.fixedElements_.forEach(function(element) {
171 var position = element[0];
172 if (position == 'bottom_left' || position == 'bottom_right') {
173 bottomPositionElements.push(element[1]);
174 } else if (position == 'bottom_right' || position == 'top_right') {
175 rightPositionElements.push(element[1]);
176 }
177 });
178
179 // Determine if the current capture is last but one.
180 var remainingCaptureHeight = body.scrollHeight - docElement.clientHeight -
181 body.scrollTop;
182 if (remainingCaptureHeight > 0 &&
183 remainingCaptureHeight < docElement.clientHeight) {
184 bottomPositionElements.forEach(function(element) {
185 if (element.offsetHeight > remainingCaptureHeight) {
186 element.style.visibility = 'visible';
187 var originalBottom = window.getComputedStyle(element).bottom;
188 that.modifiedBottomRightFixedElements.push(
189 ['bottom', element, originalBottom]);
190 element.style.bottom = -remainingCaptureHeight + 'px';
191 }
192 });
193 }
194
195 var remainingCaptureWidth = body.scrollWidth - docElement.clientWidth -
196 body.scrollLeft;
197 if (remainingCaptureWidth > 0 &&
198 remainingCaptureWidth < docElement.clientWidth) {
199 rightPositionElements.forEach(function(element) {
200 if (element.offsetWidth > remainingCaptureWidth) {
201 element.style.visibility = 'visible';
202 var originalRight = window.getComputedStyle(element).right;
203 that.modifiedBottomRightFixedElements.push(
204 ['right', element, originalRight]);
205 element.style.right = -remainingCaptureWidth + 'px';
206 }
207 });
208 }
209 },
210
211 restoreBottomRightOfFixedPositionElements: function() {
212 this.modifiedBottomRightFixedElements.forEach(function(data) {
213 var property = data[0];
214 var element = data[1];
215 var originalValue = data[2];
216 element.style[property] = originalValue;
217 });
218 this.modifiedBottomRightFixedElements = [];
219 },
220
221 hideAllFixedPositionedElements: function() {
222 this.fixedElements_.forEach(function(element) {
223 element[1].style.visibility = 'hidden';
224 });
225 },
226
227 hasScrollBar: function(axis) {
228 var body = document.body;
229 var docElement = document.documentElement;
230 if (axis == 'x') {
231 if (window.getComputedStyle(body).overflowX == 'scroll')
232 return true;
233 return Math.abs(body.scrollWidth - docElement.clientWidth) >=
234 page.defaultScrollBarWidth;
235 } else if (axis == 'y') {
236 if (window.getComputedStyle(body).overflowY == 'scroll')
237 return true;
238 return Math.abs(body.scrollHeight - docElement.clientHeight) >=
239 page.defaultScrollBarWidth;
240 }
241 },
242
243 getOriginalViewPortWidth: function() {
avm99963873bf6f2021-02-07 00:01:31 +0100244 page.originalViewPortWidth = document.documentElement.clientWidth;
avm9996304def3e2016-11-27 22:53:05 +0100245 },
246
247 calculateSizeAfterZooming: function(originalSize) {
248 var originalViewPortWidth = page.originalViewPortWidth;
249 var currentViewPortWidth = document.documentElement.clientWidth;
250 if (originalViewPortWidth == currentViewPortWidth)
251 return originalSize;
252 return Math.round(
253 originalViewPortWidth * originalSize / currentViewPortWidth);
254 },
255
256 getZoomLevel: function() {
257 return page.originalViewPortWidth / document.documentElement.clientWidth;
258 },
259
260 handleRightFloatBoxInGmail: function() {
261 var mainframe = document.getElementById('canvas_frame');
262 var boxContainer = document.querySelector('body > .dw');
263 var fBody = mainframe.contentDocument.body;
264 if (fBody.clientHeight + fBody.scrollTop == fBody.scrollHeight) {
265 boxContainer.style.display = 'block';
266 } else {
267 boxContainer.style.display = 'none';
268 }
269 },
270
271 getViewPortSize: function() {
272 var result = {
273 width: document.documentElement.clientWidth,
274 height: document.documentElement.clientHeight
275 };
276
277 if (document.compatMode == 'BackCompat') {
278 result.width = document.body.clientWidth;
279 result.height = document.body.clientHeight;
280 }
281
282 return result;
283 },
284
285 /**
286 * Check if the page is only made of invisible embed elements.
287 */
288 checkPageIsOnlyEmbedElement: function() {
289 var bodyNode = document.body.children;
290 var isOnlyEmbed = false;
291 for (var i = 0; i < bodyNode.length; i++) {
292 var tagName = bodyNode[i].tagName;
293 if (tagName == 'OBJECT' || tagName == 'EMBED' || tagName == 'VIDEO' ||
294 tagName == 'SCRIPT' || tagName == 'LINK') {
295 isOnlyEmbed = true;
296 } else if (bodyNode[i].style.display != 'none'){
297 isOnlyEmbed = false;
298 break;
299 }
300 }
301 return isOnlyEmbed;
302 },
303
304 isGMailPage: function(){
305 var hostName = window.location.hostname;
306 if (hostName == 'mail.google.com' &&
307 document.getElementById('canvas_frame')) {
308 return true;
309 }
310 return false;
311 },
312
313 /**
314 * Receive messages from background page, and then decide what to do next
315 */
316 addMessageListener: function() {
317 chrome.extension.onMessage.addListener(function(request, sender, response) {
318 if (page.isSelectionAreaTurnOn) {
319 page.removeSelectionArea();
320 }
321 switch (request.msg) {
322 case 'capture_window': response(page.getWindowSize()); break;
323 case 'show_selection_area': page.showSelectionArea(); break;
324 case 'scroll_init': // Capture whole page.
325 response(page.scrollInit(0, 0, document.body.scrollWidth,
326 document.body.scrollHeight, 'captureWhole'));
327 break;
328 case 'scroll_next':
329 page.visibleWidth = request.visibleWidth;
330 page.visibleHeight = request.visibleHeight;
331 response(page.scrollNext());
332 break;
333 case 'capture_selected':
334 response(page.scrollInit(
335 page.startX, page.startY,
336 page.calculateSizeAfterZooming(page.endX - page.startX),
337 page.calculateSizeAfterZooming(page.endY - page.startY),
338 'captureSelected'));
339 break;
340 }
341 });
342 },
343
344 /**
345 * Send Message to background page
346 */
347 sendMessage: function(message) {
348 chrome.extension.sendMessage(message);
349 },
350
351 /**
352 * Initialize scrollbar position, and get the data browser
353 */
354 scrollInit: function(startX, startY, canvasWidth, canvasHeight, type) {
355 this.hookBodyScrollValue(true);
356 page.captureHeight = canvasHeight;
357 page.captureWidth = canvasWidth;
358 var docWidth = document.body.scrollWidth;
359 var docHeight = document.body.scrollHeight;
360 window.scrollTo(startX, startY);
361
362 this.handleFixedElements('top_left');
363 this.handleSecondToLastCapture();
364
365 if (page.isGMailPage() && type == 'captureWhole') {
366 var frame = document.getElementById('canvas_frame');
367 docHeight = page.captureHeight = canvasHeight =
368 frame.contentDocument.height;
369 docWidth = page.captureWidth = canvasWidth = frame.contentDocument.width;
370 frame.contentDocument.body.scrollTop = 0;
371 frame.contentDocument.body.scrollLeft = 0;
372 page.handleRightFloatBoxInGmail();
373 }
374 page.scrollXCount = 0;
375 page.scrollYCount = 1;
376 page.scrollX = window.scrollX; // document.body.scrollLeft
377 page.scrollY = window.scrollY;
378 var viewPortSize = page.getViewPortSize();
379 return {
380 'msg': 'scroll_init_done',
381 'startX': page.calculateSizeAfterZooming(startX),
382 'startY': page.calculateSizeAfterZooming(startY),
383 'scrollX': window.scrollX,
384 'scrollY': window.scrollY,
385 'docHeight': docHeight,
386 'docWidth': docWidth,
387 'visibleWidth': viewPortSize.width,
388 'visibleHeight': viewPortSize.height,
389 'canvasWidth': canvasWidth,
390 'canvasHeight': canvasHeight,
391 'scrollXCount': 0,
392 'scrollYCount': 0,
393 'zoom': page.getZoomLevel()
394 };
395 },
396
397 /**
398 * Calculate the next position of the scrollbar
399 */
400 scrollNext: function() {
401 if (page.scrollYCount * page.visibleWidth >= page.captureWidth) {
402 page.scrollXCount++;
403 page.scrollYCount = 0;
404 }
405 if (page.scrollXCount * page.visibleHeight < page.captureHeight) {
406 this.restoreBottomRightOfFixedPositionElements();
407 var viewPortSize = page.getViewPortSize();
408 window.scrollTo(
409 page.scrollYCount * viewPortSize.width + page.scrollX,
410 page.scrollXCount * viewPortSize.height + page.scrollY);
411
412 var pagePosition = this.detectPagePosition();
413 if (pagePosition) {
414 this.handleFixedElements(pagePosition);
415 } else {
416 this.hideAllFixedPositionedElements();
417 }
418 this.handleSecondToLastCapture();
419
420 if (page.isGMailPage()) {
421 var frame = document.getElementById('canvas_frame');
422 frame.contentDocument.body.scrollLeft =
423 page.scrollYCount * viewPortSize.width;
424 frame.contentDocument.body.scrollTop =
425 page.scrollXCount * viewPortSize.height;
426 page.handleRightFloatBoxInGmail();
427 }
428 var x = page.scrollXCount;
429 var y = page.scrollYCount;
430 page.scrollYCount++;
431 return { msg: 'scroll_next_done',scrollXCount: x, scrollYCount: y };
432 } else {
433 window.scrollTo(page.startX, page.startY);
434 this.restoreFixedElements();
435 this.hookBodyScrollValue(false);
436 return {'msg': 'scroll_finished'};
437 }
438 },
439
440 /**
441 * Show the selection Area
442 */
443 showSelectionArea: function() {
444 page.createFloatLayer();
445 setTimeout(page.createSelectionArea, 100);
446 },
447
448 getWindowSize: function() {
449 var docWidth = document.body.clientWidth;
450 var docHeight = document.body.clientHeight;
451 if (page.isGMailPage()) {
452 var frame = document.getElementById('canvas_frame');
453 docHeight = frame.contentDocument.height;
454 docWidth = frame.contentDocument.width;
455 }
456 return {'msg':'capture_window',
457 'docWidth': docWidth,
458 'docHeight': docHeight};
459 },
460
461 getSelectionSize: function() {
462 page.removeSelectionArea();
463 setTimeout(function() {
464 page.sendMessage({
465 'msg': 'capture_selected',
466 'x': page.startX,
467 'y': page.startY,
468 'width': page.endX - page.startX,
469 'height': page.endY - page.startY,
470 'visibleWidth': document.documentElement.clientWidth,
471 'visibleHeight': document.documentElement.clientHeight,
472 'docWidth': document.body.clientWidth,
473 'docHeight': document.body.clientHeight
474 })}, 100);
475 },
476
477 /**
478 * Create a float layer on the webpage
479 */
480 createFloatLayer: function() {
481 page.createDiv(document.body, 'sc_drag_area_protector');
482 },
483
484 matchMarginValue: function(str) {
485 return str.match(/\d+/);
486 },
487
488 /**
489 * Load the screenshot area interface
490 */
491 createSelectionArea: function() {
492 var areaProtector = $('sc_drag_area_protector');
493 var zoom = page.getZoomLevel();
494 var bodyStyle = window.getComputedStyle(document.body, null);
495 if ('relative' == bodyStyle['position']) {
496 page.marginTop = page.matchMarginValue(bodyStyle['marginTop']);
497 page.marginLeft = page.matchMarginValue(bodyStyle['marginLeft']);
498 areaProtector.style.top = - parseInt(page.marginTop) + 'px';
499 areaProtector.style.left = - parseInt(page.marginLeft) + 'px';
500 }
501 areaProtector.style.width =
502 Math.round((document.body.clientWidth + parseInt(page.marginLeft)) / zoom) + 'px';
503 areaProtector.style.height =
504 Math.round((document.body.clientHeight + parseInt(page.marginTop)) / zoom) + 'px';
505 areaProtector.onclick = function() {
506 event.stopPropagation();
507 return false;
508 };
509
510 // Create elements for area capture.
511 page.createDiv(areaProtector, 'sc_drag_shadow_top');
512 page.createDiv(areaProtector, 'sc_drag_shadow_bottom');
513 page.createDiv(areaProtector, 'sc_drag_shadow_left');
514 page.createDiv(areaProtector, 'sc_drag_shadow_right');
515
516 var areaElement = page.createDiv(areaProtector, 'sc_drag_area');
517 page.createDiv(areaElement, 'sc_drag_container');
518 page.createDiv(areaElement, 'sc_drag_size');
519
520 // Add event listener for 'cancel' and 'capture' button.
521 var cancel = page.createDiv(areaElement, 'sc_drag_cancel');
522 cancel.addEventListener('mousedown', function () {
523 // Remove area capture containers and event listeners.
524 page.removeSelectionArea();
525 }, true);
526 cancel.innerHTML = chrome.i18n.getMessage("cancel");
527
528 var crop = page.createDiv(areaElement, 'sc_drag_crop');
529 crop.addEventListener('mousedown', function() {
530 page.removeSelectionArea();
531 page.sendMessage({msg: 'capture_selected'});
532 }, false);
533 crop.innerHTML = chrome.i18n.getMessage('ok');
534
535 page.createDiv(areaElement, 'sc_drag_north_west');
536 page.createDiv(areaElement, 'sc_drag_north_east');
537 page.createDiv(areaElement, 'sc_drag_south_east');
538 page.createDiv(areaElement, 'sc_drag_south_west');
539
540 areaProtector.addEventListener('mousedown', page.onMouseDown, false);
541 document.addEventListener('mousemove', page.onMouseMove, false);
542 document.addEventListener('mouseup', page.onMouseUp, false);
543 $('sc_drag_container').addEventListener('dblclick', function() {
544 page.removeSelectionArea();
545 page.sendMessage({msg: 'capture_selected'});
546 }, false);
547
548 page.pageHeight = $('sc_drag_area_protector').clientHeight;
549 page.pageWidth = $('sc_drag_area_protector').clientWidth;
550
551 var areaElement = $('sc_drag_area');
552 areaElement.style.left = page.getElementLeft(areaElement) + 'px';
553 areaElement.style.top = page.getElementTop(areaElement) + 'px';
554
555 page.startX = page.getElementLeft(areaElement);
556 page.startY = page.getElementTop(areaElement);
557 page.endX = page.getElementLeft(areaElement) + 250;
558 page.endY = page.getElementTop(areaElement) + 150;
559
560 areaElement.style.width = '250px';
561 areaElement.style.height = '150px';
562 page.isSelectionAreaTurnOn = true;
563 page.updateShadow(areaElement);
564 page.updateSize();
565 },
566
567 getElementLeft: function(obj) {
568 return (document.body.scrollLeft +
569 (document.documentElement.clientWidth -
570 obj.offsetWidth) / 2);
571 },
572
573 getElementTop: function(obj) {
574 return (document.body.scrollTop +
575 (document.documentElement.clientHeight - 200 -
576 obj.offsetHeight) / 2);
577 },
578
579 /**
580 * Init selection area due to the position of the mouse when mouse down
581 */
582 onMouseDown: function() {
583 if (event.button != 2) {
584 var element = event.target;
585
586 if (element) {
587 var elementName = element.tagName;
588 if (elementName && document) {
589 page.isMouseDown = true;
590
591 var areaElement = $('sc_drag_area');
592 var xPosition = event.pageX;
593 var yPosition = event.pageY;
594
595 if (areaElement) {
596 if (element == $('sc_drag_container')) {
597 page.moving = true;
598 page.moveX = xPosition - areaElement.offsetLeft;
599 page.moveY = yPosition - areaElement.offsetTop;
600 } else if (element == $('sc_drag_north_east')) {
601 page.resizing = true;
602 page.startX = areaElement.offsetLeft;
603 page.startY = areaElement.offsetTop + areaElement.clientHeight;
604 } else if (element == $('sc_drag_north_west')) {
605 page.resizing = true;
606 page.startX = areaElement.offsetLeft + areaElement.clientWidth;
607 page.startY = areaElement.offsetTop + areaElement.clientHeight;
608 } else if (element == $('sc_drag_south_east')) {
609 page.resizing = true;
610 page.startX = areaElement.offsetLeft;
611 page.startY = areaElement.offsetTop;
612 } else if (element == $('sc_drag_south_west')) {
613 page.resizing = true;
614 page.startX = areaElement.offsetLeft + areaElement.clientWidth;
615 page.startY = areaElement.offsetTop;
616 } else {
617 page.dragging = true;
618 page.endX = 0;
619 page.endY = 0;
620 page.endX = page.startX = xPosition;
621 page.endY = page.startY = yPosition;
622 }
623 }
624 event.preventDefault();
625 }
626 }
627 }
628 },
629
630 /**
631 * Change selection area position when mouse moved
632 */
633 onMouseMove: function() {
634 var element = event.target;
635 if (element && page.isMouseDown) {
636 var areaElement = $('sc_drag_area');
637 if (areaElement) {
638 var xPosition = event.pageX;
639 var yPosition = event.pageY;
640 if (page.dragging || page.resizing) {
641 var width = 0;
642 var height = 0;
643 var zoom = page.getZoomLevel();
644 var viewWidth = Math.round(document.body.clientWidth / zoom);
645 var viewHeight = Math.round(document.body.clientHeight / zoom);
646 if (xPosition > viewWidth) {
647 xPosition = viewWidth;
648 } else if (xPosition < 0) {
649 xPosition = 0;
650 }
651 if (yPosition > viewHeight) {
652 yPosition = viewHeight;
653 } else if (yPosition < 0) {
654 yPosition = 0;
655 }
656 page.endX = xPosition;
657 page.endY = yPosition;
658 if (page.startX > page.endX) {
659 width = page.startX - page.endX;
660 areaElement.style.left = xPosition + 'px';
661 } else {
662 width = page.endX - page.startX;
663 areaElement.style.left = page.startX + 'px';
664 }
665 if (page.startY > page.endY) {
666 height = page.startY - page.endY;
667 areaElement.style.top = page.endY + 'px';
668 } else {
669 height = page.endY - page.startY;
670 areaElement.style.top = page.startY + 'px';
671 }
672 areaElement.style.height = height + 'px';
673 areaElement.style.width = width + 'px';
674 if (window.innerWidth < xPosition) {
675 document.body.scrollLeft = xPosition - window.innerWidth;
676 }
677 if (document.body.scrollTop + window.innerHeight < yPosition + 25) {
678 document.body.scrollTop = yPosition - window.innerHeight + 25;
679 }
680 if (yPosition < document.body.scrollTop) {
681 document.body.scrollTop -= 25;
682 }
683 } else if (page.moving) {
684 var newXPosition = xPosition - page.moveX;
685 var newYPosition = yPosition - page.moveY;
686 if (newXPosition < 0) {
687 newXPosition = 0;
688 } else if (newXPosition + areaElement.clientWidth > page.pageWidth) {
689 newXPosition = page.pageWidth - areaElement.clientWidth;
690 }
691 if (newYPosition < 0) {
692 newYPosition = 0;
693 } else if (newYPosition + areaElement.clientHeight >
694 page.pageHeight) {
695 newYPosition = page.pageHeight - areaElement.clientHeight;
696 }
697
698 areaElement.style.left = newXPosition + 'px';
699 areaElement.style.top = newYPosition + 'px';
700 page.endX = newXPosition + areaElement.clientWidth;
701 page.startX = newXPosition;
702 page.endY = newYPosition + areaElement.clientHeight;
703 page.startY = newYPosition;
704
705 }
706 var crop = document.getElementById('sc_drag_crop');
707 var cancel = document.getElementById('sc_drag_cancel');
708 if (event.pageY + 25 > document.body.clientHeight) {
709 crop.style.bottom = 0;
710 cancel.style.bottom = 0
711 } else {
712 crop.style.bottom = '-25px';
713 cancel.style.bottom = '-25px';
714 }
715
716 var dragSizeContainer = document.getElementById('sc_drag_size');
717 if (event.pageY < 18) {
718 dragSizeContainer.style.top = 0;
719 } else {
720 dragSizeContainer.style.top = '-18px';
721 }
722 page.updateShadow(areaElement);
723 page.updateSize();
724
725 }
726 }
727 },
728
729 /**
730 * Fix the selection area position when mouse up
731 */
732 onMouseUp: function() {
733 page.isMouseDown = false;
734 if (event.button != 2) {
735 page.resizing = false;
736 page.dragging = false;
737 page.moving = false;
738 page.moveX = 0;
739 page.moveY = 0;
740 var temp;
741 if (page.endX < page.startX) {
742 temp = page.endX;
743 page.endX = page.startX;
744 page.startX = temp;
745 }
746 if (page.endY < page.startY) {
747 temp = page.endY;
748 page.endY = page.startY;
749 page.startY = temp;
750 }
751 }
752 },
753
754 /**
755 * Update the location of the shadow layer
756 */
757 updateShadow: function(areaElement) {
758 $('sc_drag_shadow_top').style.height =
759 parseInt(areaElement.style.top) + 'px';
760 $('sc_drag_shadow_top').style.width = (parseInt(areaElement.style.left) +
761 parseInt(areaElement.style.width) + 1) + 'px';
762 $('sc_drag_shadow_left').style.height =
763 (page.pageHeight - parseInt(areaElement.style.top)) + 'px';
764 $('sc_drag_shadow_left').style.width =
765 parseInt(areaElement.style.left) + 'px';
766
767 var height = (parseInt(areaElement.style.top) +
768 parseInt(areaElement.style.height) + 1);
769 height = (height < 0) ? 0 : height;
770 var width = (page.pageWidth) - 1 - (parseInt(areaElement.style.left) +
771 parseInt(areaElement.style.width));
772 width = (width < 0) ? 0 : width;
773 $('sc_drag_shadow_right').style.height = height + 'px';
774 $('sc_drag_shadow_right').style.width = width + 'px';
775
776 height = (page.pageHeight - 1 - (parseInt(areaElement.style.top) +
777 parseInt(areaElement.style.height)));
778 height = (height < 0) ? 0 : height;
779 width = (page.pageWidth) - parseInt(areaElement.style.left);
780 width = (width < 0) ? 0 : width;
781 $('sc_drag_shadow_bottom').style.height = height + 'px';
782 $('sc_drag_shadow_bottom').style.width = width + 'px';
783 },
784
785 /**
786 * Remove selection area
787 */
788 removeSelectionArea: function() {
789 document.removeEventListener('mousedown', page.onMouseDown, false);
790 document.removeEventListener('mousemove', page.onMouseMove, false);
791 document.removeEventListener('mouseup', page.onMouseUp, false);
792 $('sc_drag_container').removeEventListener('dblclick',function() {
793 page.removeSelectionArea();
794 page.sendMessage({msg: 'capture_selected'});}, false);
795 page.removeElement('sc_drag_area_protector');
796 page.removeElement('sc_drag_area');
797 page.isSelectionAreaTurnOn = false;
798 },
799
800 /**
801 * Refresh the size info
802 */
803 updateSize: function() {
804 var width = Math.abs(page.endX - page.startX);
805 var height = Math.abs(page.endY - page.startY);
806 $('sc_drag_size').innerText = page.calculateSizeAfterZooming(width) +
807 ' x ' + page.calculateSizeAfterZooming(height);
808 },
809
810 /**
811 * create div
812 */
813 createDiv: function(parent, id) {
814 var divElement = document.createElement('div');
815 divElement.id = id;
816 parent.appendChild(divElement);
817 return divElement;
818 },
819
820 /**
821 * Remove an element
822 */
823 removeElement: function(id) {
824 if($(id)) {
825 $(id).parentNode.removeChild($(id));
826 }
827 },
828
829 injectCssResource: function(cssResource) {
830 var css = document.createElement('LINK');
831 css.type = 'text/css';
832 css.rel = 'stylesheet';
833 css.href = chrome.extension.getURL(cssResource);
834 (document.head || document.body || document.documentElement).
835 appendChild(css);
836 },
837
838 injectJavaScriptResource: function(scriptResource) {
839 var script = document.createElement("script");
840 script.type = "text/javascript";
841 script.charset = "utf-8";
842 script.src = chrome.extension.getURL(scriptResource);
843 (document.head || document.body || document.documentElement).
844 appendChild(script);
845 },
846
847 /**
848 * Remove an element
849 */
avm99963476a2a62021-02-07 00:40:02 +0100850 init: function() {
avm9996304def3e2016-11-27 22:53:05 +0100851 if (document.body.hasAttribute('screen_capture_injected')) {
852 return;
853 }
avm99963476a2a62021-02-07 00:40:02 +0100854 document.body.setAttribute('screen_capture_injected', true);
avm9996304def3e2016-11-27 22:53:05 +0100855 if (isPageCapturable()) {
856 chrome.extension.sendMessage({msg: 'page_capturable'});
857 } else {
858 chrome.extension.sendMessage({msg: 'page_uncapturable'});
859 }
860 this.injectCssResource('style.css');
861 this.addMessageListener();
862 this.injectJavaScriptResource("js/page_context.js");
863
864 // Retrieve original width of view port and cache.
865 page.getOriginalViewPortWidth();
866 }
867};
868
869/**
870 * Indicate if the current page can be captured.
871 */
872var isPageCapturable = function() {
873 return !page.checkPageIsOnlyEmbedElement();
874};
875
876function $(id) {
877 return document.getElementById(id);
878}
879
880page.init();
881
882window.addEventListener('resize', function() {
883 if (page.isSelectionAreaTurnOn) {
884 page.removeSelectionArea();
885 page.showSelectionArea();
886 }
887
888 // Reget original width of view port if browser window resized or page zoomed.
889 page.getOriginalViewPortWidth();
890}, false);