You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
251 lines
9.4 KiB
251 lines
9.4 KiB
// Copyright (C) 2021 Leigh Morresi (dgtlmoon@gmail.com)
|
|
// All rights reserved.
|
|
// yes - this is really a hack, if you are a front-ender and want to help, please get in touch!
|
|
|
|
$(document).ready(function () {
|
|
|
|
var current_selected_i;
|
|
var state_clicked = false;
|
|
|
|
var c;
|
|
|
|
// greyed out fill context
|
|
var xctx;
|
|
// redline highlight context
|
|
var ctx;
|
|
|
|
var current_default_xpath = [];
|
|
var x_scale = 1;
|
|
var y_scale = 1;
|
|
var selector_image;
|
|
var selector_image_rect;
|
|
var selector_data;
|
|
|
|
$('#visualselector-tab').click(function () {
|
|
$("img#selector-background").off('load');
|
|
state_clicked = false;
|
|
current_selected_i = false;
|
|
bootstrap_visualselector();
|
|
});
|
|
|
|
$(document).on('keydown', function (event) {
|
|
if ($("img#selector-background").is(":visible")) {
|
|
if (event.key == "Escape") {
|
|
state_clicked = false;
|
|
ctx.clearRect(0, 0, c.width, c.height);
|
|
}
|
|
}
|
|
});
|
|
|
|
// For when the page loads
|
|
if (!window.location.hash || window.location.hash != '#visualselector') {
|
|
$("img#selector-background").attr('src', '');
|
|
return;
|
|
}
|
|
|
|
// Handle clearing button/link
|
|
$('#clear-selector').on('click', function (event) {
|
|
if (!state_clicked) {
|
|
alert('Oops, Nothing selected!');
|
|
}
|
|
state_clicked = false;
|
|
ctx.clearRect(0, 0, c.width, c.height);
|
|
xctx.clearRect(0, 0, c.width, c.height);
|
|
$("#include_filters").val('');
|
|
});
|
|
|
|
|
|
bootstrap_visualselector();
|
|
|
|
|
|
function bootstrap_visualselector() {
|
|
if (1) {
|
|
// bootstrap it, this will trigger everything else
|
|
$("img#selector-background").on("error", function () {
|
|
$('.fetching-update-notice').html("<strong>Ooops!</strong> The VisualSelector tool needs atleast one fetched page, please unpause the watch and/or wait for the watch to complete fetching and then reload this page.");
|
|
$('.fetching-update-notice').css('color','#bb0000');
|
|
$('#selector-current-xpath').hide();
|
|
$('#clear-selector').hide();
|
|
}).bind('load', function () {
|
|
console.log("Loaded background...");
|
|
c = document.getElementById("selector-canvas");
|
|
// greyed out fill context
|
|
xctx = c.getContext("2d");
|
|
// redline highlight context
|
|
ctx = c.getContext("2d");
|
|
if ($("#include_filters").val().trim().length) {
|
|
current_default_xpath = $("#include_filters").val().split(/\r?\n/g);
|
|
} else {
|
|
current_default_xpath = [];
|
|
}
|
|
fetch_data();
|
|
$('#selector-canvas').off("mousemove mousedown");
|
|
// screenshot_url defined in the edit.html template
|
|
}).attr("src", screenshot_url);
|
|
}
|
|
// Tell visualSelector that the image should update
|
|
var s = $("img#selector-background").attr('src') + "?" + new Date().getTime();
|
|
$("img#selector-background").attr('src', s)
|
|
}
|
|
|
|
// This is fired once the img src is loaded in bootstrap_visualselector()
|
|
function fetch_data() {
|
|
// Image is ready
|
|
$('.fetching-update-notice').html("Fetching element data..");
|
|
|
|
$.ajax({
|
|
url: watch_visual_selector_data_url,
|
|
context: document.body
|
|
}).done(function (data) {
|
|
$('.fetching-update-notice').html("Rendering..");
|
|
selector_data = data;
|
|
console.log("Reported browser width from backend: " + data['browser_width']);
|
|
state_clicked = false;
|
|
set_scale();
|
|
reflow_selector();
|
|
$('.fetching-update-notice').fadeOut();
|
|
});
|
|
|
|
}
|
|
|
|
|
|
function set_scale() {
|
|
|
|
// some things to check if the scaling doesnt work
|
|
// - that the widths/sizes really are about the actual screen size cat elements.json |grep -o width......|sort|uniq
|
|
$("#selector-wrapper").show();
|
|
selector_image = $("img#selector-background")[0];
|
|
selector_image_rect = selector_image.getBoundingClientRect();
|
|
|
|
// make the canvas the same size as the image
|
|
$('#selector-canvas').attr('height', selector_image_rect.height);
|
|
$('#selector-canvas').attr('width', selector_image_rect.width);
|
|
$('#selector-wrapper').attr('width', selector_image_rect.width);
|
|
x_scale = selector_image_rect.width / selector_data['browser_width'];
|
|
y_scale = selector_image_rect.height / selector_image.naturalHeight;
|
|
ctx.strokeStyle = 'rgba(255,0,0, 0.9)';
|
|
ctx.fillStyle = 'rgba(255,0,0, 0.1)';
|
|
ctx.lineWidth = 3;
|
|
console.log("scaling set x: " + x_scale + " by y:" + y_scale);
|
|
$("#selector-current-xpath").css('max-width', selector_image_rect.width);
|
|
}
|
|
|
|
function reflow_selector() {
|
|
$(window).resize(function () {
|
|
set_scale();
|
|
highlight_current_selected_i();
|
|
});
|
|
var selector_currnt_xpath_text = $("#selector-current-xpath span");
|
|
|
|
set_scale();
|
|
|
|
console.log(selector_data['size_pos'].length + " selectors found");
|
|
|
|
// highlight the default one if we can find it in the xPath list
|
|
// or the xpath matches the default one
|
|
found = false;
|
|
if (current_default_xpath.length) {
|
|
// Find the first one that matches
|
|
// @todo In the future paint all that match
|
|
for (const c of current_default_xpath) {
|
|
for (var i = selector_data['size_pos'].length; i !== 0; i--) {
|
|
if (selector_data['size_pos'][i - 1].xpath === c) {
|
|
console.log("highlighting " + c);
|
|
current_selected_i = i - 1;
|
|
highlight_current_selected_i();
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (found) {
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
alert("Unfortunately your existing CSS/xPath Filter was no longer found!");
|
|
}
|
|
}
|
|
|
|
|
|
$('#selector-canvas').bind('mousemove', function (e) {
|
|
if (state_clicked) {
|
|
return;
|
|
}
|
|
ctx.clearRect(0, 0, c.width, c.height);
|
|
current_selected_i = null;
|
|
|
|
// Add in offset
|
|
if ((typeof e.offsetX === "undefined" || typeof e.offsetY === "undefined") || (e.offsetX === 0 && e.offsetY === 0)) {
|
|
var targetOffset = $(e.target).offset();
|
|
e.offsetX = e.pageX - targetOffset.left;
|
|
e.offsetY = e.pageY - targetOffset.top;
|
|
}
|
|
|
|
// Reverse order - the most specific one should be deeper/"laster"
|
|
// Basically, find the most 'deepest'
|
|
var found = 0;
|
|
ctx.fillStyle = 'rgba(205,0,0,0.35)';
|
|
// Will be sorted by smallest width*height first
|
|
for (var i = 0; i <= selector_data['size_pos'].length; i++) {
|
|
// draw all of them? let them choose somehow?
|
|
var sel = selector_data['size_pos'][i];
|
|
// If we are in a bounding-box
|
|
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
|
|
|
|
) {
|
|
|
|
// FOUND ONE
|
|
set_current_selected_text(sel.xpath);
|
|
ctx.strokeRect(sel.left * x_scale, sel.top * y_scale, sel.width * x_scale, sel.height * y_scale);
|
|
ctx.fillRect(sel.left * x_scale, sel.top * y_scale, sel.width * x_scale, sel.height * y_scale);
|
|
|
|
// no need to keep digging
|
|
// @todo or, O to go out/up, I to go in
|
|
// or double click to go up/out the selector?
|
|
current_selected_i = i;
|
|
found += 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
}.debounce(5));
|
|
|
|
function set_current_selected_text(s) {
|
|
selector_currnt_xpath_text[0].innerHTML = s;
|
|
}
|
|
|
|
function highlight_current_selected_i() {
|
|
if (state_clicked) {
|
|
state_clicked = false;
|
|
xctx.clearRect(0, 0, c.width, c.height);
|
|
return;
|
|
}
|
|
|
|
var sel = selector_data['size_pos'][current_selected_i];
|
|
if (sel[0] == '/') {
|
|
// @todo - not sure just checking / is right
|
|
$("#include_filters").val('xpath:' + sel.xpath);
|
|
} else {
|
|
$("#include_filters").val(sel.xpath);
|
|
}
|
|
xctx.fillStyle = 'rgba(205,205,205,0.95)';
|
|
xctx.strokeStyle = 'rgba(225,0,0,0.9)';
|
|
xctx.lineWidth = 3;
|
|
xctx.fillRect(0, 0, c.width, c.height);
|
|
// Clear out what only should be seen (make a clear/clean spot)
|
|
xctx.clearRect(sel.left * x_scale, sel.top * y_scale, sel.width * x_scale, sel.height * y_scale);
|
|
xctx.strokeRect(sel.left * x_scale, sel.top * y_scale, sel.width * x_scale, sel.height * y_scale);
|
|
state_clicked = true;
|
|
set_current_selected_text(sel.xpath);
|
|
|
|
}
|
|
|
|
|
|
$('#selector-canvas').bind('mousedown', function (e) {
|
|
highlight_current_selected_i();
|
|
});
|
|
}
|
|
|
|
}); |