# \[DATATABLE] JQuery Datatables Editor - Alternative to the official one (ok)

<figure><img src="/files/aTaGhGadTf977AlQsUKr" alt=""><figcaption></figcaption></figure>

1. [In memory arrays](https://belongstomany.com/example/01_in_memory_arrays/example1.html)
2.

```
<figure><img src="/files/z5p9EVWq3zC9sUWedrLE" alt=""><figcaption></figcaption></figure>
```

C:\xampp\htdocs\belongstomany\example\01\_in\_memory\_arrays\example1.html

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>DataTable-AltEditor - Example #1</title>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css" />
  <link rel="stylesheet" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.css" />
  <link rel="stylesheet" href="https://cdn.datatables.net/buttons/1.6.2/css/buttons.dataTables.css" />
  <link rel="stylesheet" href="https://cdn.datatables.net/select/1.3.1/css/select.dataTables.css" />
  <link rel="stylesheet" href="https://cdn.datatables.net/responsive/2.2.5/css/responsive.dataTables.css" />
</head>
<body>
  <div class="container">
    <div class="row">
      <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
        <h1>DataTable-AltEditor - Example #1</h1>
        <h2>with array-based datatable rows</h2>
        <p>Rows are contained in some .js file in the form: [1,"Tiger Nixon", "System Architect", "Edinburgh", "5421",
          "2011/04/25", "$320,800"] <br />
          Data is managed in memory. A "Refresh" button is meaningless here.
        </p>
      </div>
    </div>
  </div>
  <div class="container">
    <table cellpadding="0" cellspacing="0" border="0" class="dataTable table table-striped" id="example">
    </table>
  </div>
  <script src="https://code.jquery.com/jquery-3.0.0.js"></script>
  <script src="https://code.jquery.com/jquery-migrate-3.3.0.js"></script>
  <script src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.js"></script>
  <script src="https://cdn.datatables.net/buttons/1.6.2/js/dataTables.buttons.js"></script>
  <script src="https://cdn.datatables.net/select/1.3.1/js/dataTables.select.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js"></script>
  <script src="https://cdn.datatables.net/responsive/2.2.5/js/dataTables.responsive.js"></script>
  <script src="../../src/dataTables.altEditor.free.js"></script>
  <script src="./example1.js"></script>
</body>
</html>

```

C:\xampp\htdocs\belongstomany\example\01\_in\_memory\_arrays\example1.html

```javascript
$(document).ready(function () {
  var dataSet = [
    [1, "Tiger Nixon", "System Architect", "Edinburgh", "5421", "2011/04/25", "$320,800"],
    [2, "Garrett Winters", "Accountant", "Tokyo", "8422", "2011/07/25", "$170,750"],
    [3, "Ashton Cox", "Junior Technical Author", "San Francisco", "1562", "2009/01/12", "$86,000"],
    [4, "Cedric Kelly", "Senior Javascript Developer", "Edinburgh", "6224", "2012/03/29", "$433,060"],
    [5, "Airi Satou", "Accountant", "Tokyo", "5407", "2008/11/28", "$162,700"],
    [6, "Brielle Williamson", "Integration Specialist", "New York", "4804", "2012/12/02", "$372,000"],
    [7, "Herrod Chandler", "Sales Assistant", "San Francisco", "9608", "2012/08/06", "$137,500"],
    [8, "Rhona Davidson", "Integration Specialist", "Tokyo", "6200", "2010/10/14", "$327,900"],
    [9, "Colleen Hurst", "Javascript Developer", "San Francisco", "2360", "2009/09/15", "$205,500"],
    [10, "Sonya Frost", "Software Engineer", "Edinburgh", "1667", "2008/12/13", "$103,600"],
    [11, "Jena Gaines", "Office Manager", "London", "3814", "2008/12/19", "$90,560"],
    [12, "Quinn Flynn", "Support Lead", "Edinburgh", "9497", "2013/03/03", "$342,000"],
    [13, "Charde Marshall", "Regional Director", "San Francisco", "6741", "2008/10/16", "$470,600"],
    [14, "Haley Kennedy", "Senior Marketing Designer", "London", "3597", "2012/12/18", "$313,500"],
    [15, "Tatyana Fitzpatrick", "Regional Director", "London", "1965", "2010/03/17", "$385,750"],
    [16, "Michael Silva", "Marketing Designer", "London", "1581", "2012/11/27", "$198,500"],
    [17, "Paul Byrd", "Chief Financial Officer (CFO)", "New York", "3059", "2010/06/09", "$725,000"],
    [18, "Gloria Little", "Systems Administrator", "New York", "1721", "2009/04/10", "$237,500"],
    [19, "Bradley Greer", "Software Engineer", "London", "2558", "2012/10/13", "$132,000"],
    [20, "Dai Rios", "Personnel Lead", "Edinburgh", "2290", "2012/09/26", "$217,500"],
    [21, "Jenette Caldwell", "Development Lead", "New York", "1937", "2011/09/03", "$345,000"],
    [22, "Yuri Berry", "Chief Marketing Officer (CMO)", "New York", "6154", "2009/06/25", "$675,000"],
    [23, "Caesar Vance", "Pre-Sales Support", "New York", "8330", "2011/12/12", "$106,450"],
    [24, "Doris Wilder", "Sales Assistant", "Sidney", "3023", "2010/09/20", "$85,600"],
    [25, "Angelica Ramos", "Chief Executive Officer (CEO)", "London", "5797", "2009/10/09", "$1,200,000"],
    [26, "Gavin Joyce", "Developer", "Edinburgh", "8822", "2010/12/22", "$92,575"],
    [27, "Jennifer Chang", "Regional Director", "Singapore", "9239", "2010/11/14", "$357,650"],
    [28, "Brenden Wagner", "Software Engineer", "San Francisco", "1314", "2011/06/07", "$206,850"],
    [29, "Fiona Green", "Chief Operating Officer (COO)", "San Francisco", "2947", "2010/03/11", "$850,000"],
    [30, "Shou Itou", "Regional Marketing", "Tokyo", "8899", "2011/08/14", "$163,000"],
    [31, "Michelle House", "Integration Specialist", "Sidney", "2769", "2011/06/02", "$95,400"],
    [32, "Suki Burks", "Developer", "London", "6832", "2009/10/22", "$114,500"],
    [33, "Prescott Bartlett", "Technical Author", "London", "3606", "2011/05/07", "$145,000"],
    [34, "Gavin Cortez", "Team Leader", "San Francisco", "2860", "2008/10/26", "$235,500"],
    [35, "Martena Mccray", "Post-Sales support", "Edinburgh", "8240", "2011/03/09", "$324,050"],
    [36, "Unity Butler", "Marketing Designer", "San Francisco", "5384", "2009/12/09", "$85,675"]
  ];
  var columnDefs = [{
    title: "Id",
    type: "readonly"
  }, {
    title: "Name",
    type: "text"
  }, {
    title: "Position",
    type: "textarea"
  }, {
    title: "Office"
    //no type = text
  }, {
    title: "Extn.",
    type: "text"
  }, {
    title: "Start date",
    type: "readonly"
  }, {
    title: "Salary",
    type: "text"
  }];
  var myTable;
  myTable = $('#example').DataTable({
    "sPaginationType": "full_numbers",
    data: dataSet,
    columns: columnDefs,
    dom: 'Bfrtip',        // Needs button container
    select: 'single',
    responsive: true,
    altEditor: false,     // Enable altEditor
    buttons: [
      {
        text: 'Add',
        name: 'add'        // do not change name
      },
      {
        extend: 'selected', // Bind to Selected row
        text: 'Edit',
        name: 'edit'        // do not change name
      },
      {
        extend: 'selected', // Bind to Selected row
        text: 'Delete',
        name: 'delete'      // do not change name
      }
    ]
  });
});

```

1. [In memory objects](https://belongstomany.com/example/02_in_memory_objects/example2.html)

<figure><img src="/files/qI2tOqkTd2MuxosxSK6E" alt=""><figcaption></figcaption></figure>

C:\xampp\htdocs\belongstomany\example\02\_in\_memory\_objects\example2.html

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>DataTable-AltEditor - Example #2</title>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css" />
  <link rel="stylesheet" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.css" />
  <link rel="stylesheet" href="https://cdn.datatables.net/buttons/1.6.2/css/buttons.dataTables.css" />
  <link rel="stylesheet" href="https://cdn.datatables.net/select/1.3.1/css/select.dataTables.css" />
  <link rel="stylesheet" href="https://cdn.datatables.net/responsive/2.2.5/css/responsive.dataTables.css" />
</head>
<body>
  <div class="container">
    <div class="row">
      <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
        <h1>DataTable-AltEditor - Example #2</h1>
        <h2>with object-based datatable rows</h2>
        Rows are contained in some .js file in the form:
        {id:1, name:"Tiger Nixon", position:"System Architect", office:"Edinburgh", extension:"5421",
        startDate:"2011/04/25",
        salary:"Tiger Nixon"} <br />
        Data is managed in memory. A "Refresh" button is meaningless here.
      </div>
    </div>
  </div>
  <div class="container">
    <table cellpadding="0" cellspacing="0" border="0" class="dataTable table table-striped" id="example">
    </table>
  </div>
  <script src="https://code.jquery.com/jquery-3.0.0.js"></script>
  <script src="https://code.jquery.com/jquery-migrate-3.3.0.js"></script>
  <script src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.js"></script>
  <script src="https://cdn.datatables.net/buttons/1.6.2/js/dataTables.buttons.js"></script>
  <script src="https://cdn.datatables.net/select/1.3.1/js/dataTables.select.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js"></script>
  <script src="https://cdn.datatables.net/responsive/2.2.5/js/dataTables.responsive.js"></script>
  <script src="../../src/dataTables.altEditor.free.js"></script>
  <script src="./example2.js"></script>
</body>
</html>

```

C:\xampp\htdocs\belongstomany\example\02\_in\_memory\_objects\example2.js

```javascript
$(document).ready(function () {
  var dataSet = [
    { id: 1, name: "Tiger Nixon", position: "System Architect", office: "Edinburgh", extension: "5421", startDate: "2011/04/25", salary: "Tiger Nixon" },
    { id: 2, name: "Garrett Winters", position: "Accountant", office: "Tokyo", extension: "8422", startDate: "2011/07/25", salary: "Garrett Winters" },
    { id: 3, name: "Ashton Cox", position: "Junior Technical Author", office: "San Francisco", extension: "1562", startDate: "2009/01/12", salary: "Ashton Cox" },
    { id: 4, name: "Cedric Kelly", position: "Senior Javascript Developer", office: "Edinburgh", extension: "6224", startDate: "2012/03/29", salary: "Cedric Kelly" },
    { id: 5, name: "Airi Satou", position: "Accountant", office: "Tokyo", extension: "5407", startDate: "2008/11/28", salary: "Airi Satou" },
    { id: 6, name: "Brielle Williamson", position: "Integration Specialist", office: "New York", extension: "4804", startDate: "2012/12/02", salary: "Brielle Williamson" },
    { id: 7, name: "Herrod Chandler", position: "Sales Assistant", office: "San Francisco", extension: "9608", startDate: "2012/08/06", salary: "Herrod Chandler" },
    { id: 8, name: "Rhona Davidson", position: "Integration Specialist", office: "Tokyo", extension: "6200", startDate: "2010/10/14", salary: "Rhona Davidson" },
    { id: 9, name: "Colleen Hurst", position: "Javascript Developer", office: "San Francisco", extension: "2360", startDate: "2009/09/15", salary: "Colleen Hurst" },
    { id: 10, name: "Sonya Frost", position: "Software Engineer", office: "Edinburgh", extension: "1667", startDate: "2008/12/13", salary: "Sonya Frost" },
    { id: 11, name: "Jena Gaines", position: "Office Manager", office: "London", extension: "3814", startDate: "2008/12/19", salary: "Jena Gaines" },
    { id: 12, name: "Quinn Flynn", position: "Support Lead", office: "Edinburgh", extension: "9497", startDate: "2013/03/03", salary: "Quinn Flynn" },
    { id: 13, name: "Charde Marshall", position: "Regional Director", office: "San Francisco", extension: "6741", startDate: "2008/10/16", salary: "Charde Marshall" },
    { id: 14, name: "Haley Kennedy", position: "Senior Marketing Designer", office: "London", extension: "3597", startDate: "2012/12/18", salary: "Haley Kennedy" },
    { id: 15, name: "Tatyana Fitzpatrick", position: "Regional Director", office: "London", extension: "1965", startDate: "2010/03/17", salary: "Tatyana Fitzpatrick" },
    { id: 16, name: "Michael Silva", position: "Marketing Designer", office: "London", extension: "1581", startDate: "2012/11/27", salary: "Michael Silva" },
    { id: 17, name: "Paul Byrd", position: "Chief Financial Officer (CFO)", office: "New York", extension: "3059", startDate: "2010/06/09", salary: "Paul Byrd" },
    { id: 18, name: "Gloria Little", position: "Systems Administrator", office: "New York", extension: "1721", startDate: "2009/04/10", salary: "Gloria Little" },
    { id: 19, name: "Bradley Greer", position: "Software Engineer", office: "London", extension: "2558", startDate: "2012/10/13", salary: "Bradley Greer" },
    { id: 20, name: "Dai Rios", position: "Personnel Lead", office: "Edinburgh", extension: "2290", startDate: "2012/09/26", salary: "Dai Rios" },
    { id: 21, name: "Jenette Caldwell", position: "Development Lead", office: "New York", extension: "1937", startDate: "2011/09/03", salary: "Jenette Caldwell" },
    { id: 22, name: "Yuri Berry", position: "Chief Marketing Officer (CMO)", office: "New York", extension: "6154", startDate: "2009/06/25", salary: "Yuri Berry" },
    { id: 23, name: "Caesar Vance", position: "Pre-Sales Support", office: "New York", extension: "8330", startDate: "2011/12/12", salary: "Caesar Vance" },
    { id: 24, name: "Doris Wilder", position: "Sales Assistant", office: "Sidney", extension: "3023", startDate: "2010/09/20", salary: "Doris Wilder" },
    { id: 25, name: "Angelica Ramos", position: "Chief Executive Officer (CEO)", office: "London", extension: "5797", startDate: "2009/10/09", salary: "Angelica Ramos" },
    { id: 26, name: "Gavin Joyce", position: "Developer", office: "Edinburgh", extension: "8822", startDate: "2010/12/22", salary: "Gavin Joyce" },
    { id: 27, name: "Jennifer Chang", position: "Regional Director", office: "Singapore", extension: "9239", startDate: "2010/11/14", salary: "Jennifer Chang" },
    { id: 28, name: "Brenden Wagner", position: "Software Engineer", office: "San Francisco", extension: "1314", startDate: "2011/06/07", salary: "Brenden Wagner" },
    { id: 29, name: "Fiona Green", position: "Chief Operating Officer (COO)", office: "San Francisco", extension: "2947", startDate: "2010/03/11", salary: "Fiona Green" },
    { id: 30, name: "Shou Itou", position: "Regional Marketing", office: "Tokyo", extension: "8899", startDate: "2011/08/14", salary: "Shou Itou" },
    { id: 30, name: "Michelle House", position: "Integration Specialist", office: "Sidney", extension: "2769", startDate: "2011/06/02", salary: "Michelle House" },
    { id: 32, name: "Suki Burks", position: "Developer", office: "London", extension: "6832", startDate: "2009/10/22", salary: "Suki Burks" },
    { id: 33, name: "Prescott Bartlett", position: "Technical Author", office: "London", extension: "3606", startDate: "2011/05/07", salary: "Prescott Bartlett" },
    { id: 34, name: "Gavin Cortez", position: "Team Leader", office: "San Francisco", extension: "2860", startDate: "2008/10/26", salary: "Gavin Cortez" },
    { id: 35, name: "Martena Mccray", position: "Post-Sales support", office: "Edinburgh", extension: "8240", startDate: "2011/03/09", salary: "Martena Mccray" },
    { id: 36, name: "Unity Butler", position: "Marketing Designer", office: "San Francisco", extension: "5384", startDate: "2009/12/09", salary: "Unity Butler" },
  ];
  var columnDefs = [{
    data: "id",
    title: "Id",
    type: "readonly"
  },
  {
    data: "name",
    title: "Name"
  },
  {
    data: "position",
    title: "Position"
  },
  {
    data: "office",
    title: "Office"
  },
  {
    data: "extension",
    title: "Extn."
  },
  {
    data: "startDate",
    title: "Start date"
  },
  {
    data: "salary",
    title: "Salary"
  }];
  var myTable;
  myTable = $('#example').DataTable({
    "sPaginationType": "full_numbers",
    data: dataSet,
    columns: columnDefs,
    dom: 'Bfrtip',        // Needs button container
    select: 'single',
    responsive: true,
    altEditor: true,     // Enable altEditor
    buttons: [{
      text: 'Add',
      name: 'add'        // do not change name
    },
    {
      extend: 'selected', // Bind to Selected row
      text: 'Edit',
      name: 'edit'        // do not change name
    },
    {
      extend: 'selected', // Bind to Selected row
      text: 'Delete',
      name: 'delete'      // do not change name
    }]
  });
});

```

1. [AJAX objects](https://belongstomany.com/example/03_ajax_objects/example3.html)

<figure><img src="/files/HbgrmlsIpC5DS9AAFkO3" alt=""><figcaption></figcaption></figure>

C:\xampp\htdocs\belongstomany\example\03\_ajax\_objects\example3.html

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>DataTable-AltEditor - Example #3</title>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css" />
  <link rel="stylesheet" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.css" />
  <link rel="stylesheet" href="https://cdn.datatables.net/buttons/1.6.2/css/buttons.dataTables.css" />
  <link rel="stylesheet" href="https://cdn.datatables.net/select/1.3.1/css/select.dataTables.css" />
  <link rel="stylesheet" href="https://cdn.datatables.net/responsive/2.2.5/css/responsive.dataTables.css" />
</head>
<body>
  <div class="container">
    <div class="row">
      <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
        <h1>DataTable-AltEditor - Example #3</h1>
        <h2>with object-based datatable rows loaded via Ajax</h2>
        Rows are retrieved from some AJAX webservice, in the form:
        {id:1, name:"Tiger Nixon", position:"System Architect", office:"Edinburgh", extension:"5421",
        startDate:"2011/04/25",
        salary:"Tiger Nixon"}<br />
        INSERT and UPDATE will fail because there is no real server set up here.
      </div>
    </div>
  </div>
  <div class="container">
    <table cellpadding="0" cellspacing="0" border="0" class="dataTable table table-striped" id="example">
    </table>
  </div>
  <script src="https://code.jquery.com/jquery-3.0.0.js"></script>
  <script src="https://code.jquery.com/jquery-migrate-3.3.0.js"></script>
  <script src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.js"></script>
  <script src="https://cdn.datatables.net/buttons/1.6.2/js/dataTables.buttons.js"></script>
  <script src="https://cdn.datatables.net/select/1.3.1/js/dataTables.select.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js"></script>
  <script src="https://cdn.datatables.net/responsive/2.2.5/js/dataTables.responsive.js"></script>
  <script src="../../src/dataTables.altEditor.free.js"></script>
  <script src="./example3.js"></script>
</body>
</html>

```

C:\xampp\htdocs\belongstomany\example\03\_ajax\_objects\example3.js

```javascript
$(document).ready(function () {
  var columnDefs = [
    {
      data: "id",
      title: "Id",
      type: "readonly"
    },
    {
      data: "name",
      title: "Name"
    },
    {
      data: "position",
      title: "Position"
    },
    {
      data: "office",
      title: "Office"
    },
    {
      data: "extension",
      title: "Extn."
    },
    {
      data: "startDate",
      title: "Start date"
    },
    {
      data: "salary",
      title: "Salary"
    }
  ];
  var myTable;
  var url_ws_mock_get = './mock_svc_load.json';
  var url_ws_mock_ok = './mock_svc_ok.json';
  if (location.href.startsWith("file://")) {
    // local URL's are not allowed
    url_ws_mock_get = 'https://luca-vercelli.github.io/DataTable-AltEditor/example/03_ajax_objects/mock_svc_load.json';
    url_ws_mock_ok = 'https://luca-vercelli.github.io/DataTable-AltEditor/example/03_ajax_objects/mock_svc_ok.json';
  }
  myTable = $('#example').DataTable({
    "sPaginationType": "full_numbers",
    ajax: {
      url: url_ws_mock_get,
      // our data is an array of objects, in the root node instead of /data node, so we need 'dataSrc' parameter
      dataSrc: ''
    },
    columns: columnDefs,
    dom: 'Bfrtip',        // Needs button container
    select: 'single',
    responsive: true,
    altEditor: true,     // Enable altEditor
    buttons: [
      {
        text: 'Add',
        name: 'add'        // do not change name
      },
      {
        extend: 'selected', // Bind to Selected row
        text: 'Edit',
        name: 'edit'        // do not change name
      },
      {
        extend: 'selected', // Bind to Selected row
        text: 'Delete',
        name: 'delete'      // do not change name
      },
      {
        text: 'Refresh',
        name: 'refresh'      // do not change name
      }
    ],
    onAddRow: function (datatable, rowdata, success, error) {
      $.ajax({
        // a tipycal url would be / with type='PUT'
        url: url_ws_mock_ok,
        type: 'GET',
        data: rowdata,
        success: success,
        error: error
      });
    },
    onDeleteRow: function (datatable, rowdata, success, error) {
      $.ajax({
        // a tipycal url would be /{id} with type='DELETE'
        url: url_ws_mock_ok,
        type: 'GET',
        data: rowdata,
        success: success,
        error: error
      });
    },
    onEditRow: function (datatable, rowdata, success, error) {
      $.ajax({
        // a tipycal url would be /{id} with type='POST'
        url: url_ws_mock_ok,
        type: 'GET',
        data: rowdata,
        success: success,
        error: error
      });
    }
  });
});

```

C:\xampp\htdocs\belongstomany\example\03\_ajax\_objects\mock\_svc\_load.json

```json
[
  {
    "id": 1,
    "name": "Tiger Nixon",
    "position": "System Architect",
    "office": "Edinburgh",
    "extension": "5421",
    "startDate": "2011/04/25",
    "salary": "Tiger Nixon"
  },
  {
    "id": 2,
    "name": "Garrett Winters",
    "position": "Accountant",
    "office": "Tokyo",
    "extension": "8422",
    "startDate": "2011/07/25",
    "salary": "Garrett Winters"
  },
  {
    "id": 3,
    "name": "Ashton Cox",
    "position": "Junior Technical Author",
    "office": "San Francisco",
    "extension": "1562",
    "startDate": "2009/01/12",
    "salary": "Ashton Cox"
  },
  {
    "id": 4,
    "name": "Cedric Kelly",
    "position": "Senior Javascript Developer",
    "office": "Edinburgh",
    "extension": "6224",
    "startDate": "2012/03/29",
    "salary": "Cedric Kelly"
  },
  {
    "id": 5,
    "name": "Airi Satou",
    "position": "Accountant",
    "office": "Tokyo",
    "extension": "5407",
    "startDate": "2008/11/28",
    "salary": "Airi Satou"
  },
  {
    "id": 6,
    "name": "Brielle Williamson",
    "position": "Integration Specialist",
    "office": "New York",
    "extension": "4804",
    "startDate": "2012/12/02",
    "salary": "Brielle Williamson"
  },
  {
    "id": 7,
    "name": "Herrod Chandler",
    "position": "Sales Assistant",
    "office": "San Francisco",
    "extension": "9608",
    "startDate": "2012/08/06",
    "salary": "Herrod Chandler"
  },
  {
    "id": 8,
    "name": "Rhona Davidson",
    "position": "Integration Specialist",
    "office": "Tokyo",
    "extension": "6200",
    "startDate": "2010/10/14",
    "salary": "Rhona Davidson"
  },
  {
    "id": 9,
    "name": "Colleen Hurst",
    "position": "Javascript Developer",
    "office": "San Francisco",
    "extension": "2360",
    "startDate": "2009/09/15",
    "salary": "Colleen Hurst"
  },
  {
    "id": 10,
    "name": "Sonya Frost",
    "position": "Software Engineer",
    "office": "Edinburgh",
    "extension": "1667",
    "startDate": "2008/12/13",
    "salary": "Sonya Frost"
  },
  {
    "id": 11,
    "name": "Jena Gaines",
    "position": "Office Manager",
    "office": "London",
    "extension": "3814",
    "startDate": "2008/12/19",
    "salary": "Jena Gaines"
  },
  {
    "id": 12,
    "name": "Quinn Flynn",
    "position": "Support Lead",
    "office": "Edinburgh",
    "extension": "9497",
    "startDate": "2013/03/03",
    "salary": "Quinn Flynn"
  },
  {
    "id": 13,
    "name": "Charde Marshall",
    "position": "Regional Director",
    "office": "San Francisco",
    "extension": "6741",
    "startDate": "2008/10/16",
    "salary": "Charde Marshall"
  },
  {
    "id": 14,
    "name": "Haley Kennedy",
    "position": "Senior Marketing Designer",
    "office": "London",
    "extension": "3597",
    "startDate": "2012/12/18",
    "salary": "Haley Kennedy"
  },
  {
    "id": 15,
    "name": "Tatyana Fitzpatrick",
    "position": "Regional Director",
    "office": "London",
    "extension": "1965",
    "startDate": "2010/03/17",
    "salary": "Tatyana Fitzpatrick"
  },
  {
    "id": 16,
    "name": "Michael Silva",
    "position": "Marketing Designer",
    "office": "London",
    "extension": "1581",
    "startDate": "2012/11/27",
    "salary": "Michael Silva"
  },
  {
    "id": 17,
    "name": "Paul Byrd",
    "position": "Chief Financial Officer (CFO)",
    "office": "New York",
    "extension": "3059",
    "startDate": "2010/06/09",
    "salary": "Paul Byrd"
  },
  {
    "id": 18,
    "name": "Gloria Little",
    "position": "Systems Administrator",
    "office": "New York",
    "extension": "1721",
    "startDate": "2009/04/10",
    "salary": "Gloria Little"
  },
  {
    "id": 19,
    "name": "Bradley Greer",
    "position": "Software Engineer",
    "office": "London",
    "extension": "2558",
    "startDate": "2012/10/13",
    "salary": "Bradley Greer"
  },
  {
    "id": 20,
    "name": "Dai Rios",
    "position": "Personnel Lead",
    "office": "Edinburgh",
    "extension": "2290",
    "startDate": "2012/09/26",
    "salary": "Dai Rios"
  },
  {
    "id": 21,
    "name": "Jenette Caldwell",
    "position": "Development Lead",
    "office": "New York",
    "extension": "1937",
    "startDate": "2011/09/03",
    "salary": "Jenette Caldwell"
  },
  {
    "id": 22,
    "name": "Yuri Berry",
    "position": "Chief Marketing Officer (CMO)",
    "office": "New York",
    "extension": "6154",
    "startDate": "2009/06/25",
    "salary": "Yuri Berry"
  },
  {
    "id": 23,
    "name": "Caesar Vance",
    "position": "Pre-Sales Support",
    "office": "New York",
    "extension": "8330",
    "startDate": "2011/12/12",
    "salary": "Caesar Vance"
  },
  {
    "id": 24,
    "name": "Doris Wilder",
    "position": "Sales Assistant",
    "office": "Sidney",
    "extension": "3023",
    "startDate": "2010/09/20",
    "salary": "Doris Wilder"
  },
  {
    "id": 25,
    "name": "Angelica Ramos",
    "position": "Chief Executive Officer (CEO)",
    "office": "London",
    "extension": "5797",
    "startDate": "2009/10/09",
    "salary": "Angelica Ramos"
  },
  {
    "id": 26,
    "name": "Gavin Joyce",
    "position": "Developer",
    "office": "Edinburgh",
    "extension": "8822",
    "startDate": "2010/12/22",
    "salary": "Gavin Joyce"
  },
  {
    "id": 27,
    "name": "Jennifer Chang",
    "position": "Regional Director",
    "office": "Singapore",
    "extension": "9239",
    "startDate": "2010/11/14",
    "salary": "Jennifer Chang"
  },
  {
    "id": 28,
    "name": "Brenden Wagner",
    "position": "Software Engineer",
    "office": "San Francisco",
    "extension": "1314",
    "startDate": "2011/06/07",
    "salary": "Brenden Wagner"
  },
  {
    "id": 29,
    "name": "Fiona Green",
    "position": "Chief Operating Officer (COO)",
    "office": "San Francisco",
    "extension": "2947",
    "startDate": "2010/03/11",
    "salary": "Fiona Green"
  },
  {
    "id": 30,
    "name": "Shou Itou",
    "position": "Regional Marketing",
    "office": "Tokyo",
    "extension": "8899",
    "startDate": "2011/08/14",
    "salary": "Shou Itou"
  },
  {
    "id": 30,
    "name": "Michelle House",
    "position": "Integration Specialist",
    "office": "Sidney",
    "extension": "2769",
    "startDate": "2011/06/02",
    "salary": "Michelle House"
  },
  {
    "id": 32,
    "name": "Suki Burks",
    "position": "Developer",
    "office": "London",
    "extension": "6832",
    "startDate": "2009/10/22",
    "salary": "Suki Burks"
  },
  {
    "id": 33,
    "name": "Prescott Bartlett",
    "position": "Technical Author",
    "office": "London",
    "extension": "3606",
    "startDate": "2011/05/07",
    "salary": "Prescott Bartlett"
  },
  {
    "id": 34,
    "name": "Gavin Cortez",
    "position": "Team Leader",
    "office": "San Francisco",
    "extension": "2860",
    "startDate": "2008/10/26",
    "salary": "Gavin Cortez"
  },
  {
    "id": 35,
    "name": "Martena Mccray",
    "position": "Post-Sales support",
    "office": "Edinburgh",
    "extension": "8240",
    "startDate": "2011/03/09",
    "salary": "Martena Mccray"
  },
  {
    "id": 36,
    "name": "Unity Butler",
    "position": "Marketing Designer",
    "office": "San Francisco",
    "extension": "5384",
    "startDate": "2009/12/09",
    "salary": "Unity Butler"
  }
]

```

C:\xampp\htdocs\belongstomany\example\03\_ajax\_objects\mock\_svc\_ok.json

```json
{
  "id": 1,
  "name": "Name modified by server",
  "position": "Modified position",
  "office": "",
  "extension": "",
  "startDate": "",
  "salary": ""
}

```

1. [Some more](https://belongstomany.com/example/04_more/DataTableExample.html)
2.

```
<figure><img src="/files/Ee6lNWhbH1mulQFEqMCb" alt=""><figcaption></figcaption></figure>
```

3. C:\xampp\htdocs\belongstomany\example\04\_more\DataTableExample.html
4. ```html
   <!DOCTYPE html>
   <html lang="en">
   <head>
     <meta charset="utf-8">
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <title>DataTable-AltEditor - Example #4</title>
     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/buttons/1.6.2/css/buttons.dataTables.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/select/1.3.1/css/select.dataTables.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/responsive/2.2.5/css/responsive.dataTables.css" />
   </head>
   <body>
     <div class="container">
       <div class="row">
         <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
           <h1>DataTable-AltEditor - Example #4</h1>
           This is the original example, not sure everything works yet.
           <table class="table table-striped" id="testTableData">
             <thead>
               <tr>
                 <th></th>
                 <th></th>
                 <th></th>
                 <th></th>
                 <th></th>
               </tr>
             </thead>
             <tbody>
               <tr>
                 <td></td>
                 <td></td>
                 <td></td>
                 <td></td>
                 <td></td>
               </tr>
             </tbody>
           </table>
           <!--
           - saveButton    - onClick, takes all the data from the datatable and sends it to the server
           - cancelButton  - onClick, asks the user if the wants to undo unsaved changes and (if yes)
                             reloads the datatable with the data from the server.
           - messages      - Displays the response from the server.
           -->
           <div>
             <button type='button' class='btn btn-default' id='saveButton' value='Save'>Save</button>
             <button type='button' class='btn btn-default' id='cancelButton' value='Cancel' disabled='true'>Cancel</button>
             <span id='messages'>&nbsp;</span>
           </div>
         </div>
       </div>
     </div>
     <script src="https://code.jquery.com/jquery-3.0.0.js"></script>
     <script src="https://code.jquery.com/jquery-migrate-3.3.0.js"></script>
     <script src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.js"></script>
     <script src="https://cdn.datatables.net/buttons/1.6.2/js/dataTables.buttons.js"></script>
     <script src="https://cdn.datatables.net/select/1.3.1/js/dataTables.select.js"></script>
     <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js"></script>
     <script src="https://cdn.datatables.net/responsive/2.2.5/js/dataTables.responsive.js"></script>
     <script src="../../src/dataTables.altEditor.free.js"></script>
     <script>
       $(document).ready(function () {
         //////////////////////////////////////////
         /*
         IMPORTANT - COLUMNDEFS
         Always add the DT_RowId row and always add it as the first column!
         - Visibility state doesnt matter but searchable
           state should be set to the same value.
         Always add a type!
         Current supported type parameters:
         text      - for editable textfields (including numbers, emails etc.)
         select    - for select menues, if used then options should be specified aswell
         readonly  - for fields with readonly attribute.
         Other parameters:
         MANDATORY:
         id        - Should be set to same value as data-parameter.
         data      - Identifier of value in data from AJAX call.
         title     - Title of column.
         OPTIONAL:
         pattern   - For inputvalidation of the textfield. Specify a regex for the pattern to use.
         errorMsg  - Message that is shown when mismatch with pattern is found.
         hoverMsg  - Message that is shown on mouseover on text fields (hints).
         unique    - Data that can only exist once in the datatable. Shows an error on input if found.
         special   - Only working setting is "portRange". This is in relation to input validation.
                     If used then validation will check for a portrange in format (startPort:endPort)
                     and validate both with the supplied regex.
         */
         //////////////////////////////////////////
         //Example of column definitions.
         var columnDefs = [{
           id: "DT_RowId",
           data: "DT_RowId",
           type: "hidden"
         }, {
           title: "Select example",
           id: "status",
           data: "status",
           type: "select",
           "options": [
             "on",
             "off"
           ]
         }, {
           title: "Text example",
           id: "ipAddress",
           data: "ipAddress",
           type: "text",
           pattern: "^((?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){0,1}$",
           errorMsg: "*Invalid address - Enter valid ip.",
           hoverMsg: "(Optional) - Ex: 82.84.86.88",
           unique: true
         }, {
           title: "Port example",
           id: "port",
           data: "port",
           type: "text",
           special: "portRange",
           pattern: "^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$",
           errorMsg: "*Invalid port - Enter valid port or range.",
           hoverMsg: "Ex: 6112 (single)   or   6111:6333 (range)",
           unique: true
         }, {
           title: "Readonly example",
           id: "read",
           data: "read",
           type: "readonly"
         }]
         var url_ws_mock_get = './example4.json';
         if (location.href.startsWith("file://")) {
           // local URL's are not allowed
           url_ws_mock_get = 'https://luca-vercelli.github.io/DataTable-AltEditor/example/04_more/example4.json';
         }
         //Table creation
         var myTable = $('#testTableData').dataTable({
           dom: 'Bfrltip',                   //Element order: Button container(B) is essential.
           ajax: url_ws_mock_get,   //Receiving data from this source.
           columns: columnDefs,            //Columns defined above.
           select: 'single',               //Only single column selection is implemented.
           altEditor: true,                //Enable altEditor.
           responsive: true,               //Enable responsiveness.
           buttons: [{                     //All implemented buttons. Do not change name attribute.
             text: 'Createddd',
             name: 'add'
           }, {
             extend: 'selected',
             text: 'Edit',
             name: 'edit'
           }, {
             extend: 'selected',
             text: 'Delete',
             name: 'delete'
           }, {
             text: 'Refresh',
             name: 'refresh'
           }]
         });
       });
       // If the user has unsaved changes when reloading/leaving the page, then
       // an alert is displayed asking the user to confirm the action
       $(window).bind('beforeunload', function () {
         if (!$('#cancelButton').is(':disabled')) {
           return "";
         }
       });
     </script>
   </body>
   </html>

   ```

C:\xampp\htdocs\belongstomany\example\04\_more\example4.json

```json
{
  "data": [
    {
      "DT_RowId": 1,
      "ipAddress": "1.2.3.4",
      "status": "on",
      "port": "8080",
      "read": "Hello"
    },
    {
      "DT_RowId": 2,
      "ipAddress": "5.6.7.8",
      "status": "off",
      "port": "8080",
      "read": "World"
    }
  ]
}

```

1. [More datatables in one page](https://belongstomany.com/example/05_two_datatables/example5.html)
2.

```
<figure><img src="/files/z7uJ0GQ1QFJhWyJI0jrM" alt=""><figcaption></figcaption></figure>
```

3. C:\xampp\htdocs\belongstomany\example\05\_two\_datatables\example5.html
4. ```html
   <!DOCTYPE html>
   <html lang="en">
   <head>
     <meta charset="utf-8">
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <title>DataTable-AltEditor - Example #5</title>
     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/buttons/1.6.2/css/buttons.dataTables.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/select/1.3.1/css/select.dataTables.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/responsive/2.2.5/css/responsive.dataTables.css" />
   </head>
   <body>
     <div class="container">
       <div class="row">
         <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
           <h1>DataTable-AltEditor - Example #5</h1>
           <h2>with object-based datatable rows loaded via Ajax. Two different datatables.</h2>
           Rows are retrieved from some AJAX webservice, in the form:
           {id:1, name:"Tiger Nixon", position:"System Architect", office:"Edinburgh", extension:"5421",
           startDate:"2011/04/25",
           salary:"Tiger Nixon"}<br />
           INSERT and UPDATE will fail because there is no real server set up here.
         </div>
       </div>
     </div>
     <div class="container">
       <table cellpadding="0" cellspacing="0" border="0" class="dataTable table table-striped" id="example">
       </table>
       <table cellpadding="0" cellspacing="0" border="0" class="dataTable table table-striped" id="example2">
       </table>
     </div>
     <script src="https://code.jquery.com/jquery-3.0.0.js"></script>
     <script src="https://code.jquery.com/jquery-migrate-3.3.0.js"></script>
     <script src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.js"></script>
     <script src="https://cdn.datatables.net/buttons/1.6.2/js/dataTables.buttons.js"></script>
     <script src="https://cdn.datatables.net/select/1.3.1/js/dataTables.select.js"></script>
     <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js"></script>
     <script src="https://cdn.datatables.net/responsive/2.2.5/js/dataTables.responsive.js"></script>
     <script src="../../src/dataTables.altEditor.free.js"></script>
     <script src="./example5.js"></script>
   </body>
   </html>

   ```

C:\xampp\htdocs\belongstomany\example\05\_two\_datatables\example5.js

```javascript
$(document).ready(function () {
  var columnDefs = [
    {
      data: "id",
      title: "Id",
      type: "readonly"
    },
    {
      data: "name",
      title: "Name"
    },
    {
      data: "position",
      title: "Position"
    },
    {
      data: "office",
      title: "Office"
    },
    {
      data: "extension",
      title: "Extn."
    },
    {
      data: "startDate",
      title: "Start date"
    },
    {
      data: "salary",
      title: "Salary"
    }
  ];
  var myTable;
  var url_ws_mock_get = '../03_ajax_objects/mock_svc_load.json';
  var url_ws_mock_ok = '../03_ajax_objects/mock_svc_ok.json';
  if (location.href.startsWith("file://")) {
    // local URL's are not allowed
    url_ws_mock_get = 'https://luca-vercelli.github.io/DataTable-AltEditor/example/03_ajax_objects/mock_svc_load.json';
    url_ws_mock_ok = 'https://luca-vercelli.github.io/DataTable-AltEditor/example/03_ajax_objects/mock_svc_ok.json';
  }
  myTable = $('#example').DataTable({
    "sPaginationType": "full_numbers",
    ajax: {
      url: url_ws_mock_get,
      // our data is an array of objects, in the root node instead of /data node, so we need 'dataSrc' parameter
      dataSrc: ''
    },
    columns: columnDefs,
    dom: 'Bfrtip',        // Needs button container
    select: 'single',
    responsive: true,
    altEditor: true,     // Enable altEditor
    buttons: [
      {
        text: 'Add',
        name: 'add'        // do not change name
      },
      {
        extend: 'selected', // Bind to Selected row
        text: 'Edit',
        name: 'edit'        // do not change name
      },
      {
        extend: 'selected', // Bind to Selected row
        text: 'Delete',
        name: 'delete'      // do not change name
      },
      {
        text: 'Refresh',
        name: 'refresh'      // do not change name
      }
    ],
    onAddRow: function (datatable, rowdata, success, error) {
      $.ajax({
        // a tipycal url would be / with type='PUT'
        url: url_ws_mock_ok,
        type: 'GET',
        data: rowdata,
        success: success,
        error: error
      });
    },
    onDeleteRow: function (datatable, rowdata, success, error) {
      $.ajax({
        // a tipycal url would be /{id} with type='DELETE'
        url: url_ws_mock_ok,
        type: 'GET',
        data: rowdata,
        success: success,
        error: error
      });
    },
    onEditRow: function (datatable, rowdata, success, error) {
      $.ajax({
        // a tipycal url would be /{id} with type='POST'
        url: url_ws_mock_ok,
        type: 'GET',
        data: rowdata,
        success: success,
        error: error
      });
    }
  });
  // ======================================================================================
  var columnDefs2 = [{
    data: "id",
    title: "Id",
    type: "readonly"
  },
  {
    data: "name",
    title: "Name"
  },
  {
    data: "office",
    title: "Office"
  },
  {
    data: "startDate",
    title: "Start date"
  },
  {
    data: "position",
    title: "Position"
  }];
  var myOtherTable = $('#example2').DataTable({
    "sPaginationType": "full_numbers",
    ajax: {
      url: url_ws_mock_get,
      // our data is an array of objects, in the root node instead of /data node, so we need 'dataSrc' parameter
      dataSrc: ''
    },
    columns: columnDefs2,
    dom: 'Bfrtip',        // Needs button container
    select: 'single',
    responsive: true,
    altEditor: true,     // Enable altEditor
    buttons: [
      {
        text: 'Add',
        name: 'add'        // do not change name
      },
      {
        extend: 'selected', // Bind to Selected row
        text: 'Edit',
        name: 'edit'        // do not change name
      },
      {
        extend: 'selected', // Bind to Selected row
        text: 'Delete',
        name: 'delete'      // do not change name
      },
      {
        text: 'Refresh',
        name: 'refresh'      // do not change name
      }
    ],
    onAddRow: function (datatable, rowdata, success, error) {
      $.ajax({
        // a tipycal url would be / with type='PUT'
        url: url_ws_mock_ok,
        type: 'GET',
        data: rowdata,
        success: success,
        error: error
      });
    },
    onDeleteRow: function (datatable, rowdata, success, error) {
      $.ajax({
        // a tipycal url would be /{id} with type='DELETE'
        url: url_ws_mock_ok,
        type: 'GET',
        data: rowdata,
        success: success,
        error: error
      });
    },
    onEditRow: function (datatable, rowdata, success, error) {
      $.ajax({
        // a tipycal url would be /{id} with type='POST'
        url: url_ws_mock_ok,
        type: 'GET',
        data: rowdata,
        success: success,
        error: error
      });
    }
  });
});

```

1. [\
   Select2 and Datetimepicker](https://belongstomany.com/example/06_select_datepicker/example6.html)

<figure><img src="/files/nX3rGje7Tb49IrkMdKVX" alt=""><figcaption></figcaption></figure>

C:\xampp\htdocs\belongstomany\example\06\_select\_datepicker\example6.html

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>DataTable-AltEditor - Example #6</title>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css" />
  <link rel="stylesheet" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.css" />
  <link rel="stylesheet" href="https://cdn.datatables.net/buttons/1.6.2/css/buttons.dataTables.css" />
  <link rel="stylesheet" href="https://cdn.datatables.net/select/1.3.1/css/select.dataTables.css" />
  <link rel="stylesheet" href="https://cdn.datatables.net/responsive/2.2.5/css/responsive.dataTables.css" />
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.7/css/select2.css" />
  <link rel="stylesheet"
    href="https://cdnjs.cloudflare.com/ajax/libs/jquery-datetimepicker/2.5.20/jquery.datetimepicker.css" />
</head>
<body>
  <div class="container">
    <div class="row">
      <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
        <h1>DataTable-AltEditor - Example #6</h1>
        <h2>Select2 and Datepicker</h2>
        <p>In this example there is a "single" select2, a "multiple" select2, a date picker, a date/time picker, and a
          "single" select2 with nested objects </p>
      </div>
    </div>
  </div>
  <div class="container">
    <table cellpadding="0" cellspacing="0" border="0" class="dataTable table table-striped" id="example">
    </table>
  </div>
  <script src="https://code.jquery.com/jquery-3.0.0.js"></script>
  <script src="https://code.jquery.com/jquery-migrate-3.3.0.js"></script>
  <script src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.js"></script>
  <script src="https://cdn.datatables.net/buttons/1.6.2/js/dataTables.buttons.js"></script>
  <script src="https://cdn.datatables.net/select/1.3.1/js/dataTables.select.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js"></script>
  <script src="https://cdn.datatables.net/responsive/2.2.5/js/dataTables.responsive.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.7/js/select2.js"></script>
  <script
    src="https://cdnjs.cloudflare.com/ajax/libs/jquery-datetimepicker/2.5.20/jquery.datetimepicker.full.js"></script>
  <script src="../../src/dataTables.altEditor.free.js"></script>
  <script src="./example6.js"></script>
</body>
</html>

```

C:\xampp\htdocs\belongstomany\example\06\_select\_datepicker\example6.js

```javascript
var employeeOptions = { "1": "Employee", "2": "Official", "3": "Director" };
var friendsOptions = { "G": "Goofy", "D": "Donald duck", "M": "Mickey", "D": "Daisy" };
var degreesOptions = { "0": "None", "1": "Degree", "2": "High school" };
$(document).ready(function () {
  var columnDefs = [{
    data: "id",
    title: "Id",
    type: "readonly"
  },
  {
    data: "name",
    title: "Name"
  },
  {
    data: "position",
    title: "Position",
    type: "select",
    options: employeeOptions,
    select2: { width: "100%" },
    render: function (data, type, row, meta) {
      if (data == null || !(data in employeeOptions)) return null;
      return employeeOptions[data];
    }
  },
  {
    data: "startDate",
    title: "Start date",
    datetimepicker: { timepicker: false, format: "Y/m/d" }
  },
  {
    data: "creationTimestamp",
    title: "Creation timestamp",
    datetimepicker: { timepicker: true, format: "Y/m/d H:i" }
  },
  {
    data: "friends",
    title: "Friends",
    type: "select",
    options: friendsOptions,
    multiple: true,
    select2: { width: "100%" },
    render: function (data, type, row, meta) {
      if (data == null || row == null || row.degree == null) return null;
      return data.map(function (x) { return friendsOptions[x]; });
    }
  },
  {
    data: "degree.id",
    title: "Degree (nested obj.)",
    type: "select",
    options: degreesOptions,
    select2: { width: "100%" },
    render: function (data, type, row, meta) {
      if (data == null || row == null || row.degree == null) return null;
      return row.degree.caption;
    }
  }];
  var myTable;
  var url_ws_mock_get = './mock_svc_load.json';
  var url_ws_mock_ok = './mock_svc_ok.json';
  if (location.href.startsWith("file://")) {
    // local URL's are not allowed
    url_ws_mock_get = 'https://luca-vercelli.github.io/DataTable-AltEditor/example/06_select_datepicker/mock_svc_load.json';
    url_ws_mock_ok = 'https://luca-vercelli.github.io/DataTable-AltEditor/example/06_select_datepicker/mock_svc_ok.json';
  }
  myTable = $('#example').DataTable({
    "sPaginationType": "full_numbers",
    ajax: {
      url: url_ws_mock_get,
      // our data is an array of objects, in the root node instead of /data node, so we need 'dataSrc' parameter
      dataSrc: ''
    },
    columns: columnDefs,
    dom: 'Bfrtip',        // Needs button container
    select: 'single',
    responsive: true,
    altEditor: true,     // Enable altEditor
    buttons: [{
      text: 'Add',
      name: 'add'        // do not change name
    },
    {
      extend: 'selected', // Bind to Selected row
      text: 'Edit',
      name: 'edit'        // do not change name
    },
    {
      extend: 'selected', // Bind to Selected row
      text: 'Delete',
      name: 'delete'      // do not change name
    },
    {
      text: 'Refresh',
      name: 'refresh'      // do not change name
    }],
    onAddRow: function (datatable, rowdata, success, error) {
      $.ajax({
        // a tipycal url would be / with type='PUT'
        url: url_ws_mock_ok,
        type: 'GET',
        data: rowdata,
        success: success,
        error: error
      });
    },
    onDeleteRow: function (datatable, rowdata, success, error) {
      $.ajax({
        // a tipycal url would be /{id} with type='DELETE'
        url: url_ws_mock_ok,
        type: 'GET',
        data: rowdata,
        success: success,
        error: error
      });
    },
    onEditRow: function (datatable, rowdata, success, error) {
      $.ajax({
        // a tipycal url would be /{id} with type='POST'
        url: url_ws_mock_ok,
        type: 'GET',
        data: rowdata,
        success: success,
        error: error
      });
    }
  });
});

```

C:\xampp\htdocs\belongstomany\example\06\_select\_datepicker\mock\_svc\_load.json

```json
[
  {
    "id": 1,
    "name": "Tiger Nixon",
    "position": "1",
    "office": "Edinburgh",
    "extension": "5421",
    "startDate": "2011/04/25",
    "salary": "Tiger Nixon",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [
      "G",
      "D"
    ],
    "degree": {
      "id": 0,
      "caption": "None"
    }
  },
  {
    "id": 2,
    "name": "Garrett Winters",
    "position": "1",
    "office": "Tokyo",
    "extension": "8422",
    "startDate": "2011/07/25",
    "salary": "Garrett Winters",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [
      "D"
    ],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 3,
    "name": "Ashton Cox",
    "position": "2",
    "office": "San Francisco",
    "extension": "1562",
    "startDate": "2009/01/12",
    "salary": "Ashton Cox",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 4,
    "name": "Cedric Kelly",
    "position": "1",
    "office": "Edinburgh",
    "extension": "6224",
    "startDate": "2012/03/29",
    "salary": "Cedric Kelly",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 5,
    "name": "Airi Satou",
    "position": "1",
    "office": "Tokyo",
    "extension": "5407",
    "startDate": "2008/11/28",
    "salary": "Airi Satou",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 6,
    "name": "Brielle Williamson",
    "position": "1",
    "office": "New York",
    "extension": "4804",
    "startDate": "2012/12/02",
    "salary": "Brielle Williamson",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 7,
    "name": "Herrod Chandler",
    "position": "1",
    "office": "San Francisco",
    "extension": "9608",
    "startDate": "2012/08/06",
    "salary": "Herrod Chandler",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 8,
    "name": "Rhona Davidson",
    "position": "1",
    "office": "Tokyo",
    "extension": "6200",
    "startDate": "2010/10/14",
    "salary": "Rhona Davidson",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 9,
    "name": "Colleen Hurst",
    "position": "2",
    "office": "San Francisco",
    "extension": "2360",
    "startDate": "2009/09/15",
    "salary": "Colleen Hurst",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 10,
    "name": "Sonya Frost",
    "position": "3",
    "office": "Edinburgh",
    "extension": "1667",
    "startDate": "2008/12/13",
    "salary": "Sonya Frost",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 11,
    "name": "Jena Gaines",
    "position": "2",
    "office": "London",
    "extension": "3814",
    "startDate": "2008/12/19",
    "salary": "Jena Gaines",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 12,
    "name": "Quinn Flynn",
    "position": "1",
    "office": "Edinburgh",
    "extension": "9497",
    "startDate": "2013/03/03",
    "salary": "Quinn Flynn",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 13,
    "name": "Charde Marshall",
    "position": "1",
    "office": "San Francisco",
    "extension": "6741",
    "startDate": "2008/10/16",
    "salary": "Charde Marshall",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 14,
    "name": "Haley Kennedy",
    "position": "1",
    "office": "London",
    "extension": "3597",
    "startDate": "2012/12/18",
    "salary": "Haley Kennedy",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 15,
    "name": "Tatyana Fitzpatrick",
    "position": "1",
    "office": "London",
    "extension": "1965",
    "startDate": "2010/03/17",
    "salary": "Tatyana Fitzpatrick",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 16,
    "name": "Michael Silva",
    "position": "1",
    "office": "London",
    "extension": "1581",
    "startDate": "2012/11/27",
    "salary": "Michael Silva",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 17,
    "name": "Paul Byrd",
    "position": "1",
    "office": "New York",
    "extension": "3059",
    "startDate": "2010/06/09",
    "salary": "Paul Byrd",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 18,
    "name": "Gloria Little",
    "position": "2",
    "office": "New York",
    "extension": "1721",
    "startDate": "2009/04/10",
    "salary": "Gloria Little",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 19,
    "name": "Bradley Greer",
    "position": "2",
    "office": "London",
    "extension": "2558",
    "startDate": "2012/10/13",
    "salary": "Bradley Greer",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 20,
    "name": "Dai Rios",
    "position": "1",
    "office": "Edinburgh",
    "extension": "2290",
    "startDate": "2012/09/26",
    "salary": "Dai Rios",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 21,
    "name": "Jenette Caldwell",
    "position": "1",
    "office": "New York",
    "extension": "1937",
    "startDate": "2011/09/03",
    "salary": "Jenette Caldwell",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 22,
    "name": "Yuri Berry",
    "position": "1",
    "office": "New York",
    "extension": "6154",
    "startDate": "2009/06/25",
    "salary": "Yuri Berry",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 23,
    "name": "Caesar Vance",
    "position": "1",
    "office": "New York",
    "extension": "8330",
    "startDate": "2011/12/12",
    "salary": "Caesar Vance",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 24,
    "name": "Doris Wilder",
    "position": "1",
    "office": "Sidney",
    "extension": "3023",
    "startDate": "2010/09/20",
    "salary": "Doris Wilder",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 25,
    "name": "Angelica Ramos",
    "position": "1",
    "office": "London",
    "extension": "5797",
    "startDate": "2009/10/09",
    "salary": "Angelica Ramos",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 26,
    "name": "Gavin Joyce",
    "position": "1",
    "office": "Edinburgh",
    "extension": "8822",
    "startDate": "2010/12/22",
    "salary": "Gavin Joyce",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 27,
    "name": "Jennifer Chang",
    "position": "1",
    "office": "Singapore",
    "extension": "9239",
    "startDate": "2010/11/14",
    "salary": "Jennifer Chang",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 28,
    "name": "Brenden Wagner",
    "position": "1",
    "office": "San Francisco",
    "extension": "1314",
    "startDate": "2011/06/07",
    "salary": "Brenden Wagner",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 29,
    "name": "Fiona Green",
    "position": "1",
    "office": "San Francisco",
    "extension": "2947",
    "startDate": "2010/03/11",
    "salary": "Fiona Green",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 30,
    "name": "Shou Itou",
    "position": "1",
    "office": "Tokyo",
    "extension": "8899",
    "startDate": "2011/08/14",
    "salary": "Shou Itou",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 30,
    "name": "Michelle House",
    "position": "1",
    "office": "Sidney",
    "extension": "2769",
    "startDate": "2011/06/02",
    "salary": "Michelle House",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 32,
    "name": "Suki Burks",
    "position": "2",
    "office": "London",
    "extension": "6832",
    "startDate": "2009/10/22",
    "salary": "Suki Burks",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 33,
    "name": "Prescott Bartlett",
    "position": "1",
    "office": "London",
    "extension": "3606",
    "startDate": "2011/05/07",
    "salary": "Prescott Bartlett",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 34,
    "name": "Gavin Cortez",
    "position": "1",
    "office": "San Francisco",
    "extension": "2860",
    "startDate": "2008/10/26",
    "salary": "Gavin Cortez",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 35,
    "name": "Martena Mccray",
    "position": "1",
    "office": "Edinburgh",
    "extension": "8240",
    "startDate": "2011/03/09",
    "salary": "Martena Mccray",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "High school"
    }
  },
  {
    "id": 36,
    "name": "Unity Butler",
    "position": "1",
    "office": "San Francisco",
    "extension": "5384",
    "startDate": "2009/12/09",
    "salary": "Unity Butler",
    "creationTimestamp": "2000-01-01 13:50:43",
    "friends": [],
    "degree": {
      "id": 2,
      "caption": "high school"
    }
  }
]

```

C:\xampp\htdocs\belongstomany\example\06\_select\_datepicker\mock\_svc\_ok.json

```json
{
  "id": 1,
  "name": "Name modified by server",
  "position": "1",
  "office": "",
  "extension": "",
  "startDate": "",
  "salary": "",
  "creationTimestamp": "",
  "friends": [],
  "degree": {
    "id": 0,
    "caption": "None"
  }
}

```

1. [Dependent items](https://belongstomany.com/example/07_dependent_select/example7.html)
2. C:\xampp\htdocs\belongstomany\example\07\_dependent\_select\example7.html
3. ```html
   <!DOCTYPE html>
   <html lang="en">
   <head>
     <meta charset="utf-8">
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <title>DataTable-AltEditor - Example #3</title>
     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/buttons/1.6.2/css/buttons.dataTables.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/select/1.3.1/css/select.dataTables.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/responsive/2.2.5/css/responsive.dataTables.css" />
     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.7/css/select2.css" />
   </head>
   <body>
     <div class="container">
       <div class="row">
         <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
           <h1>DataTable-AltEditor - Example #7</h1>
           <h2>with object-based datatable rows loaded via Ajax</h2>
           <p>Populate SELECT options according to values from another field.
             Hide/show fields according to values from another field.
           </p>
         </div>
       </div>
     </div>
     <div class="container">
       <table cellpadding="0" cellspacing="0" border="0" class="dataTable table table-striped" id="example">
       </table>
     </div>
     <script src="https://code.jquery.com/jquery-3.0.0.js"></script>
     <script src="https://code.jquery.com/jquery-migrate-3.3.0.js"></script>
     <script src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.js"></script>
     <script src="https://cdn.datatables.net/buttons/1.6.2/js/dataTables.buttons.js"></script>
     <script src="https://cdn.datatables.net/select/1.3.1/js/dataTables.select.js"></script>
     <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js"></script>
     <script src="https://cdn.datatables.net/responsive/2.2.5/js/dataTables.responsive.js"></script>
     <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.7/js/select2.js"></script>>
     <script src="../../src/dataTables.altEditor.free.js"></script>
     <script src="./example7.js"></script>
   </body>
   </html>

   ```

C:\xampp\htdocs\belongstomany\example\07\_dependent\_select\example7.js

```javascript
var url_ws_mock_prefix = './';
if (location.href.startsWith("file://")) {
  // local URL's are not allowed
  url_ws_mock_prefix = 'https://luca-vercelli.github.io/DataTable-AltEditor/example/07_dependent_select/';
}
var countryOptions = ['Italy', 'France', 'Germany'];
var allTownsOptions = ["Torino", "Roma", "Milano", "Napoli", "Paris", "Lyon", "Toulose"];
$(document).ready(function () {
  var columnDefs = [{
    data: "id",
    title: "Id",
    type: "readonly"
  },
  {
    data: "name",
    title: "Name"
  },
  {
    data: "country",
    title: "Country",
    type: "select",
    options: countryOptions,
    select2: { width: "100%" },
    editorOnChange: function (event, altEditor) {
      console.log(event, altEditor);
      var country = $(event.currentTarget).val();
      /*
      In a real world application, this should just call a single webservice,
      passing rowdatata.country as argument
      */
      if (country == "Italy") {
        $(altEditor.modal_selector).find("#alteditor-row-town").show();
        $.ajax({
          url: url_ws_mock_prefix + 'mock_svc_italy.json',
          type: 'GET',
          success: function (options) {
            console.log(options);
            var town = $(altEditor.modal_selector).find('#town');
            altEditor.reloadOptions(town, options);
          }
        });
      } else if (country == "France") {
        $(altEditor.modal_selector).find("#alteditor-row-town").show();
        $.ajax({
          url: url_ws_mock_prefix + 'mock_svc_france.json',
          type: 'GET',
          success: function (options) {
            console.log(options);
            var town = $(altEditor.modal_selector).find('#town');
            altEditor.reloadOptions(town, options);
          }
        });
      } else {
        $(altEditor.modal_selector).find("#alteditor-row-town").hide();
      }
    }
  },
  {
    data: "town",
    title: "Town",
    type: "select",
    options: allTownsOptions,
    select2: { width: "100%" }
  }];
  var myTable;
  myTable = $('#example').DataTable({
    "sPaginationType": "full_numbers",
    ajax: {
      url: url_ws_mock_prefix + 'mock_svc_load.json',
      // our data is an array of objects, in the root node instead of /data node, so we need 'dataSrc' parameter
      dataSrc: ''
    },
    columns: columnDefs,
    dom: 'Bfrtip',        // Needs button container
    select: 'single',
    responsive: true,
    altEditor: true,     // Enable altEditor
    buttons: [{
      text: 'Add',
      name: 'add'        // do not change name
    },
    {
      extend: 'selected', // Bind to Selected row
      text: 'Edit',
      name: 'edit'        // do not change name
    },
    {
      extend: 'selected', // Bind to Selected row
      text: 'Delete',
      name: 'delete'      // do not change name
    },
    {
      text: 'Refresh',
      name: 'refresh'      // do not change name
    }],
    onAddRow: function (datatable, rowdata, success, error) {
      $.ajax({
        // a tipycal url would be / with type='PUT'
        url: url_ws_mock_prefix + 'mock_svc_ok.json',
        type: 'GET',
        data: rowdata,
        success: success,
        error: error
      });
    },
    onDeleteRow: function (datatable, rowdata, success, error) {
      $.ajax({
        // a tipycal url would be /{id} with type='DELETE'
        url: url_ws_mock_prefix + 'mock_svc_ok.json',
        type: 'GET',
        data: rowdata,
        success: success,
        error: error
      });
    },
    onEditRow: function (datatable, rowdata, success, error) {
      $.ajax({
        // a tipycal url would be /{id} with type='POST'
        url: url_ws_mock_prefix + 'mock_svc_ok.json',
        type: 'GET',
        data: rowdata,
        success: success,
        error: error
      });
    }
  });
});

```

C:\xampp\htdocs\belongstomany\example\07\_dependent\_select\mock\_svc\_france.json

```json
[
  "Paris",
  "Lyon",
  "Toulose"
]

```

C:\xampp\htdocs\belongstomany\example\07\_dependent\_select\mock\_svc\_italy.json

```json
[
  "Torino",
  "Roma",
  "Milano",
  "Napoli"
]

```

C:\xampp\htdocs\belongstomany\example\07\_dependent\_select\mock\_svc\_load.json

```json
[
  {
    "id": 1,
    "name": "Tiger Nixon",
    "position": "System Architect",
    "country": "Italy",
    "town": "Torino"
  },
  {
    "id": 2,
    "name": "Garrett Winters",
    "position": "Accountant",
    "country": "Italy",
    "town": "Roma"
  },
  {
    "id": 3,
    "name": "Ashton Cox",
    "position": "Junior Technical Author",
    "country": "France",
    "town": "Lyon"
  },
  {
    "id": 4,
    "name": "Cedric Kelly",
    "position": "Senior Javascript Developer",
    "country": "Germany",
    "town": "Munich"
  },
  {
    "id": 5,
    "name": "Airi Satou",
    "position": "Accountant",
    "country": "Italy",
    "town": "Torino"
  },
  {
    "id": 6,
    "name": "Brielle Williamson",
    "position": "Integration Specialist",
    "country": "France",
    "town": "Paris"
  },
  {
    "id": 7,
    "name": "Herrod Chandler",
    "position": "Sales Assistant",
    "country": "France",
    "town": "Paris"
  },
  {
    "id": 8,
    "name": "Rhona Davidson",
    "position": "Integration Specialist",
    "country": "Germany",
    "town": "Berlin"
  },
  {
    "id": 9,
    "name": "Colleen Hurst",
    "position": "Javascript Developer",
    "country": "Germany",
    "town": "Berlin"
  },
  {
    "id": 10,
    "name": "Sonya Frost",
    "position": "Software Engineer",
    "country": "France",
    "town": "Lyon"
  },
  {
    "id": 11,
    "name": "Jena Gaines",
    "position": "Office Manager",
    "country": "Italy",
    "town": "Roma"
  },
  {
    "id": 12,
    "name": "Quinn Flynn",
    "position": "Support Lead",
    "country": "Italy",
    "town": "Roma"
  },
  {
    "id": 13,
    "name": "Charde Marshall",
    "position": "Regional Director",
    "country": "Italy",
    "town": "Roma"
  }
]

```

C:\xampp\htdocs\belongstomany\example\07\_dependent\_select\mock\_svc\_ok.json

```json
{
  "id": 1,
  "name": "Name modified by server",
  "position": "Modified position",
  "country": "Italy",
  "town": "Roma"
}

```

1. [Validation](https://belongstomany.com/example/08_validation/example8.html)
2. C:\xampp\htdocs\belongstomany\example\08\_validation\example8.html
3. ![](/files/FezF75vkiLFTR2CyZFN3)

   ```html
   <!DOCTYPE html>
   <html lang="en">
   <head>
     <meta charset="utf-8">
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <title>DataTable-AltEditor - Example #8</title>
     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/buttons/1.6.2/css/buttons.dataTables.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/select/1.3.1/css/select.dataTables.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/responsive/2.2.5/css/responsive.dataTables.css" />
   </head>
   <body>
     <div class="container">
       <div class="row">
         <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
           <h1>DataTable-AltEditor - Example #8</h1>
           <h2>Form validation</h2>
         </div>
       </div>
     </div>
     <div class="container">
       <table cellpadding="0" cellspacing="0" border="0" class="dataTable table table-striped" id="example">
       </table>
     </div>
     <style>
       input:invalid {
         border-color: red
       }
     </style>
     <script src="https://code.jquery.com/jquery-3.0.0.js"></script>
     <script src="https://code.jquery.com/jquery-migrate-3.3.0.js"></script>
     <script src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.js"></script>
     <script src="https://cdn.datatables.net/buttons/1.6.2/js/dataTables.buttons.js"></script>
     <script src="https://cdn.datatables.net/select/1.3.1/js/dataTables.select.js"></script>
     <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js"></script>
     <script src="https://cdn.datatables.net/responsive/2.2.5/js/dataTables.responsive.js"></script>
     <script src="../../src/dataTables.altEditor.free.js"></script>
     <script src="./example8.js"></script>
   </body>
   </html>

   ```

   C:\xampp\htdocs\belongstomany\example\08\_validation\example8.js
4. ```javascript
   $(document).ready(function () {
     var dataSet = [
       [1, "Tiger Nixon", "System Architect", "Edinburgh", "5421", "2011-04-25", "$320,800"],
       [2, "Garrett Winters", "Accountant", "Tokyo", "8422", "2011-07-25", "$170,750"],
       [3, "Ashton Cox", "Junior Technical Author", "San Francisco", "1562", "2009-01-12", "$86,000"],
       [4, "Cedric Kelly", "Senior Javascript Developer", "Edinburgh", "6224", "2012-03-29", "$433,060"],
       [5, "Airi Satou", "Accountant", "Tokyo", "5407", "2008-11-28", "$162,700"],
       [6, "Brielle Williamson", "Integration Specialist", "New York", "4804", "2012-12-02", "$372,000"],
       [7, "Herrod Chandler", "Sales Assistant", "San Francisco", "9608", "2012-08-06", "$137,500"],
       [8, "Rhona Davidson", "Integration Specialist", "Tokyo", "6200", "2010-10-14", "$327,900"],
       [9, "Colleen Hurst", "Javascript Developer", "San Francisco", "2360", "2009-09-15", "$205,500"],
       [10, "Sonya Frost", "Software Engineer", "Edinburgh", "1667", "2008-12-13", "$103,600"],
       [11, "Jena Gaines", "Office Manager", "London", "3814", "2008-12-19", "$90,560"],
       [12, "Quinn Flynn", "Support Lead", "Edinburgh", "9497", "2013-03-03", "$342,000"],
       [13, "Charde Marshall", "Regional Director", "San Francisco", "6741", "2008-10-16", "$470,600"],
       [14, "Haley Kennedy", "Senior Marketing Designer", "London", "3597", "2012-12-18", "$313,500"],
       [15, "Tatyana Fitzpatrick", "Regional Director", "London", "1965", "2010-03-17", "$385,750"],
       [16, "Michael Silva", "Marketing Designer", "London", "1581", "2012-11-27", "$198,500"],
       [17, "Paul Byrd", "Chief Financial Officer (CFO)", "New York", "3059", "2010-06-09", "$725,000"],
       [18, "Gloria Little", "Systems Administrator", "New York", "1721", "2009-04-10", "$237,500"],
       [19, "Bradley Greer", "Software Engineer", "London", "2558", "2012-10-13", "$132,000"],
       [20, "Dai Rios", "Personnel Lead", "Edinburgh", "2290", "2012-09-26", "$217,500"],
       [21, "Jenette Caldwell", "Development Lead", "New York", "1937", "2011-09-03", "$345,000"],
       [22, "Yuri Berry", "Chief Marketing Officer (CMO)", "New York", "6154", "2009-06-25", "$675,000"],
       [23, "Caesar Vance", "Pre-Sales Support", "New York", "8330", "2011-12-12", "$106,450"],
       [24, "Doris Wilder", "Sales Assistant", "Sidney", "3023", "2010-09-20", "$85,600"],
       [25, "Angelica Ramos", "Chief Executive Officer (CEO)", "London", "5797", "2009-10-09", "$1,200,000"],
       [26, "Gavin Joyce", "Developer", "Edinburgh", "8822", "2010-12-22", "$92,575"],
       [27, "Jennifer Chang", "Regional Director", "Singapore", "9239", "2010-11-14", "$357,650"],
       [28, "Brenden Wagner", "Software Engineer", "San Francisco", "1314", "2011-06-07", "$206,850"],
       [29, "Fiona Green", "Chief Operating Officer (COO)", "San Francisco", "2947", "2010-03-11", "$850,000"],
       [30, "Shou Itou", "Regional Marketing", "Tokyo", "8899", "2011-08-14", "$163,000"],
       [31, "Michelle House", "Integration Specialist", "Sidney", "2769", "2011-06-02", "$95,400"],
       [32, "Suki Burks", "Developer", "London", "6832", "2009-10-22", "$114,500"],
       [33, "Prescott Bartlett", "Technical Author", "London", "3606", "2011-05-07", "$145,000"],
       [34, "Gavin Cortez", "Team Leader", "San Francisco", "2860", "2008-10-26", "$235,500"],
       [35, "Martena Mccray", "Post-Sales support", "Edinburgh", "8240", "2011-03-09", "$324,050"],
       [36, "Unity Butler", "Marketing Designer", "San Francisco", "5384", "2009-12-09", "$85,675"]
     ];
     var columnDefs = [{
       title: "Id",
       type: "readonly"
     }, {
       title: "Name",
       type: "text",
       required: true,
       unique: true
     }, {
       title: "Position",
       required: true,
       type: "text"
     }, {
       title: "Office"
       //no type = text
     }, {
       title: "Extn.",
       type: "number"
     }, {
       title: "Start date",
       type: "date"
     }, {
       title: "Salary",
       type: "text",
       pattern: "\\$[0-9]*,[0-9]{3}",
       hoverMsg: "At least $1,000"
     }];
     var myTable;
     myTable = $('#example').DataTable({
       "sPaginationType": "full_numbers",
       data: dataSet,
       columns: columnDefs,
       dom: 'Bfrtip',        // Needs button container
       select: 'single',
       responsive: true,
       altEditor: true,     // Enable altEditor
       buttons: [{
         text: 'Add',
         name: 'add'        // do not change name
       },
       {
         extend: 'selected', // Bind to Selected row
         text: 'Edit',
         name: 'edit'        // do not change name
       },
       {
         extend: 'selected', // Bind to Selected row
         text: 'Delete',
         name: 'delete'      // do not change name
       }]
     });
   });

   ```
5. [Translations](https://belongstomany.com/example/09_translations/example9.html)
6.

```
<figure><img src="/files/c924AMpeeXpy7eDpigj8" alt=""><figcaption></figcaption></figure>
```

```
C:\xampp\htdocs\belongstomany\example\09\_translations\example9.js
```

7\.
8. \`\`\`javascript
$(document).ready(function () {
var dataSet = \[
\[1, "Tiger Nixon", "System Architect", "Edinburgh", "5421", "2011/04/25", "$320,800"],
\[2, "Garrett Winters", "Accountant", "Tokyo", "8422", "2011/07/25", "$170,750"],
\[3, "Ashton Cox", "Junior Technical Author", "San Francisco", "1562", "2009/01/12", "$86,000"],
\[4, "Cedric Kelly", "Senior Javascript Developer", "Edinburgh", "6224", "2012/03/29", "$433,060"],
\[5, "Airi Satou", "Accountant", "Tokyo", "5407", "2008/11/28", "$162,700"],
\[6, "Brielle Williamson", "Integration Specialist", "New York", "4804", "2012/12/02", "$372,000"],
\[7, "Herrod Chandler", "Sales Assistant", "San Francisco", "9608", "2012/08/06", "$137,500"],
\[8, "Rhona Davidson", "Integration Specialist", "Tokyo", "6200", "2010/10/14", "$327,900"],
\[9, "Colleen Hurst", "Javascript Developer", "San Francisco", "2360", "2009/09/15", "$205,500"],
\[10, "Sonya Frost", "Software Engineer", "Edinburgh", "1667", "2008/12/13", "$103,600"],
\[11, "Jena Gaines", "Office Manager", "London", "3814", "2008/12/19", "$90,560"],
\[12, "Quinn Flynn", "Support Lead", "Edinburgh", "9497", "2013/03/03", "$342,000"],
\[13, "Charde Marshall", "Regional Director", "San Francisco", "6741", "2008/10/16", "$470,600"],
\[14, "Haley Kennedy", "Senior Marketing Designer", "London", "3597", "2012/12/18", "$313,500"],
\[15, "Tatyana Fitzpatrick", "Regional Director", "London", "1965", "2010/03/17", "$385,750"],
\[16, "Michael Silva", "Marketing Designer", "London", "1581", "2012/11/27", "$198,500"],
\[17, "Paul Byrd", "Chief Financial Officer (CFO)", "New York", "3059", "2010/06/09", "$725,000"],
\[18, "Gloria Little", "Systems Administrator", "New York", "1721", "2009/04/10", "$237,500"],
\[19, "Bradley Greer", "Software Engineer", "London", "2558", "2012/10/13", "$132,000"],
\[20, "Dai Rios", "Personnel Lead", "Edinburgh", "2290", "2012/09/26", "$217,500"],
\[21, "Jenette Caldwell", "Development Lead", "New York", "1937", "2011/09/03", "$345,000"],
\[22, "Yuri Berry", "Chief Marketing Officer (CMO)", "New York", "6154", "2009/06/25", "$675,000"],
\[23, "Caesar Vance", "Pre-Sales Support", "New York", "8330", "2011/12/12", "$106,450"],
\[24, "Doris Wilder", "Sales Assistant", "Sidney", "3023", "2010/09/20", "$85,600"],
\[25, "Angelica Ramos", "Chief Executive Officer (CEO)", "London", "5797", "2009/10/09", "$1,200,000"],
\[26, "Gavin Joyce", "Developer", "Edinburgh", "8822", "2010/12/22", "$92,575"],
\[27, "Jennifer Chang", "Regional Director", "Singapore", "9239", "2010/11/14", "$357,650"],
\[28, "Brenden Wagner", "Software Engineer", "San Francisco", "1314", "2011/06/07", "$206,850"],
\[29, "Fiona Green", "Chief Operating Officer (COO)", "San Francisco", "2947", "2010/03/11", "$850,000"],
\[30, "Shou Itou", "Regional Marketing", "Tokyo", "8899", "2011/08/14", "$163,000"],
\[31, "Michelle House", "Integration Specialist", "Sidney", "2769", "2011/06/02", "$95,400"],
\[32, "Suki Burks", "Developer", "London", "6832", "2009/10/22", "$114,500"],
\[33, "Prescott Bartlett", "Technical Author", "London", "3606", "2011/05/07", "$145,000"],
\[34, "Gavin Cortez", "Team Leader", "San Francisco", "2860", "2008/10/26", "$235,500"],
\[35, "Martena Mccray", "Post-Sales support", "Edinburgh", "8240", "2011/03/09", "$324,050"],
\[36, "Unity Butler", "Marketing Designer", "San Francisco", "5384", "2009/12/09", "$85,675"]
];
var columnDefs = \[{
title: "Id",
type: "readonly"
}, {
title: "Name",
type: "text"
}, {
title: "Position",
type: "text"
}, {
title: "Office"
//no type = text
}, {
title: "Extn.",
type: "text"
}, {
title: "Start date",
type: "readonly"
}, {
title: "Salary",
type: "text"
}];
var myTable;
myTable = $('#example').DataTable({
"sPaginationType": "full\_numbers",
data: dataSet,
columns: columnDefs,
dom: 'Bfrtip',        // Needs button container
select: 'single',
responsive: true,
altEditor: true,     // Enable altEditor
buttons: \[{
text: 'Thêm',
name: 'add'        // do not change name
},
{
extend: 'selected', // Bind to Selected row
text: 'Chỉnh sửa',
name: 'edit'        // do not change name
},
{
extend: 'selected', // Bind to Selected row
text: 'Xóa',
name: 'delete'      // do not change name
}],
language: {
// url: '<https://cdn.datatables.net/plug-ins/1.10.20/i18n/Vietnamese.json>',
url: '<https://belongstomany.com/example/09_translations/Vietnamese.json>',
altEditorUrl: '../../translations/vi.json'
}
});
});

````

C:\xampp\htdocs\belongstomany\example\09\_translations\Vietnamese.json

```json


{
 "sProcessing":   "Đang xử lý...",
 "sLengthMenu":   "Xem _MENU_ mục",
 "sZeroRecords":  "Không tìm thấy dòng nào phù hợp",
 "sInfo":         "Đang xem _START_ đến _END_ trong tổng số _TOTAL_ mục",
 "sInfoEmpty":    "Đang xem 0 đến 0 trong tổng số 0 mục",
 "sInfoFiltered": "(được lọc từ _MAX_ mục)",
 "sInfoPostFix":  "",
 "sSearch":       "Tìm:",
 "sUrl":          "",
 "oPaginate": {
 	"sFirst":    "Đầu",
 	"sPrevious": "Trước",
 	"sNext":     "Tiếp",
 	"sLast":     "Cuối"
 }
}

````

1. [File upload](https://belongstomany.com/example/10_file_upload/example10.html)
2. C:\xampp\htdocs\belongstomany\example\10\_file\_upload\example10.html
3. ```html
   <!DOCTYPE html>
   <html lang="en">
   <head>
     <meta charset="utf-8">
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <title>DataTable-AltEditor - Example #10</title>
     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/buttons/1.6.2/css/buttons.dataTables.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/select/1.3.1/css/select.dataTables.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/responsive/2.2.5/css/responsive.dataTables.css" />
   </head>
   <body>
     <div class="container">
       <h1>DataTable-AltEditor - Example #10</h1>
       <h2>Files and images</h2>
       <p>For file download, your best option is to provide a direct link for each row and download it when required.</p>
       <p>For file upload, a naive implementation is provided, the whole file is encoded in base 64 and uploaded
         togheter with the row. Not intended for huge files.</p>
       <table cellpadding="0" cellspacing="0" border="0" class="dataTable table table-striped" id="example">
       </table>
     </div>
     <script src="https://code.jquery.com/jquery-3.0.0.js"></script>
     <script src="https://code.jquery.com/jquery-migrate-3.3.0.js"></script>
     <script src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.js"></script>
     <script src="https://cdn.datatables.net/buttons/1.6.2/js/dataTables.buttons.js"></script>
     <script src="https://cdn.datatables.net/select/1.3.1/js/dataTables.select.js"></script>
     <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js"></script>
     <script src="https://cdn.datatables.net/responsive/2.2.5/js/dataTables.responsive.js"></script>
     <script src="../../src/dataTables.altEditor.free.js"></script>
     <script src="./example10.js"></script>
   </body>
   </html>

   ```

C:\xampp\htdocs\belongstomany\example\10\_file\_upload\example10.js

```javascript
$(document).ready(function () {
  var columnDefs = [{
    data: "id",
    title: "Id",
    type: "readonly"
  },
  {
    data: "name",
    title: "Name"
  },
  {
    data: "position",
    title: "Position"
  },
  {
    data: "imagelink",
    title: "Avatar (direct link)",
    render: function (data, type, row, meta) {
      if (data) return `<img style='max-width:50px;max-height:50px' src='${data}'></img> or <button onclick='window.open("${data}")'>Download</button>`;
    },
    disabled: true
  },
  {
    name: "image",
    data: null,
    render: function (data, type, row, meta) {
      return "My file";
    },
    type: "file",
    title: "Avatar (base64 upload)"
  }];
  var myTable;
  // local URL's are not allowed
  var url_ws_mock_get = './mock_svc_load.json';
  var url_ws_mock_ok = './mock_svc_ok.json';
  if (location.href.startsWith("file://")) {
    // local URL's are not allowed
    url_ws_mock_get = 'https://luca-vercelli.github.io/DataTable-AltEditor/example/10_file_upload/mock_svc_load.json';
    url_ws_mock_ok = 'https://luca-vercelli.github.io/DataTable-AltEditor/example/10_file_upload/mock_svc_ok.json';
  }
  myTable = $('#example').DataTable({
    "sPaginationType": "full_numbers",
    ajax: {
      url: url_ws_mock_get,
      // our data is an array of objects, in the root node instead of /data node, so we need 'dataSrc' parameter
      dataSrc: ''
    },
    columns: columnDefs,
    dom: 'Bfrtip',        // Needs button container
    select: 'single',
    responsive: true,
    altEditor: true,     // Enable altEditor
    buttons: [{
      text: 'Add',
      name: 'add'        // do not change name
    },
    {
      extend: 'selected', // Bind to Selected row
      text: 'Edit',
      name: 'edit'        // do not change name
    },
    {
      extend: 'selected', // Bind to Selected row
      text: 'Delete',
      name: 'delete'      // do not change name
    },
    {
      text: 'Refresh',
      name: 'refresh'      // do not change name
    }],
    onAddRow: function (datatable, rowdata, success, error) {
      $.ajax({
        // a tipycal url would be / with type='PUT'
        url: url_ws_mock_ok,
        type: 'GET',
        data: rowdata,
        success: success,
        error: error
      });
    },
    onDeleteRow: function (datatable, rowdata, success, error) {
      $.ajax({
        // a tipycal url would be /{id} with type='DELETE'
        url: url_ws_mock_ok,
        type: 'GET',
        data: rowdata,
        success: success,
        error: error
      });
    },
    onEditRow: function (datatable, rowdata, success, error) {
      $.ajax({
        // a tipycal url would be /{id} with type='POST'
        url: url_ws_mock_ok,
        type: 'GET',
        data: rowdata,
        success: success,
        error: error
      });
    }
  });
});

```

C:\xampp\htdocs\belongstomany\example\10\_file\_upload\mock\_svc\_load.json

```json
[
  {
    "id": 1,
    "name": "Tiger Nixon",
    "position": "System Architect",
    "office": "Edinburgh",
    "extension": "5421",
    "startDate": "2011/04/25",
    "salary": "Tiger Nixon",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 2,
    "name": "Garrett Winters",
    "position": "Accountant",
    "office": "Tokyo",
    "extension": "8422",
    "startDate": "2011/07/25",
    "salary": "Garrett Winters",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 3,
    "name": "Ashton Cox",
    "position": "Junior Technical Author",
    "office": "San Francisco",
    "extension": "1562",
    "startDate": "2009/01/12",
    "salary": "Ashton Cox",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 4,
    "name": "Cedric Kelly",
    "position": "Senior Javascript Developer",
    "office": "Edinburgh",
    "extension": "6224",
    "startDate": "2012/03/29",
    "salary": "Cedric Kelly",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 5,
    "name": "Airi Satou",
    "position": "Accountant",
    "office": "Tokyo",
    "extension": "5407",
    "startDate": "2008/11/28",
    "salary": "Airi Satou",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 6,
    "name": "Brielle Williamson",
    "position": "Integration Specialist",
    "office": "New York",
    "extension": "4804",
    "startDate": "2012/12/02",
    "salary": "Brielle Williamson",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 7,
    "name": "Herrod Chandler",
    "position": "Sales Assistant",
    "office": "San Francisco",
    "extension": "9608",
    "startDate": "2012/08/06",
    "salary": "Herrod Chandler",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 8,
    "name": "Rhona Davidson",
    "position": "Integration Specialist",
    "office": "Tokyo",
    "extension": "6200",
    "startDate": "2010/10/14",
    "salary": "Rhona Davidson",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 9,
    "name": "Colleen Hurst",
    "position": "Javascript Developer",
    "office": "San Francisco",
    "extension": "2360",
    "startDate": "2009/09/15",
    "salary": "Colleen Hurst",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 10,
    "name": "Sonya Frost",
    "position": "Software Engineer",
    "office": "Edinburgh",
    "extension": "1667",
    "startDate": "2008/12/13",
    "salary": "Sonya Frost",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 11,
    "name": "Jena Gaines",
    "position": "Office Manager",
    "office": "London",
    "extension": "3814",
    "startDate": "2008/12/19",
    "salary": "Jena Gaines",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 12,
    "name": "Quinn Flynn",
    "position": "Support Lead",
    "office": "Edinburgh",
    "extension": "9497",
    "startDate": "2013/03/03",
    "salary": "Quinn Flynn",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 13,
    "name": "Charde Marshall",
    "position": "Regional Director",
    "office": "San Francisco",
    "extension": "6741",
    "startDate": "2008/10/16",
    "salary": "Charde Marshall",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 14,
    "name": "Haley Kennedy",
    "position": "Senior Marketing Designer",
    "office": "London",
    "extension": "3597",
    "startDate": "2012/12/18",
    "salary": "Haley Kennedy",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 15,
    "name": "Tatyana Fitzpatrick",
    "position": "Regional Director",
    "office": "London",
    "extension": "1965",
    "startDate": "2010/03/17",
    "salary": "Tatyana Fitzpatrick",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 16,
    "name": "Michael Silva",
    "position": "Marketing Designer",
    "office": "London",
    "extension": "1581",
    "startDate": "2012/11/27",
    "salary": "Michael Silva",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 17,
    "name": "Paul Byrd",
    "position": "Chief Financial Officer (CFO)",
    "office": "New York",
    "extension": "3059",
    "startDate": "2010/06/09",
    "salary": "Paul Byrd",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 18,
    "name": "Gloria Little",
    "position": "Systems Administrator",
    "office": "New York",
    "extension": "1721",
    "startDate": "2009/04/10",
    "salary": "Gloria Little",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 19,
    "name": "Bradley Greer",
    "position": "Software Engineer",
    "office": "London",
    "extension": "2558",
    "startDate": "2012/10/13",
    "salary": "Bradley Greer",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 20,
    "name": "Dai Rios",
    "position": "Personnel Lead",
    "office": "Edinburgh",
    "extension": "2290",
    "startDate": "2012/09/26",
    "salary": "Dai Rios",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 21,
    "name": "Jenette Caldwell",
    "position": "Development Lead",
    "office": "New York",
    "extension": "1937",
    "startDate": "2011/09/03",
    "salary": "Jenette Caldwell",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 22,
    "name": "Yuri Berry",
    "position": "Chief Marketing Officer (CMO)",
    "office": "New York",
    "extension": "6154",
    "startDate": "2009/06/25",
    "salary": "Yuri Berry",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 23,
    "name": "Caesar Vance",
    "position": "Pre-Sales Support",
    "office": "New York",
    "extension": "8330",
    "startDate": "2011/12/12",
    "salary": "Caesar Vance",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 24,
    "name": "Doris Wilder",
    "position": "Sales Assistant",
    "office": "Sidney",
    "extension": "3023",
    "startDate": "2010/09/20",
    "salary": "Doris Wilder",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 25,
    "name": "Angelica Ramos",
    "position": "Chief Executive Officer (CEO)",
    "office": "London",
    "extension": "5797",
    "startDate": "2009/10/09",
    "salary": "Angelica Ramos",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 26,
    "name": "Gavin Joyce",
    "position": "Developer",
    "office": "Edinburgh",
    "extension": "8822",
    "startDate": "2010/12/22",
    "salary": "Gavin Joyce",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 27,
    "name": "Jennifer Chang",
    "position": "Regional Director",
    "office": "Singapore",
    "extension": "9239",
    "startDate": "2010/11/14",
    "salary": "Jennifer Chang",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 28,
    "name": "Brenden Wagner",
    "position": "Software Engineer",
    "office": "San Francisco",
    "extension": "1314",
    "startDate": "2011/06/07",
    "salary": "Brenden Wagner",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 29,
    "name": "Fiona Green",
    "position": "Chief Operating Officer (COO)",
    "office": "San Francisco",
    "extension": "2947",
    "startDate": "2010/03/11",
    "salary": "Fiona Green",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 30,
    "name": "Shou Itou",
    "position": "Regional Marketing",
    "office": "Tokyo",
    "extension": "8899",
    "startDate": "2011/08/14",
    "salary": "Shou Itou",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 30,
    "name": "Michelle House",
    "position": "Integration Specialist",
    "office": "Sidney",
    "extension": "2769",
    "startDate": "2011/06/02",
    "salary": "Michelle House",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 32,
    "name": "Suki Burks",
    "position": "Developer",
    "office": "London",
    "extension": "6832",
    "startDate": "2009/10/22",
    "salary": "Suki Burks",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 33,
    "name": "Prescott Bartlett",
    "position": "Technical Author",
    "office": "London",
    "extension": "3606",
    "startDate": "2011/05/07",
    "salary": "Prescott Bartlett",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 34,
    "name": "Gavin Cortez",
    "position": "Team Leader",
    "office": "San Francisco",
    "extension": "2860",
    "startDate": "2008/10/26",
    "salary": "Gavin Cortez",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 35,
    "name": "Martena Mccray",
    "position": "Post-Sales support",
    "office": "Edinburgh",
    "extension": "8240",
    "startDate": "2011/03/09",
    "salary": "Martena Mccray",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  },
  {
    "id": 36,
    "name": "Unity Butler",
    "position": "Marketing Designer",
    "office": "San Francisco",
    "extension": "5384",
    "startDate": "2009/12/09",
    "salary": "Unity Butler",
    "imagelink": "http://img.timeinc.net/time/daily/2008/0811/360_mickey_mouse_1117.jpg"
  }
]

```

C:\xampp\htdocs\belongstomany\example\10\_file\_upload\mock\_svc\_ok.json

```json
{
  "id": 1,
  "name": "Tiger Nixon",
  "position": "System Architect",
  "office": "Edinburgh",
  "extension": "5421",
  "startDate": "2011/04/25",
  "salary": "Tiger Nixon",
  "imagelink": "#"
}

```

1. [Foundation support](https://belongstomany.com/example/11_foundation/example11.html)
2. ![](/files/sKtzoyFKhbd1jsaKxN2S)
3. C:\xampp\htdocs\belongstomany\example\11\_foundation\example11.html
4. ```html
   <!DOCTYPE html>
   <html lang="en">
   <head>
     <meta charset="utf-8">
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <title>DataTable-AltEditor - Example #11</title>
     <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/foundation-sites@6.6.3/dist/css/foundation.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/buttons/1.6.2/css/buttons.dataTables.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/select/1.3.1/css/select.dataTables.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/responsive/2.2.5/css/responsive.dataTables.css" />
   </head>
   <body>
     <p><br></p>
     <h1>DataTable-AltEditor - Example #11</h1>
     <h2>Foundation instead of Bootstrap</h2>
     <div class="container">
       <table cellpadding="0" cellspacing="0" border="0" class="dataTable table table-striped" id="example">
       </table>
     </div>
     <script src="https://code.jquery.com/jquery-3.0.0.js"></script>
     <script src="https://code.jquery.com/jquery-migrate-3.3.0.js"></script>
     <script src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.js"></script>
     <script src="https://cdn.datatables.net/buttons/1.6.2/js/dataTables.buttons.js"></script>
     <script src="https://cdn.datatables.net/select/1.3.1/js/dataTables.select.js"></script>
     <script src="https://cdn.jsdelivr.net/npm/foundation-sites@6.6.3/dist/js/foundation.js"></script>
     <script src="https://cdn.datatables.net/responsive/2.2.5/js/dataTables.responsive.js"></script>
     <script src="../../src/dataTables.altEditor.free.js"></script>
     <script src="./example11.js"></script>
   </body>
   </html>

   ```

C:\xampp\htdocs\belongstomany\example\11\_foundation\example11.js

```javascript
$(document).ready(function () {
  // Enable Foundation
  $(document).foundation();
  var dataSet = [
    { id: 1, name: "Tiger Nixon", position: "System Architect", office: "Edinburgh", extension: "5421", startDate: "2011/04/25", salary: "Tiger Nixon" },
    { id: 2, name: "Garrett Winters", position: "Accountant", office: "Tokyo", extension: "8422", startDate: "2011/07/25", salary: "Garrett Winters" },
    { id: 3, name: "Ashton Cox", position: "Junior Technical Author", office: "San Francisco", extension: "1562", startDate: "2009/01/12", salary: "Ashton Cox" },
    { id: 4, name: "Cedric Kelly", position: "Senior Javascript Developer", office: "Edinburgh", extension: "6224", startDate: "2012/03/29", salary: "Cedric Kelly" },
    { id: 5, name: "Airi Satou", position: "Accountant", office: "Tokyo", extension: "5407", startDate: "2008/11/28", salary: "Airi Satou" },
    { id: 6, name: "Brielle Williamson", position: "Integration Specialist", office: "New York", extension: "4804", startDate: "2012/12/02", salary: "Brielle Williamson" },
    { id: 7, name: "Herrod Chandler", position: "Sales Assistant", office: "San Francisco", extension: "9608", startDate: "2012/08/06", salary: "Herrod Chandler" },
    { id: 8, name: "Rhona Davidson", position: "Integration Specialist", office: "Tokyo", extension: "6200", startDate: "2010/10/14", salary: "Rhona Davidson" },
    { id: 9, name: "Colleen Hurst", position: "Javascript Developer", office: "San Francisco", extension: "2360", startDate: "2009/09/15", salary: "Colleen Hurst" },
    { id: 10, name: "Sonya Frost", position: "Software Engineer", office: "Edinburgh", extension: "1667", startDate: "2008/12/13", salary: "Sonya Frost" },
    { id: 11, name: "Jena Gaines", position: "Office Manager", office: "London", extension: "3814", startDate: "2008/12/19", salary: "Jena Gaines" },
    { id: 12, name: "Quinn Flynn", position: "Support Lead", office: "Edinburgh", extension: "9497", startDate: "2013/03/03", salary: "Quinn Flynn" },
    { id: 13, name: "Charde Marshall", position: "Regional Director", office: "San Francisco", extension: "6741", startDate: "2008/10/16", salary: "Charde Marshall" },
    { id: 14, name: "Haley Kennedy", position: "Senior Marketing Designer", office: "London", extension: "3597", startDate: "2012/12/18", salary: "Haley Kennedy" },
    { id: 15, name: "Tatyana Fitzpatrick", position: "Regional Director", office: "London", extension: "1965", startDate: "2010/03/17", salary: "Tatyana Fitzpatrick" },
    { id: 16, name: "Michael Silva", position: "Marketing Designer", office: "London", extension: "1581", startDate: "2012/11/27", salary: "Michael Silva" },
    { id: 17, name: "Paul Byrd", position: "Chief Financial Officer (CFO)", office: "New York", extension: "3059", startDate: "2010/06/09", salary: "Paul Byrd" },
    { id: 18, name: "Gloria Little", position: "Systems Administrator", office: "New York", extension: "1721", startDate: "2009/04/10", salary: "Gloria Little" },
    { id: 19, name: "Bradley Greer", position: "Software Engineer", office: "London", extension: "2558", startDate: "2012/10/13", salary: "Bradley Greer" },
    { id: 20, name: "Dai Rios", position: "Personnel Lead", office: "Edinburgh", extension: "2290", startDate: "2012/09/26", salary: "Dai Rios" },
    { id: 21, name: "Jenette Caldwell", position: "Development Lead", office: "New York", extension: "1937", startDate: "2011/09/03", salary: "Jenette Caldwell" },
    { id: 22, name: "Yuri Berry", position: "Chief Marketing Officer (CMO)", office: "New York", extension: "6154", startDate: "2009/06/25", salary: "Yuri Berry" },
    { id: 23, name: "Caesar Vance", position: "Pre-Sales Support", office: "New York", extension: "8330", startDate: "2011/12/12", salary: "Caesar Vance" },
    { id: 24, name: "Doris Wilder", position: "Sales Assistant", office: "Sidney", extension: "3023", startDate: "2010/09/20", salary: "Doris Wilder" },
    { id: 25, name: "Angelica Ramos", position: "Chief Executive Officer (CEO)", office: "London", extension: "5797", startDate: "2009/10/09", salary: "Angelica Ramos" },
    { id: 26, name: "Gavin Joyce", position: "Developer", office: "Edinburgh", extension: "8822", startDate: "2010/12/22", salary: "Gavin Joyce" },
    { id: 27, name: "Jennifer Chang", position: "Regional Director", office: "Singapore", extension: "9239", startDate: "2010/11/14", salary: "Jennifer Chang" },
    { id: 28, name: "Brenden Wagner", position: "Software Engineer", office: "San Francisco", extension: "1314", startDate: "2011/06/07", salary: "Brenden Wagner" },
    { id: 29, name: "Fiona Green", position: "Chief Operating Officer (COO)", office: "San Francisco", extension: "2947", startDate: "2010/03/11", salary: "Fiona Green" },
    { id: 30, name: "Shou Itou", position: "Regional Marketing", office: "Tokyo", extension: "8899", startDate: "2011/08/14", salary: "Shou Itou" },
    { id: 30, name: "Michelle House", position: "Integration Specialist", office: "Sidney", extension: "2769", startDate: "2011/06/02", salary: "Michelle House" },
    { id: 32, name: "Suki Burks", position: "Developer", office: "London", extension: "6832", startDate: "2009/10/22", salary: "Suki Burks" },
    { id: 33, name: "Prescott Bartlett", position: "Technical Author", office: "London", extension: "3606", startDate: "2011/05/07", salary: "Prescott Bartlett" },
    { id: 34, name: "Gavin Cortez", position: "Team Leader", office: "San Francisco", extension: "2860", startDate: "2008/10/26", salary: "Gavin Cortez" },
    { id: 35, name: "Martena Mccray", position: "Post-Sales support", office: "Edinburgh", extension: "8240", startDate: "2011/03/09", salary: "Martena Mccray" },
    { id: 36, name: "Unity Butler", position: "Marketing Designer", office: "San Francisco", extension: "5384", startDate: "2009/12/09", salary: "Unity Butler" },
  ];
  var columnDefs = [{
    data: "id",
    title: "Id",
    type: "readonly"
  },
  {
    data: "name",
    title: "Name"
  },
  {
    data: "position",
    title: "Position"
  },
  {
    data: "office",
    title: "Office"
  },
  {
    data: "extension",
    title: "Extn."
  },
  {
    data: "startDate",
    title: "Start date"
  },
  {
    data: "salary",
    title: "Salary"
  }];
  var myTable;
  myTable = $('#example').DataTable({
    "sPaginationType": "full_numbers",
    data: dataSet,
    columns: columnDefs,
    dom: 'Bfrtip',        // Needs button container
    select: 'single',
    responsive: true,
    altEditor: true,     // Enable altEditor
    buttons: [{
      text: 'Add',
      name: 'add'        // do not change name
    },
    {
      extend: 'selected', // Bind to Selected row
      text: 'Edit',
      name: 'edit'        // do not change name
    },
    {
      extend: 'selected', // Bind to Selected row
      text: 'Delete',
      name: 'delete'      // do not change name
    }]
  });
});

```

1. [Edit on click,delete inline](https://belongstomany.com/example/12_inline_buttons/example12.html)
2.

```
<figure><img src="/files/6jlX6rnSxMr3pUwnTBYC" alt=""><figcaption></figcaption></figure>
```

```
<figure><img src="/files/Q18gzmEJiX9Bx5rL8iGr" alt=""><figcaption></figcaption></figure>
```

3\. C:\xampp\htdocs\belongstomany\example\12\_inline\_buttons\example12.html
4\.
5. \`\`\`html

   <!DOCTYPE html>

   <html lang="en">
   <head>
     <meta charset="utf-8">
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <title>DataTable-AltEditor - Example #12</title>
     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/buttons/1.6.2/css/buttons.dataTables.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/select/1.3.1/css/select.dataTables.css" />
     <link rel="stylesheet" href="https://cdn.datatables.net/responsive/2.2.5/css/responsive.dataTables.css" />
     <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.css" />
   </head>
   <body>
     <div class="container">
       <h1>DataTable-AltEditor - Example #12</h1>
       <h2>Edit on click, delete inline</h2>
     </div>
     <div class="container">
       <button class="btn btn-primary" id="addbutton" title="Add"><span class="fa fa-plus-square"></span></button>
       <table cellpadding="0" cellspacing="0" border="0" class="dataTable table table-striped" id="example">
       </table>
     </div>
     <script src="https://code.jquery.com/jquery-3.0.0.js"></script>
     <script src="https://code.jquery.com/jquery-migrate-3.3.0.js"></script>
     <script src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.js"></script>
     <script src="https://cdn.datatables.net/buttons/1.6.2/js/dataTables.buttons.js"></script>
     <script src="https://cdn.datatables.net/select/1.3.1/js/dataTables.select.js"></script>
     <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js"></script>
     <script src="https://cdn.datatables.net/responsive/2.2.5/js/dataTables.responsive.js"></script>
     <script src="../../src/dataTables.altEditor.free.js"></script>
     <script src="./example12.js"></script>
   </body>
   </html>

````

C:\xampp\htdocs\belongstomany\example\12\_inline\_buttons\example12.js

```javascript
$(document).ready(function () {
var dataSet = [
 { id: 1, name: "Tiger Nixon", position: "System Architect", office: "Edinburgh", extension: "5421", startDate: "2011/04/25", salary: "Tiger Nixon" },
 { id: 2, name: "Garrett Winters", position: "Accountant", office: "Tokyo", extension: "8422", startDate: "2011/07/25", salary: "Garrett Winters" },
 { id: 3, name: "Ashton Cox", position: "Junior Technical Author", office: "San Francisco", extension: "1562", startDate: "2009/01/12", salary: "Ashton Cox" },
 { id: 4, name: "Cedric Kelly", position: "Senior Javascript Developer", office: "Edinburgh", extension: "6224", startDate: "2012/03/29", salary: "Cedric Kelly" },
 { id: 5, name: "Airi Satou", position: "Accountant", office: "Tokyo", extension: "5407", startDate: "2008/11/28", salary: "Airi Satou" },
 { id: 6, name: "Brielle Williamson", position: "Integration Specialist", office: "New York", extension: "4804", startDate: "2012/12/02", salary: "Brielle Williamson" },
 { id: 7, name: "Herrod Chandler", position: "Sales Assistant", office: "San Francisco", extension: "9608", startDate: "2012/08/06", salary: "Herrod Chandler" },
 { id: 8, name: "Rhona Davidson", position: "Integration Specialist", office: "Tokyo", extension: "6200", startDate: "2010/10/14", salary: "Rhona Davidson" },
 { id: 9, name: "Colleen Hurst", position: "Javascript Developer", office: "San Francisco", extension: "2360", startDate: "2009/09/15", salary: "Colleen Hurst" },
 { id: 10, name: "Sonya Frost", position: "Software Engineer", office: "Edinburgh", extension: "1667", startDate: "2008/12/13", salary: "Sonya Frost" },
 { id: 11, name: "Jena Gaines", position: "Office Manager", office: "London", extension: "3814", startDate: "2008/12/19", salary: "Jena Gaines" },
 { id: 12, name: "Quinn Flynn", position: "Support Lead", office: "Edinburgh", extension: "9497", startDate: "2013/03/03", salary: "Quinn Flynn" },
 { id: 13, name: "Charde Marshall", position: "Regional Director", office: "San Francisco", extension: "6741", startDate: "2008/10/16", salary: "Charde Marshall" },
 { id: 14, name: "Haley Kennedy", position: "Senior Marketing Designer", office: "London", extension: "3597", startDate: "2012/12/18", salary: "Haley Kennedy" },
 { id: 15, name: "Tatyana Fitzpatrick", position: "Regional Director", office: "London", extension: "1965", startDate: "2010/03/17", salary: "Tatyana Fitzpatrick" },
 { id: 16, name: "Michael Silva", position: "Marketing Designer", office: "London", extension: "1581", startDate: "2012/11/27", salary: "Michael Silva" },
 { id: 17, name: "Paul Byrd", position: "Chief Financial Officer (CFO)", office: "New York", extension: "3059", startDate: "2010/06/09", salary: "Paul Byrd" },
 { id: 18, name: "Gloria Little", position: "Systems Administrator", office: "New York", extension: "1721", startDate: "2009/04/10", salary: "Gloria Little" },
 { id: 19, name: "Bradley Greer", position: "Software Engineer", office: "London", extension: "2558", startDate: "2012/10/13", salary: "Bradley Greer" },
 { id: 20, name: "Dai Rios", position: "Personnel Lead", office: "Edinburgh", extension: "2290", startDate: "2012/09/26", salary: "Dai Rios" },
 { id: 21, name: "Jenette Caldwell", position: "Development Lead", office: "New York", extension: "1937", startDate: "2011/09/03", salary: "Jenette Caldwell" },
 { id: 22, name: "Yuri Berry", position: "Chief Marketing Officer (CMO)", office: "New York", extension: "6154", startDate: "2009/06/25", salary: "Yuri Berry" },
 { id: 23, name: "Caesar Vance", position: "Pre-Sales Support", office: "New York", extension: "8330", startDate: "2011/12/12", salary: "Caesar Vance" },
 { id: 24, name: "Doris Wilder", position: "Sales Assistant", office: "Sidney", extension: "3023", startDate: "2010/09/20", salary: "Doris Wilder" },
 { id: 25, name: "Angelica Ramos", position: "Chief Executive Officer (CEO)", office: "London", extension: "5797", startDate: "2009/10/09", salary: "Angelica Ramos" },
 { id: 26, name: "Gavin Joyce", position: "Developer", office: "Edinburgh", extension: "8822", startDate: "2010/12/22", salary: "Gavin Joyce" },
 { id: 27, name: "Jennifer Chang", position: "Regional Director", office: "Singapore", extension: "9239", startDate: "2010/11/14", salary: "Jennifer Chang" },
 { id: 28, name: "Brenden Wagner", position: "Software Engineer", office: "San Francisco", extension: "1314", startDate: "2011/06/07", salary: "Brenden Wagner" },
 { id: 29, name: "Fiona Green", position: "Chief Operating Officer (COO)", office: "San Francisco", extension: "2947", startDate: "2010/03/11", salary: "Fiona Green" },
 { id: 30, name: "Shou Itou", position: "Regional Marketing", office: "Tokyo", extension: "8899", startDate: "2011/08/14", salary: "Shou Itou" },
 { id: 30, name: "Michelle House", position: "Integration Specialist", office: "Sidney", extension: "2769", startDate: "2011/06/02", salary: "Michelle House" },
 { id: 32, name: "Suki Burks", position: "Developer", office: "London", extension: "6832", startDate: "2009/10/22", salary: "Suki Burks" },
 { id: 33, name: "Prescott Bartlett", position: "Technical Author", office: "London", extension: "3606", startDate: "2011/05/07", salary: "Prescott Bartlett" },
 { id: 34, name: "Gavin Cortez", position: "Team Leader", office: "San Francisco", extension: "2860", startDate: "2008/10/26", salary: "Gavin Cortez" },
 { id: 35, name: "Martena Mccray", position: "Post-Sales support", office: "Edinburgh", extension: "8240", startDate: "2011/03/09", salary: "Martena Mccray" },
 { id: 36, name: "Unity Butler", position: "Marketing Designer", office: "San Francisco", extension: "5384", startDate: "2009/12/09", salary: "Unity Butler" },
];
var columnDefs = [{
 data: "id",
 title: "Id",
 type: "readonly"
},
{
 data: "name",
 title: "Name"
},
{
 data: "position",
 title: "Position"
},
{
 data: "office",
 title: "Office"
},
{
 data: "extension",
 title: "Extn."
},
{
 data: "startDate",
 title: "Start date"
},
{
 data: "salary",
 title: "Salary"
},
{
 data: null,
 title: "Actions",
 name: "Actions",
 render: function (data, type, row, meta) {
   return '<a class="delbutton fa fa-minus-square btn btn-danger" href="#"></a>';
 },
 disabled: true
}
];
var myTable;
myTable = $('#example').DataTable({
 "sPaginationType": "full_numbers",
 data: dataSet,
 columns: columnDefs,
 dom: 'Bfrtip',        // Needs button container
 select: {
   style: 'single',
   toggleable: false
 },
 responsive: true,
 altEditor: true,     // Enable altEditor
 buttons: []          // no buttons, however this seems compulsory
});
// Edit
$(document).on('click', "[id^='example'] tbody ", 'tr', function () {
 var tableID = $(this).closest('table').attr('id');    // id of the table
 var that = $('#' + tableID)[0].altEditor;
 that._openEditModal();
 $('#altEditor-edit-form-' + that.random_id)
   .off('submit')
   .on('submit', function (e) {
     e.preventDefault();
     e.stopPropagation();
     that._editRowData();
   });
});
// Delete
$(document).on('click', "[id^='example'] .delbutton", 'tr', function (x) {
 var tableID = $(this).closest('table').attr('id');    // id of the table
 var that = $('#' + tableID)[0].altEditor;
 that._openDeleteModal();
 $('#altEditor-delete-form-' + that.random_id)
   .off('submit')
   .on('submit', function (e) {
     e.preventDefault();
     e.stopPropagation();
     that._deleteRow();
   });
 x.stopPropagation(); //avoid open "Edit" dialog
});
// Add row
$('#addbutton').on('click', function () {
 var that = $('#example')[0].altEditor;
 that._openAddModal();
 $('#altEditor-add-form-' + that.random_id)
   .off('submit')
   .on('submit', function (e) {
     e.preventDefault();
     e.stopPropagation();
     that._addRowData();
   });
});
});

````

C:\xampp\htdocs\belongstomany\src\dataTables.altEditor.free.js

```javascript
/**
 * @summary altEditor
 * @description Lightweight editor for DataTables
 * @version 2.0
 * @file dataTables.editor.free.js
 * @author kingkode (www.kingkode.com)
 *  Modified by: Kasper Olesen (https://github.com/KasperOlesen), Luca Vercelli (https://github.com/luca-vercelli), Zack Hable (www.cobaltdevteam.com)
 * @contact www.kingkode.com/contact
 * @contact zack@cobaltdevteam.com
 * @copyright Copyright 2016 Kingkode
 *
 * This source file is free software, available under the following license: MIT
 * license
 *
 * This source file is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
 *
 *
 */
(function (factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD
    define(['jquery', 'datatables.net'], function ($) {
      return factory($, window, document);
    });
  }
  else if (typeof exports === 'object') {
    // CommonJS
    module.exports = function (root, $) {
      if (!root) {
        root = window;
      }
      if (!$ || !$.fn.dataTable) {
        $ = require('datatables.net')(root, $).$;
      }
      return factory($, root, root.document);
    };
  }
  else {
    // Browser
    factory(jQuery, window, document);
  }
})
  (function ($, window, document, undefined) {
    'use strict';
    var DataTable = $.fn.dataTable;
    var _instance = 0;
    /**
     * altEditor provides modal editing of records for Datatables
     *
     * @class altEditor
     * @constructor
     * @param {object}
     *            oTD DataTables settings object
     * @param {object}
     *            oConfig Configuration object for altEditor
     */
    var altEditor = function (dt, opts) {
      if (!DataTable.versionCheck || !DataTable.versionCheck('1.10.8')) {
        throw ("Warning: altEditor requires DataTables 1.10.8 or greater");
      }
      // User and defaults configuration object
      this.c = $.extend(true, {}, DataTable.defaults.altEditor,
        altEditor.defaults, opts);
      /**
       * @namespace Settings object which contains customisable information
       *            for altEditor instance
       */
      this.s = {
        /** @type {DataTable.Api} DataTables' API instance */
        dt: new DataTable.Api(dt),
        /** @type {String} Unique namespace for events attached to the document */
        namespace: '.altEditor' + (_instance++)
      };
      /**
       * @namespace Common and useful DOM elements for the class instance
       */
      this.dom = {
        /** @type {jQuery} altEditor handle */
        modal: $('<div class="dt-altEditor-handle"/>'),
      };
      /* Constructor logic */
      this._constructor();
    }
    $.extend(
      altEditor.prototype,
      {
        /***************************************************************
         * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
         * Constructor * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
         */
        /**
         * Initialise the RowReorder instance
         *
         * @private
         */
        _constructor: function () {
          var that = this;
          var dt = this.s.dt;
          if (dt.settings()[0].oInit.onAddRow)
            that.onAddRow = dt.settings()[0].oInit.onAddRow;
          if (dt.settings()[0].oInit.onDeleteRow)
            that.onDeleteRow = dt.settings()[0].oInit.onDeleteRow;
          if (dt.settings()[0].oInit.onEditRow)
            that.onEditRow = dt.settings()[0].oInit.onEditRow;
          that.closeModalOnSuccess = dt.settings()[0].oInit.closeModalOnSuccess;
          if (that.closeModalOnSuccess === undefined) {
            that.closeModalOnSuccess = true;
          }
          that.encodeFiles = dt.settings()[0].oInit.encodeFiles;
          if (that.encodeFiles === undefined) {
            that.encodeFiles = true;
          }
          // Register datatable selection listener
          this.selectionListener()
          var lang = this.s.dt.settings()[0].oLanguage;
          if (lang.altEditor) {
            this.language = lang.altEditor;
            this._setup();
          }
          // Load from URL
          else if (typeof lang.altEditorUrl === 'string' && lang.altEditorUrl != '') {
            $.ajax({
              dataType: 'json',
              url: lang.altEditorUrl,
              success: function (json) {
                that.language = json;
                that._setup();
              },
              error: function () {
                // Error occurred loading language file, continue on as best we can
                that.language = {};
                that._setup();
              }
            });
          }
          // Default
          else {
            this.language = {};
            this._setup();
          }
          dt.on('destroy.altEditor', function () {
            dt.off('.altEditor');
            $(dt.table().body()).off(that.s.namespace);
            $(document.body).off(that.s.namespace);
          });
        },
        /***************************************************************
         * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
         * Private methods * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
         */
        /**
         * Setup dom and bind button actions
         *
         * @private
         */
        _setup: function () {
          var that = this;
          var dt = this.s.dt;
          this.random_id = ("" + Math.random()).replace(".", "");
          var modal_id = 'altEditor-modal-' + this.random_id;
          this.modal_selector = '#' + modal_id;
          this._initLanguage();
          var modal = '<div class="modal fade altEditor-modal reveal" id="' + modal_id + '" tabindex="-1" role="dialog" data-reveal>' +
            '<div class="modal-dialog">' +
            '<div class="modal-content">' +
            '<div class="modal-header">' +
            '<h4 style="padding-top: 1rem;padding-left: 1rem;" class="modal-title"></h4>' +
            '<button style="margin: initial;" type="button" class="close close-button" data-dismiss="modal" data-close aria-label="' + this.language.modalClose + '">' +
            '<span aria-hidden="true">&times;</span></button>' +
            '</div>' +
            '<div class="modal-body">' +
            '<p></p>' +
            '</div>' +
            '<div class="modal-footer">' +
            '</div>' +
            '</div>' +
            '</div>' +
            '</div>';
          // Add modal
          $('body').append(modal);
          // Add Edit Button
          if (dt.button('edit:name')) {
            dt.button('edit:name').action(function (e, dt, node, config) {
              that._openEditModal();
              $('#altEditor-edit-form-' + that.random_id)
                .off('submit')
                .on('submit', function (e) {
                  e.preventDefault();
                  e.stopPropagation();
                  that._editRowData();
                });
            });
          }
          // Add Delete Button
          if (dt.button('delete:name')) {
            dt.button('delete:name').action(function (e, dt, node, config) {
              that._openDeleteModal();
              $('#altEditor-delete-form-' + that.random_id)
                .off('submit')
                .on('submit', function (e) {
                  e.preventDefault();
                  e.stopPropagation();
                  that._deleteRow();
                });
            });
          }
          // Add Add Button
          if (dt.button('add:name')) {
            dt.button('add:name').action(function (e, dt, node, config) {
              that._openAddModal();
              $('#altEditor-add-form-' + that.random_id)
                .off('submit')
                .on('submit', function (e) {
                  e.preventDefault();
                  e.stopPropagation();
                  that._addRowData();
                });
            });
          }
          // Bind 'unique' error messages
          $(this.modal_selector).on('input', '[data-unique]', function (elm) {
            if ($(elm.target).attr('data-unique') == null || $(elm.target).attr('data-unique') === 'false') {
              return;
            }
            var target = $(elm.target);
            var colData = dt.column("th:contains('" + target.attr("name") + "')").data();
            // go through each item in this column
            var selectedCellData = null;
            if (dt.row({ selected: true }).index() != null)
              selectedCellData = dt.cell(dt.row({ selected: true }).index(), dt.column("th:contains('" + target.attr("name") + "')").index()).data();
            elm.target.setCustomValidity('');
            for (var j in colData) {
              // if the element is in the column and its not the selected one then its not unique
              if (target.val() == colData[j] && colData[j] != selectedCellData) {
                elm.target.setCustomValidity(that.language.error.unique);
              }
            }
          });
          // Add Refresh button
          if (this.s.dt.button('refresh:name')) {
            this.s.dt.button('refresh:name').action(function (e, dt, node, config) {
              if (dt.ajax && dt.ajax.url()) {
                dt.ajax.reload();
              }
            });
          }
        },
        /**
         * Init translate
         *
         * @private
         */
        _initLanguage: function () {
          this.language.modalClose = this.language.modalClose || 'Close';
          this.language.edit = this.language.edit || {};
          this.language.edit = {
            title: this.language.edit.title || 'Edit record',
            button: this.language.edit.button || 'Edit'
          };
          this.language.delete = this.language.delete || {};
          this.language.delete = {
            title: this.language.delete.title || 'Delete record',
            button: this.language.delete.button || 'Delete'
          };
          this.language.add = this.language.add || {};
          this.language.add = {
            title: this.language.add.title || 'Add record',
            button: this.language.add.button || 'Add'
          };
          this.language.success = this.language.success || 'Success!';
          this.language.error = this.language.error || {};
          this.language.error = {
            message: this.language.error.message || 'There was an unknown error!',
            label: this.language.error.label || 'Error!',
            responseCode: this.language.error.responseCode || 'Response code: ',
            required: this.language.error.required || 'Field is required',
            unique: this.language.error.unique || 'Duplicated field'
          };
        },
        /**
         * Emit an event on the DataTable for listeners
         *
         * @param {string}
         *            name Event name
         * @param {array}
         *            args Event arguments
         * @private
         */
        _emitEvent: function (name, args) {
          this.s.dt.iterator('table', function (ctx, i) {
            $(ctx.nTable).triggerHandler(name + '.dt', args);
          });
        },
        /**
         * Open Edit Modal for selected row
         *
         * @private
         */
        _openEditModal: function () {
          var dt = this.s.dt;
          var adata = dt.rows({
            selected: true
          });
          var columnDefs = this.completeColumnDefs();
          var data = this.createDialog(columnDefs, this.language.edit.title, this.language.edit.button,
            this.language.modalClose, 'editRowBtn', 'altEditor-edit-form');
          var selector = this.modal_selector;
          for (var j in columnDefs) {
            if (columnDefs[j].name != null) {
              var jquerySelector = "#" + columnDefs[j].name.toString().replace(/\./g, "\\.");
              var arrIndex = columnDefs[j].name.toString().split(".");
              var selectedValue = adata.data()[0];
              for (var index = 0; index < arrIndex.length; index++) {
                if (selectedValue) {
                  selectedValue = selectedValue[arrIndex[index]];
                }
              }
              if (typeof selectedValue !== 'object' && selectedValue !== null) {
                selectedValue = selectedValue.toString().trim();
              }
              // Added Select2
              if (columnDefs[j].type.indexOf("select") >= 0 && columnDefs[j].select2) {
                var jsonValue = undefined;
                try { jsonValue = JSON.parse(selectedValue); } catch (e) { }
                if (typeof jsonValue === 'object') { selectedValue = jsonValue; }
              }
              // Added checkbox
              else if (columnDefs[j].type.indexOf("checkbox") >= 0) {
                if (this._quoteattr(selectedValue) === "true" || this._quoteattr(selectedValue) == "1") { // MS SQL Databases use bits for booleans. 1 is equivlent to true, 0 is false
                  $(selector).find(jquerySelector).prop("checked", this._quoteattr(selectedValue)); // required by checkbox
                }
              }
              // Added date
              else if (columnDefs[j].type.indexOf("date") >= 0) {
                if (columnDefs[j].dateFormat !== "") {
                  var mDate = moment(this._quoteattr(selectedValue));
                  if (mDate && mDate.isValid()) {
                    $(selector).find(jquerySelector).val(mDate.format(columnDefs[j].dateFormat));
                  }
                }
              }
              $(selector).find(jquerySelector)
                .filter(':input[type!="file"]').val(selectedValue) // this._quoteattr or not? see #121
                .trigger("change"); // required by select2
            }
          }
          $(selector + ' input[0]').trigger('focus');
          $(selector).trigger("alteditor:some_dialog_opened").trigger("alteditor:edit_dialog_opened");
        },
        /**
         * Callback for "Edit" button
         */
        _editRowData: function () {
          var that = this;
          var dt = this.s.dt;
          var adata = dt.rows({
            selected: true
          });
          var rowDataArray = {}; // Complete new row data
          var originalRowDataArray = adata.data()[0]; // Original row data
          var $inputs = $('form[name="altEditor-edit-form-' + this.random_id + '"]').find('select, textarea, input');
          // Getting the inputs from the edit-modal
          $inputs.filter(':input[type!="file"], :input[type="checkbox"]').each(function (i) {
            rowDataArray[$(this).attr('id')] = $(this).val();
          });
          //Getting Files from the modal
          var numFilesQueued = 0;
          $inputs.filter(':input[type="file"]').each(function (i) {
            if ($(this).prop('files')[0]) {
              var context = this;
              if (that.encodeFiles) {
                ++numFilesQueued;
                that.getBase64($(this).prop('files')[0], function (filecontent) {
                  rowDataArray[$(context).attr('id')] = filecontent;
                  --numFilesQueued;
                });
              } else {
                rowDataArray[$(this).attr('id')] = $(this).prop('files')[0];
              }
            }
          });
          // Getting the checkbox from the modal
          $inputs.filter(':input[type="checkbox"]').each(function (i) {
            rowDataArray[$(this).attr('id')] = this.checked;
          });
          var checkFilesQueued = function () {
            if (numFilesQueued == 0) {
              that.onEditRow(that,
                rowDataArray,
                function (data, b, c, d, e) { that._editRowCallback(data, b, c, d, e); },
                function (data) { that._errorCallback(data); },
                originalRowDataArray);
            } else {
              console.log("Waiting for file base64-decoding...");
              setTimeout(checkFilesQueued, 1000);
            }
          };
          checkFilesQueued();
        },
        /**
         * Open Delete Modal for selected row
         *
         * @private
         */
        _openDeleteModal: function () {
          var that = this;
          var dt = this.s.dt;
          var adata = dt.rows({
            selected: true
          });
          var formName = 'altEditor-delete-form-' + this.random_id;
          var selector = this.modal_selector;
          var fill = function () {
            var btns = '<button type="button" data-content="remove" class="btn btn-default button secondary" data-close data-dismiss="modal">' + that.language.modalClose + '</button>' +
              '<button type="submit"  data-content="remove" class="btn btn-danger button" id="deleteRowBtn">' + that.language.delete.button + '</button>';
            $(selector).find('.modal-title').html(that.language.delete.title);
            $(selector).find('.modal-body').html(that.language.deleteMessage || `<h5>Are you sure you wish to delete ${adata.count()} rows?</h5>`);
            $(selector).find('.modal-footer').html(btns);
            var modalContent = $(selector).find('.modal-content');
            if (modalContent.parent().is('form')) {
              modalContent.parent().attr('name', formName);
              modalContent.parent().attr('id', formName);
            }
            else {
              modalContent.wrap("<form name='" + formName + "' id='" + formName + "' role='form'></form>");
            }
          };
          this.internalOpenDialog(selector, fill);
          $(selector + ' input[0]').trigger('focus');
          $(selector).trigger("alteditor:some_dialog_opened").trigger("alteditor:delete_dialog_opened");
        },
        /**
         * Callback for "Delete" button
         */
        _deleteRow: function () {
          var that = this;
          var dt = this.s.dt;
          var adata = dt.rows({
            selected: true
          }).data().toArray();
          that.onDeleteRow(that,
            adata,
            function (data) { that._deleteRowCallback(data); },
            function (data) { that._errorCallback(data); }
          );
        },
        /**
         * Open Add Modal for selected row
         *
         * @private
         */
        _openAddModal: function () {
          var dt = this.s.dt;
          var columnDefs = this.completeColumnDefs();
          var data = this.createDialog(columnDefs, this.language.add.title, this.language.add.button,
            this.language.modalClose, 'addRowBtn', 'altEditor-add-form');
          var selector = this.modal_selector;
          $(selector + ' input[0]').trigger('focus');
          $(selector).trigger("alteditor:some_dialog_opened").trigger("alteditor:add_dialog_opened");
        },
        selectionListener: function () {
          var _dt = this.s.dt
          _dt.on('select', function (e, dt, type, indexes) {
            // when multiple rows selected then disable edit button
            if (_dt.rows({ selected: true }).count() > 1) {
              _dt.buttons('edit:name').disable()
            }
          })
          _dt.on('deselect', function (e, dt, type, indexes) {
            // when multiple rows selected then disable edit button
            if (_dt.rows({ selected: true }).count() > 1) {
              _dt.buttons('edit:name').disable()
            }
          })
        },
        /**
        * Complete DataTable.context[0].aoColumns with default values
        */
        completeColumnDefs: function () {
          var columnDefs = [];
          var dt = this.s.dt;
          for (var i in dt.context[0].aoColumns) {
            var obj = dt.context[0].aoColumns[i];
            columnDefs[i] = {
              title: obj.sTitle,
              placeholder: (obj.placeholder ? obj.placeholder : obj.title), //added placeholder
              name: (obj.data ? obj.data : obj.mData),
              type: (obj.type ? obj.type : 'text'),
              rows: (obj.rows ? obj.rows : '5'),
              cols: (obj.cols ? obj.cols : '30'),
              options: (obj.options ? obj.options : []),
              readonly: (obj.readonly ? obj.readonly : false),
              disabled: (obj.disabled ? obj.disabled : false),
              required: (obj.required ? obj.required : false),
              hoverMsg: (obj.hoverMsg ? obj.hoverMsg : ''),
              pattern: (obj.pattern ? obj.pattern : '.*'),
              accept: (obj.accept ? obj.accept : ''),
              special: (obj.special ? obj.special : ''),
              unique: (obj.unique ? obj.unique : false),
              maxLength: (obj.maxLength ? obj.maxLength : false),
              multiple: (obj.multiple ? obj.multiple : false),
              select2: (obj.select2 ? obj.select2 : false),
              datepicker: (obj.datepicker ? obj.datepicker : false),
              datetimepicker: (obj.datetimepicker ? obj.datetimepicker : false),
              editorOnChange: (obj.editorOnChange ? obj.editorOnChange : null),
              style: (obj.style ? obj.style : ''),
              dateFormat: (obj.dateFormat ? obj.dateFormat : ''),
              optionsSortByLabel: (obj.optionsSortByLabel ? obj.optionsSortByLabel : false),
              inline: (obj.inline ? obj.inline : false), // Added for inline columns
              step: (obj.step ? obj.step : null), // Number fields
              min: (obj.min ? obj.min : null), // Number fields
              max: (obj.max ? obj.max : null), // Number fields
              value: (obj.value ? obj.value : '') // Allow a default value
            }
          }
          return columnDefs;
        },
        /**
        * Create both Edit and Add dialogs
        * @param columnDefs as returned by completeColumnDefs()
        */
        createDialog: function (columnDefs, modalTitle, buttonCaption, closeCaption, buttonClass, formName) {
          formName = [formName, this.random_id].join('-');
          var that = this,
            data = "",
            count = 0;
          var fillAttrs = function (obj, attrs) {
            var attrsStr = '';
            for (var i in attrs) {
              var attr = attrs[i];
              if (!obj[attr]) continue;
              attrsStr += " " + attr + "='" + that._quoteattr(obj[attr]) + "'";
            }
            return attrsStr + " ";
          };
          for (var j in columnDefs) {
            var title = columnDefs[j].title.replace(/(<([^>]+)>)/gi, "").trim();
            //handle hidden fields
            if (columnDefs[j].type.indexOf("hidden") >= 0) {
              data += "<input type='hidden' "
                + "id='" + this._quoteattr(columnDefs[j].name) + "' "
                + fillAttrs(columnDefs[j], ['name', 'value'])
                + "></input>";
            }
            else {
              // handle fields that are visible to the user
              if (columnDefs[j].inline) { //to add upto 4 inline columns
                if (count == 0) {
                  count++;
                  data += "<div style='margin-left: initial;margin-right: initial;' class='form-group row' id='alteditor-row-" + this._quoteattr(columnDefs[j].name) + "'>";
                  data += "<div class='col-sm-3 col-md-3 col-lg-3 text-right' style='padding-top:4px;'>";
                  data += "<label for='" + this._quoteattr(columnDefs[j].name) + "'>" + title + ":</label></div>";
                  data += "<div class='col-sm-2 col-md-2 col-lg-2'>";
                }
                else {
                  data += "<div class='col-sm-2 col-md-2 col-lg-2'>";
                }
              }
              else {
                data += "<div style='margin-left: initial;margin-right: initial;' class='form-group row' id='alteditor-row-" + this._quoteattr(columnDefs[j].name) + "'>";
                data += "<div class='col-sm-3 col-md-3 col-lg-3 text-right' style='padding-top:4px;'>";
                data += "<label for='" + this._quoteattr(columnDefs[j].name) + "'>" + title + ":</label></div>";
                data += "<div class='col-sm-8 col-md-8 col-lg-8'>";
              }
              // Adding select-fields
              if (columnDefs[j].type.indexOf("select") >= 0) {
                var options = "",
                  optionsArray = columnDefs[j].options;
                if (optionsArray.length > 0) {
                  // array-style select or select2
                  for (var i = 0; i < optionsArray.length; i++) {
                    options += "<option value='" + this._quoteattr(optionsArray[i])
                      + "'>" + optionsArray[i] + "</option>";
                  }
                } else {
                  // object-style select or select2
                  for (var x in optionsArray) {
                    options += "<option value='" + this._quoteattr(x) + "' >"
                      + optionsArray[x] + "</option>";
                  }
                }
                data += "<select class='form-control" + (columnDefs[j].select2 ? ' select2' : '') + "' "
                  + fillAttrs(columnDefs[j], ['name', 'style', 'readonly', 'disabled', 'required', 'multiple'])
                  + "id='" + this._quoteattr(columnDefs[j].name) + "' "
                  + "placeholder='" + this._quoteattr(columnDefs[j].placeholder ? columnDefs[j].placeholder : title) + "' "
                  + "data-special='" + this._quoteattr(columnDefs[j].special) + "' "
                  + "data-unique='" + columnDefs[j].unique + "' "
                  + ">" + options
                  + "</select>";
              }
              // Adding Text Area
              else if (columnDefs[j].type.indexOf("textarea") >= 0) {
                data += "<textarea class='form-control' "
                  + "id='" + this._quoteattr(columnDefs[j].name) + "' "
                  + fillAttrs(columnDefs[j], ['name', 'style', 'rows', 'cols', 'maxLength', 'readonly', 'disabled', 'required'])
                  + "placeholder='" + this._quoteattr(columnDefs[j].placeholder ? columnDefs[j].placeholder : title) + "' "
                  + "data-special='" + this._quoteattr(columnDefs[j].special) + "' "
                  + "data-unique='" + columnDefs[j].unique + "'>"
                  + (columnDefs[j].value ? columnDefs[j].value : '')
                  + "</textarea>";
              }
              // Adding text-inputs and error labels, but also new HTML5 types (email, color, ...)
              else {
                data += "<input class='form-control' "
                  + fillAttrs(columnDefs[j], ['type', 'pattern', 'accept', 'name', 'step', 'min', 'max', 'maxLength', 'value', 'readonly', 'disabled', 'required'])
                  + /* ???? */ (columnDefs[j].type.indexOf("readonly") >= 0 ? "readonly " : "")
                  + "id='" + this._quoteattr(columnDefs[j].name) + "' "
                  + "title='" + this._quoteattr(columnDefs[j].hoverMsg) + "' "
                  + "placeholder='" + this._quoteattr(columnDefs[j].placeholder ? columnDefs[j].placeholder : title) + "' "
                  + "data-special='" + this._quoteattr(columnDefs[j].special) + "' "
                  + "data-unique='" + columnDefs[j].unique + "' "
                  + "style='overflow: hidden; " + this._quoteattr(columnDefs[j].style) + "' "
                  + "class='form-control form-control-sm'>";
              }
              data += "<label id='" + this._quoteattr(columnDefs[j].name) + "-label"
                + "' class='errorLabel'></label>";
              if (!columnDefs[j].inline || (+j + 1 < columnDefs.length && !columnDefs[+j + 1].inline)) {
                data += "</div><div style='clear:both;'></div></div>";
              }
              else {
                data += "</div>";
              }
            }
          }
          // data += "</form>";
          var selector = this.modal_selector;
          var fill = function () {
            var btns = '<button type="button" data-content="remove" class="btn btn-default button secondary" data-dismiss="modal" data-close>' + closeCaption + '</button>'
              + '<button type="submit" form="' + formName + '" data-content="remove" class="btn btn-primary button" id="' + buttonClass + '">' + buttonCaption + '</button>';
            $(selector).find('.modal-title').html(modalTitle);
            $(selector).find('.modal-body').html(data);
            $(selector).find('.modal-footer').html(btns);
            var modalContent = $(selector).find('.modal-content');
            if (modalContent.parent().is('form')) {
              modalContent.parent().attr('name', formName);
              modalContent.parent().attr('id', formName);
            }
            else {
              modalContent.wrap("<form name='" + formName + "' id='" + formName + "' role='form'></form>");
            }
          };
          this.internalOpenDialog(selector, fill);
          $(selector + ' input[0]').trigger('focus');
          var that = this;
          // enable select 2 items, datepicker, datetimepickerm
          for (var j in columnDefs) {
            if (columnDefs[j].select2) {
              // Require select2 plugin
              $(selector).find("select#" + columnDefs[j].name).select2(columnDefs[j].select2);
            }
            else if (columnDefs[j].datepicker) {
              // Require jquery-ui
              $(selector).find("#" + columnDefs[j].name).datepicker(columnDefs[j].datepicker);
            }
            else if (columnDefs[j].datetimepicker) {
              // Require datetimepicker plugin
              $(selector).find("#" + columnDefs[j].name).datetimepicker(columnDefs[j].datetimepicker);
            }
            // custom onchange triggers
            if (columnDefs[j].editorOnChange) {
              // $.escapeSelector requires jQuery 3.x
              $(selector).find("#" + $.escapeSelector(columnDefs[j].name)).attr('alt-editor-id', this._quoteattr(j));
              $(selector).find("#" + $.escapeSelector(columnDefs[j].name)).on('change', function (elm) {
                var f = columnDefs[$(this).attr('alt-editor-id')].editorOnChange;
                f(elm, that);
              });
            }
            //added select sort
            if (columnDefs[j].type.indexOf("select") >= 0) {
              if (columnDefs[j].optionsSortByLabel) {
                var jquerySelector = "#" + columnDefs[j].name.toString().replace(/\./g, "\\.");
                var opts_list = $(selector).find(jquerySelector).find('option');
                opts_list.sort(function (a, b) { return $(a).text() > $(b).text() ? 1 : -1; });
                $(selector).find(jquerySelector).html('').append(opts_list);
                $(selector).find(jquerySelector).val($(jquerySelector + " option:first").val());
              }
            }
          }
        },
        /**
         * Callback for "Add" button
         */
        _addRowData: function () {
          var that = this;
          var rowDataArray = {};
          var $inputs = $('form[name="altEditor-add-form-' + this.random_id + '"]').find('select, textarea, input');
          // Getting the inputs from the edit-modal
          $inputs.filter(':input[type!="file"], :input[type="checkbox"]').each(function (i) {
            rowDataArray[$(this).attr('id')] = $(this).val();
          });
          //Getting Files from the modal
          var numFilesQueued = 0;
          $inputs.filter(':input[type="file"]').each(function (i) {
            var context = this;
            if ($(this).prop('files')[0]) {
              if (that.encodeFiles) {
                ++numFilesQueued;
                that.getBase64($(this).prop('files')[0], function (filecontent) {
                  rowDataArray[$(context).attr('id')] = filecontent;
                  --numFilesQueued;
                });
              } else {
                rowDataArray[$(this).attr('id')] = $(this).prop('files')[0];
              }
            }
          });
          // Getting the checkbox from the modal
          $inputs.filter(':input[type="checkbox"]').each(function (i) {
            rowDataArray[$(this).attr('id')] = this.checked;
          });
          var checkFilesQueued = function () {
            if (numFilesQueued == 0) {
              that.onAddRow(that,
                rowDataArray,
                function (data) { that._addRowCallback(data); },
                function (data) {
                  that._errorCallback(data);
                });
            } else {
              console.log("Waiting for file base64-decoding...");
              setTimeout(checkFilesQueued, 1000);
            }
          };
          checkFilesQueued();
        },
        /**
         * Called after a row has been deleted on server
         */
        _deleteRowCallback: function (response, status, more) {
          var selector = this.modal_selector;
          $(selector + ' .modal-body .alert').remove();
          if (this.closeModalOnSuccess) {
            this.internalCloseDialog(selector);
          } else {
            var message = '<div class="alert alert-success" role="alert">' +
              '<strong>' + this.language.success + '</strong>' +
              '</div>';
            $(selector + ' .modal-body').append(message);
          }
          this.s.dt.rows({
            selected: true
          }).remove();
          this.s.dt.draw('page');
          // Disabling submit button
          $("div" + selector).find("button#addRowBtn").prop('disabled', true);
          $("div" + selector).find("button#editRowBtn").prop('disabled', true);
          $("div" + selector).find("button#deleteRowBtn").prop('disabled', true);
        },
        /**
         * Called after a row has been inserted on server
         */
        _addRowCallback: function (response, status, more) {
          //TODO should honor dt.ajax().dataSrc
          var data = (typeof response === "string") ? JSON.parse(response) : response;
          var selector = this.modal_selector;
          $(selector + ' .modal-body .alert').remove();
          if (this.closeModalOnSuccess) {
            this.internalCloseDialog(selector);
          }
          else {
            var message = '<div class="alert alert-success" role="alert">' +
              '<strong>' + this.language.success + '</strong>' +
              '</div>';
            $(selector + ' .modal-body').append(message);
          }
          this.s.dt.row.add(data).draw(false);
          // Disabling submit button
          $("div" + selector).find("button#addRowBtn").prop('disabled', true);
          $("div" + selector).find("button#editRowBtn").prop('disabled', true);
          $("div" + selector).find("button#deleteRowBtn").prop('disabled', true);
        },
        /**
         * Called after a row has been updated on server
         */
        _editRowCallback: function (response, status, more) {
          //TODO should honor dt.ajax().dataSrc
          var data = (typeof response === "string") ? JSON.parse(response) : response;
          var selector = this.modal_selector;
          $(selector + ' .modal-body .alert').remove();
          if (this.closeModalOnSuccess) {
            this.internalCloseDialog(selector);
          }
          else {
            var message = '<div class="alert alert-success" role="alert">' +
              '<strong>' + this.language.success + '</strong>' +
              '</div>';
            $(selector + ' .modal-body').append(message);
          }
          this.s.dt.row({ selected: true }).data(data);
          this.s.dt.draw('page');
          // Disabling submit button
          $("div" + selector).find("button#addRowBtn").prop('disabled', true);
          $("div" + selector).find("button#editRowBtn").prop('disabled', true);
          $("div" + selector).find("button#deleteRowBtn").prop('disabled', true);
        },
        /**
         * Called after AJAX server returned an error
         */
        _errorCallback: function (response, status, more) {
          var error = response;
          var selector = this.modal_selector;
          $(selector + ' .modal-body .alert').remove();
          var errstr = this.language.error.message;
          if (error.responseJSON) {
            if (error.responseJSON.errors) {
              errstr = "";
              for (var key in error.responseJSON.errors) {
                errstr += error.responseJSON.errors[key][0];
              }
            }
          }
          else if (error.responseText) {
            errstr = error.responseText;
          }
          else {
            errstr = (error.status == null) ? "" : this.language.error.responseCode + error.status;
          }
          var message = '<div class="alert alert-danger" role="alert">' +
            '<strong>' + this.language.error.label + '</strong>'
            + (errstr ? '<br />' + errstr : '') +
            '</div>';
          $(selector + ' .modal-body').append(message);
        },
        /**
         * Default callback for insertion: mock webservice, always success.
         */
        onAddRow: function (dt, rowdata, success, error) {
          console.log("Missing AJAX configuration for INSERT");
          success(rowdata);
        },
        /**
         * Default callback for editing: mock webservice, always success.
         */
        onEditRow: function (dt, rowdata, success, error) {
          console.log("Missing AJAX configuration for UPDATE");
          success(rowdata);
        },
        /**
         * Default callback for deletion: mock webservice, always success.
         */
        onDeleteRow: function (dt, rowdata, success, error) {
          console.log("Missing AJAX configuration for DELETE");
          rowdata.every(function (rowIdx, tableLoop, rowLoop) {
            success(rowdata[rowIdx])
          })
        },
        /**
         * Open a dialog using available framework
         */
        internalOpenDialog(selector, onopen) {
          var $sel = $(selector);
          if ($sel.modal) {
            // Bootstrap
            $sel.on('show.bs.modal', onopen);
            $sel.modal('show');
          }
          else if ($sel.foundation) {
            // Foundation
            $sel.on('open.zf.reveal', onopen);
            $sel.on('closed.zf.reveal', function () { $('.reveal-overlay').hide(); });
            var popup = new Foundation.Reveal($sel);
            popup.open();
          }
          else {
            console.error('You must load Bootstrap or Foundation in order to open modal dialogs');
            return;
          }
        },
        /**
         * Close a dialog using available framework
         */
        internalCloseDialog(selector) {
          var $sel = $(selector);
          if ($sel.modal) {
            // Bootstrap
            $sel.modal('hide');
          } else if ($sel.foundation) {
            // Foundation
            var popup = new Foundation.Reveal($sel);
            popup.close();
            $('.reveal-overlay').hide();
          } else {
            console.error('You must load Bootstrap or Foundation in order to open modal dialogs');
            return;
          }
        },
        /**
         * Dinamically reload options in SELECT menu
        */
        reloadOptions: function ($select, options) {
          var oldValue = $select.val();
          $select.empty(); // remove old options
          if (options.length > 0) {
            // array-style select or select2
            $.each(options, function (key, value) {
              $select.append($("<option></option>")
                .attr("value", value).text(value));
            });
          }
          else {
            // object-style select or select2
            $.each(options, function (key, value) {
              $select.append($("<option></option>")
                .attr("value", value).text(key));
            });
          }
          $select.val(oldValue); // if still present, of course
          $select.trigger('change');
        },
        /**
         * Convert file to Base 64 form
         * @see https://stackoverflow.com/questions/36280818
         */
        getBase64: function (file, onSuccess, onError) {
          var reader = new FileReader();
          reader.readAsDataURL(file);
          reader.onload = function () {
            if (onSuccess) onSuccess(reader.result);
          };
          reader.onerror = function (error) {
            console.log('Error: ', error);
            if (onError) onError(error);
          };
        },
        /**
         * Sanitizes input for use in HTML
         * @param s
         * @param preserveCR
         * @returns {string}
         * @private
         */
        _quoteattr: function (s, preserveCR) {
          if (s == null) {
            return "";
          }
          preserveCR = preserveCR ? '&#13;' : '\n';
          if (Array.isArray(s)) {
            // for MULTIPLE SELECT
            var newArray = [];
            var x;
            for (x in s) newArray.push(s[x]);
            return newArray;
          }
          return ('' + s) /* Forces the conversion to string. */
            .replace(/&/g, '&amp;') /* This MUST be the 1st replacement. */
            .replace(/'/g, '&apos;') /* The 4 other predefined entities, required. */
            .replace(/"/g, '&quot;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/\r\n/g, preserveCR) /* Must be before the next replacement. */
            .replace(/[\r\n]/g, preserveCR);
        },
      });
    /**
     * altEditor version
     *
     * @static
     * @type String
     */
    altEditor.version = '2.0';
    /**
     * altEditor defaults
     *
     * @namespace
     */
    altEditor.defaults = {
      /**
       * @type {Boolean} Ask user what they want to do, even for a single
       *       option
       */
      alwaysAsk: false,
      /** @type {string|null} What will trigger a focus */
      focus: null, // focus, click, hover
      /** @type {column-selector} Columns to provide auto fill for */
      columns: '', // all
      /** @type {boolean|null} Update the cells after a drag */
      update: null, // false is editor given, true otherwise
      /** @type {DataTable.Editor} Editor instance for automatic submission */
      editor: null
    };
    /**
     * Classes used by altEditor that are configurable
     *
     * @namespace
     */
    altEditor.classes = {
      /** @type {String} Class used by the selection button */
      btn: 'btn'
    };
    // Attach a listener to the document which listens for DataTables
    // initialisation
    // events so we can automatically initialise
    $(document).on('preInit.dt.altEditor', function (e, settings, json) {
      if (e.namespace !== 'dt') {
        return;
      }
      var init = settings.oInit.altEditor;
      var defaults = DataTable.defaults.altEditor;
      if (init || defaults) {
        var opts = $.extend({}, init, defaults);
        if (init !== false) {
          var editor = new altEditor(settings, opts);
          // e is a jQuery event object
          // e.target is the underlying jQuery object, e.g. $('#mytable')
          // so that you can retrieve the altEditor object later
          e.target.altEditor = editor;
        }
      }
    });
    // Alias for access
    DataTable.altEditor = altEditor;
    return altEditor;
  });

```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://javascriptuse.gitbook.io/javascript/advanced/datatable-jquery-datatables-editor-alternative-to-the-official-one-ok.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
