Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JQuery draggable image with saved position

OK it's getting awkward, already searched and tried for about 5 hours and I'm just running in circles...

The scenario is easy: It's the header image of a user profile, it can be dragged into an position and then the top position of the image get's saved into a DB.

Thanks to Beetroot-Beetroot's "containment: 'parent'" I am down to this piece of code, which actually reacts as I want it to! Except for one big problem. The Picture just jumps either to the top or the bottom. There is no smooth scrolling? If I change the 'parent' to -'parent' it scrolls nicely but... the containment of course isn't there anymore. Help? :D

The JS

$(function(){
    $(".headerimage").css('cursor','s-resize');
    $(".headerimage").draggable({ containment: 'parent', scroll: false, axis: "y",    stop: function(event, ui) {
            var data = "profileheaderposition="+ui.position.top;
            var destination = "/modules/users/profile/save.php";
            get_data(data, destination, function(test){
                notice(test);
            });
        }
    });                 
});

So and last but not least the Header is included like that:

<div class="<?php if ($user->id == $profileuser->id) echo "changer"; ?> ui-corner-all" id="profileheader" style="overflow: hidden; width: 650px; height: 260px; position:relative;">
<?php if($profile->profileheader){
    $size = getimagesize($profile->profileheader);
?>
<img id="" class="draggable headerimage" style="position: absolute; top: <?php echo $profile->profileheaderposition; ?>px;" src="<?php echo $profile->profileheader; ?>" alt="profileheader" width="650" />

As I said hours of googling weren't giving any results - and if i wouldn't save the results it would work just fine but oh well...

-- Edit --

Right now I am about to cry out -.- I've set up a bounty on this one and the tools for helping me ain jsfiddle but an guest account on my webpage which is: http://www.animize.de

There you can log on to the page with the Username: Gast and the pw gast - Click on the top right on the name (gast) and you'll see the profile - there you can move the headerpicture - and of course it should behave in another way than it does - help :(

like image 681
Ivan Schrecklich Avatar asked Sep 25 '12 02:09

Ivan Schrecklich


3 Answers

Try this fiddle.

I added an if-statement to the drag event which checks the current positioning of the image and sets the current top position into ui.position.top if the condition returns true so the draggable event does not increase or decrease the top position while hitting the boundaries of the div. This way you can keep the position properties of your div's.

like image 54
QQping Avatar answered Oct 18 '22 21:10

QQping


Ivan,

It's hard to see why the code should be in a named function wrapper. Unless dragability needs to be turned on/off, then .draggable() just needs to be invoked once in a $(function(){...}); structure.

It's also hard to see why you would need to write static data from php into javascript. There should be nothing about the draggable image that javascript/jQuery cannot discover for itself by enquiring the DOM, and even then it's not clear why this might be necessary.

I would expect to see something like this :

$(function() {
    $(".headerimage").draggable({
        containment: 'parent',
        scroll: false,
        axis: "y",
        stop: function(event, ui) {
            $.ajax(
                url: "/modules/users/profile/save.php",
                data: "profileheaderposition=" + ui.position.top,
                success: function() {
                    //do something here to indicate that the new position has been successfully saved
                }
            );
        }
    });
});
like image 44
Beetroot-Beetroot Avatar answered Oct 18 '22 20:10

Beetroot-Beetroot


See this fiddle for my solution to this. I also handled left and right dragging, which is not necessary for your case at this time but could be useful in future if you plan to use an image greater than its parent. In your case your image is same width as its parent so I added a threshold param to let vertical dragging be used without being canceled by the right and left boundaries being hit.

I also added some css for grab and grabbing cursors, so to get a cursor effect similar to when you drag a pdf around, unfortunately the support for this cursors is somewhat broken in some browsers(IE and chrome in my tests) but firefox is showing them right.

Pasting my code here to prevent from a future fiddle broken link.

HTML:

<br><br><br><br><br><br><br>
<div class="ui-widget-content" style="padding:10px;">

<div class="picturecontainer" style="overflow: hidden; position: relative; width: 650px; height: 150px; border: 1px solid #888;">
    <img style="position: absolute;" class="headerimage ui-corner-all" src="http://www.animize.de/modules/users/profile/images/profileheader/header_3722386791348526090.jpg" />
    </div>

</div>

CSS:

.headerimage {
    cursor:hand;
    cursor:grab;
    cursor:-moz-grab;
    cursor:-webkit-grab;
}
.grabbing {
  cursor:grabbing !important;
  cursor:-moz-grabbing !important;
  cursor:-webkit-grabbing !important;
}

JAVASCRIPT:

var container = $(".picturecontainer");
var childimage = $(".headerimage");

childimage.draggable({  scroll: false, start:function(event,ui) {
                  childimage.addClass('grabbing');
     }, stop: function(event, ui) {
                  childimage.removeClass('grabbing');
     },drag: function(event,ui) {
        //left and right threshold
        //to ease draggin images that have same width as container
        threshold = 20;//pixels
        ltop = childimage.offset().top -1 > container.offset().top;
        lbottom = childimage.offset().top + childimage[0].offsetHeight 
                  <= container.offset().top + container[0].offsetHeight;
        lleft = childimage.offset().left > container.offset().left + threshold;
        lright = childimage.offset().left + childimage[0].offsetWidth <
                container.offset().left + container[0].offsetWidth - threshold;
        if (ltop || lbottom || lleft || lright) {
            $(this).data("draggable").cancel();
            if (ltop) {
                 $(this).offset({ top: $(this).parent().offset().top+1});
            } else if (lbottom) {
                newtop = container.offset().top + container[0].offsetHeight 
                         - childimage[0].offsetHeight;
                $(this).offset({ top: newtop+1});
            } else if (lleft) {
                newleft = container.offset().left;
                $(this).offset({ left: newleft});
            } else if (lright) {                     
                newleft = container.offset().left + container[0].offsetWidth;
                          - childimage[0].offsetWidth;
                $(this).offset({ left: newleft});
            }
         }
     }
}).parent().bind('mouseout',function() {
     childimage.trigger('mouseup');
});
like image 25
Nelson Avatar answered Oct 18 '22 21:10

Nelson