Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(566)

Side by Side Diff: ios/web/web_state/js/resources/context_menu.js

Issue 2800003002: Pull context menu related APIs from core.js to their own file. (Closed)
Patch Set: git squash commit for context-menu. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ios/web/BUILD.gn ('k') | ios/web/web_state/js/resources/core.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2017 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.
4
5 /**
6 * @fileoverview APIs used by CRWContextMenuController.
7 */
8
9 goog.provide('__crWeb.contextMenu');
10
11 /** Beginning of anonymous object */
12 (function() {
13
14 /**
15 * Returns the url of the image or link under the selected point. Returns an
16 * empty string if no links or images are found.
17 * @param {number} x Horizontal center of the selected point.
18 * @param {number} y Vertical center of the selected point.
19 * @return {!Object} An object of the form {
20 * href, // URL of the link under the point
21 * innerText, // innerText of the link, if the selected element is a link
22 * src, // src of the image, if the selected element is an image
23 * title, // title of the image, if the selected
24 * referrerPolicy
25 * }
26 * where:
27 * <ul>
28 * <li>href, innerText are set if the selected element is a link.
29 * <li>src, title are set if the selected element is an image.
30 * <li>href is also set if the selected element is an image with a link.
31 * <li>referrerPolicy is the referrer policy to use for navigations away
32 * from the current page.
33 * </ul>
34 */
35 __gCrWeb['getElementFromPoint'] = function(x, y) {
36 var hitCoordinates = spiralCoordinates_(x, y);
37 for (var index = 0; index < hitCoordinates.length; index++) {
38 var coordinates = hitCoordinates[index];
39
40 var element = elementFromPoint_(coordinates.x, coordinates.y);
41 if (!element || !element.tagName) {
42 // Nothing under the hit point. Try the next hit point.
43 continue;
44 }
45
46 if (getComputedWebkitTouchCallout_(element) === 'none')
47 continue;
48 // Also check element's ancestors. A bound on the level is used here to
49 // avoid large overhead when no links or images are found.
50 var level = 0;
51 while (++level < 8 && element && element != document) {
52 var tagName = element.tagName;
53 if (!tagName)
54 continue;
55 tagName = tagName.toLowerCase();
56
57 if (tagName === 'input' || tagName === 'textarea' ||
58 tagName === 'select' || tagName === 'option') {
59 // If the element is a known input element, stop the spiral search and
60 // return empty results.
61 return {};
62 }
63
64 if (tagName === 'a' && element.href) {
65 // Found a link.
66 return {
67 href: element.href,
68 referrerPolicy: getReferrerPolicy_(element),
69 innerText: element.innerText
70 };
71 }
72
73 if (tagName === 'img' && element.src) {
74 // Found an image.
75 var result = {
76 src: element.src,
77 referrerPolicy: getReferrerPolicy_()
78 };
79 // Copy the title, if any.
80 if (element.title) {
81 result.title = element.title;
82 }
83 // Check if the image is also a link.
84 var parent = element.parentNode;
85 while (parent) {
86 if (parent.tagName &&
87 parent.tagName.toLowerCase() === 'a' &&
88 parent.href) {
89 // This regex identifies strings like void(0),
90 // void(0) ;void(0);, ;;;;
91 // which result in a NOP when executed as JavaScript.
92 var regex = RegExp("^javascript:(?:(?:void\\(0\\)|;)\\s*)+$");
93 if (parent.href.match(regex)) {
94 parent = parent.parentNode;
95 continue;
96 }
97 result.href = parent.href;
98 result.referrerPolicy = getReferrerPolicy_(parent);
99 break;
100 }
101 parent = parent.parentNode;
102 }
103 return result;
104 }
105 element = element.parentNode;
106 }
107 }
108 return {};
109 };
110
111 /**
112 * Suppresses the next click such that they are not handled by JS click
113 * event handlers.
114 * @type {void}
115 */
116 __gCrWeb['suppressNextClick'] = function() {
117 var suppressNextClick = function(evt) {
118 evt.preventDefault();
119 document.removeEventListener('click', suppressNextClick, false);
120 };
121 document.addEventListener('click', suppressNextClick);
122 };
123
124 /**
125 * Returns the margin in points around touchable elements (e.g. links for
126 * custom context menu).
127 * @type {number}
128 */
129 __gCrWeb['getPageWidth'] = function() {
130 var documentElement = document.documentElement;
131 var documentBody = document.body;
132 return Math.max(documentElement.clientWidth,
133 documentElement.scrollWidth,
134 documentElement.offsetWidth,
135 documentBody.scrollWidth,
136 documentBody.offsetWidth);
137 };
138
139 /**
140 * Implementation of document.elementFromPoint that is working for iOS4 and
141 * iOS5 and that also goes into frames and iframes.
142 * @private
143 */
144 var elementFromPoint_ = function(x, y) {
145 var elementFromPointIsUsingViewPortCoordinates = function(win) {
146 if (win.pageYOffset > 0) { // Page scrolled down.
147 return (win.document.elementFromPoint(
148 0, win.pageYOffset + win.innerHeight - 1) === null);
149 }
150 if (win.pageXOffset > 0) { // Page scrolled to the right.
151 return (win.document.elementFromPoint(
152 win.pageXOffset + win.innerWidth - 1, 0) === null);
153 }
154 return false; // No scrolling, don't care.
155 };
156
157 var newCoordinate = function(x, y) {
158 var coordinates = {
159 x: x, y: y,
160 viewPortX: x - window.pageXOffset, viewPortY: y - window.pageYOffset,
161 useViewPortCoordinates: false,
162 window: window
163 };
164 return coordinates;
165 };
166
167 // Returns the coordinates of the upper left corner of |obj| in the
168 // coordinates of the window that |obj| is in.
169 var getPositionInWindow = function(obj) {
170 var coord = { x: 0, y: 0 };
171 while (obj.offsetParent) {
172 coord.x += obj.offsetLeft;
173 coord.y += obj.offsetTop;
174 obj = obj.offsetParent;
175 }
176 return coord;
177 };
178
179 var elementsFromCoordinates = function(coordinates) {
180 coordinates.useViewPortCoordinates = coordinates.useViewPortCoordinates ||
181 elementFromPointIsUsingViewPortCoordinates(coordinates.window);
182
183 var currentElement = null;
184 if (coordinates.useViewPortCoordinates) {
185 currentElement = coordinates.window.document.elementFromPoint(
186 coordinates.viewPortX, coordinates.viewPortY);
187 } else {
188 currentElement = coordinates.window.document.elementFromPoint(
189 coordinates.x, coordinates.y);
190 }
191 // We have to check for tagName, because if a selection is made by the
192 // UIWebView, the element we will get won't have one.
193 if (!currentElement || !currentElement.tagName) {
194 return null;
195 }
196 if (currentElement.tagName.toLowerCase() === 'iframe' ||
197 currentElement.tagName.toLowerCase() === 'frame') {
198 // The following condition is true if the iframe is in a different
199 // domain; no further information is accessible.
200 if (typeof(currentElement.contentWindow.document) == 'undefined') {
201 return currentElement;
202 }
203 var framePosition = getPositionInWindow(currentElement);
204 coordinates.viewPortX -=
205 framePosition.x - coordinates.window.pageXOffset;
206 coordinates.viewPortY -=
207 framePosition.y - coordinates.window.pageYOffset;
208 coordinates.window = currentElement.contentWindow;
209 coordinates.x -= framePosition.x + coordinates.window.pageXOffset;
210 coordinates.y -= framePosition.y + coordinates.window.pageYOffset;
211 return elementsFromCoordinates(coordinates);
212 }
213 return currentElement;
214 };
215
216 return elementsFromCoordinates(newCoordinate(x, y));
217 };
218
219 /** @private */
220 var spiralCoordinates_ = function(x, y) {
221 var MAX_ANGLE = Math.PI * 2.0 * 3.0;
222 var POINT_COUNT = 30;
223 var ANGLE_STEP = MAX_ANGLE / POINT_COUNT;
224 var TOUCH_MARGIN = 25;
225 var SPEED = TOUCH_MARGIN / MAX_ANGLE;
226
227 var coordinates = [];
228 for (var index = 0; index < POINT_COUNT; index++) {
229 var angle = ANGLE_STEP * index;
230 var radius = angle * SPEED;
231
232 coordinates.push({x: x + Math.round(Math.cos(angle) * radius),
233 y: y + Math.round(Math.sin(angle) * radius)});
234 }
235
236 return coordinates;
237 };
238
239 /** @private */
240 var getComputedWebkitTouchCallout_ = function(element) {
241 return window.getComputedStyle(element, null)['webkitTouchCallout'];
242 };
243
244 /**
245 * Gets the referrer policy to use for navigations away from the current page.
246 * If a link element is passed, and it includes a rel=noreferrer tag, that
247 * will override the page setting.
248 * @param {HTMLElement=} opt_linkElement The link triggering the navigation.
249 * @return {string} The policy string.
250 * @private
251 */
252 var getReferrerPolicy_ = function(opt_linkElement) {
253 if (opt_linkElement) {
254 var rel = opt_linkElement.getAttribute('rel');
255 if (rel && rel.toLowerCase() == 'noreferrer') {
256 return 'never';
257 }
258 }
259
260 var metaTags = document.getElementsByTagName('meta');
261 for (var i = 0; i < metaTags.length; ++i) {
262 if (metaTags[i].name.toLowerCase() == 'referrer') {
263 return metaTags[i].content.toLowerCase();
264 }
265 }
266 return 'default';
267 };
268
269 }()); // End of anonymouse object
OLDNEW
« no previous file with comments | « ios/web/BUILD.gn ('k') | ios/web/web_state/js/resources/core.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698