JQuery Datatable - Split single cell into multiple

2019-07-19 15:14发布

问题:

With JQuery Data tables, is it possible to split a single column up into parts purely for readability? For example, I have a databases of URLs split into the domain and the path. I want to keep the path whole, but for readability I would like each part of the path split up into columns. For example:

DOMAIN | PATH
www.xxx| /p | /rty |   |
www.zzz| /o |      |   |
www.yyy| /yu| /x   | /t|

I have tried using render to split up each URL with spaces, but this is less than ideal as everything is within the same column and rather an eyesore.

EDIT Just to be clear, I would really like to keep the path as one data entry. I am aware this is an odd choice, but in my case it is preferable.

EDIT Code to fill in the table

Javascript

<script>
$(function() {
    $('#ut-table').DataTable({
        processing: true,
        serverSide: true,
        ajax: '{!! url('/all') !!}',
        columns: [
            { data: 'frequency'},
            { data: 'occurrences'},
            { data: 'protocol'},
            { data: 'domain'},
            { data: 'path', render: function(data, type, row){
                var newchar = '  |  ';
                return data.split('/').join(newchar);
                }
            },
        ],
    });
});

HTML

<table class="table table-bordered" id="ut-table">
    <thead>
    <tr>
        <th>frequency</th>
        <th>occurrences</th>
        <th>protocol</th>
        <th>domain</th>
        <th>path</th>
    </tr>
    </thead>
</table>


Laravel Back End

public function all()
{
    Debugbar::warning('query fired');
    return Datatables::of(
        Unknown_Tag::query()
        ->orderBy('frequency', 'desc')
        ->groupBy('urlTrimmed')
    )->make(true);
}

EDIT: Thanks a million to Louys and his answer, however I still have a problem. I need to split up my path, not my url. EX I need to split this: "/this/is/my/path" into this: this is my path I tried the below code:

<script>
$(function() {
    var table = $('#ut-table');
    table.dataTable({
        processing: true,
        serverSide: true,
        ajax: '{!! url('/all') !!}',
        columns: [
            { data: 'domain'},
            { data: 'path', render: function(data, type, row){
                var regexp = /^\/.*?(?=\/|$)/g;
                var match = regexp.exec(data);
                return match[0];
            }
            },
            { data: 'path', render: function(data, type, row){
                var regexp = /^\/.*?(?=\/|$)/g;
                var match = regexp.exec(data);
                return match[1];
            }
            },
        ],
    });
});

However, since both calls to my regex are in different scopes, only my first match will be returned. Any idea how I can get around this without having to run a loop for each iteration? Actually, this thought just came to me, is there anyway I can edit the JSON from my PHP call to include the split up path?

回答1:

I would try using a regular expression like this one : /^(https?:\/\/)(.+\/)(.+)/.

So, assuming your data is in JSON formed like in this example.
And that you have ONE JSON attribute containg the full URL.

Say... Something like this:

{
    "frequency":{value},
    "occurrences":{value},
    "fullurl":{value}
}

Your function would look like:

$(function() {
    $('#ut-table').DataTable({
        processing: true,
        serverSide: true,
        ajax: '{!! url('/all') !!}',
        columns: [
            { data: 'frequency'},
            { data: 'occurrences'},
            { data: 'fullurl', render: function(data, type, row){
                var regexp = /^(https?:\/\/)(.+\/)(.+)/;
                var match = regexp.exec(data);
                return match[0];                        // PROTOCOL
                }
            },
            { data: 'fullurl', render: function(data, type, row){
                var regexp = /^(https?:\/\/)(.+\/)(.+)/;
                var match = regexp.exec(data);
                return match[1];                        // DOMAIN
                }
            },
            { data: 'fullurl', render: function(data, type, row){
                var regexp = /^(https?:\/\/)(.+\/)(.+)/;
                var match = regexp.exec(data);
                return match[2];                        // PATH
                }
            },
        ],
    });
});

So the regular expression has 3 possible "matches" determined by the parenthesis.
The trick is to return the right match in the right column.

You can test your own regular expression here.

Hoping it helps!
;)





EDIT

To "split" the path only... instead of the full URL, as asked in comments:

You better use the .split function then.
Because this part will not be as "regular" has the previous case.
It can have different sub-directory level...
It can have a trailing slash and sometimes not.

So let say you have 4 columns, like for the example you provided : "/this/is/my/path"

Since the function is a bit longuer, I think it is best to avoid having it repeated 4 times.
So let's create a function to place in global scope.

// This var is the real column amount of your table (not zero-based).
var maxPathParts = 4;

function pathSplitter(pathPart){

    // Check if the first char is a / and remove if it's the case.
    // It would oddly make the first array element as empty.
    if(data.charAt(0)=="/"){
        data = data.sustr(1);
    }

    // Check if last char is a slash.
    var lastWasSlash=false;
    if(data.charAt(data.length-1)=="/"){
        lastWasSlash=true;
        data = data.substr(0,data.length-1);
    }

    // Now split the data in an array based on slashes.
    var splittedData = data.split("/");

    // If there is more parts than maxPathParts... Aggregate all the excedent in the last part.
    if(splittedData.length>maxPathParts){
        var tempLastPart;
        for(i=maxPathParts-1;i<splittedData.length;i++){
        tempLastPart += splittedData[i] + "/";
        }
        splittedData[maxPathParts]=tempLastPart;
    }

    // If it exist.
    if(typeof(splittedData[pathPart]!="undefined"){

        // Add a trailing slash to it if it is not the last element.
        if( pathPart != splittedData.length-1 ){

            // Add a trailing slash to it.
            splittedData[pathPart] += "/";
        }

        // But add it anyway if the last char of the path was a slash.
        if (pathPart != splittedData.length-1 && lastWasSlash ){

            // Add a trailing slash to it.
            splittedData[pathPart] += "/";
        }
        return splittedData[pathPart];

    }else{
        // If there is no value for this column.
        return "";
    }
}

So now that you have a function, just call it in the DataTable column settings with the right column number as argument:

columns: [
    { data: 'domain'},
    { data: 'path', render: pathSplitter(0)},
    { data: 'path', render: pathSplitter(1)},
    { data: 'path', render: pathSplitter(2)},
    { data: 'path', render: pathSplitter(3)},
],

Let me know it it bugs... I didn't test anything.