2

So I have two sortable lists that a user can drag items out of and into a third list where they can hopefully export that list to a downloadable csv file. I have the multiple selectable and sortable part working fine at this jsfiddle, but now need to include the export to csv funtionality.

Can anyone help?

Here is a screenshot of what I am attempting to achieve from the jsfiddle: enter image description here Here is my code so far:

    <html>
<meta charset="utf-8" />
<title>jQuery UI Sortable with Selectable</title>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
$(function() {
//

$('body').selectable({
    filter: 'li'
    //filter: '#album2 > li'
});

$('.connectedSortable').sortable({
    connectWith: ".connectedSortable",
    delay: 100,
    start: function(e, ui) {
        var topleft = 0;

        // if the current sorting LI is not selected, select
        $(ui.item).addClass('ui-selected');

        $('.ui-selected div').each(function() {

            // save reference to original parent
            var originalParent = $(this).parent()[0];
            $(this).data('origin', originalParent);

            // position each DIV in cascade
            $(this).css('position', 'absolute');
            $(this).css('top', topleft);
            $(this).css('left', topleft);
            topleft += 20;

        }).appendTo(ui.item); // glue them all inside current sorting LI

    },
    stop: function(e, ui) {
        $(ui.item).children().each(function() {

            // restore all the DIVs in the sorting LI to their original parents
            var originalParent = $(this).data('origin');
            $(this).appendTo(originalParent);

            // remove the cascade positioning
            $(this).css('position', '');
            $(this).css('top', '');
            $(this).css('left', '');
        });

        // put the selected LIs after the just-dropped sorting LI
        $('#album .ui-selected').insertAfter(ui.item);

        // put the selected LIs after the just-dropped sorting LI
        $('#album2 .ui-selected').insertAfter(ui.item);
    }
});




//
});


<style>
*,
*:before,
*:after {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

#album {
    list-style: none;
    float: left;
    width: 20%;
    border: 1px solid blue;
}
#album2 {
    list-style: none;
    float: left;
    width: 20%;
    border: 1px solid blue;
}
#album li  {
    float: left;
    margin: 5px;
}

#album2 li  {
    float: left;
    margin: 5px;
}


#album div {
    width: 100px;
    height: 100px;
    border: 1px solid #CCC;

    background: #F6F6F6;    
}
#album2 div {
    width: 100px;
    height: 100px;
    border: 1px solid #CCC;

    background: #F6F6F6;    
}
#album .ui-sortable-placeholder {
    border: 1px dashed #CCC;
    width: 100px;
    height: 100px;
    background: none;
    visibility: visible !important;
}
#album2 .ui-sortable-placeholder {
    border: 1px dashed #CCC;
    width: 100px;
    height: 100px;
    background: none;
    visibility: visible !important;
}

#album .ui-selecting div, 
#album .ui-selected div {
    background-color: #3C6;
}

#album2 .ui-selecting div, 
#album2 .ui-selected div {
    background-color: #3C6;
}

#anotheralbum {
    list-style: none;
    float: left;
    width: 20%;
    height: 800px;
    border: 1px solid green;
}
</style>


<body>

<ul id="album" class="connectedSortable">
    <li id="li1"><div>1- First</div></li>
    <li id="li2"><div>2- Second</div></li>
    <li id="li3"><div>3- Third</div></li>
    <li id="li4"><div>4- Fourth</div></li>
    <li id="li5"><div>5- Fifth</div></li>
    <li id="li6"><div>6- Sixth</div></li>
    <li id="li7"><div>7- Seventh</div></li>
    <li id="li8"><div>8- Eighth</div></li>
</ul>

<ul id="album2" class="connectedSortable">
    <li id="li1"><div>1- 1</div></li>
    <li id="li2"><div>2- 2</div></li>
    <li id="li3"><div>3- 3</div></li>
    <li id="li4"><div>4- 4</div></li>
    <li id="li5"><div>5- 5</div></li>
    <li id="li6"><div>6- 6</div></li>
    <li id="li7"><div>7- 7</div></li>
    <li id="li8"><div>8- 8</div></li>
</ul>
<div id="anotheralbum" class="connectedSortable">
This is a list of what to export to csv
</div>

<br style="clear:both">
</body>
</html>
snowtimber
  • 168
  • 1
  • 9
  • The answer from [this post](http://stackoverflow.com/questions/4639372/export-to-csv-in-jquery?rq=1)[1] seems to answer your question, using URIs. [1]: http://stackoverflow.com/questions/4639372/export-to-csv-in-jquery?rq=1 – Berjurand Feb 13 '15 at 16:15
  • I'm currently working on csv export with `data:uri`. The major problem is the detection of support which gives false positives. I'm back to browser detection (ie) and a flash fallback (downloadify). Otherwise in modern browsers => `var dataUri = 'data:text/csv;charset=utf-8,' + escape(csvData);` – Tim Vermaelen Feb 13 '15 at 16:16
  • Thanks @TimVermaelen. Do you know an easy way I can get the text of the items in the third list into "csvData"? – snowtimber Feb 13 '15 at 16:25
  • Something along the lines of `var arr = []; $('li').each(function(){ arr.push($(this).text()) });` and then `arr.join(',')` – Tim Vermaelen Feb 13 '15 at 16:29

1 Answers1

1

The biggest problem is detecting browser support. If you need it to work x-browser you want to know which browsers support the download attribute.

There's your biggest issue right there: in order to detect it, you fall back to a dynamic iframe which holds the data. IE has a data url limit and actually only supports it for images. In short, false positives occur and for those who support it, will trigger the download immediately.

That said, I don't believe you can do it x-browser without detecting the useragent.

function addDataUri(){
    var csvData = convertJsonToCsv('<%= JsonResults %>'),
        dataUri = 'data:text/csv;charset=utf-8,' + escape(csvData),
        exportLink = $('.exportLink a');

    if (exportLink.length) {
        // if browser is unsupported, fallback to flash
        if (isIe()) {
            getDownloadify(function () {
                setupDownloadify(csvData, exportLink);
            });
        } else {
            exportLink.prop({
                href: dataUri,
                target: '_blank',
                download: 'export_' + +(new Date()) + '.csv'
            });
        }
    }
}

function convertJsonToCsv(json) {
    var objArray = json, array = JSON.parse(objArray), str = '', line, i = 0;
    for (; i < array.length; i++) {
        line = '';

        for (var index in array[i]) {
            line += array[i][index] + ',';
        }

        line.slice(0, line.length - 1);
        str += line + '\r\n';
    }

    return str;
}

So in your example the convertJsonToCsv() should be different. As stated in the comments, something along the lines of:

function convertJQueryToCsv(){
    var arr = [];
    $.each($yourObj, function(){
        arr.push($(this).text());
    });
    return arr.join(',');
}

If you're interested in how I set up the flash fallback, let me know.

Tim Vermaelen
  • 6,869
  • 1
  • 25
  • 39
  • I think I am getting close at jsfiddle.net/MooseEagleShark/hz0eqbqg/6, but keep getting function not defined errors... do you know what I'm doing wrong? – snowtimber Feb 13 '15 at 20:23
  • No, you weren't "that" close, ... [this](http://jsfiddle.net/tive/pchefj0a/) is getting close. Still need to finetune `convertJQueryToCsv()` and fallback. – Tim Vermaelen Feb 14 '15 at 13:41
  • Apologies for being dense here, but I am having trouble seeing any action happening let alone a txt file download, even if I style the fallback as in http://jsfiddle.net/MooseEagleShark/2q22ww0j/5/. What else am I missing here? Thanks for your help @Tim Vermaelen! – snowtimber Feb 16 '15 at 17:39
  • I've made an update to the fiddle with the flash fallback (not tested yet). The data uri gets generated in your `stop` function. Now you can use save as but I'm not sure if the fiddle blocks `download` links or something else is wrong ... – Tim Vermaelen Feb 16 '15 at 21:17
  • Thanks Tim, can't tell you how much I appreciate it! Yea the link doesn't seem to work on a left click, but with a right click and "save link as" it works fine on my machine. Thanks again! – snowtimber Feb 16 '15 at 21:56