columns.render

columns.render

robobriefrobobrief Posts: 9Questions: 2Answers: 2
edited February 2016 in Editor

I have a table which has two columns where the data is serialized. I use a custom function to unserialize the data, and when the table loads all is as it should be. But when I submit an edit I encounter a problem. The database is updated but the edit for doesn't disappear and the spinner displays forever as if the form is waiting for something. I can see that the ajax call returns a correctly formatted json so I am assuming that the render function doesn't like something. (The form works as expected if I populate the field without using render). Does anyone see anything wrong with what I'm doing?

This is the javascript:

function unserialize(data) {
  //  discuss at: http://phpjs.org/functions/unserialize/
  // original by: Arpad Ray (mailto:arpad@php.net)
  // improved by: Pedro Tainha (http://www.pedrotainha.com)
  // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  // improved by: Chris
  // improved by: James
  // improved by: Le Torbi
  // improved by: Eli Skeggs
  // bugfixed by: dptr1988
  // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  // bugfixed by: Brett Zamir (http://brett-zamir.me)
  //  revised by: d3x
  //    input by: Brett Zamir (http://brett-zamir.me)
  //    input by: Martin (http://www.erlenwiese.de/)
  //    input by: kilops
  //    input by: Jaroslaw Czarniak
  //        note: We feel the main purpose of this function should be to ease the transport of data between php & js
  //        note: Aiming for PHP-compatibility, we have to translate objects to arrays
  //   example 1: unserialize('a:3:{i:0;s:5:"Kevin";i:1;s:3:"van";i:2;s:9:"Zonneveld";}');
  //   returns 1: ['Kevin', 'van', 'Zonneveld']
  //   example 2: unserialize('a:3:{s:9:"firstName";s:5:"Kevin";s:7:"midName";s:3:"van";s:7:"surName";s:9:"Zonneveld";}');
  //   returns 2: {firstName: 'Kevin', midName: 'van', surName: 'Zonneveld'}

  "use strict";
    var utf8Overhead = function(chr) {
      // http://phpjs.org/functions/unserialize:571#comment_95906
      var code = chr.charCodeAt(0);
      if (  code < 0x0080 
            || 0x00A0 <= code && code <= 0x00FF 
            || [338,339,352,353,376,402,8211,8212,8216,8217,8218,8220,8221,8222,8224,8225,8226,8230,8240,8364,8482].indexOf(code)!=-1) 
      {
        return 0;
      }
      if (code < 0x0800) {
        return 1;
      }
      return 2;
    };
  var read_until = function(data, offset, stopchr) {
    var i = 2,
      buf = [],
      chr = data.slice(offset, offset + 1);

    while (chr != stopchr) {
      if ((i + offset) > data.length) {
      }
      buf.push(chr);
      chr = data.slice(offset + (i - 1), offset + i);
      i += 1;
    }
    return [buf.length, buf.join('')];
  };
  var read_chrs = function(data, offset, length) {
    var i, chr, buf;

    buf = [];
    for (i = 0; i < length; i++) {
      chr = data.slice(offset + (i - 1), offset + i);
      buf.push(chr);
      length -= utf8Overhead(chr);
    }
    return [buf.length, buf.join('')];
  };
  var _unserialize = function(data, offset) {
    var dtype, dataoffset, keyandchrs, keys, contig,
      length, array, readdata, readData, ccount,
      stringlength, i, key, kprops, kchrs, vprops,
      vchrs, value, chrs = 0,
      typeconvert = function(x) {
        return x;
      };

    if (!offset) {
      offset = 0;
    }
    dtype = (data.slice(offset, offset + 1))
      .toLowerCase();

    dataoffset = offset + 2;

    switch (dtype) {
    case 'i':
      typeconvert = function(x) {
        return parseInt(x, 10);
      };
      readData = read_until(data, dataoffset, ';');
      chrs = readData[0];
      readdata = readData[1];
      dataoffset += chrs + 1;
      break;
    case 'b':
      typeconvert = function(x) {
        return parseInt(x, 10) !== 0;
      };
      readData = read_until(data, dataoffset, ';');
      chrs = readData[0];
      readdata = readData[1];
      dataoffset += chrs + 1;
      break;
    case 'd':
      typeconvert = function(x) {
        return parseFloat(x);
      };
      readData = read_until(data, dataoffset, ';');
      chrs = readData[0];
      readdata = readData[1];
      dataoffset += chrs + 1;
      break;
    case 'n':
      readdata = null;
      break;
    case 's':
      ccount = read_until(data, dataoffset, ':');
      chrs = ccount[0];
      stringlength = ccount[1];
      dataoffset += chrs + 2;

      readData = read_chrs(data, dataoffset + 1, parseInt(stringlength, 10));
      chrs = readData[0];
      readdata = readData[1];
      dataoffset += chrs + 2;
      if (chrs != parseInt(stringlength, 10) && chrs != readdata.length) {
      }
      break;
    case 'a':
      readdata = {};

      keyandchrs = read_until(data, dataoffset, ':');
      chrs = keyandchrs[0];
      keys = keyandchrs[1];
      dataoffset += chrs + 2;

      length = parseInt(keys, 10);
      contig = true;

      for (i = 0; i < length; i++) {
        kprops = _unserialize(data, dataoffset);
        kchrs = kprops[1];
        key = kprops[2];
        dataoffset += kchrs;

        vprops = _unserialize(data, dataoffset);
        vchrs = vprops[1];
        value = vprops[2];
        dataoffset += vchrs;

        if (key !== i)
          var contig = false;
        readdata[key] = value;
      }

      if (contig) {
        array = new Array(length);
        for (i = 0; i < length; i++)
          array[i] = readdata[i];
        readdata = array;
      }

      dataoffset += 1;
      break;
    default:
      break;
    }
    return [dtype, dataoffset - offset, typeconvert(readdata)];
  };

  return _unserialize((data + ''), 0)[2];
}
    var editor; // use a global for the submit and return data rendering in the examples        
    $(document).ready(function() 
    {   
        "use strict";       
        editor = new $.fn.dataTable.Editor
        (
            {    
                table: "#example",
                fields: 
                [ 
                    {
                        label: "First Name:",
                        name: "m_first_name.meta_value"
                    }, 
                    {
                        label: "Last Name:",
                        name: "m_last_name.meta_value"
                    }, 
                    {
                        label: "Auto EOT:",
                        name: "m_auto_eot_time.meta_value"
                    }               ],
                ajax: 
                { 
                    edit: "edit-lastname.php?id=_id_"
                }
            }
        );      
        $('#example').DataTable
        (
            {
                dom: "Bfrtip",
                ajax: "users.php",
                type: 'POST',
                columns: 
                [
                    { data: "ul.ID", className: "dt-body-center"  },
                    { 
                        data: "m_user_capabilities.meta_value",
                        className: "dt-body-center",
                        render : function ( data )
                        {
                            var $user_capabilities = unserialize( data );
                            var $user_level = 'Undefined';
                            if ($user_capabilities.subscriber)
                            { // a whole series of tests go here                                                                                
                            return $user_level;
                        }                       
                    },                          
                    { data: "m_first_name.meta_value", className: "dt-body-center" },
                    { data: "m_last_name.meta_value", className: "dt-body-center"  },
                    { 
                        data: "m_custom_fields.meta_value", 
                        className: "dt-body-center", 
                        render : function ( data )
                        {
                            var $business_name = unserialize( data ).business_name;
                            if ($business_name === undefined || $business_name === null)
                            {
                                return '';
                            }
                            else
                            {
                                return $business_name;
                            }
                        }                       
                    },                  
                    { data: "m_subscriber_id.meta_value", className: "dt-body-center"  },
                    { data: "m_auto_eot_time.meta_value" , editField: "m_auto_eot_time.meta_value", className: "dt-body-center" }
                ],
                select: true,
                buttons: 
                [
                    { extend: "edit",   editor: editor }
                ]
            }
        );      
    });

I can see the JS throws an uncaught exception: out of memory.

Any help would be much appreciated.

This question has an accepted answers - jump to answer

Answers

  • robobriefrobobrief Posts: 9Questions: 2Answers: 2
    Answer ✓

    I have answered my question. The render function does fire once a form is successfully submitted and processed so you need to make sure the data that is being returned to it is identical in format / type to that when the table was first drawn, or have the function called when rendering handle all possible datatypes that it may encounter.

  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin

    Hi,

    Thanks for posting back (nice unserialise function btw!). You are absolutely correct - you need to use the same data format in the edit request return as the DataTable is feed when loading data.

    I hope to be able to relax that somewhat in future.

    Regards,
    Allan

This discussion has been closed.