Vue - CSV Editor

by Ben Clayton

HTML

<script src="https://unpkg.com/vue"></script>
<hr>
<div id="graph-editor">
  YOU SHOULD'NT SEE THIS !
</div>
<hr>
<hr>


<script id="vue-tmpl-graph-editor" type="text/x-template">
  <div>
	<h1>GRAPH EDITOR</h1>
  <holo-csv-editor v-bind:grid-data="csvdata"></holo-csv-editor>
  </div>
</script>

<script id="vue-tmpl-csv-editor" type="text/x-template">
  <div v-on:paste="paste()" contentEditable=true>
   <div>DATA</div>
   <textarea placeholder="Paste Data Here" rows=1 cols=20 v-on:paste="paste()" v-model="textarea"></textarea>
   <holo-data-grid v-bind:grid-data="this.gridData"></holo-data-grid>
   <button v-on:click="clear()">Clear Data</button>
   </div>
</script>

<script id="vue-tmpl-data-grid" type="text/x-template">
  <div class="datagrid">
		<table cellspacing=0 cellpadding=0 bgcolor=#CCCCCC>
			<tr v-for="(row,rowidx) in gridData">
				<td class="datacell" bgcolor=#FFFFFF v-on:click="select(rowidx,colidx)" v-for="(col,colidx) in row">
					{{col}}
				</td>
			</tr>
		</table>
  </div>
</script>

CSS

body {
  font-size: 18px;
  font-family: "arial";
}

.text, textarea.edit {
  font-size: 24px;
	line-height: 28px;
	width:100%;
	height:100%;
}

.datagrid {
  max-width:200px;
  max-height:150px;
  overflow:auto;
}

.datacell {
  font-size: 12px;
    border:1px solid gray;
    padding:3px;
}

JavaScript

//---------------------------------------------------------

Vue.component('holo-csv-editor', {
  template: "#vue-tmpl-csv-editor",
  props: ['gridData'],
  data: function() {
    return {
      textarea: ""
    }
  },
  created: function() {
    console.log("holo-csv-editor gets:", this.gridData);
  },
  methods: {
    paste: function() {
      //alert("paste");
      navigator.clipboard.readText()
        .then(text => {
          console.log('Pasted content: ', text);
          this.textarea = "";
          this.import(text);
        })
        .catch(err => {
          console.error('Failed to read clipboard contents: ', err);
        });

    },
    clear: function() {
      while (this.gridData.pop()) {};
      this.textarea = "";
    },
    import: function(text) {
      // data from Excel copy is tabs (9) and newlines (13) seperated
      // text.split('').forEach(function(c){console.log(c.charCodeAt())});

      //this.gridData = []; // empty the array, but not like this otherwise you mutate the data.

      while (this.gridData.pop()) {};

      var linesplit = "";
      if (text.indexOf("\x0D\x0A") > -1) {
        linesplit = "\x0D\x0A"
      } else if (text.indexOf("\x0D") > -1) {
        linesplit = "\x0D"
      } else if (text.indexOf("\x0A") > -1) {
        linesplit = "\x0A"
      }

      var rowStrings = text.split(linesplit); // line split
      if (rowStrings.length < 1) {
        alert("DUFF");
        return;
      }

      rowStrings.forEach(rowStr => {
        var tempCols = rowStr.split('\x09'); // tab split
        var columns = [];
        tempCols.forEach(colStr => {
          columns.push(colStr);
        });
        this.gridData.push(columns);
      });

      // now find the max number of cols in a row
      var maxCols = 0;

      this.gridData.forEach(columns => {
        if (columns.length > maxCols) {
          maxCols = columns.length;
        }
      });

      // make sure all rows have same number of columns, if too few...