SitePoint Sponsor

User Tag List

Results 1 to 14 of 14

Hybrid View

  1. #1
    SitePoint Zealot soapergem's Avatar
    Join Date
    Mar 2005
    Location
    Madison, WI
    Posts
    165
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Find text position/width within textarea

    I'm really not sure how to go about doing this, so any and all pointers are welcome. What I'd like to do is be able to find the position and width of a word that has been typed inside of a <textarea>, so that I might overlay some absolutely-positioned elements on top, and size them properly. I would really like to be able to do this in the most general case as possible (independent of fonts, font size, size of the textarea, etc.), but as stated any help is welcome. If I'm being ambiguous I can try to re-explain things with pictures. Thanks!
    // useless crap about my relationships, philosophy,
    // theology, music and programming projects:

    my $blog = 'http://gordon-myers.com/';

  2. #2
    SitePoint Zealot soapergem's Avatar
    Join Date
    Mar 2005
    Location
    Madison, WI
    Posts
    165
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    ...anyone?
    // useless crap about my relationships, philosophy,
    // theology, music and programming projects:

    my $blog = 'http://gordon-myers.com/';

  3. #3
    SitePoint Wizard gRoberts's Avatar
    Join Date
    Oct 2004
    Location
    Birtley, UK
    Posts
    2,439
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Could you explain what you are trying to achieve, as there may be a different and easier approach to it.


  4. #4
    SitePoint Zealot soapergem's Avatar
    Join Date
    Mar 2005
    Location
    Madison, WI
    Posts
    165
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Sure, I'm essentially trying to emulate the behavior of the "Track Changes" feature in Microsoft Word, but on the web. This essentially means I am going to diff two files, but then display it in a familiar and clean way similar to the style Word uses. If you're unfamiliar with the "Track Changes" feature in Word, here's a screen shot demonstrating what it does:



    So you see, I would need to be able to determine character positions so that I can draw arrows to them. I may also have to use something like TinyMCE if I want the underlining and colors.
    // useless crap about my relationships, philosophy,
    // theology, music and programming projects:

    my $blog = 'http://gordon-myers.com/';

  5. #5
    SitePoint Wizard gRoberts's Avatar
    Join Date
    Oct 2004
    Location
    Birtley, UK
    Posts
    2,439
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Do you happen to have a way to get the differences between the two files?

    The insertion differences are easily sorted by using a replace to replace the inserted text with the inserted text wrapped in a style or span element.

    As for deleted differences, this would be harder to replicate. So I suggest you use the same approach as above, by graying out the deleted text or something.


  6. #6
    SitePoint Zealot soapergem's Avatar
    Join Date
    Mar 2005
    Location
    Madison, WI
    Posts
    165
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    So, in other words, you don't know how to answer my original question? I'm not trying to be a jerk by saying that; it's just that these are really alternatives, not answers.

    Writing a diff algorithm is easy enough, to find both what's been added and what's been removed. What's hard is finding a pixel position on the screen (within this textarea). I can always do something similar to what Wikipedia does when they diff two files, but that doesn't look as nice IMO as what Word does. So I was hoping to do it that way, although as you can see I'm not sure how to do it!
    // useless crap about my relationships, philosophy,
    // theology, music and programming projects:

    my $blog = 'http://gordon-myers.com/';

  7. #7
    SitePoint Wizard gRoberts's Avatar
    Join Date
    Oct 2004
    Location
    Birtley, UK
    Posts
    2,439
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    there are too many variants making this question almost impossible to answer.

    Although, whilst thinking about it, there may be a way using Monospaced fonts.

    I will see what I can do, give me a bit longer.


  8. #8
    SitePoint Wizard gRoberts's Avatar
    Join Date
    Oct 2004
    Location
    Birtley, UK
    Posts
    2,439
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    My theory will work only if you can guarentee a certain amount of data per line. Monospace font chars are all the same width, and if you set a line height, providing you can guarentee the length of characters and amount of lines, then you can use indexOf and a for loop to generate a grid location.

    Hope that helps in any way


  9. #9
    SitePoint Wizard gRoberts's Avatar
    Join Date
    Oct 2004
    Location
    Birtley, UK
    Posts
    2,439
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What about this? I've found a javascript diff script, and you can style the results and set javascript to them.

    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
        <head>
            <title>Untitled Document</title>
            <link rel="stylesheet" type="text/css" media="screen" />
            <style type="text/css">
                del {
                    color: white;
                    background-color: red;
                }
                ins {
                    color: white;
                    background-color: darkGreen;
                }
                #tooltip {
                    border: solid 1px;
                    width: 150px;
                    position: absolute;
                    display: none;
                }
                #tooltip span {
                    font-family: vardana, tahoma, sans-serif;
                    font-size: 66&#37;;
                    text-indent: 5px;
                    background-color: #ccc;
                    border-bottom: solid 1px;
                    display: block;
                    line-height: 2em;
                }
                #tooltip div {
                    font-family: vardana, tahoma, sans-serif;
                    font-size: 66%;
                    padding: 5px;
                }
            </style>
            <script type="text/javascript" src="http://ejohn.org/files/jsdiff.js"></script>
            <script type="text/javascript">
                function getDifference() {
                    document.getElementById('diff').innerHTML = diffString(document.getElementById('data1').value, 
                    document.getElementById('data2').value);
                    alert(document.getElementById('diff').innerHTML);
                    getDels();
                    getIns();
                }
                function getDels() {
                    var dels = document.getElementById('diff').getElementsByTagName('del');
                    for(var i = 0; i < dels.length; i++) {
                        dels[i].onmouseover = function(e) {
                            if(!e) e = window.event;
    
                            var tooltip = document.getElementById('tooltip');
                                tooltip.style.display = 'block';
                                tooltip.style.top = e.clientY + 20;
                                tooltip.style.left = e.clientX + 20;
                                tooltip.getElementsByTagName('SPAN')[0].innerHTML = 'Deleted';
                                tooltip.getElementsByTagName('DIV')[0].innerHTML = this.innerHTML;
    
                        }
                        dels[i].onmousemove = function(e) {
                            if(!e) e = window.event;
    
                            var tooltip = document.getElementById('tooltip');
                                tooltip.style.top = e.clientY + 20;
                                tooltip.style.left = e.clientX + 20;
                        }
                        dels[i].onmouseout = function() {
                            var tooltip = document.getElementById('tooltip');
                                tooltip.style.display = 'none';
                        }
                    }
                }
                function getIns() {
                    var ins = document.getElementById('diff').getElementsByTagName('ins');
                    for(var i = 0; i < ins.length; i++) {
                        ins[i].onmouseover = function(e) {
                            if(!e) e = window.event;
    
                            var tooltip = document.getElementById('tooltip');
                                tooltip.style.display = 'block';
                                tooltip.style.top = e.clientY + 20;
                                tooltip.style.left = e.clientX + 20;
                                tooltip.getElementsByTagName('SPAN')[0].innerHTML = 'Inserted';
                                tooltip.getElementsByTagName('DIV')[0].innerHTML = this.innerHTML;
    
                        }
                        ins[i].onmousemove = function(e) {
                            if(!e) e = window.event;
    
                            var tooltip = document.getElementById('tooltip');
                                tooltip.style.top = e.clientY + 20;
                                tooltip.style.left = e.clientX + 20;
                        }
                        ins[i].onmouseout = function() {
                            var tooltip = document.getElementById('tooltip');
                                tooltip.style.display = 'none';
                        }
                    }
                }
            </script>
        </head>
        <body>
            
            <div id="tooltip">
                <span>Added</span><div>Value</div>
            </div>
    
            <table width="700px" height="350px" cellpadding="0" cellspacing="0">
                <tr>
                    <td>One</td>
                    <td>&nbsp;</td>
                    <td>Two</td>
                </tr>
                <tr>
                    <td><textarea id="data1" style="width: 345px; height: 300px;">The red brown fox jumped over the rolling log.</textarea></td>
                    <td>&nbsp;</td>
                    <td><textarea id="data2" style="width: 345px; height: 300px;">The brown spotted fox leaped over the rolling log</textarea></td>
                </tr>
            </table>
    
            <input type="button" onclick="getDifference();" value="getDiff" />
    
            <p>Difference:<p>
    
            <div id="diff"></div>
    
        </body>
    </html>


  10. #10
    SitePoint Zealot soapergem's Avatar
    Join Date
    Mar 2005
    Location
    Madison, WI
    Posts
    165
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for your help so far gRoberts. Question: let's say we use a mono-space font, like Courier New, for instance. Is there some way, then, that JavaScript can determine the height and width of a character (in pixels)? This can probably vary on different platforms and for different users, depending on how large they have their text set, so I'd need a programmatic way to determine the dimensions of a character.
    // useless crap about my relationships, philosophy,
    // theology, music and programming projects:

    my $blog = 'http://gordon-myers.com/';

  11. #11
    SitePoint Wizard gRoberts's Avatar
    Join Date
    Oct 2004
    Location
    Birtley, UK
    Posts
    2,439
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    theres the monospace font, which set to 12px, I found that each caracter was roughly 7px wide, and providing you set a line-height (ie, 20px) you can work out the height as well.


  12. #12
    SitePoint Zealot soapergem's Avatar
    Join Date
    Mar 2005
    Location
    Madison, WI
    Posts
    165
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    No no no no no... "rougly 7px wide" offers NO guarantee that it actually will be 7px wide. I'd need a JavaScript programmatic method for finding the width of the character, or nothing at all. What is roughly 7px wide on your screen could be 9px on the screen of someone who's running Linux and doesn't have that font, or 25px on the screen of someone else who has their system set to enlarge all fonts automatically because of their poor eyesight, etc.

    Guessing simply doesn't work; the whole reason I posted the question here is because I wasn't sure there that there was a method to calculating character width on the fly, but I wanted to see if anyone else knew.
    // useless crap about my relationships, philosophy,
    // theology, music and programming projects:

    my $blog = 'http://gordon-myers.com/';

  13. #13
    SitePoint Wizard gRoberts's Avatar
    Join Date
    Oct 2004
    Location
    Birtley, UK
    Posts
    2,439
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    As one of my previous posts, there are too many variants to stop you from being able to work out the size of a font on the fly.

    Personally I don't see whats wrong with the javascript example I provided.

    Its able to show the text thats been added and removed, and using css you can style that pretty much any way you want. Including underlining the added text and moving the removed to the side like in the image (the line is probably not worth trying to replicate).


  14. #14
    SitePoint Zealot soapergem's Avatar
    Join Date
    Mar 2005
    Location
    Madison, WI
    Posts
    165
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Again, thanks. I'm coming to think you're right--that it's not really possible as far as I can tell to calculate character size. So thanks for the code you did provide.
    // useless crap about my relationships, philosophy,
    // theology, music and programming projects:

    my $blog = 'http://gordon-myers.com/';


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •