HTML 带有 Java 和 Vaadin 的元素选择器
HTML Element Selector with Java & Vaadin
我目前正在构建一个 Vaadin Webapp,用于从网站获取某些 HTML-Elements 的路径。因此,我想
- 在 Vaadin 页面的 IFrame / BrowserFrame 中加载网页
- 让用户直观地点击突出显示的 HTML-元素(类似于 http://selectorgadget.com/)
- 生成路径(XPath 似乎是最好的选择)和
- 在 Vaadin 页面的公式中显示它(在同一站点上,以检查选择)
我的问题:
- 从 iFrame 内的网站到 Vaadin App 的路径数据真的可以传输吗?
- 是否可以使用 Vaadin 应用程序提供的技术选择 html 元素(这样我就不需要 IFrame 中的任何 Javascript)?
- 是否有 iFrame 以外的技术可以更好地实现我的目标?
提前致谢!
我已经找到了解决办法:
iframe 内的 Javascript 和 VaadinUI 之间的完全交互(因为要构建的组件必须集成到现有的 VaadinUI 中)可以通过以下方式实现:
1. 将脚本、css 和其他需要的 Html 内容注入加载的网页。解决方案的选择脚本取自 here
var elements = {
top: $('#selector-top'),
left: $('#selector-left'),
right: $('#selector-right'),
bottom: $('#selector-bottom')
};
function registerMouseMove() {
$(document).mousemove(function(event) {
if (event.target.id.indexOf('selector') !== -1 || event.target.tagName === 'BODY' || event.target.tagName === 'HTML') return;
var $target = $(event.target);
targetOffset = $target[0].getBoundingClientRect(),
targetHeight = targetOffset.height,
targetWidth = targetOffset.width;
//console.log(targetOffset);
elements.top.css({
left: (targetOffset.left - 4),
top: (targetOffset.top - 4),
width: (targetWidth + 5)
});
elements.bottom.css({
top: (targetOffset.top + targetHeight + 1),
left: (targetOffset.left - 3),
width: (targetWidth + 4)
});
elements.left.css({
left: (targetOffset.left - 5),
top: (targetOffset.top - 4),
height: (targetHeight + 8)
});
elements.right.css({
left: (targetOffset.left + targetWidth + 1),
top: (targetOffset.top - 4),
height: (targetHeight + 8)
});
});
};
function unregisterMouseMove() {
$(document).unbind();
elements.top.css({
left: 0,
top: 0,
width: 0
});
elements.bottom.css({
top: 0,
left: 0,
width: 0
});
elements.left.css({
left: 0,
top: 0,
height: 0
});
elements.right.css({
left: 0,
top: 0,
height: 0
});
};
function registerClickListener() {
$(document).click(function(event) {
if (event.target.id.indexOf('selector') !== -1 || event.target.tagName === 'BODY' || event.target.tagName === 'HTML')
return;
var target = event.target;
var xpath = Xpath.getElementXPath(target);
$.ajax({
type: "POST",
url: "/rest?text=" + xpath //,
});
console.log(xpath);
});
};
function unregisterClickListener() {
$(document).off("click");
}
function disableLinks() {
$('a').click(function(event) {
event.preventDefault();
});
}
function enableLinks() {
$('a').unbind('click');
}
function startSelecting() {
registerMouseMove();
registerClickListener();
disableLinks();
}
function stopSelecting() {
unregisterClickListener();
unregisterMouseMove();
enableLinks();
}
<!-- only for demonstration, delete! for use in programm call startSelecting by a Javascript call from the UI -->
window.onload = function(event) {
startSelecting();
};
#selector-top,
#selector-bottom {
background: blue;
height: 3px;
position: fixed;
transition: all 300ms ease;
}
#selector-left,
#selector-right {
background: blue;
width: 3px;
position: fixed;
transition: all 300ms ease;
}
<div id="selector">
<div id="selector-top"></div>
<div id="selector-left"></div>
<div id="selector-right"></div>
<div id="selector-bottom"></div>
</div>
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js " /></script>
<script type="text/javascript" src="link/to/xpath.js"></script>
</head>
<body>
<span><b>Test</b></span>
<p>trallalalala</p>
</body>
</html>
2. 使用 Vaadins Javascript 调用(参见 here)和一些 Javascript 在 iframe 中调用定义的 Javascripts ] 路径魔法:
Page.getCurrent().getJavaScript().execute("window.frames[1].frameElement.contentWindow.startSelecting();");
3. 使用 Firebugs xpath.js 脚本在单击项目时获取 XPath(注意 license):
var xpath = Xpath.getElementXPath(event.target);
4. 使用 ajax rest 调用 post 数据到您的 Vaadin 应用程序:
$.ajax({
type: "POST",
url: "/rest?text="+xpath
});
5. 创建一个 rest 接口,即使用 Vaadin Broadcaster 将 xpath 值广播到 UI。有关如何使用 Broadcaster 和 Push for VaadinUI 的详细信息,请参阅 Eric G。 post
@RequestMapping("/rest")
public String sayHello(@RequestParam(value = "text", required = true) String text) {
Broadcaster.broadcast(text);
}
6. 最后:VaadinUI 接收广播并打印 xpath,例如到 TextField 并进一步处理它
唯一的缺点是,它只能用于单用户应用程序,因为我无法区分同一 UI 的不同实例,即一个休息调用将开始向 UI 的所有实例广播,并将相同的数据传输给它们。
希望这对未来的访客有所帮助。 :)
我目前正在构建一个 Vaadin Webapp,用于从网站获取某些 HTML-Elements 的路径。因此,我想
- 在 Vaadin 页面的 IFrame / BrowserFrame 中加载网页
- 让用户直观地点击突出显示的 HTML-元素(类似于 http://selectorgadget.com/)
- 生成路径(XPath 似乎是最好的选择)和
- 在 Vaadin 页面的公式中显示它(在同一站点上,以检查选择)
我的问题:
- 从 iFrame 内的网站到 Vaadin App 的路径数据真的可以传输吗?
- 是否可以使用 Vaadin 应用程序提供的技术选择 html 元素(这样我就不需要 IFrame 中的任何 Javascript)?
- 是否有 iFrame 以外的技术可以更好地实现我的目标?
提前致谢!
我已经找到了解决办法: iframe 内的 Javascript 和 VaadinUI 之间的完全交互(因为要构建的组件必须集成到现有的 VaadinUI 中)可以通过以下方式实现:
1. 将脚本、css 和其他需要的 Html 内容注入加载的网页。解决方案的选择脚本取自 here
var elements = {
top: $('#selector-top'),
left: $('#selector-left'),
right: $('#selector-right'),
bottom: $('#selector-bottom')
};
function registerMouseMove() {
$(document).mousemove(function(event) {
if (event.target.id.indexOf('selector') !== -1 || event.target.tagName === 'BODY' || event.target.tagName === 'HTML') return;
var $target = $(event.target);
targetOffset = $target[0].getBoundingClientRect(),
targetHeight = targetOffset.height,
targetWidth = targetOffset.width;
//console.log(targetOffset);
elements.top.css({
left: (targetOffset.left - 4),
top: (targetOffset.top - 4),
width: (targetWidth + 5)
});
elements.bottom.css({
top: (targetOffset.top + targetHeight + 1),
left: (targetOffset.left - 3),
width: (targetWidth + 4)
});
elements.left.css({
left: (targetOffset.left - 5),
top: (targetOffset.top - 4),
height: (targetHeight + 8)
});
elements.right.css({
left: (targetOffset.left + targetWidth + 1),
top: (targetOffset.top - 4),
height: (targetHeight + 8)
});
});
};
function unregisterMouseMove() {
$(document).unbind();
elements.top.css({
left: 0,
top: 0,
width: 0
});
elements.bottom.css({
top: 0,
left: 0,
width: 0
});
elements.left.css({
left: 0,
top: 0,
height: 0
});
elements.right.css({
left: 0,
top: 0,
height: 0
});
};
function registerClickListener() {
$(document).click(function(event) {
if (event.target.id.indexOf('selector') !== -1 || event.target.tagName === 'BODY' || event.target.tagName === 'HTML')
return;
var target = event.target;
var xpath = Xpath.getElementXPath(target);
$.ajax({
type: "POST",
url: "/rest?text=" + xpath //,
});
console.log(xpath);
});
};
function unregisterClickListener() {
$(document).off("click");
}
function disableLinks() {
$('a').click(function(event) {
event.preventDefault();
});
}
function enableLinks() {
$('a').unbind('click');
}
function startSelecting() {
registerMouseMove();
registerClickListener();
disableLinks();
}
function stopSelecting() {
unregisterClickListener();
unregisterMouseMove();
enableLinks();
}
<!-- only for demonstration, delete! for use in programm call startSelecting by a Javascript call from the UI -->
window.onload = function(event) {
startSelecting();
};
#selector-top,
#selector-bottom {
background: blue;
height: 3px;
position: fixed;
transition: all 300ms ease;
}
#selector-left,
#selector-right {
background: blue;
width: 3px;
position: fixed;
transition: all 300ms ease;
}
<div id="selector">
<div id="selector-top"></div>
<div id="selector-left"></div>
<div id="selector-right"></div>
<div id="selector-bottom"></div>
</div>
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js " /></script>
<script type="text/javascript" src="link/to/xpath.js"></script>
</head>
<body>
<span><b>Test</b></span>
<p>trallalalala</p>
</body>
</html>
2. 使用 Vaadins Javascript 调用(参见 here)和一些 Javascript 在 iframe 中调用定义的 Javascripts ] 路径魔法:
Page.getCurrent().getJavaScript().execute("window.frames[1].frameElement.contentWindow.startSelecting();");
3. 使用 Firebugs xpath.js 脚本在单击项目时获取 XPath(注意 license):
var xpath = Xpath.getElementXPath(event.target);
4. 使用 ajax rest 调用 post 数据到您的 Vaadin 应用程序:
$.ajax({
type: "POST",
url: "/rest?text="+xpath
});
5. 创建一个 rest 接口,即使用 Vaadin Broadcaster 将 xpath 值广播到 UI。有关如何使用 Broadcaster 和 Push for VaadinUI 的详细信息,请参阅 Eric G。 post
@RequestMapping("/rest")
public String sayHello(@RequestParam(value = "text", required = true) String text) {
Broadcaster.broadcast(text);
}
6. 最后:VaadinUI 接收广播并打印 xpath,例如到 TextField 并进一步处理它
唯一的缺点是,它只能用于单用户应用程序,因为我无法区分同一 UI 的不同实例,即一个休息调用将开始向 UI 的所有实例广播,并将相同的数据传输给它们。
希望这对未来的访客有所帮助。 :)