blob: 2c5702d61d5889f91e426d428581dbbf5e4ba450 [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() {
244 chrome.extension.sendMessage({ msg: 'original_view_port_width'},
245 function(originalViewPortWidth) {
246 if (originalViewPortWidth) {
247 page.originalViewPortWidth = page.hasScrollBar('y') ?
248 originalViewPortWidth - page.defaultScrollBarWidth : originalViewPortWidth;
249 } else {
250 page.originalViewPortWidth = document.documentElement.clientWidth;
251 }
252 });
253 },
254
255 calculateSizeAfterZooming: function(originalSize) {
256 var originalViewPortWidth = page.originalViewPortWidth;
257 var currentViewPortWidth = document.documentElement.clientWidth;
258 if (originalViewPortWidth == currentViewPortWidth)
259 return originalSize;
260 return Math.round(
261 originalViewPortWidth * originalSize / currentViewPortWidth);
262 },
263
264 getZoomLevel: function() {
265 return page.originalViewPortWidth / document.documentElement.clientWidth;
266 },
267
268 handleRightFloatBoxInGmail: function() {
269 var mainframe = document.getElementById('canvas_frame');
270 var boxContainer = document.querySelector('body > .dw');
271 var fBody = mainframe.contentDocument.body;
272 if (fBody.clientHeight + fBody.scrollTop == fBody.scrollHeight) {
273 boxContainer.style.display = 'block';
274 } else {
275 boxContainer.style.display = 'none';
276 }
277 },
278
279 getViewPortSize: function() {
280 var result = {
281 width: document.documentElement.clientWidth,
282 height: document.documentElement.clientHeight
283 };
284
285 if (document.compatMode == 'BackCompat') {
286 result.width = document.body.clientWidth;
287 result.height = document.body.clientHeight;
288 }
289
290 return result;
291 },
292
293 /**
294 * Check if the page is only made of invisible embed elements.
295 */
296 checkPageIsOnlyEmbedElement: function() {
297 var bodyNode = document.body.children;
298 var isOnlyEmbed = false;
299 for (var i = 0; i < bodyNode.length; i++) {
300 var tagName = bodyNode[i].tagName;
301 if (tagName == 'OBJECT' || tagName == 'EMBED' || tagName == 'VIDEO' ||
302 tagName == 'SCRIPT' || tagName == 'LINK') {
303 isOnlyEmbed = true;
304 } else if (bodyNode[i].style.display != 'none'){
305 isOnlyEmbed = false;
306 break;
307 }
308 }
309 return isOnlyEmbed;
310 },
311
312 isGMailPage: function(){
313 var hostName = window.location.hostname;
314 if (hostName == 'mail.google.com' &&
315 document.getElementById('canvas_frame')) {
316 return true;
317 }
318 return false;
319 },
320
321 /**
322 * Receive messages from background page, and then decide what to do next
323 */
324 addMessageListener: function() {
325 chrome.extension.onMessage.addListener(function(request, sender, response) {
326 if (page.isSelectionAreaTurnOn) {
327 page.removeSelectionArea();
328 }
329 switch (request.msg) {
330 case 'capture_window': response(page.getWindowSize()); break;
331 case 'show_selection_area': page.showSelectionArea(); break;
332 case 'scroll_init': // Capture whole page.
333 response(page.scrollInit(0, 0, document.body.scrollWidth,
334 document.body.scrollHeight, 'captureWhole'));
335 break;
336 case 'scroll_next':
337 page.visibleWidth = request.visibleWidth;
338 page.visibleHeight = request.visibleHeight;
339 response(page.scrollNext());
340 break;
341 case 'capture_selected':
342 response(page.scrollInit(
343 page.startX, page.startY,
344 page.calculateSizeAfterZooming(page.endX - page.startX),
345 page.calculateSizeAfterZooming(page.endY - page.startY),
346 'captureSelected'));
347 break;
348 }
349 });
350 },
351
352 /**
353 * Send Message to background page
354 */
355 sendMessage: function(message) {
356 chrome.extension.sendMessage(message);
357 },
358
359 /**
360 * Initialize scrollbar position, and get the data browser
361 */
362 scrollInit: function(startX, startY, canvasWidth, canvasHeight, type) {
363 this.hookBodyScrollValue(true);
364 page.captureHeight = canvasHeight;
365 page.captureWidth = canvasWidth;
366 var docWidth = document.body.scrollWidth;
367 var docHeight = document.body.scrollHeight;
368 window.scrollTo(startX, startY);
369
370 this.handleFixedElements('top_left');
371 this.handleSecondToLastCapture();
372
373 if (page.isGMailPage() && type == 'captureWhole') {
374 var frame = document.getElementById('canvas_frame');
375 docHeight = page.captureHeight = canvasHeight =
376 frame.contentDocument.height;
377 docWidth = page.captureWidth = canvasWidth = frame.contentDocument.width;
378 frame.contentDocument.body.scrollTop = 0;
379 frame.contentDocument.body.scrollLeft = 0;
380 page.handleRightFloatBoxInGmail();
381 }
382 page.scrollXCount = 0;
383 page.scrollYCount = 1;
384 page.scrollX = window.scrollX; // document.body.scrollLeft
385 page.scrollY = window.scrollY;
386 var viewPortSize = page.getViewPortSize();
387 return {
388 'msg': 'scroll_init_done',
389 'startX': page.calculateSizeAfterZooming(startX),
390 'startY': page.calculateSizeAfterZooming(startY),
391 'scrollX': window.scrollX,
392 'scrollY': window.scrollY,
393 'docHeight': docHeight,
394 'docWidth': docWidth,
395 'visibleWidth': viewPortSize.width,
396 'visibleHeight': viewPortSize.height,
397 'canvasWidth': canvasWidth,
398 'canvasHeight': canvasHeight,
399 'scrollXCount': 0,
400 'scrollYCount': 0,
401 'zoom': page.getZoomLevel()
402 };
403 },
404
405 /**
406 * Calculate the next position of the scrollbar
407 */
408 scrollNext: function() {
409 if (page.scrollYCount * page.visibleWidth >= page.captureWidth) {
410 page.scrollXCount++;
411 page.scrollYCount = 0;
412 }
413 if (page.scrollXCount * page.visibleHeight < page.captureHeight) {
414 this.restoreBottomRightOfFixedPositionElements();
415 var viewPortSize = page.getViewPortSize();
416 window.scrollTo(
417 page.scrollYCount * viewPortSize.width + page.scrollX,
418 page.scrollXCount * viewPortSize.height + page.scrollY);
419
420 var pagePosition = this.detectPagePosition();
421 if (pagePosition) {
422 this.handleFixedElements(pagePosition);
423 } else {
424 this.hideAllFixedPositionedElements();
425 }
426 this.handleSecondToLastCapture();
427
428 if (page.isGMailPage()) {
429 var frame = document.getElementById('canvas_frame');
430 frame.contentDocument.body.scrollLeft =
431 page.scrollYCount * viewPortSize.width;
432 frame.contentDocument.body.scrollTop =
433 page.scrollXCount * viewPortSize.height;
434 page.handleRightFloatBoxInGmail();
435 }
436 var x = page.scrollXCount;
437 var y = page.scrollYCount;
438 page.scrollYCount++;
439 return { msg: 'scroll_next_done',scrollXCount: x, scrollYCount: y };
440 } else {
441 window.scrollTo(page.startX, page.startY);
442 this.restoreFixedElements();
443 this.hookBodyScrollValue(false);
444 return {'msg': 'scroll_finished'};
445 }
446 },
447
448 /**
449 * Show the selection Area
450 */
451 showSelectionArea: function() {
452 page.createFloatLayer();
453 setTimeout(page.createSelectionArea, 100);
454 },
455
456 getWindowSize: function() {
457 var docWidth = document.body.clientWidth;
458 var docHeight = document.body.clientHeight;
459 if (page.isGMailPage()) {
460 var frame = document.getElementById('canvas_frame');
461 docHeight = frame.contentDocument.height;
462 docWidth = frame.contentDocument.width;
463 }
464 return {'msg':'capture_window',
465 'docWidth': docWidth,
466 'docHeight': docHeight};
467 },
468
469 getSelectionSize: function() {
470 page.removeSelectionArea();
471 setTimeout(function() {
472 page.sendMessage({
473 'msg': 'capture_selected',
474 'x': page.startX,
475 'y': page.startY,
476 'width': page.endX - page.startX,
477 'height': page.endY - page.startY,
478 'visibleWidth': document.documentElement.clientWidth,
479 'visibleHeight': document.documentElement.clientHeight,
480 'docWidth': document.body.clientWidth,
481 'docHeight': document.body.clientHeight
482 })}, 100);
483 },
484
485 /**
486 * Create a float layer on the webpage
487 */
488 createFloatLayer: function() {
489 page.createDiv(document.body, 'sc_drag_area_protector');
490 },
491
492 matchMarginValue: function(str) {
493 return str.match(/\d+/);
494 },
495
496 /**
497 * Load the screenshot area interface
498 */
499 createSelectionArea: function() {
500 var areaProtector = $('sc_drag_area_protector');
501 var zoom = page.getZoomLevel();
502 var bodyStyle = window.getComputedStyle(document.body, null);
503 if ('relative' == bodyStyle['position']) {
504 page.marginTop = page.matchMarginValue(bodyStyle['marginTop']);
505 page.marginLeft = page.matchMarginValue(bodyStyle['marginLeft']);
506 areaProtector.style.top = - parseInt(page.marginTop) + 'px';
507 areaProtector.style.left = - parseInt(page.marginLeft) + 'px';
508 }
509 areaProtector.style.width =
510 Math.round((document.body.clientWidth + parseInt(page.marginLeft)) / zoom) + 'px';
511 areaProtector.style.height =
512 Math.round((document.body.clientHeight + parseInt(page.marginTop)) / zoom) + 'px';
513 areaProtector.onclick = function() {
514 event.stopPropagation();
515 return false;
516 };
517
518 // Create elements for area capture.
519 page.createDiv(areaProtector, 'sc_drag_shadow_top');
520 page.createDiv(areaProtector, 'sc_drag_shadow_bottom');
521 page.createDiv(areaProtector, 'sc_drag_shadow_left');
522 page.createDiv(areaProtector, 'sc_drag_shadow_right');
523
524 var areaElement = page.createDiv(areaProtector, 'sc_drag_area');
525 page.createDiv(areaElement, 'sc_drag_container');
526 page.createDiv(areaElement, 'sc_drag_size');
527
528 // Add event listener for 'cancel' and 'capture' button.
529 var cancel = page.createDiv(areaElement, 'sc_drag_cancel');
530 cancel.addEventListener('mousedown', function () {
531 // Remove area capture containers and event listeners.
532 page.removeSelectionArea();
533 }, true);
534 cancel.innerHTML = chrome.i18n.getMessage("cancel");
535
536 var crop = page.createDiv(areaElement, 'sc_drag_crop');
537 crop.addEventListener('mousedown', function() {
538 page.removeSelectionArea();
539 page.sendMessage({msg: 'capture_selected'});
540 }, false);
541 crop.innerHTML = chrome.i18n.getMessage('ok');
542
543 page.createDiv(areaElement, 'sc_drag_north_west');
544 page.createDiv(areaElement, 'sc_drag_north_east');
545 page.createDiv(areaElement, 'sc_drag_south_east');
546 page.createDiv(areaElement, 'sc_drag_south_west');
547
548 areaProtector.addEventListener('mousedown', page.onMouseDown, false);
549 document.addEventListener('mousemove', page.onMouseMove, false);
550 document.addEventListener('mouseup', page.onMouseUp, false);
551 $('sc_drag_container').addEventListener('dblclick', function() {
552 page.removeSelectionArea();
553 page.sendMessage({msg: 'capture_selected'});
554 }, false);
555
556 page.pageHeight = $('sc_drag_area_protector').clientHeight;
557 page.pageWidth = $('sc_drag_area_protector').clientWidth;
558
559 var areaElement = $('sc_drag_area');
560 areaElement.style.left = page.getElementLeft(areaElement) + 'px';
561 areaElement.style.top = page.getElementTop(areaElement) + 'px';
562
563 page.startX = page.getElementLeft(areaElement);
564 page.startY = page.getElementTop(areaElement);
565 page.endX = page.getElementLeft(areaElement) + 250;
566 page.endY = page.getElementTop(areaElement) + 150;
567
568 areaElement.style.width = '250px';
569 areaElement.style.height = '150px';
570 page.isSelectionAreaTurnOn = true;
571 page.updateShadow(areaElement);
572 page.updateSize();
573 },
574
575 getElementLeft: function(obj) {
576 return (document.body.scrollLeft +
577 (document.documentElement.clientWidth -
578 obj.offsetWidth) / 2);
579 },
580
581 getElementTop: function(obj) {
582 return (document.body.scrollTop +
583 (document.documentElement.clientHeight - 200 -
584 obj.offsetHeight) / 2);
585 },
586
587 /**
588 * Init selection area due to the position of the mouse when mouse down
589 */
590 onMouseDown: function() {
591 if (event.button != 2) {
592 var element = event.target;
593
594 if (element) {
595 var elementName = element.tagName;
596 if (elementName && document) {
597 page.isMouseDown = true;
598
599 var areaElement = $('sc_drag_area');
600 var xPosition = event.pageX;
601 var yPosition = event.pageY;
602
603 if (areaElement) {
604 if (element == $('sc_drag_container')) {
605 page.moving = true;
606 page.moveX = xPosition - areaElement.offsetLeft;
607 page.moveY = yPosition - areaElement.offsetTop;
608 } else if (element == $('sc_drag_north_east')) {
609 page.resizing = true;
610 page.startX = areaElement.offsetLeft;
611 page.startY = areaElement.offsetTop + areaElement.clientHeight;
612 } else if (element == $('sc_drag_north_west')) {
613 page.resizing = true;
614 page.startX = areaElement.offsetLeft + areaElement.clientWidth;
615 page.startY = areaElement.offsetTop + areaElement.clientHeight;
616 } else if (element == $('sc_drag_south_east')) {
617 page.resizing = true;
618 page.startX = areaElement.offsetLeft;
619 page.startY = areaElement.offsetTop;
620 } else if (element == $('sc_drag_south_west')) {
621 page.resizing = true;
622 page.startX = areaElement.offsetLeft + areaElement.clientWidth;
623 page.startY = areaElement.offsetTop;
624 } else {
625 page.dragging = true;
626 page.endX = 0;
627 page.endY = 0;
628 page.endX = page.startX = xPosition;
629 page.endY = page.startY = yPosition;
630 }
631 }
632 event.preventDefault();
633 }
634 }
635 }
636 },
637
638 /**
639 * Change selection area position when mouse moved
640 */
641 onMouseMove: function() {
642 var element = event.target;
643 if (element && page.isMouseDown) {
644 var areaElement = $('sc_drag_area');
645 if (areaElement) {
646 var xPosition = event.pageX;
647 var yPosition = event.pageY;
648 if (page.dragging || page.resizing) {
649 var width = 0;
650 var height = 0;
651 var zoom = page.getZoomLevel();
652 var viewWidth = Math.round(document.body.clientWidth / zoom);
653 var viewHeight = Math.round(document.body.clientHeight / zoom);
654 if (xPosition > viewWidth) {
655 xPosition = viewWidth;
656 } else if (xPosition < 0) {
657 xPosition = 0;
658 }
659 if (yPosition > viewHeight) {
660 yPosition = viewHeight;
661 } else if (yPosition < 0) {
662 yPosition = 0;
663 }
664 page.endX = xPosition;
665 page.endY = yPosition;
666 if (page.startX > page.endX) {
667 width = page.startX - page.endX;
668 areaElement.style.left = xPosition + 'px';
669 } else {
670 width = page.endX - page.startX;
671 areaElement.style.left = page.startX + 'px';
672 }
673 if (page.startY > page.endY) {
674 height = page.startY - page.endY;
675 areaElement.style.top = page.endY + 'px';
676 } else {
677 height = page.endY - page.startY;
678 areaElement.style.top = page.startY + 'px';
679 }
680 areaElement.style.height = height + 'px';
681 areaElement.style.width = width + 'px';
682 if (window.innerWidth < xPosition) {
683 document.body.scrollLeft = xPosition - window.innerWidth;
684 }
685 if (document.body.scrollTop + window.innerHeight < yPosition + 25) {
686 document.body.scrollTop = yPosition - window.innerHeight + 25;
687 }
688 if (yPosition < document.body.scrollTop) {
689 document.body.scrollTop -= 25;
690 }
691 } else if (page.moving) {
692 var newXPosition = xPosition - page.moveX;
693 var newYPosition = yPosition - page.moveY;
694 if (newXPosition < 0) {
695 newXPosition = 0;
696 } else if (newXPosition + areaElement.clientWidth > page.pageWidth) {
697 newXPosition = page.pageWidth - areaElement.clientWidth;
698 }
699 if (newYPosition < 0) {
700 newYPosition = 0;
701 } else if (newYPosition + areaElement.clientHeight >
702 page.pageHeight) {
703 newYPosition = page.pageHeight - areaElement.clientHeight;
704 }
705
706 areaElement.style.left = newXPosition + 'px';
707 areaElement.style.top = newYPosition + 'px';
708 page.endX = newXPosition + areaElement.clientWidth;
709 page.startX = newXPosition;
710 page.endY = newYPosition + areaElement.clientHeight;
711 page.startY = newYPosition;
712
713 }
714 var crop = document.getElementById('sc_drag_crop');
715 var cancel = document.getElementById('sc_drag_cancel');
716 if (event.pageY + 25 > document.body.clientHeight) {
717 crop.style.bottom = 0;
718 cancel.style.bottom = 0
719 } else {
720 crop.style.bottom = '-25px';
721 cancel.style.bottom = '-25px';
722 }
723
724 var dragSizeContainer = document.getElementById('sc_drag_size');
725 if (event.pageY < 18) {
726 dragSizeContainer.style.top = 0;
727 } else {
728 dragSizeContainer.style.top = '-18px';
729 }
730 page.updateShadow(areaElement);
731 page.updateSize();
732
733 }
734 }
735 },
736
737 /**
738 * Fix the selection area position when mouse up
739 */
740 onMouseUp: function() {
741 page.isMouseDown = false;
742 if (event.button != 2) {
743 page.resizing = false;
744 page.dragging = false;
745 page.moving = false;
746 page.moveX = 0;
747 page.moveY = 0;
748 var temp;
749 if (page.endX < page.startX) {
750 temp = page.endX;
751 page.endX = page.startX;
752 page.startX = temp;
753 }
754 if (page.endY < page.startY) {
755 temp = page.endY;
756 page.endY = page.startY;
757 page.startY = temp;
758 }
759 }
760 },
761
762 /**
763 * Update the location of the shadow layer
764 */
765 updateShadow: function(areaElement) {
766 $('sc_drag_shadow_top').style.height =
767 parseInt(areaElement.style.top) + 'px';
768 $('sc_drag_shadow_top').style.width = (parseInt(areaElement.style.left) +
769 parseInt(areaElement.style.width) + 1) + 'px';
770 $('sc_drag_shadow_left').style.height =
771 (page.pageHeight - parseInt(areaElement.style.top)) + 'px';
772 $('sc_drag_shadow_left').style.width =
773 parseInt(areaElement.style.left) + 'px';
774
775 var height = (parseInt(areaElement.style.top) +
776 parseInt(areaElement.style.height) + 1);
777 height = (height < 0) ? 0 : height;
778 var width = (page.pageWidth) - 1 - (parseInt(areaElement.style.left) +
779 parseInt(areaElement.style.width));
780 width = (width < 0) ? 0 : width;
781 $('sc_drag_shadow_right').style.height = height + 'px';
782 $('sc_drag_shadow_right').style.width = width + 'px';
783
784 height = (page.pageHeight - 1 - (parseInt(areaElement.style.top) +
785 parseInt(areaElement.style.height)));
786 height = (height < 0) ? 0 : height;
787 width = (page.pageWidth) - parseInt(areaElement.style.left);
788 width = (width < 0) ? 0 : width;
789 $('sc_drag_shadow_bottom').style.height = height + 'px';
790 $('sc_drag_shadow_bottom').style.width = width + 'px';
791 },
792
793 /**
794 * Remove selection area
795 */
796 removeSelectionArea: function() {
797 document.removeEventListener('mousedown', page.onMouseDown, false);
798 document.removeEventListener('mousemove', page.onMouseMove, false);
799 document.removeEventListener('mouseup', page.onMouseUp, false);
800 $('sc_drag_container').removeEventListener('dblclick',function() {
801 page.removeSelectionArea();
802 page.sendMessage({msg: 'capture_selected'});}, false);
803 page.removeElement('sc_drag_area_protector');
804 page.removeElement('sc_drag_area');
805 page.isSelectionAreaTurnOn = false;
806 },
807
808 /**
809 * Refresh the size info
810 */
811 updateSize: function() {
812 var width = Math.abs(page.endX - page.startX);
813 var height = Math.abs(page.endY - page.startY);
814 $('sc_drag_size').innerText = page.calculateSizeAfterZooming(width) +
815 ' x ' + page.calculateSizeAfterZooming(height);
816 },
817
818 /**
819 * create div
820 */
821 createDiv: function(parent, id) {
822 var divElement = document.createElement('div');
823 divElement.id = id;
824 parent.appendChild(divElement);
825 return divElement;
826 },
827
828 /**
829 * Remove an element
830 */
831 removeElement: function(id) {
832 if($(id)) {
833 $(id).parentNode.removeChild($(id));
834 }
835 },
836
837 injectCssResource: function(cssResource) {
838 var css = document.createElement('LINK');
839 css.type = 'text/css';
840 css.rel = 'stylesheet';
841 css.href = chrome.extension.getURL(cssResource);
842 (document.head || document.body || document.documentElement).
843 appendChild(css);
844 },
845
846 injectJavaScriptResource: function(scriptResource) {
847 var script = document.createElement("script");
848 script.type = "text/javascript";
849 script.charset = "utf-8";
850 script.src = chrome.extension.getURL(scriptResource);
851 (document.head || document.body || document.documentElement).
852 appendChild(script);
853 },
854
855 /**
856 * Remove an element
857 */
858 init: function() {
859 if (document.body.hasAttribute('screen_capture_injected')) {
860 return;
861 }
862 if (isPageCapturable()) {
863 chrome.extension.sendMessage({msg: 'page_capturable'});
864 } else {
865 chrome.extension.sendMessage({msg: 'page_uncapturable'});
866 }
867 this.injectCssResource('style.css');
868 this.addMessageListener();
869 this.injectJavaScriptResource("js/page_context.js");
870
871 // Retrieve original width of view port and cache.
872 page.getOriginalViewPortWidth();
873 }
874};
875
876/**
877 * Indicate if the current page can be captured.
878 */
879var isPageCapturable = function() {
880 return !page.checkPageIsOnlyEmbedElement();
881};
882
883function $(id) {
884 return document.getElementById(id);
885}
886
887page.init();
888
889window.addEventListener('resize', function() {
890 if (page.isSelectionAreaTurnOn) {
891 page.removeSelectionArea();
892 page.showSelectionArea();
893 }
894
895 // Reget original width of view port if browser window resized or page zoomed.
896 page.getOriginalViewPortWidth();
897}, false);
898
899// Send page url for retriving and parsing access token for facebook and picasa.
900var message = {
901 msg: 'url_for_access_token',
902 url: window.location.href
903}
904if (window.location.href.indexOf('https://api.weibo.com/oauth2/default.html') == 0) {
905 message.siteId = 'sina'
906}
907page.sendMessage(message);