Hi,

I have been trying to save the state of a sortable list. I have been able to save the sort order to localStorage and get the sort order so that I can display it on the console but I cannot get it to be the order it was last set at in localStorage. Any help on this would be appreciated as after looking at the JQuery documentation I havn't found an event to do with sortable that updates the ids.

$(document).ready(function() {

                // I get the order from localStorage
                var saved = localStorage.getItem("sorted");
                // I get the number on the end of the sort order
                var firstset = saved.substring(5,6);
                var secondset = saved.substring(12,13);
                // I then concatanate set which is the first part of the id with the numbe
                firstset = "\"set_"+firstset+"\"";
                secondset ="\"set_"+secondset+"\"";
                console.log(firstset);
                console.log(secondset);
                // This was my attempt to update the ids
                $('innercontainer').attr('set_1', firstset);
                $('innercontainer').attr('set_2', secondset); 


                $(function(){
                    $( "#container" ).sortable({ cursor: "pointer", 
                        placeholder: "highlight",

                        // this is where I store the order in localStorage
                        update: function( event, ui ) {
                            var sorted = $(this).sortable( "serialize", { key: "set_" } );
                            localStorage["sorted"] = sorted;
                        }


                    });
                }); 
                $( "#container" ).disableSelection()



        });
        //]]>
    </script>
    <title>
        My homepage 
    </title> 
    </head>
    <body>
            <div id="container">
                <div class="innercontainer" id="set_1">

                    <h2 class="firstsection"><img class="moveicon" src="images/moveicon.png" alt="click and drag to swap order of text" width="25" height="28" border="0" />Introduction <button class="sh">show/hide </button> </h2>

                    <p class="firstpara">
                        text goes here
                    </p>
                </div>
                <div class="innercontainer" id="set_2">
                    <h2><img class="moveicon" src="images/moveicon.png" alt="click and drag to swap order of text" width="25" height="28" border="0" />Web Development <button class="sh">show/hide </button></h2>
                    <div class="knowledgebasesteps">
                        <ul>
                            <li><a href="#" class="hidden" id="html5flash">HTML5 video with Flash fallback </a> </li>
                            <li><a href="#" class="hidden" id="responsivenav">Creating responsive navigation </a> </li>
                        </ul>    
                        <iframe name="webframe" id="webframe" src="http://localhost/MyWebsite/Knowledgebasecontent/Usingknowledgebase.html"></iframe>
                    </div>
                </div>
            </div>

Recommended Answers

All 12 Replies

Hi piers, the selector on your attempt to update the ids is not valid.
Try like this:

$('div.innercontainer')
        .attr('set_1', firstset);
        .attr('set_2', secondset); 

Hi AleMonteiro,

Thank you for pointing that out. Below is the solution I used to change the ids.
The issue is whilst it now changes the ids it doesn't move the divs in the place they should be. I think it is because this needs to be applied to the sortable
function. Any ideas on how this can be done?

var saved = localStorage.getItem("sorted");
                            var firstset = saved.substring(5,6);
                            var secondset = saved.substring(12,13);

                            firstset ="set_"+firstset;
                            secondset ="set_"+secondset;

                            $('div#set_1').first().attr('id', firstset);
                            $('div#set_2').first().next().attr('id', secondset); 

I didn't understand much of what you are trying to do.
You have two divs with Ids: set_1 and set_2.
So, do you want to change thoses Ids for what?

What I am trying to do is:

when you refresh the page, how you have sorted the divs previously displays in that order.

my approach to this:

I noticed that when you use sortable it changes the ids for the innercontainer class so I have tried to copy that by retrieving the id information from localStorage and changing the ids but whilst the ids change it doesn't show the divs in the same order as was set previously.

I have used substring so that I am only getting the numbers for each id from localStorage as I found it an easy method to rebuild the string into what the ids are for updating them.

the knowledge I am missing:

Whilst I have got the ids now and can change them I am unable to work out how to apply that to sortable so that the order of the divs reflects what it was before the page was refreshed.

I have put some images below one showing a re-sort of the divs and the other what happens after you do a re-sort where the ids are updated in the developer toolbar in chrome.

divsaftersort.png
developer.png

Ok, I got what you want. But let me say, you don't need to change Ids for this.
What you need is to store the Id and his order.

Take a look at this: http://jsfiddle.net/86nu1wkw/2/

It's simple but it does what you need. If you change the indexes on current_order you'll see that they are displayed correctly.

You'll just need to store that info and get it as you already do with localStorage.

Hi,

I am not quite getting how to apply this. What I have tried to do is store some default data in localStorage if there is nothing there. Then I have tried to get the id and the index from LocalStorage but I am only ever returning -1 which I reckon is to do with the index number. I am then trying to set the updated localStorage information in your append function.
At the moment I am only able to set the current order as default in LocalStorage. How would you do this?

    var current_order = {
        'set_1' : 0,
        'set_2' : 1
    };
    if (JSON.parse(localStorage.getItem("sorted"))== " ")
    {
        localStorage.setItem("sorted", JSON.stringify(current_order));
    }
    $(function(){
        var returningValues = JSON.parse(localStorage.getItem("sorted"));
        console.log("returning"+returningValues);
        $( "#container" ).sortable({ cursor: "pointer", 
            placeholder: "highlight",

            update: function(event, ui){
                $(this).children('div.innercontainer').each(function() {
                    returningValue[$(this).attr("id")] = $(this).index();
                }).get();   
            }   
        });
    }); 
    $( "#container" ).disableSelection()


    $("div#container").append(
    $("div.innercontainer").sort(function(a, b) {
        var sorted = current_order[$(a).attr('id')] - current_order[$(b).attr('id')];
        //console.log(sorted);
        localStorage.setItem("sorted", JSON.stringify(sorted));
        return sorted;
    })
    ); 

Hey, I think this should work for you:

// Store the Ids order
var current_order = {
    'set_1' : 0,
    'set_2' : 1
};
// If there's no previous order, create it with default values
if (JSON.parse(localStorage.getItem("sorted"))== " ")
{
    localStorage.setItem("sorted", JSON.stringify(current_order));
}

$(function(){
    // Get last saved order
    current_order = JSON.parse(localStorage.getItem("sorted"));
    console.log("returning"+current_order);

    // Sort container
    $( "#container" ).sortable({ cursor: "pointer", 
        placeholder: "highlight",

        update: function(event, ui){
            // When an element is sorted, update all the Indexes at current_order
            $(this).children('div.innercontainer').each(function() {
                current_order[$(this).attr("id")] = $(this).index();
            }).get();   
        }   
    });
    //Disable text selecion
    $( "#container" ).disableSelection()

    //Sort the divs based on the current_order
    $("div#container").append(
        $("div.innercontainer").sort(function(a, b) {
            var sorted = current_order[$(a).attr('id')] - current_order[$(b).attr('id')];
            //console.log(sorted);
            return sorted;
        })
    );
}); 

Obs.: Not tested ^^

commented: You have helped me on different things and provided the understanding that I needed in regards to the indexes and therefore helped me solve this. +3

I have now been able to do it! your indexing code ensures there is the right content set to localStorage and it was the index I was missing previously. There is one line of the code I don't quite understand. What does the below code do?

current_order[$(a).attr('id')] - current_order[$(b).attr('id')];

To see how I put it together with the localStorage see code below:

var current_order = {
        'set_1' : 0,
        'set_2' : 1
    };
    if (localStorage.getItem("sorted") === null)
    {
        localStorage.setItem("sorted", JSON.stringify(current_order));
    }
    else{

        current_order = JSON.parse(localStorage.getItem("sorted"));
    }
    $(function(){

        $( "#container" ).sortable({ cursor: "pointer", 
            placeholder: "highlight",

            update: function(event, ui){
                $(this).children('div.innercontainer').each(function() {
                    current_order[$(this).attr("id")] = $(this).index();
                }).get();
                localStorage.setItem("sorted", JSON.stringify(current_order));
            }   
        });
    }); 
    $( "#container" ).disableSelection()


    $("div#container").append(
    $("div.innercontainer").sort(function(a, b) {
        var sorted = current_order[$(a).attr('id')] - current_order[$(b).attr('id')];
        return sorted;
    })
    ); 

I'm glad to know that it worked =)

jQuery.sort(a, b) need us to define which one those come first.
And we'll decide who comes first based on our stored indexes at current_order

So return current_order[$(a).attr('id')] - current_order[$(b).attr('id')]; would be easier to read like this:

var aIndex = current_order[$(a).attr('id')];
var bIndex = current_order[$(b).attr('id')];

// if aIndex > bIndex => returns positive value (meaning that b comes first)
// if aIndex < bIndex => returns negative value (meaning that a comes first)
// if aIndex == bIndex => returns 0 (meaning that it doesn't matter)
 return aIndex - bIndex;

That cuts some if statements out. I have looked into the JQuery documentation on index() and get() but do you know any documentation on using that approach for the return value? I am interested to learn how such an approach can be used in other contexts as how you have explained it seems like - is not being used like an arithmetic operator as subtraction is.

piers, this return value based on negative/positive values are only for the JavaScript Array.sort method, is not from jQuery itself.

And why does Array.sort works on a jQuery object? Well, because every jQuery object is actually a JavaScript Array. That's why you can always check if the jQuery object has elements using $(".myselector").length;

You can read more about the .sort function at: http://www.w3schools.com/jsref/jsref_sort.asp

Now I get it. Thanks for that.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.