mirror of
https://github.com/dgtlmoon/changedetection.io.git
synced 2026-10-03 02:28:13 +00:00
WIP
This commit is contained in:
@@ -1119,12 +1119,11 @@ def changedetection_app(config=None, datastore_o=None):
|
||||
with sync_playwright() as p:
|
||||
browser = p.chromium.connect_over_cdp("ws://127.0.0.1:3000")
|
||||
page = browser.new_page()
|
||||
page.set_viewport_size({"width": 1220, "height": 800})
|
||||
page.goto(watch['url'])
|
||||
# time.sleep(3)
|
||||
#time.sleep(3)
|
||||
# https://github.com/microsoft/playwright/issues/620
|
||||
screenshot = page.screenshot(type='jpeg', clip={'x': 1.0, 'y': 1.0, 'width': 1280, 'height': 1024})
|
||||
screenshot = page.screenshot(type='jpeg', full_page=True)
|
||||
|
||||
# Could be made a lot faster
|
||||
# https://toruskit.com/blog/how-to-get-element-bounds-without-reflow/
|
||||
|
||||
@@ -1141,13 +1140,13 @@ def changedetection_app(config=None, datastore_o=None):
|
||||
var bbox;
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
bbox = elements[i].getBoundingClientRect();
|
||||
|
||||
if (! bbox['width'] || !bbox['height'] ) {
|
||||
if ( bbox['width'] == window.innerWidth ) {
|
||||
continue;
|
||||
}
|
||||
if (bbox['width'] >500 && bbox['height'] >500 ) {
|
||||
if (bbox['width'] <10 || bbox['height'] <10 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(! 'textContent' in elements[i] || elements[i].textContent.length < 2 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* debounce
|
||||
* @param {integer} milliseconds This param indicates the number of milliseconds
|
||||
* to wait after the last call before calling the original function.
|
||||
* @param {object} What "this" refers to in the returned function.
|
||||
* @return {function} This returns a function that when called will wait the
|
||||
* indicated number of milliseconds after the last call before
|
||||
* calling the original function.
|
||||
*/
|
||||
Function.prototype.debounce = function (milliseconds, context) {
|
||||
var baseFunction = this,
|
||||
timer = null,
|
||||
wait = milliseconds;
|
||||
|
||||
return function () {
|
||||
var self = context || this,
|
||||
args = arguments;
|
||||
|
||||
function complete() {
|
||||
baseFunction.apply(self, args);
|
||||
timer = null;
|
||||
}
|
||||
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
|
||||
timer = setTimeout(complete, wait);
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* throttle
|
||||
* @param {integer} milliseconds This param indicates the number of milliseconds
|
||||
* to wait between calls before calling the original function.
|
||||
* @param {object} What "this" refers to in the returned function.
|
||||
* @return {function} This returns a function that when called will wait the
|
||||
* indicated number of milliseconds between calls before
|
||||
* calling the original function.
|
||||
*/
|
||||
Function.prototype.throttle = function (milliseconds, context) {
|
||||
var baseFunction = this,
|
||||
lastEventTimestamp = null,
|
||||
limit = milliseconds;
|
||||
|
||||
return function () {
|
||||
var self = context || this,
|
||||
args = arguments,
|
||||
now = Date.now();
|
||||
|
||||
if (!lastEventTimestamp || now - lastEventTimestamp >= limit) {
|
||||
lastEventTimestamp = now;
|
||||
baseFunction.apply(self, args);
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -1,4 +1,6 @@
|
||||
$("img#selector-background").bind('load', function () {
|
||||
var current_selected_i;
|
||||
|
||||
function fetch_data() {
|
||||
// Image is ready
|
||||
$('.fetching-update-notice').html("Fetching element data..");
|
||||
|
||||
@@ -9,62 +11,51 @@ $("img#selector-background").bind('load', function () {
|
||||
$('.fetching-update-notice').html("Rendering..");
|
||||
reflow_selector(data);
|
||||
});
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
function reflow_selector(selector_data) {
|
||||
$('#selector-canvas').attr('width', $("img#selector-background").width());
|
||||
$('#selector-canvas').attr('height', $("img#selector-background").height());
|
||||
|
||||
//.attr('height', $("img#selector-background").height());
|
||||
// $('#selector-canvas').attr('width',
|
||||
// $("img#selector-background")[0].getBoundingClientRect().width);
|
||||
var c = document.getElementById("selector-canvas");
|
||||
var selector_image = document.getElementById("selector-background");
|
||||
var selector_image_rect = selector_image.getBoundingClientRect();
|
||||
|
||||
// could trim it according to the lowest/furtheret item in the dataset
|
||||
stage = new createjs.Stage("selector-canvas");
|
||||
|
||||
// to get onMouseOver & onMouseOut events, we need to enable them on the
|
||||
// stage:
|
||||
stage.enableMouseOver();
|
||||
output = new createjs.Text("Test press, click, doubleclick, mouseover, and mouseout", "14px Arial");
|
||||
output.x = output.y = 10;
|
||||
stage.addChild(output);
|
||||
|
||||
var squares = [];
|
||||
for (var i = 0; i < selector_data.length; i++) {
|
||||
|
||||
squares[i] = new createjs.Shape();
|
||||
|
||||
squares[i].graphics.beginFill("rgba(215,0,0,0.2)").drawRect(
|
||||
selector_data[i]['left'],
|
||||
selector_data[i]['top'],
|
||||
selector_data[i]['width'],
|
||||
selector_data[i]['height']);
|
||||
|
||||
squares[i].name = selector_data[i]['xpath'];
|
||||
stage.addChild(squares[i]);
|
||||
|
||||
squares[i].on("click", handleMouseEvent);
|
||||
squares[i].on("dblclick", handleMouseEvent);
|
||||
squares[i].on("mouseover", handleMouseEvent);
|
||||
squares[i].on("mouseout", handleMouseEvent);
|
||||
squares.push(squares[i]);
|
||||
}
|
||||
$('#selector-canvas').attr('height', selector_image_rect.height);
|
||||
$('#selector-canvas').attr('width', selector_image_rect.width);
|
||||
|
||||
|
||||
stage.update();
|
||||
$('.fetching-update-notice').hide();
|
||||
}
|
||||
var ctx = c.getContext("2d");
|
||||
ctx.strokeStyle = 'rgba(255,0,0,5)';
|
||||
|
||||
function handleMouseEvent(evt) {
|
||||
output.text = "evt.target: " + evt.target + ", evt.type: " + evt.type;
|
||||
// set this on resize too
|
||||
var x_scale = selector_image_rect.width / selector_image.naturalWidth;
|
||||
var y_scale = selector_image_rect.height / selector_image.naturalHeight;
|
||||
|
||||
if(evt.type == 'mouseover') {
|
||||
evt.target.graphics.beginFill("rgba(225,220,220,0.9)");
|
||||
}
|
||||
console.log(selector_data.length + " selectors found");
|
||||
$('#selector-canvas').bind('mousemove', function (e) {
|
||||
ctx.clearRect(0, 0, c.width, c.height);
|
||||
current_selected_i=null;
|
||||
|
||||
if(evt.type == 'mouseout') {
|
||||
evt.target.graphics.beginFill("rgba(1,1,1,0.4)");
|
||||
}
|
||||
// Reverse order - the most specific one should be deeper/"laster"
|
||||
for (var i = selector_data.length; i!=0; i--) {
|
||||
// draw all of them? let them choose somehow?
|
||||
var sel = selector_data[i-1];
|
||||
if (e.offsetY > sel.top * y_scale && e.offsetY < sel.top * y_scale + sel.height * y_scale
|
||||
&&
|
||||
e.offsetX > sel.left * y_scale && e.offsetX < sel.left * y_scale + sel.width * y_scale
|
||||
) {
|
||||
ctx.strokeRect(sel.left * x_scale, sel.top * y_scale, sel.width * x_scale, sel.height * y_scale);
|
||||
// no need to keep digging
|
||||
current_selected_i=i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// to save CPU, we're only updating when we need to, instead of on a tick:1
|
||||
stage.update();
|
||||
}.debounce(5));
|
||||
|
||||
$('#selector-canvas').bind('mousedown', function (e) {
|
||||
alert(selector_data[current_selected_i].xpath);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -450,7 +450,11 @@ ul {
|
||||
position: relative; }
|
||||
#selector-wrapper > img {
|
||||
position: absolute;
|
||||
z-index: 4; }
|
||||
z-index: 4;
|
||||
max-width: 100%; }
|
||||
#selector-wrapper > canvas {
|
||||
position: absolute;
|
||||
z-index: 5; }
|
||||
position: relative;
|
||||
z-index: 5;
|
||||
max-width: 100%; }
|
||||
#selector-wrapper > canvas:hover {
|
||||
cursor: pointer; }
|
||||
|
||||
@@ -637,14 +637,19 @@ ul {
|
||||
|
||||
#selector-wrapper {
|
||||
position: relative;
|
||||
|
||||
//width: 100%;
|
||||
> img {
|
||||
position: absolute;
|
||||
z-index: 4;
|
||||
max-width: 100%;
|
||||
}
|
||||
>canvas {
|
||||
position: absolute;
|
||||
position: relative;
|
||||
z-index: 5;
|
||||
max-width: 100%;
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
</script>
|
||||
<script type="text/javascript" src="{{url_for('static_content', group='js', filename='notifications.js')}}" defer></script>
|
||||
<script type="text/javascript" src="{{url_for('static_content', group='js', filename='visual-selector.js')}}" defer></script>
|
||||
<script src="https://code.createjs.com/easeljs-0.8.2.min.js"></script>
|
||||
<script type="text/javascript" src="{{url_for('static_content', group='js', filename='limit.js')}}" defer></script>
|
||||
|
||||
<div class="edit-form monospaced-textarea">
|
||||
|
||||
@@ -187,7 +187,13 @@ nav
|
||||
<div id="selector-wrapper">
|
||||
<!-- request the screenshot and get the element offset info ready -->
|
||||
<!-- use img src ready load to know everything is ready to map out -->
|
||||
<img id="selector-background" src="{{ url_for('visualselector_request_current_screenshot_and_metadata', uuid=uuid) }}"/>
|
||||
<img id="selector-background" />
|
||||
<script>
|
||||
$("img#selector-background").attr("src", "{{ url_for('visualselector_request_current_screenshot_and_metadata', uuid=uuid) }}");
|
||||
$("img#selector-background").bind('load', function () {
|
||||
fetch_data();
|
||||
});
|
||||
</script>
|
||||
<canvas id="selector-canvas"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user