Venkateshwaran Selvaraj
Venkateshwaran Selvaraj

Reputation: 1785

Uncaught TypeError: Cannot read property 'position' of undefined

I am working on draggable items. I am trying to store the final position of the draggable div once it is stopped from being dragged.It was working fine when I had the following javascript code.

function make_draggable(elements)
 {
  /* Elements is a jquery object: */
  elements.draggable({
    containment: 'parent',
    start: function (e, ui) {
      ui.helper.css('z-index', ++zIndex);
    },
    stop: function (e, ui) {
      /* Sending the z-index and positon of the note to update_position.php via AJAX GET: */
      $.get('ajax/update_position.php', {
        x: ui.position.left,
        y: ui.position.top,
        z: zIndex,
        id: parseInt(ui.helper.find('span.data').html())
      });
    }
  });
}

I did not want the database to be updated everytime the user stops dragging the div. So I wanted to add a confirm button(which appears when the users stops dragging) to make the AJAX call. So I tried the following code

var $button = $("#button");

function make_draggable(elements) {
    /* Elements is a jquery object: */
    elements.draggable({
        containment: 'parent',
        start: function (e, ui) {
            ui.helper.css('z-index', ++zIndex);
            $("#button").animate({
                opacity: 0
            }, 1000);
        },
        stop: function (e, ui) {
            /* Sending the z-index and positon of the note to update_position.php via AJAX GET: */
            $('#chatAudio')[0].play();
            $("#button").animate({
                opacity: 1
            }, 1000);
            /*  $.get('ajax/update_position.php',{x : ui.position.left,y: ui.position.top,z: zIndex,id:parseInt(ui.helper.find('span.data').html())});*/
        } /*stop is ending */
    }); /* element.draggable is ending */

}

 function myFunction() {
    alert(1);
    /* Sending the z-index and positon of the note to update_position.php via AJAX GET: */
    $.get('ajax/update_position.php', {
        x: ui.position.left,
        y: ui.position.top,
        z: zIndex,
        id: parseInt(ui.helper.find('span.data').html())
    });

}

But when I click the confirm button, I am seeing the Uncaught ReferenceError: ui is not defined error on my javascript console.

I thought that ui was not defined. So I added (e,ui) as shown below

function myFunction(e,ui) {
        alert(1);
        /* Sending the z-index and positon of the note to update_position.php via AJAX GET: */
        $.get('ajax/update_position.php', {
            x: ui.position.left,
            y: ui.position.top,
            z: zIndex,
            id: parseInt(ui.helper.find('span.data').html())
        });

    }

But now I am getting Uncaught TypeError: Cannot read property 'position' of undefined

Here is my website

Upvotes: 3

Views: 16315

Answers (5)

Buzinas
Buzinas

Reputation: 11725

Well, it seems you were updating each div at a time, when you were calling the PHP inside your stop function. And it seems you want to update all your divs at once now, after clicking the confirm button.

There are two ways to solve your problem, the first is to change your PHP to receive all the divs in a parameter (an Object with all those divs, for example), and the second is to loop your PHP request, passing all divs, one by one.

You change your make_draggable function to:

function make_draggable(elements) {
    window.myDragglableDivs = {}; // add an object to keep your data
    elements.draggable({
        containment: 'parent',
        start: function (e, ui) {
            ui.helper.css('z-index', ++zIndex);
            $("#button").animate({
                opacity: 0
            }, 1000);
        },
        stop: function (e, ui) {
            // add/update the div positions in your object:
            var divID = ui.helper.find('span.data').html();
            window.myDragglableDivs[divID] = {
                x: ui.position.left,
                y: ui.position.top,
                z: zIndex,
                id: parseInt(divID)
            };

            $('#chatAudio')[0].play();
            $("#button").animate({
                opacity: 1
            }, 1000);
        }
    });
}

My first solution is sending all divs at once (you must change your PHP to receive them in this case):

function myFunction() {
    $.get('ajax/update_position.php', window.myDraggableDivs);
}

Or, my second solution, you won't need to make any change in your PHP:

function myFunction() {
    for (var key in window.myDraggableDivs) {
        $.get('ajax/update_position.php', window.myDraggableDivs[key]);
    }
}

Upvotes: 0

Montri M
Montri M

Reputation: 1766

This is all about passing parameter and expose objects. You can't access the ui parameter in your "myFunction" because, if I guess right, it was invoked by the "click" event of the "#button" object. The click event have no idea about the "ui" helper object, so it doesn't get passed to your function.

So, basically, you have many draggable element, but only one confirm button. The easiest way to fix the problem you had is, like Mohit suggested, bind the data you need with the element through its 'data' function. However, don't bind the 'ui' helper object itself, just bind the data that you need.

In short, try this.

var $button = $("#button");

function make_draggable(elements) {
    /* Elements is a jquery object: */
    elements.draggable({
        containment: 'parent',
        start: function (e, ui) {
            ui.helper.css('z-index', ++zIndex);
            $("#button").animate({
                opacity: 0
            }, 1000);
        },
        stop: function (e, ui) {

            // All those fancy objects are accessible here, so we get the snapshot of their values, as simple non-cyclic javascript object, and store it with data function.
            $("#button").data('position', {
                x: ui.position.left,
                y: ui.position.top,
                z: zIndex,
                id: parseInt(ui.helper.find('span.data').html())
            });

            $('#chatAudio')[0].play();
            $("#button").animate({
                opacity: 1
            }, 1000);

        } /*stop is ending */
    }); /* element.draggable is ending */
}

function myFunction() {
    alert(1);
    /* Sending the z-index and positon of the note to update_position.php via AJAX GET: */
    $.get('ajax/update_position.php', $("#button").data('position'));
}

Upvotes: 7

Mohit Pandey
Mohit Pandey

Reputation: 3833

You can use data atribute property to pass ui value to button.

Try this:

var $button = $("#button");

function make_draggable(elements) {
    /* Elements is a jquery object: */
    elements.draggable({
        containment: 'parent',
        start: function (e, ui) {
            ui.helper.css('z-index', ++zIndex);
            $("#button").animate({
                opacity: 0
            }, 1000);
        },
        stop: function (e, ui) {
            /* adding ui to button data attribute */
            $("#button").data('ui', JSON.stringify(ui));
            /* Sending the z-index and positon of the note to update_position.php via AJAX GET: */
            $('#chatAudio')[0].play();
            $("#button").animate({
                opacity: 1
            }, 1000);
            /*  $.get('ajax/update_position.php',{x : ui.position.left,y: ui.position.top,z: zIndex,id:parseInt(ui.helper.find('span.data').html())});*/
        } /*stop is ending */
    }); /* element.draggable is ending */

}

function myFunction() {
    /* get data attribute for ui value */
    var ui = JSON.parse($("#button").data('ui'));
    /* Sending the z-index and positon of the note to update_position.php via AJAX GET: */
    $.get('ajax/update_position.php', {
        x: ui.position.left,
        y: ui.position.top,
        z: zIndex,
        id: parseInt(ui.helper.find('span.data').html())
    });
}

Upvotes: 2

Lee Gary
Lee Gary

Reputation: 2397

Shouldn't you be using droppable together with draggable? Under the documentation for droppable, you can get ui.position too

Upvotes: 0

stevethecollier
stevethecollier

Reputation: 1034

you are not setting ui to anything in your stop function, so when you try to send the ui.position, there is nothing to send.

you can fix this by setting ui in the stop function and then using it in your get.

function make_draggable(elements) {
    /* Elements is a jquery object: */
    elements.draggable({
        containment: 'parent',
        start: function (e, ui) {
            ui.helper.css('z-index', ++zIndex);
            $("#button").animate({
                opacity: 0
            }, 1000);
        },
        stop: function (e, ui) {

            window.ui = ui //----------------ADD THIS LINE TO SET IT---------------------------

            /* Sending the z-index and positon of the note to update_position.php via AJAX GET: */
            $('#chatAudio')[0].play();
            $("#button").animate({
                opacity: 1
            }, 1000);
            /*  $.get('ajax/update_position.php',{x : ui.position.left,y: ui.position.top,z: zIndex,id:parseInt(ui.helper.find('span.data').html())});*/
        } /*stop is ending */
    }); /* element.draggable is ending */

}

 function myFunction(e, ui) {
    alert(1);

    ui = window.ui   //------------AND SET IT HERE SO IT IS NOT UNDEFINED IN THE GET-------

    $.get('ajax/update_position.php', {
        x: ui.position.left,
        y: ui.position.top,
        z: zIndex,
        id: parseInt(ui.helper.find('span.data').html())
    });
}

Upvotes: 0

Related Questions