0

I got this script from another question here on stackoverflow and it works perfectly. The script updates the element in px, and I specially like the way you can move the element diagonally by holding up+left arrow keys for instance.

My question now is: Is it possible to change the script so it sets and updates values of the element in percent instead?

The reason for this is that I'm developing a site with responsive design and I need the elements to stay (and move) on the page relative to the window size. I have tried to figure it out, but no success so far.

Here is the script:

HTML

<div id="pane">
    <div id="box"></div>
</div>

CSS

#pane {
    position:relative;
    width:300px; height:300px;
    border:2px solid red;
}

#box {
    position:absolute; top:140px; left:140px;
    width:20px; height:20px;          
    background-color:black;
}

JavaScript

var pane = $('#pane'),
    box = $('#box'),
    w = pane.width() - box.width(),
    d = {},
    x = 3;

function newv(v,a,b) {
    var n = parseInt(v, 10) - (d[a] ? x : 0) + (d[b] ? x : 0);
    return n < 0 ? 0 : n > w ? w : n;
}

$(window).keydown(function(e) { d[e.which] = true; });
$(window).keyup(function(e) { d[e.which] = false; });

setInterval(function() {
    box.css({
        left: function(i,v) { return newv(v, 37, 39); }, //Function should set values in %
        top: function(i,v) { return newv(v, 38, 40); }   //here for left and top
    });
}, 20);

COFFE SCRIPT

jQuery ->       
    pane = $('body')
    box = $('.myDiv')
    w = pane.width() - box.width()
    c = [37,38,39,40] # Set key values for arrow keys in an array
    d = []
    x = 4

    newv = (v,a,b) ->
        n = parseInt(v, 10) - (if d[a] then x else 0) + (if d[b] then x else 0)
        if n < 0 then 0 else if n > w then w else n

    $(window).keydown((e) ->
        d[e.which] = true
    )

    $(window).keyup((e) -> 
        d[e.which] = false
        if true not in d and e.which in c #Check that all arrow keys are released

        divID = $('.myDiv').attr('id')  # Grab values from the element
        top = $('.myDiv').css('top')
        left = $('.myDiv').css('left')

        setTimeout ->  #Set a timeout and then send element values with Ajax to database to preserve state of element for next time window is opened
            $.ajax(
                type: "PUT"
                url: "/url/to/update/database"
                data:
                    positiontop: top
                    positionleft: left
            )
            ,1000
         )

    setInterval ->
        box.css
            left: (i,v) ->
                newv(v, 37, 39)
            top: (i,v) -> 
                newv(v, 38, 40)
    ,40
Community
  • 1
  • 1
T4E
  • 9
  • 2
  • You took this code somewhere and now you want us to change it for you. What have **you** done to solve **your** problem? – zerkms May 28 '12 at 03:46
  • Well, I think I have figured out that the change to a percent value has to take place in the function newv(v,a,b). So I have tried to recalculate n with something like n/$(window).height()*100. Also tried do the same with the x in that function. Makes more sense to do the recalculation with the x values... – T4E May 28 '12 at 03:54
  • I have also translated this JavaScript to CoffeeScript and added some features. Is it a good practice here to post my changes maybe? – T4E May 28 '12 at 04:02
  • I added my Coffee Script if someone should have use for it :-) – T4E May 28 '12 at 04:30

2 Answers2

0

You are on the right track according to your comment. You have to figure out what his code is doing. He is using ternary operators which you may not be familiar with. I will use his return variable line to help explain it.

return n < 0 ? 0 : n > w ? w : n;

This says, return n if it is less than zero or greater than the box width. Otherwise leave it alone because we are at a boundary. In your case you would want it to return n > 0 or < 100. Then you just need to change it to return in terms of % instead of px. You do that by appending '%'.

http://jsfiddle.net/bDMnX/332/

w = 100; //pane.width() - box.width(),

function newv(v,a,b) {
    var n = parseInt(v, 10) - (d[a] ? x : 0) + (d[b] ? x : 0);
    //console.log((n < 0 ? 0 : n > w ? w : n) + '%');   
    return (n < 0 ? 0 : n > w ? w : n) + '%';
}

I will leave getting the bounding and incrementing up to you.

Community
  • 1
  • 1
mrtsherman
  • 39,342
  • 23
  • 87
  • 111
  • Ahhh....thank you. No I was not familiar with ternary operators, I will read up the subject. – T4E May 28 '12 at 04:29
0

Ok, this is what I ended up doing. It probably can use some tweaking to make the code more efficient, and I probably also will make the percent calculation values use one decimal to make the moving of the div more smoother.

I ran into one problem with Firefox and Opera: In the setInterval-function the v value is returned in pixels. So I added the v = box[0].style.left and v = box[0].style.top to get the value returned as percent in all browsers.

Since the browser window isn't always a square, I also added another function to calculate the width and height separately.

JavaScript

var pane = $(window),
    box = $('#box'),
    w = (pane.width() - box.width())/pane.width()*100,
    h = (pane.height() - box.height())/pane.height()*100,
    d = {},
    x = 1;

//Caclulate height movement and window height bounds in %
function newvHeight(v,a,b) {
    v = box[0].style.top  //Grab :top value of the #box div as % in all browsers
    var n = parseInt(v, 10) - (d[a] ? x : 0) + (d[b] ? x : 0);
    return (n < 0 ? 0 : n > h ? h : n) + '%';
}

//Calculate width movement and window width bounds in %
function newvWidth(v,a,b) {
    v = box[0].style.left   //Grab :left value of the #box div as % in all browsers
    var n = parseInt(v, 10) - (d[a] ? x : 0) + (d[b] ? x : 0);
    return (n < 0 ? 0 : n > w ? w : n) + '%';
}

$(window).keydown(function(e) { d[e.which] = true; });
$(window).keyup(function(e) { d[e.which] = false; });

setInterval(function() {
    box.css({
        left: function(i,v) { return newvWidth(v, 37, 39); },   //Function should set values in %
        top: function(i,v) { return newvHeight(v, 38, 40); }    //here for left and top
    });
}, 20);
T4E
  • 9
  • 2