1

I believe my issue may be to do with the length of time a function is taking to refresh the list but 2 days of trying everything a dozen different google searches can find has left me stuck...

I am creating a list dynamically:

<ul id="events" class="select" name="events" style="width:40vw;"></ul>

LoadEvents()
{
    var xhttp;
    var EventList;
    xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() 
    {
        if (this.readyState == 4 && this.status == 200)
        {
            EventList =  this.responseText.split(",");
            //Clear List
            $('#events').empty();
            EventList.forEach(function(item, index, array) 
            {
                if(item !== "")
                {
                    $ID = item.split(";")[0];
                    $('#events').append('<li class="event" id=\"' + $ID '\">' + item.split(";")[1] + '</li>');
                }
            });  
        }
    };
    xhttp.open("GET", "DataLink2.php?con=GetFullEvents&orderby=" + $OrderBy, true);
    xhttp.send();
}

EventList is an array of strings "ID;EventName" drawn from a database.

To extract the ID I am using:

var selectedid;
//Within the function that requests the refresh I do
selectedid = $('#events').find('li.selected').attr('id');
//calling the refresh function
LoadEvents();
//And trying to reselect the item in the list
$('#' + selectedid).click();

On a fiddle it works perfectly but in reality it always selects the item before refreshing the list!

I have tried various ideas from similar questions on here including:

$.when(LoadEvents()).then($('#' + selectedid).click());

and I also tried the above putting $('#' + selectedid).click(); into a function.

I then tried the first two solutions offered on this question (haven't quite worked out how to do the third option with the "myCustomevent" yet) but in every case the $('#' + selectedid).click(); was performed before the li's were re-generated.

Is there a way to force one event to wait until another has completely finished?

php:

$connect = mysqli_connect($host_name, $user_name, $password, $database);

if(mysqli_connect_errno())
{
    $query = "SELECT * FROM `Events` WHERE `FinishTime` > '00:00:00' ORDER BY `FinishTime` DESC";
    //Query Result
    if ($result = mysqli_query($connect, $query)) 
    {
        /* fetch associative array */
        while ($obj = mysqli_fetch_object($result)) 
            {
            printf ("%s,", $obj->ID.";".$obj->EventName;
            }
            /* free result set */
            mysqli_free_result($result);
    }
    else
    {
        echo '<p>Connection failed.</p>';
    }
}
OSKM
  • 728
  • 14
  • 25

3 Answers3

0

I believe you are making an async call for retrieving the events from the DB. It returns immediately (even that the response is not loaded yet) and passes control to the selection logic.

You could try putting the selection logic inside the response callback:

LoadEvents(preselect)
    {
        if (typeof preselect === 'undefined') {
            preselect = false;
        }

        var xhttp;
        var EventList;
        xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function()
        {
            if (this.readyState == 4 && this.status == 200)
            {
                EventList =  this.responseText.split(",");
                //Clear List
                $('#events').empty();
                EventList.forEach(function(item, index, array)
                {
                    if(item !== "")
                    {
                        $ID = item.split(";")[0];
                        $('#events').append('<li class="event" id=\"' + $ID '\">' + item.split(";")[1] + '</li>');
                    }
                });

                if (preselect) {
                    //And trying to reselect the item in the list
                    $('#' + selectedid).click();
                }
            }
        };
        xhttp.open("GET", "DataLink2.php?con=GetFullEvents&orderby=" + $OrderBy, true);
        xhttp.send();
    }

I hope that helps!

Asen Arizanov
  • 930
  • 1
  • 9
  • 11
  • Thanks for the explanation of what is happening, very much appreciated, that will give me some further google material. If you have any suggestion on how to correct the issue please let me know. – OSKM Jun 21 '17 at 13:00
  • Just provide the retrieval code (i.e. 'code can be posted if it is relevant') because the actual solution depends on the async API being used. – Asen Arizanov Jun 21 '17 at 13:07
  • How do you call the php code? In other words what does the 'Code to get EventList here' do? – Asen Arizanov Jun 21 '17 at 14:10
  • Apologies, now added, always concerned I am cluttering the question with unnecessary code. – OSKM Jun 21 '17 at 14:21
  • I cant seem to get this to work, I am probably being really thick but what changes the state of `preselect`? – OSKM Jun 21 '17 at 16:34
  • I added the preselect arg because as far as I saw you use the LoadEvents method both for initial loading and for refreshing the events. Also, I believe you want to select a value only refreshing. Both mine and your are solution are in essence one and the same. The $('#' + selectedid).click(); code has to be executed inside onreadystatechange. Good luck! – Asen Arizanov Jun 22 '17 at 06:47
  • OK, my knowledge of js is very limited but for some reason anything after and outside of the forEach loop never happens, so unfortunately when I tried your suggestion the `if (preselect) {` is never called. – OSKM Jun 22 '17 at 07:48
0

Simple solution would be to save id or some other data to local storage more info here
Simply localStorage.setItem('selected', selectedid);
And after any page reload you can call it with localStorage.getItem('selected');

Grynets
  • 2,477
  • 1
  • 17
  • 41
  • Thanks for the suggestion, my issue is not storing the id, I can pass that into the function, the problem is getting one function to wait for another to complete. – OSKM Jun 22 '17 at 07:51
0

What eventually got it working (more of a work around than a solution)...

I added a test at the end of the loading loop to check I am at the last iteration and then executed the .click()

LoadEvents()
{
    var xhttp;
    var EventList;
    xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() 
    {
        if (this.readyState == 4 && this.status == 200)
        {
            EventList =  this.responseText.split(",");
            //Clear List
            $('#events').empty();
            EventList.forEach(function(item, index, array) 
            {
                if(item !== "")
                {
                    $ID = item.split(";")[0];
                    $('#events').append('<li class="event" id=\"' + $ID '\">' + item.split(";")[1] + '</li>');
                }
                if (index == EventList.length - 1)
                {
                    $('#' + selectedid).click();
                }
            });  
        }
    };
    xhttp.open("GET", "DataLink2.php?con=GetFullEvents&orderby=" + $OrderBy, true);
    xhttp.send();
}

If anyone can post a better solution I would love to see it!

OSKM
  • 728
  • 14
  • 25