From 67bd75f4ae70219f9e224186be2a650d5a59c754 Mon Sep 17 00:00:00 2001
From: Amanda Ghassaei <amandaghassaei@gmail.com>
Date: Mon, 25 May 2015 11:12:46 -0700
Subject: [PATCH] global file saver

---
 index.html                   |  19 +++---
 js/main.js                   |   5 +-
 js/menus/Navbar.js           | 122 ++++++++++++++++++-----------------
 js/models/AllAppPLists.js    |   2 +-
 js/models/AppState.js        |  79 +++--------------------
 js/models/GlobalFileSaver.js |  83 ++++++++++++++++++++++++
 js/models/Lattice.js         |   6 +-
 7 files changed, 170 insertions(+), 146 deletions(-)
 create mode 100644 js/models/GlobalFileSaver.js

diff --git a/index.html b/index.html
index 489f83e8..59fdde42 100644
--- a/index.html
+++ b/index.html
@@ -67,6 +67,7 @@
     <script src="js/cam/ShopbotExporter.js"></script>
     <script src="js/cam/GCodeExporter.js"></script>
     <script src="js/cam/TinyGExporter.js"></script>
+    <script src="js/models/GlobalFileSaver.js"></script>
 
     <!--views-->
     <script src="js/menus/MenuWrapperView.js"></script>
@@ -107,22 +108,22 @@
           <a href="#" class="dropdown-toggle" data-toggle="dropdown">File <b class="caret"></b></a>
           <span class="dropdown-arrow"></span>
           <ul class="dropdown-menu">
-                <li><a id="saveJSON" href="#">Save JSON &nbsp&nbsp&nbsp&nbsp(CTRL/&#8984; + S)</a></li>
+                <li><a class="saveJSON" href="#">Save JSON &nbsp&nbsp&nbsp&nbsp(CTRL/&#8984; + S)</a></li>
                 <li><a data-toggle="modal" data-target="#saveAsModel" href="#">Save JSON As... &nbsp&nbsp&nbsp&nbsp(CTRL/&#8984 + Shift + S)</a></li>
                 <li><a class="importJSON" href="#">Open JSON... &nbsp&nbsp&nbsp&nbsp(CTRL/&#8984 + O)</a></li>
                 <li class="dropdown-submenu">
                 <a tabindex="-1">Demo Files<span class="pull-right fui-arrow-right"></span></a>
                 <ul class="dropdown-menu">
-                    <li><a data-file="oneBitBot.json" class="savedDemo" href="#">One Bit Assembly</a></li>
+                    <li><a data-file="oneBitBot.json" class="loadDemo" href="#">One Bit Assembly</a></li>
                 </ul></li>
                 <li class="divider"></li>
                 <li class="dropdown-submenu">
                 <a tabindex="-1">Load User Settings<span class="pull-right fui-arrow-right"></span></a>
                 <ul class="dropdown-menu">
                     <!--<li><a id="resetDefaultSettings" href="#">Reset Settings</a></li>-->
-                    <li><a data-file="ben.user" class="savedUserSettings" href="#">Ben</a></li>
-                    <li><a data-file="matt.user" class="savedUserSettings" href="#">Matt</a></li>
-                    <li><a data-file="will.user" class="savedUserSettings" href="#">Will</a></li>
+                    <li><a data-file="ben.user" class="loadUser" href="#">Ben</a></li>
+                    <li><a data-file="matt.user" class="loadUser" href="#">Matt</a></li>
+                    <li><a data-file="will.user" class="loadUser" href="#">Will</a></li>
                     <li><a class="importJSON" href="#">From File...</a></li>
                 </ul>
               </li>
@@ -164,11 +165,11 @@
             <p class="modal-title" >Enter File Name</p>
             </div>
             <div class="modal-body">
-                <input id="saveAsFileName" type="text" value="lattice" placeholder="Enter file name" class="form-control filename">
+                <input id="saveAsFileName" type="text" value="file" placeholder="Enter file name" class="form-control filename">
             </div>
             <div class="modal-footer">
                 <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
-                <button type="button" id="saveAsJSON" class="btn btn-primary">Save</button>
+                <button type="button" class="saveAsJSON btn btn-primary">Save</button>
             </div>
         </div>
     </div>
@@ -182,11 +183,11 @@
             <p class="modal-title" >Save User Settings</p>
             </div>
             <div class="modal-body">
-                <input id="userSettingsFilename" type="text" value="lattice" placeholder="Enter file name" class="form-control filename">
+                <input id="saveUserFileName" type="text" value="user" placeholder="Enter file name" class="form-control filename">
             </div>
             <div class="modal-footer">
                 <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
-                <button type="button" id="saveUser" class="btn btn-primary">Save</button>
+                <button type="button" class="saveUser btn btn-primary">Save</button>
             </div>
         </div>
     </div>
diff --git a/js/main.js b/js/main.js
index 8171a5ce..68b781ba 100644
--- a/js/main.js
+++ b/js/main.js
@@ -12,12 +12,13 @@ $(function(){
 //    window.workers = persistentWorkers(8);
 
     //init global singletons
-    globals.plist = buildAppPList();
-    globals.three = new ThreeModel();
+    globals.three = ThreeModel();
+    globals.plist = AppPList();
     globals.appState = new AppState();
     globals.lattice = new Lattice();
     globals.lattice.delayedInit();//todo need this?
     globals.assembler = new Assembler({appState: globals.appState, lattice:globals.lattice});
+    globals.fileSaver = GlobalFilesaver();
 
     //ui
     new MenuWrapper({model: globals.appState});
diff --git a/js/menus/Navbar.js b/js/menus/Navbar.js
index 20873867..e57f0480 100644
--- a/js/menus/Navbar.js
+++ b/js/menus/Navbar.js
@@ -11,33 +11,35 @@ NavBar = Backbone.View.extend({
     el: "body",
 
     events: {
-        "click #showHideMenu":                                  "_setMenuVis",
+        "click #showHideMenu":                                  "_setMenuVisibility",
         "click .menuHoverControls":                             "_setNavSelection",
-        "click #saveJSON":                                      "_save",
-        "click #saveAsJSON":                                    "_saveAs",
-        "change #saveAsModel":                                  "_saveAs",//detect enter key
-        "click #saveUser":                                      "_saveUserSettings",
         "shown.bs.modal .modal":                                "_showModal",
         "hide.bs.modal .modal":                                 "_hideModal",
+
+        "click .saveJSON":                                      "_save",
+        "click .saveAsJSON":                                    "_saveAs",
+//        "change #saveAsModel":                                  "_saveAs",//detect enter key
+        "click .saveUser":                                      "_saveUser",
+
         "click .importJSON":                                    "_importJSON",
         "change #jsonInput":                                    "_selectJSONFiles",
-        "click .savedUserSettings":                             "_loadSavedUser",
-        "click .savedDemo":                                     "_loadDemo"
+        "click .loadUser":                                      "_loadUser",
+        "click .loadDemo":                                      "_loadDemo"
     },
 
     initialize: function(){
 
-        _.bindAll(this, "_setMenuVis", "_setNavSelection");
+        _.bindAll(this, "_setMenuVisibility", "_setNavSelection");
 
         this.listenTo(this.model, "change:menuIsVisible", this._updateShowHideButton);
         this.listenTo(this.model, "change:currentNav", this._updateNavSelectionUI);
 
-        this._uiStuff();
+        this._logo();
         this._updateShowHideButton();
         this._updateNavSelectionUI();
     },
 
-    _setMenuVis: function(e){
+    _setMenuVisibility: function(e){
         e.preventDefault();
         var state = this.model.get("menuIsVisible");
         this.model.set("menuIsVisible", !state);
@@ -73,6 +75,53 @@ NavBar = Backbone.View.extend({
         });
     },
 
+    _logo: function(){
+        var $logo = $("#logo");
+        $logo.mouseover(function(){
+            $logo.attr("src","assets/imgs/logo-active.png");
+        });
+        $logo.mouseout(function(){
+            $logo.attr("src","assets/imgs/logo.png");
+        });
+    },
+
+    _deselectAllNavItems: function(){
+        $(".open").removeClass("open");//no highlight
+    },
+
+    _showModal: function(e){
+        var input = $(e.target).find("input.filename");
+        input.focus();
+        input.select();
+    },
+
+    _hideModal: function(e){
+        $(e.target).find("input.filename").blur();
+    },
+
+
+
+
+
+    _save: function(e){
+        e.preventDefault();
+        globals.fileSaver.save();
+    },
+
+    _saveAs: function(e){
+        e.preventDefault();
+        var fileName = $("#saveAsFileName").val();
+        globals.fileSaver.save(fileName);
+        $('#saveAsModel').modal('hide');
+    },
+
+    _saveUser: function(e){
+        e.preventDefault();
+        var fileName = $("#saveUserFileName").val();
+        globals.fileSaver.saveUser(fileName);
+        $('#saveUserModel').modal('hide');
+    },
+
     _importJSON: function(e){
         e.preventDefault();
         $("#jsonInput").click();
@@ -95,38 +144,19 @@ NavBar = Backbone.View.extend({
             return function(e) {
                 var extension = filename.substr(filename.length - 5);
                 if (extension == ".json"){
-                    globals.appState.loadLatticeFromJSON(JSON.parse(e.target.result));
+                    globals.fileSaver.loadFile(JSON.parse(e.target.result));
                 } else if (extension == ".user"){
-                    globals.appState.loadUser(e.target.result);
+                    globals.fileSaver.loadUser(JSON.parse(e.target.result));
                 } else console.warn("file type not recognized");
             }
         })();
     },
 
-    _save: function(e){
-        e.preventDefault();
-        globals.appState.saveJSON();
-    },
-
-    _saveAs: function(e){
-        e.preventDefault();
-        var fileName = $("#saveAsFileName").val();
-        globals.appState.saveJSON(fileName);
-        $('#saveAsModel').modal('hide');
-    },
-
-    _saveUserSettings: function(e){
-        e.preventDefault();
-        var fileName = $("#userSettingsFilename").val();
-        globals.appState.saveUser(fileName);
-        $('#saveUserModel').modal('hide');
-    },
-
-    _loadSavedUser: function(e){
+    _loadUser: function(e){
         e.preventDefault();
         var url = "data/users/" + $(e.target).data("file");
         $.getJSON( url, function(data) {
-            globals.appState.loadUser(data, true);
+            globals.fileSaver.loadUser(data);
         });
     },
 
@@ -134,32 +164,8 @@ NavBar = Backbone.View.extend({
         e.preventDefault();
         var url = "data/demos/" + $(e.target).data("file");
         $.getJSON( url, function(data) {
-            globals.appState.loadLatticeFromJSON(data);
-        });
-    },
-
-    _showModal: function(e){
-        var input = $(e.target).find("input.filename");
-        input.focus();
-        input.select();
-    },
-
-    _hideModal: function(e){
-        $(e.target).find("input.filename").blur();
-    },
-
-    _uiStuff: function(){
-        var $logo = $("#logo");
-        $logo.mouseover(function(){
-            $logo.attr("src","assets/imgs/logo-active.png");
-        });
-        $logo.mouseout(function(){
-            $logo.attr("src","assets/imgs/logo.png");
+            globals.fileSaver.loadFile(data);
         });
-    },
-
-    _deselectAllNavItems: function(){
-        $(".open").removeClass("open");//no highlight
     }
 
 });
\ No newline at end of file
diff --git a/js/models/AllAppPLists.js b/js/models/AllAppPLists.js
index b667c09a..322bc864 100644
--- a/js/models/AllAppPLists.js
+++ b/js/models/AllAppPLists.js
@@ -1,6 +1,6 @@
 //all property lists for the app, these are "static" variables
 
-function buildAppPList(){
+function AppPList(){
     return {
 
 
diff --git a/js/models/AppState.js b/js/models/AppState.js
index e3f5609a..52bb59f2 100644
--- a/js/models/AppState.js
+++ b/js/models/AppState.js
@@ -40,11 +40,10 @@ AppState = Backbone.Model.extend({
         //bind events
         $(document).bind('keydown', {state:true}, this._handleKeyStroke);
         $(document).bind('keyup', {state:false}, this._handleKeyStroke);
-        $(document).bind('mousewheel', {}, this._handleScroll);
+        $(document).bind('mousewheel', {}, this._handleScroll);//disable browser back scroll
 
         this.listenTo(this, "change:currentTab", this._tabChanged);
-        this.listenTo(this, "change:currentNav", this._updateCurrentTabForNav);
-        this.listenTo(this, "change:currentTab", this._updateCellMode);
+        this.listenTo(this, "change:currentNav", this._navChanged);
 
         this.downKeys = {};//track keypresses to prevent repeat keystrokeson hold
 
@@ -52,9 +51,6 @@ AppState = Backbone.Model.extend({
     },
 
     isMobile: function() {
-//        var check = false;
-//        (function(a,b){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))check = true})(navigator.userAgent||navigator.vendor||window.opera);
-//        return check;
         return (window.innerWidth <= 700);
     },
 
@@ -70,6 +66,7 @@ AppState = Backbone.Model.extend({
         if (currentTab != "cam") this.set("manualSelectOrigin", false);
         if (currentTab == "import" && globals.lattice.get("connectionType") == "edgeRot") globals.lattice.set("partType", "voxLowPoly");
         this._storeTab(this.get("currentNav"), currentTab);
+        this._updateCellMode(currentTab);
     },
 
     _storeTab: function(currentNav, currentTab){
@@ -78,16 +75,15 @@ AppState = Backbone.Model.extend({
         else if (currentNav == "navAssemble") this.set("lastAssembleTab", currentTab);
     },
 
-    _updateCellMode: function(){
-        var currentTab = this.get("currentTab");
+    _updateCellMode: function(currentTab){
         if (currentTab == "lattice" || currentTab == "import") this.set("cellMode", "cell");
         //else if (currentTab == "import") this.set("cellMode", "cell");
         //else if (currentTab == "sketch") this.set("cellMode", "cell");
         else if (currentTab == "part") this.set("cellMode", "part");
     },
 
-    //update to last tab open in that section
-    _updateCurrentTabForNav: function(){
+    _navChanged: function(){
+        //update to last tab open in that section
         var navSelection = this.get("currentNav");
         if (navSelection == "navDesign") this.set("currentTab",
             this.get("lastDesignTab"));
@@ -112,7 +108,7 @@ AppState = Backbone.Model.extend({
         this.set("shift", false);//just in case, this is getting all weird during other meta commands in the browser
 
         if (e.ctrlKey || e.metaKey){
-        }else if (state) {
+        } else if (state) {
             if (this.downKeys[e.keyCode]) return;
             this.downKeys[e.keyCode] = true;
         } else this.downKeys[e.keyCode] = false;
@@ -145,7 +141,7 @@ AppState = Backbone.Model.extend({
                         this.set("shift", false);
                         $("#saveAsModel").modal("show");
                     } else {
-                        globals.appState.saveJSON();
+                        globals.fileSaver.save();
                     }
                 }
                 break;
@@ -191,65 +187,6 @@ AppState = Backbone.Model.extend({
 
     _handleScroll: function(e){//disable two finger swipe back
         if (Math.abs(e.originalEvent.deltaX) > Math.abs(e.originalEvent.deltaY)) e.preventDefault();
-    },
-
-        ////////////////////////////////////////////////////////////////////////////////////
-    ////////////////////////////////////SAVE////////////////////////////////////////////
-    ////////////////////////////////////////////////////////////////////////////////////
-
-    _saveFile: function(data, name, extension){
-        var blob = new Blob([data], {type: "text/plain;charset=utf-8"});
-        saveAs(blob, name + extension);
-    },
-
-    saveJSON: function(name){
-        if (!name) name = "lattice";
-        var data = JSON.stringify({
-            lattice:this._getLatticeDataToSave(),
-            assembler: this._getAssemblerDataToSave()
-        });
-        this._saveFile(data, name, ".json");
-    },
-
-    _getAssemblerDataToSave: function(){
-        var assemblerData = _.omit(globals.assembler.toJSON(), ["origin", "stock", "exporter", "appState", "lattice", "machine", "simLineNumber"]);
-        if (!globals.assembler.get("editsMadeToProgram")) assemblerData.dataOut = "";
-        return assemblerData;
-    },
-
-    _getLatticeDataToSave: function(){
-        return _.omit(globals.lattice.toJSONFull(), ["highlighter", "basePlane", "nodes", "appState"]);
-    },
-
-    loadLatticeFromJSON: function(data){
-        globals.lattice.clearCells();
-        this._setData(data, false);
-        globals.lattice._updateLatticeType(null, null, null, true);
-        globals.lattice.trigger("change:scale");//todo make this better
-    },
-
-    saveUser: function(name){
-        var latticeData = _.omit(this._getLatticeDataToSave(), ["cells", "cellsMin", "cellsMax", "numCells"]);
-        var assemblerData = _.omit(this._getAssemblerDataToSave(), ["dataOut", "needsPostProcessing", "editsMadeToProgram"]);
-        var data = JSON.stringify({
-            lattice:latticeData,
-            assembler:assemblerData
-        });
-        this._saveFile(data, name, ".user");
-    },
-
-    loadUser: function(data, isParsed){
-        if (!isParsed) data = JSON.parse(data);
-        this._setData(data, false);
-    },
-
-    _setData: function(data, silent){
-        _.each(_.keys(data.lattice), function(key){
-            globals.lattice.set(key, data.lattice[key], {silent:silent});
-        });
-        _.each(_.keys(data.assembler), function(key){
-            globals.assembler.set(key, data.assembler[key]);
-        });
     }
 
 });
\ No newline at end of file
diff --git a/js/models/GlobalFileSaver.js b/js/models/GlobalFileSaver.js
new file mode 100644
index 00000000..23ed5feb
--- /dev/null
+++ b/js/models/GlobalFileSaver.js
@@ -0,0 +1,83 @@
+/**
+ * Created by aghassaei on 5/25/15.
+ */
+
+
+function GlobalFilesaver(){
+
+    function _saveFile(data, name, extension){
+        var blob = new Blob([data], {type: "text/plain;charset=utf-8"});
+        saveAs(blob, name + extension);
+    }
+
+    function save(name){
+        if (!name || name == "" || name == undefined) name = "file";
+        var data = JSON.stringify({
+            lattice:_getLatticeDataToSave(),
+            assembler:_getAssemblerDataToSave()
+        });
+        _saveFile(data, name, ".json");
+    }
+
+    function saveLattice(name){
+        if (!name || name == "" || name == undefined) name = "lattice";
+        var data = JSON.stringify({
+            lattice:_getLatticeDataToSave()
+        });
+        _saveFile(data, name, ".json");
+    }
+
+    function saveAssembler(){
+
+    }
+
+    function saveUser(name){
+        if (!name || name == "" || name == undefined) name = "user";
+        var latticeData = _.omit(_getLatticeDataToSave(), ["cells", "cellsMin", "cellsMax", "numCells"]);
+        var assemblerData = _.omit(_getAssemblerDataToSave(), ["dataOut", "needsPostProcessing", "editsMadeToProgram"]);
+        var data = JSON.stringify({
+            lattice:latticeData,
+            assembler:assemblerData
+        });
+        _saveFile(data, name, ".user");
+    }
+
+    function _getAssemblerDataToSave(){
+        var assemblerData = _.omit(globals.assembler.toJSON(), ["origin", "stock", "exporter", "appState", "lattice", "machine", "simLineNumber"]);
+        if (!globals.assembler.get("editsMadeToProgram")) assemblerData.dataOut = "";
+        return assemblerData;
+    }
+
+    function _getLatticeDataToSave(){
+        return globals.lattice.attributes;
+    }
+
+    function loadFile(data){//todo make this better
+        globals.lattice.clearCells();
+        _setData(data, false);
+        globals.lattice._updateLatticeType(null, null, null, true);
+        globals.lattice.trigger("change:scale");
+    }
+
+    function loadUser(data){
+        _setData(data, false);
+    }
+
+    function _setData(data, silent){
+        _.each(_.keys(data.lattice), function(key){
+            globals.lattice.set(key, data.lattice[key], {silent:silent});
+        });
+        _.each(_.keys(data.assembler), function(key){
+            globals.assembler.set(key, data.assembler[key]);
+        });
+    }
+
+    return {//return public methods
+        save: save,
+        saveLattice: saveLattice,
+//        saveAssembler: saveAssembler,
+        saveUser: saveUser,
+        loadFile: loadFile,
+        loadUser: loadUser
+    }
+}
\ No newline at end of file
diff --git a/js/models/Lattice.js b/js/models/Lattice.js
index 4d069f2b..c7ca2f44 100644
--- a/js/models/Lattice.js
+++ b/js/models/Lattice.js
@@ -605,11 +605,7 @@ Lattice = Backbone.Model.extend({
     ////////////////////////////////////////////////////////////////////////////////////
 
     toJSON: function(){//a minimal toJSON for ui stuff - no need to parse all cells
-        return _.omit(this.attributes, ["cells", "nodes"]);
+        return _.omit(this.attributes, ["cells", "nodes"]);//omit makes a copy
     },//todo something weird here
 
-    toJSONFull: function(){//for saving only - it's ok to pass attributes
-        return this.attributes;
-    }
-
 });
\ No newline at end of file
-- 
GitLab