Changes

Jump to navigation Jump to search
m
no edit summary
Line 1: Line 1:  
console.log('_');
 
console.log('_');
 +
 +
// parts of structures from the wikibase entity used for our interest
    
var controller_item_id = 96,
 
var controller_item_id = 96,
    personal_data_id = 421,
+
personal_data_id = 421,
    interface_button_id = 487,
+
interface_button_id = 487,
    wbEStruct = {
+
language = "en";
    subclassOfRelations: 'claims.P4', // location of P4 relations in wbEntity
+
wbEStruct = {
    defaultValRelation: 'claims.P108',
+
        subclassOfRelations: 'claims.P4', // location of P4 relations in wbEntity
    instanceOfRelations: 'claims.P3',
+
        defaultValRelation: 'claims.P108',
         IDPropLoc: 'mainsnak.datavalue.value', // location of ID properties in related entity
+
        instanceOfRelations: 'claims.P3',
    IDName: 'numeric-id', // ID property name which checked  
+
         IDPropLoc: 'mainsnak.datavalue.value', // location of ID properties in related entity
    qIDPropName: 'id'
+
        IDName:   'numeric-id', // ID property name which checked  
    },
+
        qIDPropName: 'id',
    mwEStruct = {
+
        standardValue: 'labels' + '.' + language + '.' + 'value';
    wbXntity: 'config.values.wbEntity'
+
      },
    };
+
      mwEStruct = {
 +
        wbXntity: 'config.values.wbEntity'
 +
      };
 +
 
 +
      // Take username for standard databasename format
 +
      var PersonalDataDataBaseName = "PD.IO" + mw.user.getName() + "Database";
 +
      // Use username in user to get up to date version of self
 +
      var CurrentPerson = {id: 0, name: {user: mw.user.getName(), first: "", last: ""}, age: 0};
 +
 
 +
      recordAdd(PersonalDataDataBaseName, CurrentPerson);
 +
      recordUpdate(PersonalDataDataBaseName, CurrentPerson, '', value);
 +
      recordCheck(PersonalDataDataBaseName, CurrentPerson);
 +
      recordDeleteFrom(PersonalDataDataBaseName, CurrentPerson,                        )
    
// check if we are on a page of any of the targeted Entity
 
// check if we are on a page of any of the targeted Entity
 
// more exactly, use iterateAcheckBC to check in mw.config.values.wbEntity if instanceOfRelations exist, than if yes, check if numeric id of any matches controller id
 
// more exactly, use iterateAcheckBC to check in mw.config.values.wbEntity if instanceOfRelations exist, than if yes, check if numeric id of any matches controller id
  −
   
if ( iterateAcheckBC(mw, mwEStruct['wbXntity'], wbEStruct['instanceOfRelations'], wbEStruct['IDPropLoc'], wbEStruct['IDName'], controller_item_id) ) {
 
if ( iterateAcheckBC(mw, mwEStruct['wbXntity'], wbEStruct['instanceOfRelations'], wbEStruct['IDPropLoc'], wbEStruct['IDName'], controller_item_id) ) {
console.log("This is a Data Controller");
+
  console.log("This is a Data Controller");
controller_display_function();
+
  controller_display_function();
 
}
 
}
    
// use iterateAcheckBC to check in mw.config.values.wbEntity if subClassOfRelations exist, than if yes, check if numeric id of any matches personal data id
 
// use iterateAcheckBC to check in mw.config.values.wbEntity if subClassOfRelations exist, than if yes, check if numeric id of any matches personal data id
 
if ( iterateAcheckBC(mw, mwEStruct['wbXntity'], wbEStruct['subclassOfRelations'], wbEStruct['IDPropLoc'], wbEStruct['IDName'], personal_data_id) ) {
 
if ( iterateAcheckBC(mw, mwEStruct['wbXntity'], wbEStruct['subclassOfRelations'], wbEStruct['IDPropLoc'], wbEStruct['IDName'], personal_data_id) ) {
console.log("This is a Personal Data Type");
+
  console.log("This is a Personal Data Type");
input_display_function();
+
  input_display_function();
 
}
 
}
    
// use iterateAcheckBC to check in mw.config.values.wbEntity if instanceOfRelations exist, than if yes, check if numeric id of any matches interface button id
 
// use iterateAcheckBC to check in mw.config.values.wbEntity if instanceOfRelations exist, than if yes, check if numeric id of any matches interface button id
 
if ( iterateAcheckBC(mw, mwEStruct['wbXntity'], wbEStruct['instanceOfRelations'], wbEStruct['IDPropLoc'], wbEStruct['IDName'], interface_button_id) ) {
 
if ( iterateAcheckBC(mw, mwEStruct['wbXntity'], wbEStruct['instanceOfRelations'], wbEStruct['IDPropLoc'], wbEStruct['IDName'], interface_button_id) ) {
console.log("This is a Data Input Interface");
+
  console.log("This is a Data Input Interface");
data_maintenance_display();
+
  data_maintenance_display();
 
}
 
}
    
// show popup from template for controllers
 
// show popup from template for controllers
 
function controller_display_function(){
 
function controller_display_function(){
console.log( "it's a controller" )
+
  console.log( "it's a controller" )
var obj2 = interjson( get_Y_from_X( mw, mwEStruct['wbXntity'] ) );
+
  var obj2 = interjson( get_Y_from_X( mw, mwEStruct['wbXntity'] ) );
var qId = obj2[wbEStruct["qIDPropName"]];
+
  var qId = dive( obj2, wbEStruct["qIDPropName"] );
var api = new mw.Api();
+
  var api = new mw.Api();
api.get( {
+
  api.get( {
action: 'expandtemplates',
+
    action: 'expandtemplates',
text: '{{MailtoAccess|'+qId+'}}'
+
    text: '{{MailtoAccess|'+qId+'}}'
} ).done( function ( data ) {
+
  } ).done( function ( data ) {
mw.notify( $('<a href="'+data.expandtemplates["*"]+'"> Do a SAR to this data controller!</a>') , { autoHide: false } );
+
    mw.notify( $('<a href="'+data.expandtemplates["*"]+'"> Do a SAR to this data controller!</a>') , { autoHide: false } );
} );
+
  } );
 
}
 
}
    
// show input for personal data
 
// show input for personal data
 
function input_display_function() {
 
function input_display_function() {
var obj = interjson( get_Y_from_X( mw, mwEStruct['wbXntity'] ) );
+
  var obj = interjson( get_Y_from_X( mw, mwEStruct['wbXntity'] ) );
   var string_temporary_store = get_Y_from_X ( get_Y_from_X ( get_Y_from_X( obj, wbEStruct['defaultValRelation'] ), '0'), wbEStruct['IDPropLoc'] );
+
   var string_temporary_store_1 = get_Y_from_X( obj, wbEStruct['standardValue'] );
mw.notify( $('<input type="text" placeholder="' + string_temporary_store + '" id="place_0" />'), { autoHide: false } );
+
  var string_temporary_store_2 = get_Y_from_X ( get_Y_from_X ( get_Y_from_X( obj, wbEStruct['defaultValRelation'] ), '0'), wbEStruct['IDPropLoc'] );
 +
  var string_temporary_store_3 = 0;
 +
 
 +
  mw.notify(  
 +
    $('<input type="text" placeholder="' + string_temporary_store_2 + '" id="' + string_temporary_store_1 + '_' + 0 + '" />'), { autoHide: false } );
 
}
 
}
    
// show maintenance options for personal data
 
// show maintenance options for personal data
 
function data_maintenance_display() {
 
function data_maintenance_display() {
var obj = interjson( get_Y_from_X( mw, mwEStruct['wbXntity'] ) );
+
  var obj = interjson( get_Y_from_X( mw, mwEStruct['wbXntity'] ) ); // wbEntity as json obj
 +
  var string_temporary_store_1 = get_Y_from_X( obj, wbEStruct['standardValue'] );  // input name
 +
  var string_temporary_store_2 = get_Y_from_X ( get_Y_from_X ( get_Y_from_X( obj, wbEStruct['defaultValRelation'] ), '0'), wbEStruct['IDPropLoc'] ); //placeholder_text
 +
  var string_temporary_store_3 = 0; //get user value & relevant object parts here
 +
  interface_media( PersonalDataDataBaseName, CurrentPerson, string_temporary_store_1, string_temporary_store_2, string_temporary_store_3 );
 
}
 
}
    
// repeating code patterns
 
// repeating code patterns
 +
 +
function interface_media( db /* database */, prs /* user */ , rel_A /* current value location */, rel_B /* placeholder value */, rel_C /* which attribute it is in the inddb database */ ) {
 +
  mw.loader.using( 'oojs-ui-core' ).done( function () {
 +
    $( function () {
 +
     
 +
      var person = recordCheck( db, prs );
 +
//    var data = interjson( get_Y_from_X( mw, mwEStruct['wbXntity'] ) ); // wbEntity as json obj
 +
 +
      var button = [],
 +
          textInput = [];
 +
      var ii;
 +
      for ( var i = 0 ; i < recordcheck(db, prs, rel_C).length; i++ ) {
 +
        ii = i + 1;
 +
        button_save[i] = new OO.ui.ButtonWidget( { label: "Save"  } );
 +
        button_new[i] = new OO.ui.ButtonWidget( { label: "New" } );
 +
        button_delete[i] = new OO.ui.ButtonWidget( { label: "Delete" } );
 +
        textInput[i] = new OO.ui.TextInputWidget( {
 +
          value: check( person, rel_C + '.' + i ),
 +
          placeholder: rel_B 
 +
        } );
 +
        $(textInput[i]).on("keydown",function search(e) {
 +
            if(e.keyCode == 13) {
 +
                  recordUpdate( db, prs , rel_C + '.' + i , ($(this).val())  );
 +
            }
 +
        });
 +
        button_new[i].on( 'click', function () {
 +
   
 +
          // new
 +
          recordUpdate( db, prs, rel_C + '.' + ii , '');
 +
          interface_media( db, prs, rel_A, rel_B, rel_C );
 +
          return;
 +
 +
        } );
 +
        button_delete[i].on( 'click', function () {
 +
   
 +
          // delete
 +
          recordDeleteFrom( db, prs,  rel_C + '.' + i );
 +
          interface_media( db, prs, rel_A, rel_B, rel_C );
 +
          return;
 +
 +
        } );
 +
        button_save[i].on( 'click', function () {
 +
         
 +
          // save
 +
          recordUpdate( db, prs, rel_C + '.' + i , textInput[i].val()) ;
 +
          interface_media( db, prs, rel_A, rel_B, rel_C );
 +
          return;
 +
 +
        } );
 +
        $( '#mw-content-text' ).prepend( button_new[i].$element );
 +
        $( '#mw-content-text' ).prepend( button_delete[i].$element );
 +
        $( '#mw-content-text' ).prepend( button_save[i].$element );
 +
        $( '#mw-content-text' ).prepend( textInput[i].$element );
 +
        $( '#mw-content-text' ).prepend( '<br>' );
 +
 +
      }
 +
 +
//
 +
/*
 +
 +
      recordCheck(PersonalDataDataBaseName, CurrentPerson);
 +
 +
*/
 +
//
 +
 +
    } );
 +
  } );
 +
}
    
// get obj.'rel_0' (gets wbEntity), check if it has 'A', iterate over 'A', get 'B' and 'C' and check if any contains 'to_check'. if yes, return true
 
// get obj.'rel_0' (gets wbEntity), check if it has 'A', iterate over 'A', get 'B' and 'C' and check if any contains 'to_check'. if yes, return true
Line 78: Line 166:  
       for( var i = 0; i < current.length; i++ ) {
 
       for( var i = 0; i < current.length; i++ ) {
 
         console.log("dived in ");
 
         console.log("dived in ");
         console.log(current[i]);
+
         console.log(current[i]);  
 
         // check if we have controller id constructed from wbEntity  
 
         // check if we have controller id constructed from wbEntity  
 
         if ( check( current[i], rel_B ) != undefined ) {
 
         if ( check( current[i], rel_B ) != undefined ) {
Line 85: Line 173:  
               console.log("mark +");
 
               console.log("mark +");
 
               future = true;
 
               future = true;
             };
+
             };
 
           }
 
           }
 
         }
 
         }
Line 94: Line 182:  
}
 
}
    +
// get a.b from a and b
 
function get_Y_from_X( obj, B ){
 
function get_Y_from_X( obj, B ){
if ( check(obj, B) !==  undefined ) {
+
  if ( check(obj, B) !==  undefined ) {
console.log( "entity is defined" )
+
    console.log( "entity is defined" )
return dive(obj, B);
+
    return dive(obj, B);
}
+
  }
 
}
 
}
   −
function interjson(obj) {
+
// try to convert something into JSON
try {
+
function interjson( obj ) {
return JSON.parse( obj )
+
  try {
} catch (e) {
+
    return JSON.parse( obj )
// if not JSON, do silly things
+
  } catch (e) {
};
+
    // if not JSON, do silly things
 
+
  };
 
}
 
}
    +
//find second argument in first argument as a boolean
 
function check_Y_in_X(obj, to_check){
 
function check_Y_in_X(obj, to_check){
if (obj === to_check) { return true };
+
  if (obj === to_check) { return true };  
 
   for (var i = 0; i < obj.length; i++ ){
 
   for (var i = 0; i < obj.length; i++ ){
if (obj[i] === to_check) { return true };
+
    if (obj[i] === to_check) { return true };
}
+
  }
return false;
+
  return false;
 
}
 
}
   Line 124: Line 214:  
// if a.b.c.d does not exists, it returns the substructure until the substructure exists, if d does not exist, it returns matrix.a.b.c e.g.
 
// if a.b.c.d does not exists, it returns the substructure until the substructure exists, if d does not exist, it returns matrix.a.b.c e.g.
 
function dive(array, read){
 
function dive(array, read){
return read.split('.').reduce(indexinterpolate, array);
+
  return read.split('.').reduce(indexinterpolate, array);
 
}
 
}
 
function check(array, read){
 
function check(array, read){
return read.split('.').reduce(indexcheck, array);
+
  return read.split('.').reduce(indexcheck, array);
 
}
 
}
    
// ADD MORE DOC
 
// ADD MORE DOC
 
+
// Add new record (create pddbname@record) if it does not exist.
var PersonalDataDataBaseName = "PDIO3";
+
// If it exists, the contents of record are disregarded, and the indexeddb version is returned
var Jonathan = {id: 11345, name: {first: "Jonatha", last: "Lemmings"}, age: 32};
  −
 
  −
recordAdd(PersonalDataDataBaseName, Jonathan);
  −
recordUpdate(PersonalDataDataBaseName, Jonathan, 'phone', '+313851777');
  −
recordCheck(PersonalDataDataBaseName, Jonathan);
      
function recordAdd(pddbname, record){
 
function recordAdd(pddbname, record){
Line 144: Line 229:  
     var db = pddb.result;
 
     var db = pddb.result;
 
     var store = db.createObjectStore(PersonalDataDataBaseName, {keyPath: "id"});
 
     var store = db.createObjectStore(PersonalDataDataBaseName, {keyPath: "id"});
 +
 
// shouldn't the index be the wiki.personaldata.io username?  
 
// shouldn't the index be the wiki.personaldata.io username?  
var index = store.createIndex("NameIndex", ["name.last", "name.first"]);
+
 
};
+
  var index = store.createIndex("NameIndex", ["name.user"]);
pddb.onsuccess = function() {
+
  };
  var db = pddb.result;
+
  pddb.onsuccess = function() {
  var tx = db.transaction(PersonalDataDataBaseName, "readwrite");
+
    var db = pddb.result;
  var store = tx.objectStore(PersonalDataDataBaseName);
+
    var tx = db.transaction(PersonalDataDataBaseName, "readwrite");
  var index = store.index("NameIndex");   
+
    var store = tx.objectStore(PersonalDataDataBaseName);
//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||[  Essential recordAdd  ]||||||||||||||||||||||||||||||
+
    var index = store.index("NameIndex");   
var getRecord = index.get([record.name.last, record.name.first]);
+
 
getRecord.onsuccess = function() {
+
  //||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||[  Essential recordAdd  ]||||||||||||||||||||||||||||||
  if (getRecord.result != undefined) {
+
 
    console.log("updating");
+
    // Get the original record from the db...
    inp_obj = getRecord.result;
+
    var getRecord = index.get([record.name.user]);
  } else {
+
    getRecord.onsuccess = function() {
    inp_obj = record;
+
      if (getRecord.result != undefined) {
    store.put(inp_obj);
+
        // if found, let's use that from now on
  }
+
        console.log("updating");
  var sanitycheck = index.get([inp_obj.name.last, inp_obj.name.first]);
+
        inp_obj = getRecord.result;
  sanitycheck.onsuccess = function() {
+
        // let's return it so that our addrecord can be used as a getter as well
    console.log(sanitycheck);
+
        return inp_obj;
  }
+
      } else {
}
+
        // if it didn't exist, let's use the provided record to push to store
 +
        inp_obj = record;
 +
        store.put(inp_obj);
 +
      }
 +
      var sanitycheck = index.get([inp_obj.name.user]);
 +
      sanitycheck.onsuccess = function() {
 +
        console.log(sanitycheck);
 +
      }
 +
    }
 +
 
 
     //|||||||||||||||||||||||||||||||||||||||||||||
 
     //|||||||||||||||||||||||||||||||||||||||||||||
 +
 
     tx.oncomplete = function() {
 
     tx.oncomplete = function() {
 
       db.close();
 
       db.close();
Line 174: Line 270:  
};
 
};
   −
function recordUpdate(pddbname, record, field, value){
+
// Update pddbname@record:field value
 +
// Use store copy if exists
 +
// If record does not exist, create it
 +
// Otherwise all other fields of the record object are disregarded
 +
function recordUpdate( pddbname, record, field, value ) {
 +
 
 
   var pddb = window.indexedDB.open(pddbname, 3);
 
   var pddb = window.indexedDB.open(pddbname, 3);
 
   pddb.onupgradeneeded = function() {
 
   pddb.onupgradeneeded = function() {
 
     var db = pddb.result;
 
     var db = pddb.result;
 
     var store = db.createObjectStore(PersonalDataDataBaseName, {keyPath: "id"});
 
     var store = db.createObjectStore(PersonalDataDataBaseName, {keyPath: "id"});
     var index = store.createIndex("NameIndex", ["name.last", "name.first"]);
+
     var index = store.createIndex("NameIndex", ["name.user"]);
 
   };
 
   };
 
   pddb.onsuccess = function() {
 
   pddb.onsuccess = function() {
Line 187: Line 288:  
         var store = tx.objectStore(PersonalDataDataBaseName);
 
         var store = tx.objectStore(PersonalDataDataBaseName);
 
         var index = store.index("NameIndex");
 
         var index = store.index("NameIndex");
 +
 
//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||[  Essential recordUpdate  ]||||||||||||||||||||||||||||||
 
//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||[  Essential recordUpdate  ]||||||||||||||||||||||||||||||
var inp_obj;
  −
var getRecord = index.get([record.name.last, record.name.first]);
  −
getRecord.onsuccess = function() {
  −
  if( getRecord.result != undefined ) {
  −
  console.log("updating");
  −
  inp_obj = getRecord.result;
  −
} else {
  −
  inp_obj = record;
  −
}
     −
             inp_obj[field] = value;  // => "Bob"
+
        var inp_obj;
            store.put(inp_obj);
+
        var getRecord = index.get([record.name.user]);
 +
        // let's try to get the record to be updated from the store
 +
        getRecord.onsuccess = function() {
 +
          if( getRecord.result != undefined ) {
 +
            // if we have it, use that copy to update on
 +
            console.log("updating");
 +
             inp_obj = getRecord.result;
 +
          } else {
 +
            // if it does not exist in store, use the given record
 +
          inp_obj = record;
 +
        }
 +
        //give the value to the field to update
 +
        inp_obj[field] = value;  // => "Bob"
 +
        // write new version of record back to database
 +
        store.put(inp_obj);
 +
 
 +
 
 +
        // perform a sanity check if the update was successful, could be used to initiate a retry upon false
 +
        getRecordAgain = index.get([record.name.user]);
 +
        getRecordAgain.onsuccess = function() {
 +
            console.log(getRecordAgain);  // => "Bob"
 +
            if ( getRecordAgain.result[field] == value ) {
 +
              console.log("Update succeeded");
 +
            } else {
 +
              console.log("Update unsuccessful");
 +
            }
 +
          }; 
 +
        };
   −
            getRecordAgain = index.get([record.name.last, record.name.first]);
  −
            getRecordAgain.onsuccess = function() {
  −
                console.log(getRecordAgain);  // => "Bob"
  −
                if ( getRecordAgain.result[field] == value ) {
  −
                  console.log("Update succeeded");
  −
                } else {
  −
                  console.log("Update unsuccessful");
  −
                }
  −
              }; 
  −
            };
   
//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 
//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tx.oncomplete = function() {
+
    tx.oncomplete = function() {
  db.close();
+
      db.close();
};
+
    };
};
+
  };
 
};
 
};
 +
    
function recordCheck(pddbname, record){
 
function recordCheck(pddbname, record){
Line 223: Line 334:  
     var db = pddb.result;
 
     var db = pddb.result;
 
     var store = db.createObjectStore(PersonalDataDataBaseName, {keyPath: "id"});
 
     var store = db.createObjectStore(PersonalDataDataBaseName, {keyPath: "id"});
     var index = store.createIndex("NameIndex", ["name.last", "name.first"]);
+
     var index = store.createIndex("NameIndex", ["name.user"]);
 
   };
 
   };
 
   pddb.onsuccess = function() {
 
   pddb.onsuccess = function() {
Line 230: Line 341:  
     var store = tx.objectStore(PersonalDataDataBaseName);
 
     var store = tx.objectStore(PersonalDataDataBaseName);
 
     var index = store.index("NameIndex");   
 
     var index = store.index("NameIndex");   
 +
 
//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||[ Essential recordCheck ]||||||||||||||
 
//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||[ Essential recordCheck ]||||||||||||||
var recordcheck = index.get([record.name.last, record.name.first]);
+
 
recordcheck.onsuccess = function() {
+
    var recordcheck = index.get([record.name.user]);
  if ( recordcheck.result != undefined ) {
+
    recordcheck.onsuccess = function() {
  console.log(recordcheck);
+
      if ( recordcheck.result != undefined ) {
} else {
+
        console.log(recordcheck);
  console.log("...else undefined");
+
        return recordCheck;
}
+
      } else {
 +
        console.log("...else undefined");
 +
        return undefined;
 +
      };
 +
    };
 +
 
 
//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 
//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}
+
 
tx.oncomplete = function() {
+
    tx.oncomplete = function() {
  db.close();
+
      db.close();
};   
+
    };   
 +
  };
 
};
 
};
 +
 +
function recordDeleteFrom(pddbname, record,  field ){
 +
  var pddb = window.indexedDB.open(pddbname, 3);
 +
  pddb.onupgradeneeded = function() {
 +
    var db = pddb.result;
 +
    var store = db.createObjectStore(PersonalDataDataBaseName, {keyPath: "id"});
 +
    var index = store.createIndex("NameIndex", ["name.user"]);
 +
  };
 +
  pddb.onsuccess = function() {
 +
    var db = pddb.result;
 +
    var tx = db.transaction(PersonalDataDataBaseName, "readwrite");
 +
    var store = tx.objectStore(PersonalDataDataBaseName);
 +
    var index = store.index("NameIndex"); 
 +
 +
//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||[ Essential recordCheck ]||||||||||||||
 +
   
 +
    var inp_obj;
 +
    var recordcheck = index.get([record.name.user]);
 +
    recordcheck.onsuccess = function() {
 +
      if ( recordcheck.result != undefined ) {
 +
          console.log("updating");
 +
          inp_obj = recordcheck.result;
 +
          } else {
 +
          inp_obj = record;
 +
          }
 +
        delete check( inp_obj, field );  // => "Bob"
 +
        store.put(inp_obj);
 +
    }
 +
 +
//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 +
 +
    tx.oncomplete = function() {
 +
      db.close();
 +
    }; 
 +
  };
 
};
 
};
530

edits

Navigation menu