How do I ensure saved click coordinates can be reloaed to the same place, even if the page layout changed?

I'm storing click coordinates in my db and then reloading them later and showing them on the site where the click happened, how do I make sure it loads in the same place?

Storing the click coordinates is obviously the simple step, but once I have them if the user comes back and their window is smaller or larger the coordinates are wrong. Am I going about this in the wrong way, should I also store an element id/dom reference or something of that nature.

Also, this script will be run over many different websites with more than one layout. Is there a way to do this where the layout is independent of how the coordinates are stored?

Answers:

Answer

Yeah, there are many, many ways a page's layout can alter between loads. Different window sizes, different font sizes, different font availability, different browser/settings (even a small change in layout or font preference can throw out the wrapping). Storing page-relative co-ordinates is unlikely to be that useful unless your page is almost entirely fixed-size images.

You could try looking up the ancestors of the clicked element to find the nearest easily-identifiable one, then make a plot from that element down to the element you want based on which child number it is.

Example using simple XPath syntax:

document.onclick= function(event) {
    if (event===undefined) event= window.event;                     // IE hack
    var target= 'target' in event? event.target : event.srcElement; // another IE hack

    var root= document.compatMode==='CSS1Compat'? document.documentElement : document.body;
    var mxy= [event.clientX+root.scrollLeft, event.clientY+root.scrollTop];

    var path= getPathTo(target);
    var txy= getPageXY(target);
    alert('Clicked element '+path+' offset '+(mxy[0]-txy[0])+', '+(mxy[1]-txy[1]));
}

function getPathTo(element) {
    if (element.id!=='')
        return 'id("'+element.id+'")';
    if (element===document.body)
        return element.tagName;

    var ix= 0;
    var siblings= element.parentNode.childNodes;
    for (var i= 0; i<siblings.length; i++) {
        var sibling= siblings[i];
        if (sibling===element)
            return getPathTo(element.parentNode)+'/'+element.tagName+'['+(ix+1)+']';
        if (sibling.nodeType===1 && sibling.tagName===element.tagName)
            ix++;
    }
}

function getPageXY(element) {
    var x= 0, y= 0;
    while (element) {
        x+= element.offsetLeft;
        y+= element.offsetTop;
        element= element.offsetParent;
    }
    return [x, y];
}

You can see it in action using this JSFiddle: http://jsfiddle.net/luisperezphd/L8pXL/

Answer

I prefer not using the id selector and just going recursive.

function getPathTo(element) {
    if (element.tagName == 'HTML')
        return '/HTML[1]';
    if (element===document.body)
        return '/HTML[1]/BODY[1]';

    var ix= 0;
    var siblings= element.parentNode.childNodes;
    for (var i= 0; i<siblings.length; i++) {
        var sibling= siblings[i];
        if (sibling===element)
            return getPathTo(element.parentNode)+'/'+element.tagName+'['+(ix+1)+']';
        if (sibling.nodeType===1 && sibling.tagName===element.tagName)
            ix++;
    }
}
Answer

It probably depands on the meaning of the click. That is, are you concerned about which elements of the page that you user clicked on? If that is the case then I would store the coordinates relative to the element.

So the user clicked on element X. Do you need the precise location in element X? Then store that coordinate with the origin at top left of the element itself. This way, when the element moves relative to other content on the page then the position within the element remains valid.

Answer

Your coordinates should be relative to the page contents, not the window. Use the upper-left of your HTML as the origin.

You will need to do a calculation to determine this at the time the data is recorded.

Answer

I was hoping that someone had a much more brilliant solution to this problem, but my original thoughts must be the only way to effectively do this.

  1. Each website must have a base setup described (e.g. [Centered layout, 960px] or [Fluid layout, Col1: 25%, Col2: 60%, Col3: 15%]
  2. Click coordiantes must be recorded in relation to the screen:x/scroll:y along with screen coordinates.
  3. On return the click coords will look at the stored layout, current screen size and calculate based on that.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.