<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.personaldata.io/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Abel</id>
	<title>Wikibase Personal data - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.personaldata.io/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Abel"/>
	<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/wiki/Special:Contributions/Abel"/>
	<updated>2026-06-09T19:41:49Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.1</generator>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/WbProcessor.js&amp;diff=5458</id>
		<title>User:Abel/WbProcessor.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/WbProcessor.js&amp;diff=5458"/>
		<updated>2019-06-04T12:07:43Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// Wikibase Processor&lt;br /&gt;
console.log('wbprocessor loading');&lt;br /&gt;
&lt;br /&gt;
function WikibaseProcessorContainer(universe, location) {&lt;br /&gt;
&lt;br /&gt;
  Debug_switch = false;&lt;br /&gt;
&lt;br /&gt;
  this.main = interjson(checkdive(universe, location));&lt;br /&gt;
  var the = this.main;&lt;br /&gt;
&lt;br /&gt;
  /* The following is the main exposed function of the current Wb Processing class&lt;br /&gt;
  	usage cases&lt;br /&gt;
&lt;br /&gt;
  	to check the last value in a location given by a preceding array of internal paths to find, with the possibility of array layers between elements of array of paths: &lt;br /&gt;
  	wbproc.checkentity( [ wbEStruct['instanceOfRelations'], wbEStruct['IDPropLoc'], wbEStruct['IDName'], 96 ] );&lt;br /&gt;
&lt;br /&gt;
  	to return for example content of default value given by array of location paths, or check for existence of &lt;br /&gt;
  	wbproc.checkentity( { default_value: [ wbEStruct['defaultValRelation'], wbEStruct['IDPropLoc'] ] } )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
  this.checkentity = function(paths) {&lt;br /&gt;
    if ((the !== undefined) &amp;amp;&amp;amp; (paths !== undefined)) {&lt;br /&gt;
      return proceed(the, paths);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // Exposed general wrapper for proceed for object other than what the class is originally instanced on, currently unused&lt;br /&gt;
  // Could be used to create a further function to cross check current object with another object 'universe' with another for example&lt;br /&gt;
&lt;br /&gt;
  this.xcontains = function(unv, angle) {&lt;br /&gt;
    if ((unv !== undefined) &amp;amp;&amp;amp; (angle !== undefined)) {&lt;br /&gt;
      return proceed(unv, angle);&lt;br /&gt;
    };&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  /* Exposed helper function to get Entity object of alien entity, if ever needed */&lt;br /&gt;
&lt;br /&gt;
  this.EnqueueWB = async function(idk) {&lt;br /&gt;
    var k = await wbqueue(idk);&lt;br /&gt;
    return k;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  /* Private part of wb Entity getter */&lt;br /&gt;
&lt;br /&gt;
  async function wbqueue(id) {&lt;br /&gt;
    return new Promise(&lt;br /&gt;
      function(resolve, reject) {&lt;br /&gt;
        $.getJSON('/w/api.php?action=wbgetentities&amp;amp;format=json&amp;amp;ids=' + id, function(json) {&lt;br /&gt;
          var h = json.entities;&lt;br /&gt;
          resolve(h);&lt;br /&gt;
        })&lt;br /&gt;
      }).then(function(result) {&lt;br /&gt;
      debuglog(result);&lt;br /&gt;
      return result;&lt;br /&gt;
    });&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  // the list of private helper functions, could not be accessed from outside&lt;br /&gt;
  // helper function for descend into an object if key exists, otherwise stay at current level of object		&lt;br /&gt;
  function indexinterpolate(obj, i) {&lt;br /&gt;
    return (obj[i] !== undefined) ? obj[i] : obj&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
  // helper function for checking a part of an array exists, if it doesn't, go undefined&lt;br /&gt;
  function indexcheck(obj, i) {&lt;br /&gt;
    if (obj !== undefined) {&lt;br /&gt;
      return (obj[i] !== undefined) ? obj[i] : undefined&lt;br /&gt;
    }&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
  // dive selects matrix.a.b.c.d from the array called matrix and 'a.b.c.d' as string&lt;br /&gt;
  // 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.&lt;br /&gt;
  function dive(array, read) {&lt;br /&gt;
    if (array !== undefined) {&lt;br /&gt;
      return (read + '').split('.').reduce(indexinterpolate, array);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  // Check returns matrix.a.b.c.d from 'array' ~ 'matrix' and 'read' ~ 'a.b.c.d' only if it exists all the way, otherwise go undefined&lt;br /&gt;
  function check(array, read) {&lt;br /&gt;
    if (array !== undefined) {&lt;br /&gt;
      return (read + '').split('.').reduce(indexcheck, array);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // Main object / array processing instrument&lt;br /&gt;
  // Array can be a composition of objects and arrays &lt;br /&gt;
  // Read is the instructions, could be an array, or a single path, but for now it should be an object based on our inner convention, example:&lt;br /&gt;
  /* &lt;br /&gt;
  	relational_id_list = { &lt;br /&gt;
  		controller_id: [ wbEStructure['instanceOfRelations'], wbEStructure['IDPropLoc'], wbEStructure['IDName'], 96 ],&lt;br /&gt;
  		personal_data_id: [ wbEStructure['subclassOfRelations'], wbEStructure['IDPropLoc'], wbEStructure['IDName'], 421 ],&lt;br /&gt;
  		interface_button_id: [ wbEStructure ['instanceOfRelations'], wbEStructure['IDPropLoc'], wbEStructure['IDName'], 487 ]&lt;br /&gt;
  	} &lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
  function proceed(array, read) {&lt;br /&gt;
    var ret_obj = {},&lt;br /&gt;
      temp_obj = array,&lt;br /&gt;
&lt;br /&gt;
      // If we encounter something seriously wrong we will just raise a red flag by setting this false, will check before returning this.&lt;br /&gt;
      success_o_meter = true,&lt;br /&gt;
&lt;br /&gt;
      // If all goes well, for each path checked, we will have a member in this&lt;br /&gt;
      future_instructional_return = [];&lt;br /&gt;
&lt;br /&gt;
    //|||||||||||||||||||||||||||||||||||||||||||||||||||||[ I N S T R U C T I O N S  C O N T R O L   ]||||||||||||||||||||||||||||||||||||||||||||||||||||||&lt;br /&gt;
&lt;br /&gt;
    // Init program, check if instructions are an object (not an array but has multiple keys) :&lt;br /&gt;
    // This is the main path of the function. Could be improved to have it for simple array of instructions&lt;br /&gt;
    if ((!Array.isArray(read)) &amp;amp;&amp;amp; (Object.keys(read).length &amp;gt; 0)) {&lt;br /&gt;
&lt;br /&gt;
      Object.keys(read).forEach(function(path) {&lt;br /&gt;
        debuglog(&amp;quot;instructions are an object, in path &amp;quot; + path);&lt;br /&gt;
&lt;br /&gt;
        //||||||||||||||||||||||||||[ Check if elements of instruction object are arrays themselves ]||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||&lt;br /&gt;
&lt;br /&gt;
        if (Array.isArray(read[path])) {&lt;br /&gt;
&lt;br /&gt;
          // for each path, future_instructional_return will be filled with the future_return_partition after proceeding through that path&lt;br /&gt;
          var future_return_partition = temp_obj;&lt;br /&gt;
&lt;br /&gt;
          Object.keys(read[path]).forEach(function(path2) {&lt;br /&gt;
&lt;br /&gt;
            debuglog(&amp;quot;instructions are an array of arrays, going through &amp;quot; + read[path][path2]);&lt;br /&gt;
            // for each step, see if it led anywhere other than where we were.&lt;br /&gt;
            if (data_function(future_return_partition, read[path][path2]) != future_return_partition) {&lt;br /&gt;
              // if it did, proceed;&lt;br /&gt;
              future_return_partition = data_function(future_return_partition, read[path][path2]);&lt;br /&gt;
            } else {&lt;br /&gt;
              // if it didn, raise flag&lt;br /&gt;
              success_o_meter = false;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            //|||||||||||||||||||||||||||||||||||||||||||||||||||[   I N S T R U C T I O N S   C O N T R O L |||||||||||||||||||||||||||||||||||||||||||||||||||||||||&lt;br /&gt;
&lt;br /&gt;
          });&lt;br /&gt;
          //Now that we went through the path, lets see if everything was ok.&lt;br /&gt;
          if (success_o_meter === true) {&lt;br /&gt;
            // If yes, put the result of the travel 'future_return_partition' into 'future_instructional_return'&lt;br /&gt;
&lt;br /&gt;
            debuglog(&amp;quot;arrived at&amp;quot;)&lt;br /&gt;
            debuglog(future_return_partition);&lt;br /&gt;
            future_instructional_return[path] = future_return_partition;&lt;br /&gt;
          } else {&lt;br /&gt;
&lt;br /&gt;
            // Otherwise let's put an undefined in there&lt;br /&gt;
            debuglog(&amp;quot;seeking derailed&amp;quot;);&lt;br /&gt;
            success_o_meter = true;&lt;br /&gt;
            future_instructional_return[path] = undefined;&lt;br /&gt;
          }&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        //|||||||||||||||||| If instruction object element is not an array, lets just try to do that one step ||||||||||||||||||||||||||||||||||||||||||||||||||||||||&lt;br /&gt;
        // Unused&lt;br /&gt;
        else {&lt;br /&gt;
&lt;br /&gt;
          // INCLUDE step block with read[path] &lt;br /&gt;
          if (data_function(temp_obj, read[path]) !== temp_obj) {&lt;br /&gt;
            future_instructional_return[path] = data_function(temp_obj, read[path]);&lt;br /&gt;
          } else {&lt;br /&gt;
            // future_instructional_return.push( undefined );&lt;br /&gt;
          }&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
      });&lt;br /&gt;
&lt;br /&gt;
      // Now that we have gone through all paths, make future return object into what we got&lt;br /&gt;
      temp_obj = future_instructional_return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    //||||||||||||[ If we are not in instruction object, let's see if we have an instruction array ]||||||||||||||||||||||||||||||||||||||||||||||||||||||||||&lt;br /&gt;
    //Unused, this part could be improved&lt;br /&gt;
    else if (Array.isArray(read)) {&lt;br /&gt;
      // If so let's follow the array of instructions&lt;br /&gt;
      Object.keys(read).forEach(function(ect) {&lt;br /&gt;
        if (data_function(temp_obj, read[ect]) !== temp_obj) {&lt;br /&gt;
&lt;br /&gt;
          temp_obj = data_function(temp_obj, read[ect]);&lt;br /&gt;
&lt;br /&gt;
        } else {&lt;br /&gt;
&lt;br /&gt;
          success_o_meter = false;&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
      });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    //||||||||||||[ If we have a single instruction, let's try following that |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||&lt;br /&gt;
    //Unused, this part could be improved&lt;br /&gt;
    else {&lt;br /&gt;
&lt;br /&gt;
      if (data_function(temp_obj, read) !== temp_obj) {&lt;br /&gt;
&lt;br /&gt;
        temp_obj = data_function(temp_obj, read);&lt;br /&gt;
&lt;br /&gt;
      } else {&lt;br /&gt;
&lt;br /&gt;
        success_o_meter = false;&lt;br /&gt;
&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // If we haven't got a not found signal along the way, let's try returning the object&lt;br /&gt;
&lt;br /&gt;
    if (success_o_meter === true) {&lt;br /&gt;
      return temp_obj;&lt;br /&gt;
    } else {&lt;br /&gt;
      return undefined;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //|||||||||||||||||||||||||||||||||||||||||||||||||||||[   S T E P   B L O C K   ]||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||&lt;br /&gt;
&lt;br /&gt;
  // Function that takes 1 step. Proceed (along a path) uses this for each step.&lt;br /&gt;
&lt;br /&gt;
  function data_function(temp_obj, moving) {&lt;br /&gt;
&lt;br /&gt;
    // we will return an array&lt;br /&gt;
    var future_temp_obj = [];&lt;br /&gt;
&lt;br /&gt;
    // Check if we are on an array level, &lt;br /&gt;
    if (Array.isArray(temp_obj)) {&lt;br /&gt;
      debuglog(&amp;quot;data is on an array level&amp;quot;);&lt;br /&gt;
      Object.keys(temp_obj).forEach(function(ect) {&lt;br /&gt;
&lt;br /&gt;
        // if so, try proceeding in all directions.&lt;br /&gt;
        debuglog(&amp;quot;Within partition: &amp;quot; + ect);&lt;br /&gt;
        if (checkdive(temp_obj[ect], moving) !== undefined) {&lt;br /&gt;
          future_temp_obj.push(checkdive(temp_obj[ect], moving));&lt;br /&gt;
        }&lt;br /&gt;
        // Put an element into the return array for each direction we could move into&lt;br /&gt;
&lt;br /&gt;
      });&lt;br /&gt;
&lt;br /&gt;
      temp_obj = future_temp_obj;&lt;br /&gt;
&lt;br /&gt;
    } else {&lt;br /&gt;
&lt;br /&gt;
      // if we are not on an array level, proceed with the path&lt;br /&gt;
&lt;br /&gt;
      debuglog(&amp;quot;data is on an objective level&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
      if (checkdive(temp_obj, moving) !== temp_obj) {&lt;br /&gt;
        future_temp_obj = checkdive(temp_obj, moving);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (future_temp_obj !== undefined) {&lt;br /&gt;
        temp_obj = future_temp_obj;&lt;br /&gt;
      } else {&lt;br /&gt;
        debuglog('nothing to see here')&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // NOTE this function works now but shows syntactic variance between the else branches&lt;br /&gt;
    // Rigorous testing recommended&lt;br /&gt;
&lt;br /&gt;
    return temp_obj;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //|||||||||||||||||||||||||||||||||||||||||||||||||||||[  E N D   O F   S T E P   B L O C K    ]|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||&lt;br /&gt;
&lt;br /&gt;
  // This function substitutes a bunch of try catches and also tries to dive into 'array' in different ways&lt;br /&gt;
&lt;br /&gt;
  function checkdive(array, read) {&lt;br /&gt;
&lt;br /&gt;
    // simple case, array is an object containing property 'read'&lt;br /&gt;
&lt;br /&gt;
    if (check(array, read) !== undefined) {&lt;br /&gt;
      return dive(array, read);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // array case, 'array' is an actual array, lets return an array of successful trials to dive into each direction&lt;br /&gt;
&lt;br /&gt;
    if (Array.isArray(array)) {&lt;br /&gt;
      var potential_return = [];&lt;br /&gt;
      Object.keys(array).forEach(function(item) {&lt;br /&gt;
        if (check(array[item], read) !== undefined) {&lt;br /&gt;
          potential_return.push(dive(array[item], read));&lt;br /&gt;
        }&lt;br /&gt;
      });&lt;br /&gt;
      return potential_return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // mystical case, 'what you have been seeking you had it all along... or at least you have it now'&lt;br /&gt;
    // This is for when you already at a value level, and are looking for that value.&lt;br /&gt;
    // Or when on an object level, and looking for that object&lt;br /&gt;
    // or when on an array level, and looking for that array :O &lt;br /&gt;
&lt;br /&gt;
    if (array === read) {&lt;br /&gt;
      return read;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /* If we did this, it would probably open up a wormhole or a segfault, or that strange error message browsers give when they are maxed out&lt;br /&gt;
&lt;br /&gt;
    if (Object.keys( array ).length &amp;gt; 0 ){&lt;br /&gt;
    	Object.keys( array ).forEach( function ( piece ) {&lt;br /&gt;
    		if ( array[ piece ] === read ) { return read };&lt;br /&gt;
    	});&lt;br /&gt;
    }&lt;br /&gt;
    */&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // Try parsing json. If not a json, go void.&lt;br /&gt;
  this.rxjson = function(rx) {&lt;br /&gt;
    return interjson(rx);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function interjson(obj) {&lt;br /&gt;
    try {&lt;br /&gt;
      return JSON.parse(obj)&lt;br /&gt;
    } catch (e) {&lt;br /&gt;
      // if not JSON, do silly things&lt;br /&gt;
      debuglog('not a json ¯\_(ツ)_/¯');&lt;br /&gt;
    };&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // Heavyweight solution to suppress error messages. &lt;br /&gt;
&lt;br /&gt;
  function debuglog(l0g) {&lt;br /&gt;
    if (Debug_switch) {&lt;br /&gt;
      console.log(l0g);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5322</id>
		<title>User:Abel/PersonalData.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5322"/>
		<updated>2019-05-30T10:34:30Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// Indexeddb JavaScript &lt;br /&gt;
console.log('Indb loading');&lt;br /&gt;
&lt;br /&gt;
function IndexedDBContainer( ww	) {&lt;br /&gt;
&lt;br /&gt;
	// suppress console.log, switch to true for debug&lt;br /&gt;
	var Debug_switch = false;&lt;br /&gt;
	// seemingly the Safari engine uses a somewhat different implementation of arguments for db.transaction and index.get&lt;br /&gt;
	// because no browser on any mac / ios is allowed to use a different engine, rather than user agent, platform can be tested&lt;br /&gt;
	var iOS = !!navigator.platform &amp;amp;&amp;amp; /iPad|iPhone|iPod/.test(navigator.platform);&lt;br /&gt;
	var Safari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);&lt;br /&gt;
	debuglog(&amp;quot;iOS:&amp;quot; + iOS + &amp;quot; &amp;amp; Saf:&amp;quot; + Safari);&lt;br /&gt;
 &lt;br /&gt;
	// deterministic hash generator for creating user id#s from usernames, should be replaced by something more functional (guaranteed to be transitively different)&lt;br /&gt;
	hashCode = function(s) {&lt;br /&gt;
		if ( s == undefined) {&lt;br /&gt;
			s = '00'&lt;br /&gt;
		}&lt;br /&gt;
		var h = 0, l = s.length, i = 0;&lt;br /&gt;
		if ( l &amp;gt; 0 )&lt;br /&gt;
			while (i &amp;lt; l)&lt;br /&gt;
				h = (h &amp;lt;&amp;lt; 5) - h + s.charCodeAt(i++) | 0;&lt;br /&gt;
			return h;&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
		if ( ww.user != undefined ) {&lt;br /&gt;
// if user exists in object passed to constructor, get username		&lt;br /&gt;
			var self = ww.user.getName();&lt;br /&gt;
// create userid by hashing username&lt;br /&gt;
			var idgen = hashCode(self);																										&lt;br /&gt;
			debuglog(idgen);&lt;br /&gt;
&lt;br /&gt;
// Take username for standard databasename format:&lt;br /&gt;
// Our current convention for personal databasename (separate dbname for each user)&lt;br /&gt;
			var PersonalDataDataBaseName = &amp;quot;PD.IO&amp;quot; + idgen + &amp;quot;Database&amp;quot;;&lt;br /&gt;
			// Use username in user to get up to date version of self&lt;br /&gt;
// Blank object for personal data Record with id and username included&lt;br /&gt;
			this.CurrentPerson = {id: idgen, name: {user: self}, age: 0};&lt;br /&gt;
			debuglog(PersonalDataDataBaseName);&lt;br /&gt;
			debuglog(this.CurrentPerson);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	// ADD MORE DOC&lt;br /&gt;
&lt;br /&gt;
	// EnqueuePDIO a PDIOLocalDatabase:User database access function with modes&lt;br /&gt;
	// Externally accessible wrapper for Enquire with current user / db preloaded&lt;br /&gt;
&lt;br /&gt;
	this.EnqueuePDIO = async function( sw, c1, c2, c3 ) {&lt;br /&gt;
		debuglog(&amp;quot;enquing pdio db &amp;quot; + PersonalDataDataBaseName + &amp;quot; with user &amp;quot; + JSON.stringify(this.CurrentPerson));&lt;br /&gt;
		var k = await Enquire( PersonalDataDataBaseName, this.CurrentPerson, sw, c1, c2, c3 );&lt;br /&gt;
		return k;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Enquire, a general purpose indexeddb update function with modes&lt;br /&gt;
&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
&lt;br /&gt;
	// Mode 'get record'&lt;br /&gt;
	// updates record given as argument&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
	&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'import record' field1&lt;br /&gt;
	// retrieve record, add all fields from field1, push back&lt;br /&gt;
&lt;br /&gt;
	async function Enquire( pddbname, record, sqitch, control_1, control_2, control_3 ) {&lt;br /&gt;
		return new Promise(&lt;br /&gt;
			function(resolve, reject) {&lt;br /&gt;
&lt;br /&gt;
				var pddb = window.indexedDB.open(pddbname, 3);&lt;br /&gt;
				var inp_obj;&lt;br /&gt;
&lt;br /&gt;
				pddb.onerror = function() {  &lt;br /&gt;
				    console.log(&amp;quot;Warning: Access to IndexedDB for application has been rejected.&amp;quot;);&lt;br /&gt;
				};&lt;br /&gt;
&lt;br /&gt;
				// indexeddb internal mechanism for version tracking of schema&lt;br /&gt;
				pddb.onupgradeneeded = function() {&lt;br /&gt;
					console.log('upgrading database');&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var store = db.createObjectStore(pddbname, {keyPath: &amp;quot;id&amp;quot;});&lt;br /&gt;
					var index = store.createIndex(&amp;quot;NameIndex&amp;quot;, [&amp;quot;id&amp;quot;]);&lt;br /&gt;
						&lt;br /&gt;
				};&lt;br /&gt;
				// Database successfully opened function.&lt;br /&gt;
				pddb.onsuccess = function() {&lt;br /&gt;
					debuglog(pddb.result);&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var tx;&lt;br /&gt;
				&lt;br /&gt;
					if ( iOS || Safari ) {&lt;br /&gt;
						tx = db.transaction([pddbname], &amp;quot;readwrite&amp;quot;);&lt;br /&gt;
					} else {&lt;br /&gt;
						tx = db.transaction(pddbname, &amp;quot;readwrite&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
				&lt;br /&gt;
					var store = tx.objectStore(pddbname);&lt;br /&gt;
					var index = store.index(&amp;quot;NameIndex&amp;quot;);	&lt;br /&gt;
&lt;br /&gt;
					// Get the original record from the db...&lt;br /&gt;
					var getRecord;&lt;br /&gt;
					if ( iOS || Safari ) {&lt;br /&gt;
					 	getRecord = index.get(record.id);&lt;br /&gt;
					} else {&lt;br /&gt;
						getRecord = index.get([record.id]);&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					getRecord.onsuccess = function() {&lt;br /&gt;
							debuglog( &amp;quot;Record in database: \n &amp;lt;&amp;lt;&amp;quot;);&lt;br /&gt;
							debuglog( getRecord.result );&lt;br /&gt;
							debuglog( &amp;quot;&amp;gt;&amp;gt;&amp;quot;);&lt;br /&gt;
						// Essential recordAdd																													&lt;br /&gt;
						if ( sqitch === &amp;quot;aggressive push&amp;quot; ) {&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
							inp_obj = record;&lt;br /&gt;
							store.put( inp_obj );&lt;br /&gt;
							return inp_obj;&lt;br /&gt;
						} else if ( sqitch === &amp;quot;checkin&amp;quot; ) {&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
							if ( getRecord.result != undefined ) {&lt;br /&gt;
								debuglog(&amp;quot;getting from store&amp;quot;);&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
							} else {&lt;br /&gt;
								debuglog(&amp;quot;overriding whatever in there&amp;quot;);&lt;br /&gt;
								inp_obj = record;&lt;br /&gt;
								store.put(inp_obj);&lt;br /&gt;
							}&lt;br /&gt;
&lt;br /&gt;
						} else {&lt;br /&gt;
	// Methods manipulationg the actual record come here&lt;br /&gt;
	// Update &amp;amp; Remove from&lt;br /&gt;
							// If we got the record from store, use that version to be manipulated&lt;br /&gt;
							if ( getRecord.result !== undefined ) {		&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
								&lt;br /&gt;
								if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
									&lt;br /&gt;
									debuglog(&amp;quot;Getting record&amp;quot;);&lt;br /&gt;
									// we will return later&lt;br /&gt;
									&lt;br /&gt;
								} &lt;br /&gt;
&lt;br /&gt;
								// endof onsuccess&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								debuglog(&amp;quot;Record not found&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
								if ( sqitch === &amp;quot;update record&amp;quot; ) {&lt;br /&gt;
									// Update record will use supplied copy to update it&lt;br /&gt;
									inp_obj = record;&lt;br /&gt;
								} else {&lt;br /&gt;
									if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
										inp_obj = undefined;&lt;br /&gt;
									} else if ( sqitch === &amp;quot;remove from record&amp;quot; ) {&lt;br /&gt;
										inp_obj = record;&lt;br /&gt;
									} else {&lt;br /&gt;
										// any other method ...... would quit as record was not even foun&lt;br /&gt;
										return undefined;&lt;br /&gt;
									}&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
						} &lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;update record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
									if ( control_3 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
										if ( inp_obj[ control_1 ] == undefined ) { inp_obj[ control_1 ] = (isNaN( control_2 )) ? {} : [] };&lt;br /&gt;
										inp_obj[ control_1 ][ control_2 ] = control_3;	// =&amp;gt; &amp;quot;Bob&amp;quot;&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
									} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
										inp_obj[ control_1 ] = inp_obj[ control_1 ] || {};&lt;br /&gt;
										if ( Array.isArray( inp_obj[ control_1 ] ) ) {&lt;br /&gt;
											inp_obj[ control_1 ].push( control_2 );&lt;br /&gt;
										} else {&lt;br /&gt;
											inp_obj[ control_1 ] = control_2;&lt;br /&gt;
										}&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
&lt;br /&gt;
									}&lt;br /&gt;
								} else {&lt;br /&gt;
									// Only one control defined. We will return that part of the record, and change nothing&lt;br /&gt;
									inp_obj = inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								// There's not even control_1, we will just return the record itself&lt;br /&gt;
&lt;br /&gt;
							}&lt;br /&gt;
							debuglog(&amp;quot;return 3&amp;quot;)&lt;br /&gt;
							// return inp_obj;&lt;br /&gt;
&lt;br /&gt;
						};&lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;remove from record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
									&lt;br /&gt;
									if ( Array.isArray( inp_obj[ control_1 ] ) &amp;amp;&amp;amp; !isNaN( control_2 ) ) {&lt;br /&gt;
										inp_obj[ control_1 ].splice( control_2, 1 );&lt;br /&gt;
									} else {&lt;br /&gt;
										delete inp_obj[ control_1 ][ control_2 ];&lt;br /&gt;
									}&lt;br /&gt;
&lt;br /&gt;
								} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
&lt;br /&gt;
									delete inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
							debuglog(&amp;quot;putting object to store:&amp;quot;);&lt;br /&gt;
							debuglog(inp_obj);&lt;br /&gt;
							store.put(inp_obj);&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;import record&amp;quot; ) {&lt;br /&gt;
							debuglog(&amp;quot;import command&amp;quot;);&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								// Only import if control_1 is a non-empty object&lt;br /&gt;
								if ( ( !Array.isArray(control_1) ) &amp;amp;&amp;amp; ( Object.keys(control_1).length &amp;gt; 0 ) ) {&lt;br /&gt;
									debuglog(&amp;quot;command is obj&amp;quot;);&lt;br /&gt;
									 Object.keys(control_1).forEach( function( importkey ){&lt;br /&gt;
									 		debuglog(&amp;quot;importing &amp;quot; + importkey );&lt;br /&gt;
								 	        if (control_1.hasOwnProperty(importkey)) { inp_obj[importkey] = control_1[importkey] };&lt;br /&gt;
									 })&lt;br /&gt;
								store.put(inp_obj);&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
	// We are past all methodic code, Async return						&lt;br /&gt;
	&lt;br /&gt;
						resolve( inp_obj );&lt;br /&gt;
&lt;br /&gt;
					};&lt;br /&gt;
	&lt;br /&gt;
	// Indexeddb internal mechanism, close db&lt;br /&gt;
	&lt;br /&gt;
					tx.oncomplete = function() {&lt;br /&gt;
						debuglog(&amp;quot;return 1&amp;quot;)&lt;br /&gt;
						db.close();&lt;br /&gt;
					};&lt;br /&gt;
				};&lt;br /&gt;
				debuglog(&amp;quot;return 0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
	// End of promise&lt;br /&gt;
	&lt;br /&gt;
			}).then( function(result) {&lt;br /&gt;
				debuglog(&amp;quot;Mark 3&amp;quot;);&lt;br /&gt;
				debuglog(result);&lt;br /&gt;
				return result;&lt;br /&gt;
			});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function debuglog( l0g ){&lt;br /&gt;
		if ( Debug_switch ) {&lt;br /&gt;
			console.log( l0g );&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
};&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5321</id>
		<title>User:Abel/PersonalData.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5321"/>
		<updated>2019-05-30T09:12:33Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// Indexeddb JavaScript &lt;br /&gt;
console.log('Indb loading');&lt;br /&gt;
&lt;br /&gt;
function IndexedDBContainer( ww	) {&lt;br /&gt;
&lt;br /&gt;
	// suppress console.log, switch to true for debug&lt;br /&gt;
	var Debug_switch = true;&lt;br /&gt;
	// seemingly the Safari engine uses a somewhat different implementation of arguments for db.transaction and index.get&lt;br /&gt;
	// because no browser on any mac / ios is allowed to use a different engine, rather than user agent, platform can be tested&lt;br /&gt;
	var iOS = !!navigator.platform &amp;amp;&amp;amp; /iPad|iPhone|iPod/.test(navigator.platform);&lt;br /&gt;
	var Safari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);&lt;br /&gt;
	debuglog(&amp;quot;iOS:&amp;quot; + iOS + &amp;quot; &amp;amp; Saf:&amp;quot; + Safari);&lt;br /&gt;
 &lt;br /&gt;
	// deterministic hash generator for creating user id#s from usernames, should be replaced by something more functional (guaranteed to be transitively different)&lt;br /&gt;
	hashCode = function(s) {&lt;br /&gt;
		if ( s == undefined) {&lt;br /&gt;
			s = '00'&lt;br /&gt;
		}&lt;br /&gt;
		var h = 0, l = s.length, i = 0;&lt;br /&gt;
		if ( l &amp;gt; 0 )&lt;br /&gt;
			while (i &amp;lt; l)&lt;br /&gt;
				h = (h &amp;lt;&amp;lt; 5) - h + s.charCodeAt(i++) | 0;&lt;br /&gt;
			return h;&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
		if ( ww.user != undefined ) {&lt;br /&gt;
// if user exists in object passed to constructor, get username		&lt;br /&gt;
			var self = ww.user.getName();&lt;br /&gt;
// create userid by hashing username&lt;br /&gt;
			var idgen = hashCode(self);																										&lt;br /&gt;
			debuglog(idgen);&lt;br /&gt;
&lt;br /&gt;
// Take username for standard databasename format:&lt;br /&gt;
// Our current convention for personal databasename (separate dbname for each user)&lt;br /&gt;
			var PersonalDataDataBaseName = &amp;quot;PD.IO&amp;quot; + idgen + &amp;quot;Database&amp;quot;;&lt;br /&gt;
			// Use username in user to get up to date version of self&lt;br /&gt;
// Blank object for personal data Record with id and username included&lt;br /&gt;
			this.CurrentPerson = {id: idgen, name: {user: self}, age: 0};&lt;br /&gt;
			debuglog(PersonalDataDataBaseName);&lt;br /&gt;
			debuglog(this.CurrentPerson);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	// ADD MORE DOC&lt;br /&gt;
&lt;br /&gt;
	// EnqueuePDIO a PDIOLocalDatabase:User database access function with modes&lt;br /&gt;
	// Externally accessible wrapper for Enquire with current user / db preloaded&lt;br /&gt;
&lt;br /&gt;
	this.EnqueuePDIO = async function( sw, c1, c2, c3 ) {&lt;br /&gt;
		debuglog(&amp;quot;enquing pdio db &amp;quot; + PersonalDataDataBaseName + &amp;quot; with user &amp;quot; + JSON.stringify(this.CurrentPerson));&lt;br /&gt;
		var k = await Enquire( PersonalDataDataBaseName, this.CurrentPerson, sw, c1, c2, c3 );&lt;br /&gt;
		return k;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Enquire, a general purpose indexeddb update function with modes&lt;br /&gt;
&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
&lt;br /&gt;
	// Mode 'get record'&lt;br /&gt;
	// updates record given as argument&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
	&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'import record' field1&lt;br /&gt;
	// retrieve record, add all fields from field1, push back&lt;br /&gt;
&lt;br /&gt;
	async function Enquire( pddbname, record, sqitch, control_1, control_2, control_3 ) {&lt;br /&gt;
		return new Promise(&lt;br /&gt;
			function(resolve, reject) {&lt;br /&gt;
&lt;br /&gt;
				var pddb = window.indexedDB.open(pddbname, 3);&lt;br /&gt;
				var inp_obj;&lt;br /&gt;
&lt;br /&gt;
				pddb.onerror = function() {  &lt;br /&gt;
				    console.log(&amp;quot;Warning: Access to IndexedDB for application has been rejected.&amp;quot;);&lt;br /&gt;
				};&lt;br /&gt;
&lt;br /&gt;
				// indexeddb internal mechanism for version tracking of schema&lt;br /&gt;
				pddb.onupgradeneeded = function() {&lt;br /&gt;
					console.log('upgrading database');&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var store = db.createObjectStore(pddbname, {keyPath: &amp;quot;id&amp;quot;});&lt;br /&gt;
					var index = store.createIndex(&amp;quot;NameIndex&amp;quot;, [&amp;quot;id&amp;quot;]);&lt;br /&gt;
						&lt;br /&gt;
				};&lt;br /&gt;
				// Database successfully opened function.&lt;br /&gt;
				pddb.onsuccess = function() {&lt;br /&gt;
					debuglog(pddb.result);&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var tx;&lt;br /&gt;
				&lt;br /&gt;
					if ( iOS || Safari ) {&lt;br /&gt;
						tx = db.transaction([pddbname], &amp;quot;readwrite&amp;quot;);&lt;br /&gt;
					} else {&lt;br /&gt;
						tx = db.transaction(pddbname, &amp;quot;readwrite&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
				&lt;br /&gt;
					var store = tx.objectStore(pddbname);&lt;br /&gt;
					var index = store.index(&amp;quot;NameIndex&amp;quot;);	&lt;br /&gt;
&lt;br /&gt;
					// Get the original record from the db...&lt;br /&gt;
					var getRecord;&lt;br /&gt;
					if ( iOS || Safari ) {&lt;br /&gt;
					 	getRecord = index.get(record.id);&lt;br /&gt;
					} else {&lt;br /&gt;
						getRecord = index.get([record.id]);&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					getRecord.onsuccess = function() {&lt;br /&gt;
							debuglog( &amp;quot;Record in database: \n &amp;lt;&amp;lt;&amp;quot;);&lt;br /&gt;
							debuglog( getRecord.result );&lt;br /&gt;
							debuglog( &amp;quot;&amp;gt;&amp;gt;&amp;quot;);&lt;br /&gt;
						// Essential recordAdd																													&lt;br /&gt;
						if ( sqitch === &amp;quot;aggressive push&amp;quot; ) {&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
							inp_obj = record;&lt;br /&gt;
							store.put( inp_obj );&lt;br /&gt;
							return inp_obj;&lt;br /&gt;
						} else if ( sqitch === &amp;quot;checkin&amp;quot; ) {&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
							if ( getRecord.result != undefined ) {&lt;br /&gt;
								debuglog(&amp;quot;getting from store&amp;quot;);&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
							} else {&lt;br /&gt;
								debuglog(&amp;quot;overriding whatever in there&amp;quot;);&lt;br /&gt;
								inp_obj = record;&lt;br /&gt;
								store.put(inp_obj);&lt;br /&gt;
							}&lt;br /&gt;
&lt;br /&gt;
						} else {&lt;br /&gt;
	// Methods manipulationg the actual record come here&lt;br /&gt;
	// Update &amp;amp; Remove from&lt;br /&gt;
							// If we got the record from store, use that version to be manipulated&lt;br /&gt;
							if ( getRecord.result !== undefined ) {		&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
								&lt;br /&gt;
								if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
									&lt;br /&gt;
									debuglog(&amp;quot;Getting record&amp;quot;);&lt;br /&gt;
									// we will return later&lt;br /&gt;
									&lt;br /&gt;
								} &lt;br /&gt;
&lt;br /&gt;
								// endof onsuccess&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								debuglog(&amp;quot;Record not found&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
								if ( sqitch === &amp;quot;update record&amp;quot; ) {&lt;br /&gt;
									// Update record will use supplied copy to update it&lt;br /&gt;
									inp_obj = record;&lt;br /&gt;
								} else {&lt;br /&gt;
									if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
										inp_obj = undefined;&lt;br /&gt;
									} else if ( sqitch === &amp;quot;remove from record&amp;quot; ) {&lt;br /&gt;
										inp_obj = record;&lt;br /&gt;
									} else {&lt;br /&gt;
										// any other method ...... would quit as record was not even foun&lt;br /&gt;
										return undefined;&lt;br /&gt;
									}&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
						} &lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;update record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
									if ( control_3 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
										if ( inp_obj[ control_1 ] == undefined ) { inp_obj[ control_1 ] = (isNaN( control_2 )) ? {} : [] };&lt;br /&gt;
										inp_obj[ control_1 ][ control_2 ] = control_3;	// =&amp;gt; &amp;quot;Bob&amp;quot;&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
									} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
										inp_obj[ control_1 ] = inp_obj[ control_1 ] || {};&lt;br /&gt;
										if ( Array.isArray( inp_obj[ control_1 ] ) ) {&lt;br /&gt;
											inp_obj[ control_1 ].push( control_2 );&lt;br /&gt;
										} else {&lt;br /&gt;
											inp_obj[ control_1 ] = control_2;&lt;br /&gt;
										}&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
&lt;br /&gt;
									}&lt;br /&gt;
								} else {&lt;br /&gt;
									// Only one control defined. We will return that part of the record, and change nothing&lt;br /&gt;
									inp_obj = inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								// There's not even control_1, we will just return the record itself&lt;br /&gt;
&lt;br /&gt;
							}&lt;br /&gt;
							debuglog(&amp;quot;return 3&amp;quot;)&lt;br /&gt;
							// return inp_obj;&lt;br /&gt;
&lt;br /&gt;
						};&lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;remove from record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
									&lt;br /&gt;
									if ( Array.isArray( inp_obj[ control_1 ] ) &amp;amp;&amp;amp; !isNaN( control_2 ) ) {&lt;br /&gt;
										inp_obj[ control_1 ].splice( control_2, 1 );&lt;br /&gt;
									} else {&lt;br /&gt;
										delete inp_obj[ control_1 ][ control_2 ];&lt;br /&gt;
									}&lt;br /&gt;
&lt;br /&gt;
								} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
&lt;br /&gt;
									delete inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
							debuglog(&amp;quot;putting object to store:&amp;quot;);&lt;br /&gt;
							debuglog(inp_obj);&lt;br /&gt;
							store.put(inp_obj);&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;import record&amp;quot; ) {&lt;br /&gt;
							debuglog(&amp;quot;import command&amp;quot;);&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								// Only import if control_1 is a non-empty object&lt;br /&gt;
								if ( ( !Array.isArray(control_1) ) &amp;amp;&amp;amp; ( Object.keys(control_1).length &amp;gt; 0 ) ) {&lt;br /&gt;
									debuglog(&amp;quot;command is obj&amp;quot;);&lt;br /&gt;
									 Object.keys(control_1).forEach( function( importkey ){&lt;br /&gt;
									 		debuglog(&amp;quot;importing &amp;quot; + importkey );&lt;br /&gt;
								 	        if (control_1.hasOwnProperty(importkey)) { inp_obj[importkey] = control_1[importkey] };&lt;br /&gt;
									 })&lt;br /&gt;
								store.put(inp_obj);&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
	// We are past all methodic code, Async return						&lt;br /&gt;
	&lt;br /&gt;
						resolve( inp_obj );&lt;br /&gt;
&lt;br /&gt;
					};&lt;br /&gt;
	&lt;br /&gt;
	// Indexeddb internal mechanism, close db&lt;br /&gt;
	&lt;br /&gt;
					tx.oncomplete = function() {&lt;br /&gt;
						debuglog(&amp;quot;return 1&amp;quot;)&lt;br /&gt;
						db.close();&lt;br /&gt;
					};&lt;br /&gt;
				};&lt;br /&gt;
				debuglog(&amp;quot;return 0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
	// End of promise&lt;br /&gt;
	&lt;br /&gt;
			}).then( function(result) {&lt;br /&gt;
				debuglog(&amp;quot;Mark 3&amp;quot;);&lt;br /&gt;
				debuglog(result);&lt;br /&gt;
				return result;&lt;br /&gt;
			});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function debuglog( l0g ){&lt;br /&gt;
		if ( Debug_switch ) {&lt;br /&gt;
			console.log( l0g );&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
};&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=MediaWiki:Development_of_SAR_service&amp;diff=5305</id>
		<title>MediaWiki:Development of SAR service</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=MediaWiki:Development_of_SAR_service&amp;diff=5305"/>
		<updated>2019-05-27T19:21:16Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= General information =&lt;br /&gt;
&lt;br /&gt;
* Contractor: [[User:Abel]]&lt;br /&gt;
* Reference: [[architecture of SAR service]]&lt;br /&gt;
* [https://docs.google.com/spreadsheets/d/1J-JxoldE10mKDJNilnE84Wb7ylMZ-B2ArxRiWzYXRz0/edit#gid=0 Logged hours] (request access)&lt;br /&gt;
&lt;br /&gt;
= General instructions =&lt;br /&gt;
* Read and constantly document [[architecture of SAR service]]&lt;br /&gt;
* Always document extensively (comments in code, for instance)&lt;br /&gt;
* Make sure you watch pages that are relevant (star)&lt;br /&gt;
* Be mindful of [https://www.mediawiki.org/wiki/Manual:Coding_conventions/JavaScript Javascript conventions] (within reason)&lt;br /&gt;
* '''Whenever using property or item numbers in code, define a new variable early in the code with that &amp;lt;name&amp;gt;_id locally, for example &amp;quot;controller_item_id = 96&amp;quot; (see {{Q|96}})'''  (this makes the code produced less dependent on which Wikibase instance we are using, as the numbers will change)&lt;br /&gt;
&lt;br /&gt;
= Blockers = &lt;br /&gt;
* Mailto url limits (mainly affected chrome on Windows), see [[How to send emails]]&lt;br /&gt;
&lt;br /&gt;
= Removed blockers = &lt;br /&gt;
* (solved) [https://www.mediawiki.org/wiki/Manual:$wgAllowUserJs user JS] not currently activated on wiki.personaldata.io (but this system can be tested on Wikidata)&lt;br /&gt;
&lt;br /&gt;
= To do =&lt;br /&gt;
The goal is to streamline the SAR process. There are many ways this could be made easier. If one looks at the generated requests, they miss some of the information, particularly identifiers for the individual requesting the data. We want to enable filling some data (like name or telephone number) only once, and then be able to make multiple requests. One way to do this is by using LocalStorage, but which data attributes to collect and where should be stored in the database itself. &lt;br /&gt;
&lt;br /&gt;
Specific instructions:&lt;br /&gt;
* Create a [[SAR tool testing page]], with a OOUI button tied to the mailto, generated through a new [[Template:ButtonMailtoAccess]]. &lt;br /&gt;
* Modify the SAR user script [[MediaWiki:Access.js]] so that this button appears instead.&lt;br /&gt;
* (needs clarification:) Above this button, add an OOUI entry field for first name and last name, dynamically affecting what is launched when clicking the button. If nothing is entered, have some code making explicit what should be entered. &lt;br /&gt;
* (needs clarification:) Starting a separate stream of work, at the top of {{Q|119}} (or rather all &amp;quot;instance of&amp;quot; &amp;quot;personal attribute&amp;quot;), add an entry field to store the phone number --or that attribute-- locally (using [https://www.mediawiki.org/wiki/ResourceLoader/Core_modules#mediawiki.storage LocalStorage])&lt;br /&gt;
* Implement an [[MediaWiki:InterfaceButton.js]] script, displaying a button based on data contained in an item (for instance: {{Q|488}}), and interacting with client-side storage (data stored in a key given by &amp;quot;concerns&amp;quot; field)&lt;br /&gt;
* Based on selector on &amp;quot;instance of&amp;quot; &amp;quot;interface button&amp;quot;, implemented in [[MediaWiki:Common.js]], make this button appear at the top of the &amp;quot;interface button&amp;quot; pages (by reusing [[MediaWiki:InterfaceButton.js]] of course).&lt;br /&gt;
&lt;br /&gt;
= Done =&lt;br /&gt;
* Modify the [[MediaWiki:Access.js]] code to follow the conventions above. &lt;br /&gt;
* Make sure the SAR popup only shows up selectively, for those items that are &amp;quot;instance of&amp;quot; &amp;quot;data controller&amp;quot; (here: [http://wiki.personaldata.io/wiki/Property:P3 P3]--{{Q|96}})&lt;br /&gt;
* Have a look at [https://www.mediawiki.org/wiki/OOUI OOUI]&lt;br /&gt;
&lt;br /&gt;
= To be tested = &lt;br /&gt;
* On any page on &amp;quot;instance of&amp;quot; &amp;quot;interface button&amp;quot; ( e.g. [http://wiki.personaldata.io/wiki/Item:Q488 Telephone number interface button] ) , test whether the save function to localstorage works ( whether input data persists after page reload / browser restart ). Cross platform/browser compatibility should include Firefox, Chrome under Android, Firefox, Chrome under Windows 10, Safari, Firefox, Chrome under MacOS and as well as under iOS.&lt;br /&gt;
* Cross browser transfer of data should be available on page [[Item:Q102]] ( or any instance of data controller as of current setup ). Current import mechanism will overwrite original data with the imported where they overlap, hopefully leave other original data intact&lt;br /&gt;
* Script files to be revised:&lt;br /&gt;
** [[ User:Abel/experimental.js ]] Main thread creating instances of:&lt;br /&gt;
** [[ User:Abel/WbProcessor.js ]] Wikibase Entity Checker and Retriever&lt;br /&gt;
** [[ User:Abel/PersonalData.js ]] Indexed Database Queueryer Facility&lt;br /&gt;
** [[ User:Abel/OOInterface.js ]] Interfacing UI elements with IDXB functions&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=MediaWiki:Development_of_SAR_service&amp;diff=5304</id>
		<title>MediaWiki:Development of SAR service</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=MediaWiki:Development_of_SAR_service&amp;diff=5304"/>
		<updated>2019-05-27T18:39:45Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= General information =&lt;br /&gt;
&lt;br /&gt;
* Contractor: [[User:Abel]]&lt;br /&gt;
* Reference: [[architecture of SAR service]]&lt;br /&gt;
* [https://docs.google.com/spreadsheets/d/1J-JxoldE10mKDJNilnE84Wb7ylMZ-B2ArxRiWzYXRz0/edit#gid=0 Logged hours] (request access)&lt;br /&gt;
&lt;br /&gt;
= General instructions =&lt;br /&gt;
* Read and constantly document [[architecture of SAR service]]&lt;br /&gt;
* Always document extensively (comments in code, for instance)&lt;br /&gt;
* Make sure you watch pages that are relevant (star)&lt;br /&gt;
* Be mindful of [https://www.mediawiki.org/wiki/Manual:Coding_conventions/JavaScript Javascript conventions] (within reason)&lt;br /&gt;
* '''Whenever using property or item numbers in code, define a new variable early in the code with that &amp;lt;name&amp;gt;_id locally, for example &amp;quot;controller_item_id = 96&amp;quot; (see {{Q|96}})'''  (this makes the code produced less dependent on which Wikibase instance we are using, as the numbers will change)&lt;br /&gt;
&lt;br /&gt;
= Blockers = &lt;br /&gt;
* Mailto url limits (mainly affected chrome on Windows), see [[How to send emails]]&lt;br /&gt;
&lt;br /&gt;
= Removed blockers = &lt;br /&gt;
* (solved) [https://www.mediawiki.org/wiki/Manual:$wgAllowUserJs user JS] not currently activated on wiki.personaldata.io (but this system can be tested on Wikidata)&lt;br /&gt;
&lt;br /&gt;
= To do =&lt;br /&gt;
The goal is to streamline the SAR process. There are many ways this could be made easier. If one looks at the generated requests, they miss some of the information, particularly identifiers for the individual requesting the data. We want to enable filling some data (like name or telephone number) only once, and then be able to make multiple requests. One way to do this is by using LocalStorage, but which data attributes to collect and where should be stored in the database itself. &lt;br /&gt;
&lt;br /&gt;
Specific instructions:&lt;br /&gt;
* Create a [[SAR tool testing page]], with a OOUI button tied to the mailto, generated through a new [[Template:ButtonMailtoAccess]]. &lt;br /&gt;
* Modify the SAR user script [[MediaWiki:Access.js]] so that this button appears instead.&lt;br /&gt;
* (needs clarification:) Above this button, add an OOUI entry field for first name and last name, dynamically affecting what is launched when clicking the button. If nothing is entered, have some code making explicit what should be entered. &lt;br /&gt;
* (needs clarification:) Starting a separate stream of work, at the top of {{Q|119}} (or rather all &amp;quot;instance of&amp;quot; &amp;quot;personal attribute&amp;quot;), add an entry field to store the phone number --or that attribute-- locally (using [https://www.mediawiki.org/wiki/ResourceLoader/Core_modules#mediawiki.storage LocalStorage])&lt;br /&gt;
* Implement an [[MediaWiki:InterfaceButton.js]] script, displaying a button based on data contained in an item (for instance: {{Q|488}}), and interacting with client-side storage (data stored in a key given by &amp;quot;concerns&amp;quot; field)&lt;br /&gt;
* Based on selector on &amp;quot;instance of&amp;quot; &amp;quot;interface button&amp;quot;, implemented in [[MediaWiki:Common.js]], make this button appear at the top of the &amp;quot;interface button&amp;quot; pages (by reusing [[MediaWiki:InterfaceButton.js]] of course).&lt;br /&gt;
&lt;br /&gt;
= Done =&lt;br /&gt;
* Modify the [[MediaWiki:Access.js]] code to follow the conventions above. &lt;br /&gt;
* Make sure the SAR popup only shows up selectively, for those items that are &amp;quot;instance of&amp;quot; &amp;quot;data controller&amp;quot; (here: [http://wiki.personaldata.io/wiki/Property:P3 P3]--{{Q|96}})&lt;br /&gt;
* Have a look at [https://www.mediawiki.org/wiki/OOUI OOUI]&lt;br /&gt;
&lt;br /&gt;
= To be tested = &lt;br /&gt;
* On any page on &amp;quot;instance of&amp;quot; &amp;quot;interface button&amp;quot; ( e.g. [[Item:Q488]] ) , test whether the save function to localstorage works ( whether input data persists after page reload / browser restart ). Cross platform/browser compatibility should include Firefox, Chrome under Android, Firefox, Chrome under Windows 10, Safari, Firefox, Chrome under MacOS and as well as under iOS.&lt;br /&gt;
* Cross browser transfer of data should be available on page [[Item:Q102]] ( or any instance of data controller as of current setup ). Current import mechanism will overwrite original data with the imported where they overlap, hopefully leave other original data intact&lt;br /&gt;
* Script files to be revised:&lt;br /&gt;
** [[ User:Abel/experimental.js ]] Main thread creating instances of:&lt;br /&gt;
** [[ User:Abel/WbProcessor.js ]] Wikibase Entity Checker and Retriever&lt;br /&gt;
** [[ User:Abel/PersonalData.js ]] Indexed Database Queueryer Facility&lt;br /&gt;
** [[ User:Abel/OOInterface.js ]] Interfacing UI elements with IDXB functions&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=MediaWiki:Development_of_SAR_service&amp;diff=5303</id>
		<title>MediaWiki:Development of SAR service</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=MediaWiki:Development_of_SAR_service&amp;diff=5303"/>
		<updated>2019-05-27T18:39:23Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= General information =&lt;br /&gt;
&lt;br /&gt;
* Contractor: [[User:Abel]]&lt;br /&gt;
* Reference: [[architecture of SAR service]]&lt;br /&gt;
* [https://docs.google.com/spreadsheets/d/1J-JxoldE10mKDJNilnE84Wb7ylMZ-B2ArxRiWzYXRz0/edit#gid=0 Logged hours] (request access)&lt;br /&gt;
&lt;br /&gt;
= General instructions =&lt;br /&gt;
* Read and constantly document [[architecture of SAR service]]&lt;br /&gt;
* Always document extensively (comments in code, for instance)&lt;br /&gt;
* Make sure you watch pages that are relevant (star)&lt;br /&gt;
* Be mindful of [https://www.mediawiki.org/wiki/Manual:Coding_conventions/JavaScript Javascript conventions] (within reason)&lt;br /&gt;
* '''Whenever using property or item numbers in code, define a new variable early in the code with that &amp;lt;name&amp;gt;_id locally, for example &amp;quot;controller_item_id = 96&amp;quot; (see {{Q|96}})'''  (this makes the code produced less dependent on which Wikibase instance we are using, as the numbers will change)&lt;br /&gt;
&lt;br /&gt;
= Blockers = &lt;br /&gt;
* Mailto url limits (mainly affected chrome on Windows), see [[How to send emails]]&lt;br /&gt;
&lt;br /&gt;
= Removed blockers = &lt;br /&gt;
* (solved) [https://www.mediawiki.org/wiki/Manual:$wgAllowUserJs user JS] not currently activated on wiki.personaldata.io (but this system can be tested on Wikidata)&lt;br /&gt;
&lt;br /&gt;
= To do =&lt;br /&gt;
The goal is to streamline the SAR process. There are many ways this could be made easier. If one looks at the generated requests, they miss some of the information, particularly identifiers for the individual requesting the data. We want to enable filling some data (like name or telephone number) only once, and then be able to make multiple requests. One way to do this is by using LocalStorage, but which data attributes to collect and where should be stored in the database itself. &lt;br /&gt;
&lt;br /&gt;
Specific instructions:&lt;br /&gt;
* Create a [[SAR tool testing page]], with a OOUI button tied to the mailto, generated through a new [[Template:ButtonMailtoAccess]]. &lt;br /&gt;
* Modify the SAR user script [[MediaWiki:Access.js]] so that this button appears instead.&lt;br /&gt;
* (needs clarification:) Above this button, add an OOUI entry field for first name and last name, dynamically affecting what is launched when clicking the button. If nothing is entered, have some code making explicit what should be entered. &lt;br /&gt;
* (needs clarification:) Starting a separate stream of work, at the top of {{Q|119}} (or rather all &amp;quot;instance of&amp;quot; &amp;quot;personal attribute&amp;quot;), add an entry field to store the phone number --or that attribute-- locally (using [https://www.mediawiki.org/wiki/ResourceLoader/Core_modules#mediawiki.storage LocalStorage])&lt;br /&gt;
* Implement an [[MediaWiki:InterfaceButton.js]] script, displaying a button based on data contained in an item (for instance: {{Q|488}}), and interacting with client-side storage (data stored in a key given by &amp;quot;concerns&amp;quot; field)&lt;br /&gt;
* Based on selector on &amp;quot;instance of&amp;quot; &amp;quot;interface button&amp;quot;, implemented in [[MediaWiki:Common.js]], make this button appear at the top of the &amp;quot;interface button&amp;quot; pages (by reusing [[MediaWiki:InterfaceButton.js]] of course).&lt;br /&gt;
&lt;br /&gt;
= Done =&lt;br /&gt;
* Modify the [[MediaWiki:Access.js]] code to follow the conventions above. &lt;br /&gt;
* Make sure the SAR popup only shows up selectively, for those items that are &amp;quot;instance of&amp;quot; &amp;quot;data controller&amp;quot; (here: [http://wiki.personaldata.io/wiki/Property:P3 P3]--{{Q|96}})&lt;br /&gt;
* Have a look at [https://www.mediawiki.org/wiki/OOUI OOUI]&lt;br /&gt;
&lt;br /&gt;
= To be tested = &lt;br /&gt;
* On any page on &amp;quot;instance of&amp;quot; &amp;quot;interface button&amp;quot; ( e.g. [[Item:Q488]] ) , test whether the save function to localstorage works ( whether input data persists after page reload / browser restart ). Cross platform/browser compatibility should include Firefox, Chrome under Android, Firefox, Chrome under Windows 10, Safari, Firefox, Chrome under MacOS and as well as under iOS.&lt;br /&gt;
* Cross browser transfer of data should be available on page [[Item:Q102]] ( or any instance of data controller as of current setup ). Current import mechanism will overwrite original data with the imported where they overlap, hopefully leave other original data intact&lt;br /&gt;
* Script files to be revised:&lt;br /&gt;
** [[ User:Abel/Experimental.js ]] Main thread creating instances of:&lt;br /&gt;
** [[ User:Abel/WbProcessor.js ]] Wikibase Entity Checker and Retriever&lt;br /&gt;
** [[ User:Abel/PersonalData.js ]] Indexed Database Queueryer Facility&lt;br /&gt;
** [[ User:Abel/OOInterface.js ]] Interfacing UI elements with IDXB functions&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=MediaWiki:Development_of_SAR_service&amp;diff=5302</id>
		<title>MediaWiki:Development of SAR service</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=MediaWiki:Development_of_SAR_service&amp;diff=5302"/>
		<updated>2019-05-27T18:25:00Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= General information =&lt;br /&gt;
&lt;br /&gt;
* Contractor: [[User:Abel]]&lt;br /&gt;
* Reference: [[architecture of SAR service]]&lt;br /&gt;
* [https://docs.google.com/spreadsheets/d/1J-JxoldE10mKDJNilnE84Wb7ylMZ-B2ArxRiWzYXRz0/edit#gid=0 Logged hours] (request access)&lt;br /&gt;
&lt;br /&gt;
= General instructions =&lt;br /&gt;
* Read and constantly document [[architecture of SAR service]]&lt;br /&gt;
* Always document extensively (comments in code, for instance)&lt;br /&gt;
* Make sure you watch pages that are relevant (star)&lt;br /&gt;
* Be mindful of [https://www.mediawiki.org/wiki/Manual:Coding_conventions/JavaScript Javascript conventions] (within reason)&lt;br /&gt;
* '''Whenever using property or item numbers in code, define a new variable early in the code with that &amp;lt;name&amp;gt;_id locally, for example &amp;quot;controller_item_id = 96&amp;quot; (see {{Q|96}})'''  (this makes the code produced less dependent on which Wikibase instance we are using, as the numbers will change)&lt;br /&gt;
&lt;br /&gt;
= Blockers = &lt;br /&gt;
* Mailto url limits (mainly affected chrome on Windows), see [[How to send emails]]&lt;br /&gt;
&lt;br /&gt;
= Removed blockers = &lt;br /&gt;
* (solved) [https://www.mediawiki.org/wiki/Manual:$wgAllowUserJs user JS] not currently activated on wiki.personaldata.io (but this system can be tested on Wikidata)&lt;br /&gt;
&lt;br /&gt;
= To do =&lt;br /&gt;
The goal is to streamline the SAR process. There are many ways this could be made easier. If one looks at the generated requests, they miss some of the information, particularly identifiers for the individual requesting the data. We want to enable filling some data (like name or telephone number) only once, and then be able to make multiple requests. One way to do this is by using LocalStorage, but which data attributes to collect and where should be stored in the database itself. &lt;br /&gt;
&lt;br /&gt;
Specific instructions:&lt;br /&gt;
* Create a [[SAR tool testing page]], with a OOUI button tied to the mailto, generated through a new [[Template:ButtonMailtoAccess]]. &lt;br /&gt;
* Modify the SAR user script [[MediaWiki:Access.js]] so that this button appears instead.&lt;br /&gt;
* (needs clarification:) Above this button, add an OOUI entry field for first name and last name, dynamically affecting what is launched when clicking the button. If nothing is entered, have some code making explicit what should be entered. &lt;br /&gt;
* (needs clarification:) Starting a separate stream of work, at the top of {{Q|119}} (or rather all &amp;quot;instance of&amp;quot; &amp;quot;personal attribute&amp;quot;), add an entry field to store the phone number --or that attribute-- locally (using [https://www.mediawiki.org/wiki/ResourceLoader/Core_modules#mediawiki.storage LocalStorage])&lt;br /&gt;
* Implement an [[MediaWiki:InterfaceButton.js]] script, displaying a button based on data contained in an item (for instance: {{Q|488}}), and interacting with client-side storage (data stored in a key given by &amp;quot;concerns&amp;quot; field)&lt;br /&gt;
* Based on selector on &amp;quot;instance of&amp;quot; &amp;quot;interface button&amp;quot;, implemented in [[MediaWiki:Common.js]], make this button appear at the top of the &amp;quot;interface button&amp;quot; pages (by reusing [[MediaWiki:InterfaceButton.js]] of course).&lt;br /&gt;
&lt;br /&gt;
= Done =&lt;br /&gt;
* Modify the [[MediaWiki:Access.js]] code to follow the conventions above. &lt;br /&gt;
* Make sure the SAR popup only shows up selectively, for those items that are &amp;quot;instance of&amp;quot; &amp;quot;data controller&amp;quot; (here: [http://wiki.personaldata.io/wiki/Property:P3 P3]--{{Q|96}})&lt;br /&gt;
* Have a look at [https://www.mediawiki.org/wiki/OOUI OOUI]&lt;br /&gt;
&lt;br /&gt;
= To be tested = &lt;br /&gt;
* On any page on &amp;quot;instance of&amp;quot; &amp;quot;interface button&amp;quot; , test whether the save function to localstorage works ( whether input data persists after page reload / browser restart ). Cross platform/browser compatibility should include Firefox, Chrome under Android, Firefox, Chrome under Windows 10, Safari, Firefox, Chrome under MacOS and as well as under iOS&lt;br /&gt;
* Cross browser transfer of data should be available on page Deliveroo ( or any instance of data controller as of current setup ). Current import mechanism will overwrite original data with the imported where they overlap, hopefully leave other original data intact&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5301</id>
		<title>User:Abel/PersonalData.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5301"/>
		<updated>2019-05-27T18:20:01Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// Indexeddb JavaScript &lt;br /&gt;
console.log('Indb loading');&lt;br /&gt;
&lt;br /&gt;
function IndexedDBContainer( ww	) {&lt;br /&gt;
&lt;br /&gt;
	// suppress console.log, switch to true for debug&lt;br /&gt;
	var Debug_switch = false;&lt;br /&gt;
	// seemingly the Safari engine uses a somewhat different implementation of arguments for db.transaction and index.get&lt;br /&gt;
	// because no browser on any mac / ios is allowed to use a different engine, rather than user agent, platform can be tested&lt;br /&gt;
	var iOS = !!navigator.platform &amp;amp;&amp;amp; /Macintosh|MacIntel|MacPPC|Mac68K|Mac|iPad|iPhone|iPod/.test(navigator.platform);&lt;br /&gt;
&lt;br /&gt;
	// deterministic hash generator for creating user id#s from usernames, should be replaced by something more functional (guaranteed to be transitively different)&lt;br /&gt;
	hashCode = function(s) {&lt;br /&gt;
		if ( s == undefined) {&lt;br /&gt;
			s = '00'&lt;br /&gt;
		}&lt;br /&gt;
		var h = 0, l = s.length, i = 0;&lt;br /&gt;
		if ( l &amp;gt; 0 )&lt;br /&gt;
			while (i &amp;lt; l)&lt;br /&gt;
				h = (h &amp;lt;&amp;lt; 5) - h + s.charCodeAt(i++) | 0;&lt;br /&gt;
			return h;&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
		if ( ww.user != undefined ) {&lt;br /&gt;
// if user exists in object passed to constructor, get username		&lt;br /&gt;
			var self = ww.user.getName();&lt;br /&gt;
// create userid by hashing username&lt;br /&gt;
			var idgen = hashCode(self);																										&lt;br /&gt;
			debuglog(idgen);&lt;br /&gt;
&lt;br /&gt;
// Take username for standard databasename format:&lt;br /&gt;
// Our current convention for personal databasename (separate dbname for each user)&lt;br /&gt;
			var PersonalDataDataBaseName = &amp;quot;PD.IO&amp;quot; + idgen + &amp;quot;Database&amp;quot;;&lt;br /&gt;
			// Use username in user to get up to date version of self&lt;br /&gt;
// Blank object for personal data Record with id and username included&lt;br /&gt;
			this.CurrentPerson = {id: idgen, name: {user: self}, age: 0};&lt;br /&gt;
			debuglog(PersonalDataDataBaseName);&lt;br /&gt;
			debuglog(this.CurrentPerson);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	// ADD MORE DOC&lt;br /&gt;
&lt;br /&gt;
	// EnqueuePDIO a PDIOLocalDatabase:User database access function with modes&lt;br /&gt;
	// Externally accessible wrapper for Enquire with current user / db preloaded&lt;br /&gt;
&lt;br /&gt;
	this.EnqueuePDIO = async function( sw, c1, c2, c3 ) {&lt;br /&gt;
		debuglog(&amp;quot;enquing pdio db &amp;quot; + PersonalDataDataBaseName + &amp;quot; with user &amp;quot; + JSON.stringify(this.CurrentPerson));&lt;br /&gt;
		var k = await Enquire( PersonalDataDataBaseName, this.CurrentPerson, sw, c1, c2, c3 );&lt;br /&gt;
		return k;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Enquire, a general purpose indexeddb update function with modes&lt;br /&gt;
&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
&lt;br /&gt;
	// Mode 'get record'&lt;br /&gt;
	// updates record given as argument&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
	&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
&lt;br /&gt;
	async function Enquire( pddbname, record, sqitch, control_1, control_2, control_3 ) {&lt;br /&gt;
		return new Promise(&lt;br /&gt;
			function(resolve, reject) {&lt;br /&gt;
&lt;br /&gt;
				var pddb = window.indexedDB.open(pddbname, 3);&lt;br /&gt;
				var inp_obj;&lt;br /&gt;
&lt;br /&gt;
				pddb.onerror = function() {  &lt;br /&gt;
				    console.log(&amp;quot;Warning: Access to IndexedDB for application has been rejected.&amp;quot;);&lt;br /&gt;
				};&lt;br /&gt;
&lt;br /&gt;
				// indexeddb internal mechanism for version tracking of schema&lt;br /&gt;
				pddb.onupgradeneeded = function() {&lt;br /&gt;
					console.log('upgrading database');&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var store = db.createObjectStore(pddbname, {keyPath: &amp;quot;id&amp;quot;});&lt;br /&gt;
					var index = store.createIndex(&amp;quot;NameIndex&amp;quot;, [&amp;quot;id&amp;quot;]);&lt;br /&gt;
						&lt;br /&gt;
				};&lt;br /&gt;
				// Database successfully opened function.&lt;br /&gt;
				pddb.onsuccess = function() {&lt;br /&gt;
					debuglog(pddb.result);&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var tx;&lt;br /&gt;
				&lt;br /&gt;
					if ( iOS ) {&lt;br /&gt;
						tx = db.transaction([pddbname], &amp;quot;readwrite&amp;quot;);&lt;br /&gt;
					} else {&lt;br /&gt;
						tx = db.transaction(pddbname, &amp;quot;readwrite&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
				&lt;br /&gt;
					var store = tx.objectStore(pddbname);&lt;br /&gt;
					var index = store.index(&amp;quot;NameIndex&amp;quot;);	&lt;br /&gt;
&lt;br /&gt;
					// Get the original record from the db...&lt;br /&gt;
					var getRecord;&lt;br /&gt;
					if ( iOS ) {&lt;br /&gt;
					 	getRecord = index.get(record.id);&lt;br /&gt;
					} else {&lt;br /&gt;
						getRecord = index.get([record.id]);&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					getRecord.onsuccess = function() {&lt;br /&gt;
							debuglog( &amp;quot;Record in database: \n &amp;lt;&amp;lt;&amp;quot;);&lt;br /&gt;
							debuglog( getRecord.result );&lt;br /&gt;
							debuglog( &amp;quot;&amp;gt;&amp;gt;&amp;quot;);&lt;br /&gt;
						// Essential recordAdd																													&lt;br /&gt;
						if ( sqitch === &amp;quot;aggressive push&amp;quot; ) {&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
							inp_obj = record;&lt;br /&gt;
							store.put( inp_obj );&lt;br /&gt;
							return inp_obj;&lt;br /&gt;
						} else if ( sqitch === &amp;quot;checkin&amp;quot; ) {&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
							if ( getRecord.result != undefined ) {&lt;br /&gt;
								debuglog(&amp;quot;getting from store&amp;quot;);&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
							} else {&lt;br /&gt;
								debuglog(&amp;quot;overriding whatever in there&amp;quot;);&lt;br /&gt;
								inp_obj = record;&lt;br /&gt;
								store.put(inp_obj);&lt;br /&gt;
							}&lt;br /&gt;
&lt;br /&gt;
						} else {&lt;br /&gt;
	// Methods manipulationg the actual record come here&lt;br /&gt;
	// Update &amp;amp; Remove from&lt;br /&gt;
							// If we got the record from store, use that version to be manipulated&lt;br /&gt;
							if ( getRecord.result !== undefined ) {		&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
								&lt;br /&gt;
								if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
									&lt;br /&gt;
									debuglog(&amp;quot;Getting record&amp;quot;);&lt;br /&gt;
									// we will return later&lt;br /&gt;
									&lt;br /&gt;
								} &lt;br /&gt;
&lt;br /&gt;
								// endof onsuccess&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								debuglog(&amp;quot;Record not found&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
								if ( sqitch === &amp;quot;update record&amp;quot; ) {&lt;br /&gt;
									// Update record will use supplied copy to update it&lt;br /&gt;
									inp_obj = record;&lt;br /&gt;
								} else {&lt;br /&gt;
									if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
										inp_obj = undefined;&lt;br /&gt;
									} else if ( sqitch === &amp;quot;remove from record&amp;quot; ) {&lt;br /&gt;
										inp_obj = record;&lt;br /&gt;
									} else {&lt;br /&gt;
										// any other method ...... would quit as record was not even foun&lt;br /&gt;
										return undefined;&lt;br /&gt;
									}&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
						} &lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;update record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
									if ( control_3 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
										if ( inp_obj[ control_1 ] == undefined ) { inp_obj[ control_1 ] = (isNaN( control_2 )) ? {} : [] };&lt;br /&gt;
										inp_obj[ control_1 ][ control_2 ] = control_3;	// =&amp;gt; &amp;quot;Bob&amp;quot;&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
									} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
										inp_obj[ control_1 ] = inp_obj[ control_1 ] || {};&lt;br /&gt;
										if ( Array.isArray( inp_obj[ control_1 ] ) ) {&lt;br /&gt;
											inp_obj[ control_1 ].push( control_2 );&lt;br /&gt;
										} else {&lt;br /&gt;
											inp_obj[ control_1 ] = control_2;&lt;br /&gt;
										}&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
&lt;br /&gt;
									}&lt;br /&gt;
								} else {&lt;br /&gt;
									// Only one control defined. We will return that part of the record, and change nothing&lt;br /&gt;
									inp_obj = inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								// There's not even control_1, we will just return the record itself&lt;br /&gt;
&lt;br /&gt;
							}&lt;br /&gt;
							debuglog(&amp;quot;return 3&amp;quot;)&lt;br /&gt;
							// return inp_obj;&lt;br /&gt;
&lt;br /&gt;
						};&lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;remove from record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
									&lt;br /&gt;
									if ( Array.isArray( inp_obj[ control_1 ] ) &amp;amp;&amp;amp; !isNaN( control_2 ) ) {&lt;br /&gt;
										inp_obj[ control_1 ].splice( control_2, 1 );&lt;br /&gt;
									} else {&lt;br /&gt;
										delete inp_obj[ control_1 ][ control_2 ];&lt;br /&gt;
									}&lt;br /&gt;
&lt;br /&gt;
								} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
&lt;br /&gt;
									delete inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
							debuglog(&amp;quot;putting object to store:&amp;quot;);&lt;br /&gt;
							debuglog(inp_obj);&lt;br /&gt;
							store.put(inp_obj);&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;import record&amp;quot; ) {&lt;br /&gt;
							debuglog(&amp;quot;import command&amp;quot;);&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								// Only import if control_1 is a non-empty object&lt;br /&gt;
								if ( ( !Array.isArray(control_1) ) &amp;amp;&amp;amp; ( Object.keys(control_1).length &amp;gt; 0 ) ) {&lt;br /&gt;
									debuglog(&amp;quot;command is obj&amp;quot;);&lt;br /&gt;
									 Object.keys(control_1).forEach( function( importkey ){&lt;br /&gt;
									 		debuglog(&amp;quot;importing &amp;quot; + importkey );&lt;br /&gt;
								 	        if (control_1.hasOwnProperty(importkey)) { inp_obj[importkey] = control_1[importkey] };&lt;br /&gt;
									 })&lt;br /&gt;
								store.put(inp_obj);&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
	// We are past all methodic code, Async return						&lt;br /&gt;
	&lt;br /&gt;
						resolve( inp_obj );&lt;br /&gt;
&lt;br /&gt;
					};&lt;br /&gt;
	&lt;br /&gt;
	// Indexeddb internal mechanism, close db&lt;br /&gt;
	&lt;br /&gt;
					tx.oncomplete = function() {&lt;br /&gt;
						debuglog(&amp;quot;return 1&amp;quot;)&lt;br /&gt;
						db.close();&lt;br /&gt;
					};&lt;br /&gt;
				};&lt;br /&gt;
				debuglog(&amp;quot;return 0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
	// End of promise&lt;br /&gt;
	&lt;br /&gt;
			}).then( function(result) {&lt;br /&gt;
				debuglog(&amp;quot;Mark 3&amp;quot;);&lt;br /&gt;
				debuglog(result);&lt;br /&gt;
				return result;&lt;br /&gt;
			});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function debuglog( l0g ){&lt;br /&gt;
		if ( Debug_switch ) {&lt;br /&gt;
			console.log( l0g );&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
};&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=5300</id>
		<title>User:Abel/OOInterface.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=5300"/>
		<updated>2019-05-27T18:18:09Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
		notify_porting();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['qIDPropName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
			ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
	&lt;br /&gt;
	function notify_porting() {&lt;br /&gt;
&lt;br /&gt;
		mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
			var button_import = new OO.ui.SelectFileWidget( { label: &amp;quot;Import Personal Data&amp;quot;, classes: [ 'pduimark' ] } ), &lt;br /&gt;
&lt;br /&gt;
				button_export = new OO.ui.ButtonWidget( { label: &amp;quot;Export Personal Data&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
&lt;br /&gt;
				button_import.on( 'change', function (event) {&lt;br /&gt;
&lt;br /&gt;
					if (window.webkitURL != null) {&lt;br /&gt;
						console.log(&amp;quot;loading file on webkit&amp;quot;)&lt;br /&gt;
					} else {&lt;br /&gt;
						console.log(&amp;quot;loading file non webkit&amp;quot;)&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					console.log( event );&lt;br /&gt;
					var input_object = event;&lt;br /&gt;
					readFileContent( input_object ).then( function(content) {&lt;br /&gt;
						var data = WikibaseProcessor.rxjson(content);&lt;br /&gt;
						indexedDBobject.EnqueuePDIO('import record', data);&lt;br /&gt;
					});&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			button_export.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
				var get_record = indexedDBobject.EnqueuePDIO('get record');&lt;br /&gt;
&lt;br /&gt;
				get_record.then( function(result) {&lt;br /&gt;
					console.log(&amp;quot;happening&amp;quot;);&lt;br /&gt;
					if ( result === undefined ) { window.alert(&amp;quot;No local data to export&amp;quot;) } else { &lt;br /&gt;
&lt;br /&gt;
						var filename_tosaveas = &amp;quot;pdiolocalexport_&amp;quot; + result.name.user + &amp;quot;_&amp;quot; + Date.now() + '.json';&lt;br /&gt;
						&lt;br /&gt;
						delete result.id;&lt;br /&gt;
						delete result.name.user;&lt;br /&gt;
						&lt;br /&gt;
						var export_to_text = JSON.stringify(result);&lt;br /&gt;
						var textFileAsBlob = new Blob([export_to_text], {type:'text/plain'});&lt;br /&gt;
						var downloadLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
						downloadLink.download = filename_tosaveas;&lt;br /&gt;
						if (window.webkitURL != null)&lt;br /&gt;
						{&lt;br /&gt;
							// Chrome allows the link to be clicked&lt;br /&gt;
							// without actually adding it to the DOM.&lt;br /&gt;
							downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);&lt;br /&gt;
						}&lt;br /&gt;
						else&lt;br /&gt;
						{&lt;br /&gt;
							// Firefox requires the link to be added to the DOM&lt;br /&gt;
							// before it can be clicked.&lt;br /&gt;
							downloadLink.href = window.URL.createObjectURL(textFileAsBlob);&lt;br /&gt;
							downloadLink.style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
							document.body.appendChild(downloadLink);&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
						downloadLink.click();&lt;br /&gt;
&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			mw.notify( $( button_import.$element ), { autoHide: false }	);&lt;br /&gt;
			mw.notify( $( button_export.$element ), { autoHide: false }	);&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function readFileContent(file) {&lt;br /&gt;
		const reader = new FileReader()&lt;br /&gt;
		return new Promise((resolve, reject) =&amp;gt; {&lt;br /&gt;
			reader.onload = event =&amp;gt; resolve(event.target.result)&lt;br /&gt;
			reader.onerror = error =&amp;gt; reject(error)&lt;br /&gt;
			reader.readAsText(file)&lt;br /&gt;
		})&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=5299</id>
		<title>User:Abel/OOInterface.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=5299"/>
		<updated>2019-05-27T18:17:18Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
		notify_porting();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['qIDPropName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
			ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
	&lt;br /&gt;
	function notify_porting() {&lt;br /&gt;
&lt;br /&gt;
		mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
			var button_import = new OO.ui.SelectFileWidget( { label: &amp;quot;Import Personal Data&amp;quot;, classes: [ 'pduimark' ] } ), &lt;br /&gt;
&lt;br /&gt;
				button_export = new OO.ui.ButtonWidget( { label: &amp;quot;Export Personal Data&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
&lt;br /&gt;
				button_import.on( 'change', function (event) {&lt;br /&gt;
&lt;br /&gt;
					if (window.webkitURL != null) {&lt;br /&gt;
						console.log(&amp;quot;loading file on webkit&amp;quot;)&lt;br /&gt;
					} else {&lt;br /&gt;
						console.log(&amp;quot;loading file non webkit&amp;quot;)&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					console.log( event );&lt;br /&gt;
					var input_object = event;&lt;br /&gt;
					readFileContent( input_object ).then( function(content) {&lt;br /&gt;
						var data = WikibaseProcessor.rxjson(content);&lt;br /&gt;
						indexedDBobject.EnqueuePDIO('import record', data);&lt;br /&gt;
					});&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			button_export.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
				var get_record = indexedDBobject.EnqueuePDIO('get record');&lt;br /&gt;
&lt;br /&gt;
				get_record.then( function(result) {&lt;br /&gt;
					console.log(&amp;quot;happening&amp;quot;);&lt;br /&gt;
					if ( result === undefined ) { window.alert(&amp;quot;No local data to export&amp;quot;) } else { &lt;br /&gt;
&lt;br /&gt;
						var filename_tosaveas = &amp;quot;pdiolocalexport_&amp;quot; + result.name.user + &amp;quot;_&amp;quot; + Date.now() + '.json';&lt;br /&gt;
						&lt;br /&gt;
						delete result.id;&lt;br /&gt;
						delete name.user;&lt;br /&gt;
						&lt;br /&gt;
						var export_to_text = JSON.stringify(result);&lt;br /&gt;
						var textFileAsBlob = new Blob([export_to_text], {type:'text/plain'});&lt;br /&gt;
						var downloadLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
						downloadLink.download = filename_tosaveas;&lt;br /&gt;
						if (window.webkitURL != null)&lt;br /&gt;
						{&lt;br /&gt;
							// Chrome allows the link to be clicked&lt;br /&gt;
							// without actually adding it to the DOM.&lt;br /&gt;
							downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);&lt;br /&gt;
						}&lt;br /&gt;
						else&lt;br /&gt;
						{&lt;br /&gt;
							// Firefox requires the link to be added to the DOM&lt;br /&gt;
							// before it can be clicked.&lt;br /&gt;
							downloadLink.href = window.URL.createObjectURL(textFileAsBlob);&lt;br /&gt;
							downloadLink.style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
							document.body.appendChild(downloadLink);&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
						downloadLink.click();&lt;br /&gt;
&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			mw.notify( $( button_import.$element ), { autoHide: false }	);&lt;br /&gt;
			mw.notify( $( button_export.$element ), { autoHide: false }	);&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function readFileContent(file) {&lt;br /&gt;
		const reader = new FileReader()&lt;br /&gt;
		return new Promise((resolve, reject) =&amp;gt; {&lt;br /&gt;
			reader.onload = event =&amp;gt; resolve(event.target.result)&lt;br /&gt;
			reader.onerror = error =&amp;gt; reject(error)&lt;br /&gt;
			reader.readAsText(file)&lt;br /&gt;
		})&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=5298</id>
		<title>User:Abel/OOInterface.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=5298"/>
		<updated>2019-05-27T18:14:15Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
		notify_porting();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['qIDPropName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
			ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
	&lt;br /&gt;
	function notify_porting() {&lt;br /&gt;
&lt;br /&gt;
		mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
			var button_import = new OO.ui.SelectFileWidget( { label: &amp;quot;Import Personal Data&amp;quot;, classes: [ 'pduimark' ] } ), &lt;br /&gt;
&lt;br /&gt;
				button_export = new OO.ui.ButtonWidget( { label: &amp;quot;Export Personal Data&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
&lt;br /&gt;
				button_import.on( 'change', function (event) {&lt;br /&gt;
&lt;br /&gt;
					if (window.webkitURL != null) {&lt;br /&gt;
						console.log(&amp;quot;loading file on webkit&amp;quot;)&lt;br /&gt;
					} else {&lt;br /&gt;
						console.log(&amp;quot;loading file non webkit&amp;quot;)&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					console.log( event );&lt;br /&gt;
					var input_object = event;&lt;br /&gt;
					readFileContent( input_object ).then( function(content) {&lt;br /&gt;
						var data = WikibaseProcessor.rxjson(content);&lt;br /&gt;
						indexedDBobject.EnqueuePDIO('import record', data);&lt;br /&gt;
					});&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			button_export.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
				var get_record = indexedDBobject.EnqueuePDIO('get record');&lt;br /&gt;
&lt;br /&gt;
				get_record.then( function(result) {&lt;br /&gt;
					console.log(&amp;quot;happening&amp;quot;);&lt;br /&gt;
					if ( result === undefined ) { window.alert(&amp;quot;No local data to export&amp;quot;) } else { &lt;br /&gt;
&lt;br /&gt;
						var filename_tosaveas = &amp;quot;pdiolocalexport_&amp;quot; + result.name.user + &amp;quot;_&amp;quot; + Date.now() + '.json';&lt;br /&gt;
						&lt;br /&gt;
						result.id = '';&lt;br /&gt;
						result.name.user = '';&lt;br /&gt;
						&lt;br /&gt;
						var export_to_text = JSON.stringify(result);&lt;br /&gt;
						var textFileAsBlob = new Blob([export_to_text], {type:'text/plain'});&lt;br /&gt;
						var downloadLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
						downloadLink.download = filename_tosaveas;&lt;br /&gt;
						if (window.webkitURL != null)&lt;br /&gt;
						{&lt;br /&gt;
							// Chrome allows the link to be clicked&lt;br /&gt;
							// without actually adding it to the DOM.&lt;br /&gt;
							downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);&lt;br /&gt;
						}&lt;br /&gt;
						else&lt;br /&gt;
						{&lt;br /&gt;
							// Firefox requires the link to be added to the DOM&lt;br /&gt;
							// before it can be clicked.&lt;br /&gt;
							downloadLink.href = window.URL.createObjectURL(textFileAsBlob);&lt;br /&gt;
							downloadLink.style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
							document.body.appendChild(downloadLink);&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
						downloadLink.click();&lt;br /&gt;
&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			mw.notify( $( button_import.$element ), { autoHide: false }	);&lt;br /&gt;
			mw.notify( $( button_export.$element ), { autoHide: false }	);&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function readFileContent(file) {&lt;br /&gt;
		const reader = new FileReader()&lt;br /&gt;
		return new Promise((resolve, reject) =&amp;gt; {&lt;br /&gt;
			reader.onload = event =&amp;gt; resolve(event.target.result)&lt;br /&gt;
			reader.onerror = error =&amp;gt; reject(error)&lt;br /&gt;
			reader.readAsText(file)&lt;br /&gt;
		})&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=5297</id>
		<title>User:Abel/OOInterface.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=5297"/>
		<updated>2019-05-27T18:12:39Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
		notify_porting();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['qIDPropName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
			ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
	&lt;br /&gt;
	function notify_porting() {&lt;br /&gt;
&lt;br /&gt;
		mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
			var button_import = new OO.ui.SelectFileWidget( { label: &amp;quot;Import Personal Data&amp;quot;, classes: [ 'pduimark' ] } ), &lt;br /&gt;
&lt;br /&gt;
				button_export = new OO.ui.ButtonWidget( { label: &amp;quot;Export Personal Data&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
&lt;br /&gt;
				button_import.on( 'change', function (event) {&lt;br /&gt;
&lt;br /&gt;
					if (window.webkitURL != null) {&lt;br /&gt;
						console.log(&amp;quot;loading file on webkit&amp;quot;)&lt;br /&gt;
					} else {&lt;br /&gt;
						console.log(&amp;quot;loading file non webkit&amp;quot;)&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					console.log( event );&lt;br /&gt;
					var input_object = event.target;&lt;br /&gt;
					readFileContent( input_object ).then( function(content) {&lt;br /&gt;
						var data = WikibaseProcessor.rxjson(content);&lt;br /&gt;
						indexedDBobject.EnqueuePDIO('import record', data);&lt;br /&gt;
					});&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			button_export.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
				var get_record = indexedDBobject.EnqueuePDIO('get record');&lt;br /&gt;
&lt;br /&gt;
				get_record.then( function(result) {&lt;br /&gt;
					console.log(&amp;quot;happening&amp;quot;);&lt;br /&gt;
					if ( result === undefined ) { window.alert(&amp;quot;No local data to export&amp;quot;) } else { &lt;br /&gt;
&lt;br /&gt;
						var filename_tosaveas = &amp;quot;pdiolocalexport_&amp;quot; + result.name.user + &amp;quot;_&amp;quot; + Date.now() + '.json';&lt;br /&gt;
						&lt;br /&gt;
						result.id = '';&lt;br /&gt;
						result.name.user = '';&lt;br /&gt;
						&lt;br /&gt;
						var export_to_text = JSON.stringify(result);&lt;br /&gt;
						var textFileAsBlob = new Blob([export_to_text], {type:'text/plain'});&lt;br /&gt;
						var downloadLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
						downloadLink.download = filename_tosaveas;&lt;br /&gt;
						if (window.webkitURL != null)&lt;br /&gt;
						{&lt;br /&gt;
							// Chrome allows the link to be clicked&lt;br /&gt;
							// without actually adding it to the DOM.&lt;br /&gt;
							downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);&lt;br /&gt;
						}&lt;br /&gt;
						else&lt;br /&gt;
						{&lt;br /&gt;
							// Firefox requires the link to be added to the DOM&lt;br /&gt;
							// before it can be clicked.&lt;br /&gt;
							downloadLink.href = window.URL.createObjectURL(textFileAsBlob);&lt;br /&gt;
							downloadLink.style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
							document.body.appendChild(downloadLink);&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
						downloadLink.click();&lt;br /&gt;
&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			mw.notify( $( button_import.$element ), { autoHide: false }	);&lt;br /&gt;
			mw.notify( $( button_export.$element ), { autoHide: false }	);&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function readFileContent(file) {&lt;br /&gt;
		const reader = new FileReader()&lt;br /&gt;
		return new Promise((resolve, reject) =&amp;gt; {&lt;br /&gt;
			reader.onload = event =&amp;gt; resolve(event.target.result)&lt;br /&gt;
			reader.onerror = error =&amp;gt; reject(error)&lt;br /&gt;
			reader.readAsText(file)&lt;br /&gt;
		})&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5296</id>
		<title>User:Abel/PersonalData.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5296"/>
		<updated>2019-05-27T18:08:53Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// Indexeddb JavaScript &lt;br /&gt;
console.log('Indb loading');&lt;br /&gt;
&lt;br /&gt;
function IndexedDBContainer( ww	) {&lt;br /&gt;
&lt;br /&gt;
	// suppress console.log, switch to true for debug&lt;br /&gt;
	var Debug_switch = false;&lt;br /&gt;
	// seemingly the Safari engine uses a somewhat different implementation of arguments for db.transaction and index.get&lt;br /&gt;
	// because no browser on any mac / ios is allowed to use a different engine, rather than user agent, platform can be tested&lt;br /&gt;
	var iOS = !!navigator.platform &amp;amp;&amp;amp; /Macintosh|MacIntel|MacPPC|Mac68K|Mac|iPad|iPhone|iPod/.test(navigator.platform);&lt;br /&gt;
&lt;br /&gt;
	// deterministic hash generator for creating user id#s from usernames, should be replaced by something more functional (guaranteed to be transitively different)&lt;br /&gt;
	hashCode = function(s) {&lt;br /&gt;
		if ( s == undefined) {&lt;br /&gt;
			s = '00'&lt;br /&gt;
		}&lt;br /&gt;
		var h = 0, l = s.length, i = 0;&lt;br /&gt;
		if ( l &amp;gt; 0 )&lt;br /&gt;
			while (i &amp;lt; l)&lt;br /&gt;
				h = (h &amp;lt;&amp;lt; 5) - h + s.charCodeAt(i++) | 0;&lt;br /&gt;
			return h;&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
		if ( ww.user != undefined ) {&lt;br /&gt;
// if user exists in object passed to constructor, get username		&lt;br /&gt;
			var self = ww.user.getName();&lt;br /&gt;
// create userid by hashing username&lt;br /&gt;
			var idgen = hashCode(self);																										&lt;br /&gt;
			debuglog(idgen);&lt;br /&gt;
&lt;br /&gt;
// Take username for standard databasename format:&lt;br /&gt;
// Our current convention for personal databasename (separate dbname for each user)&lt;br /&gt;
			var PersonalDataDataBaseName = &amp;quot;PD.IO&amp;quot; + idgen + &amp;quot;Database&amp;quot;;&lt;br /&gt;
			// Use username in user to get up to date version of self&lt;br /&gt;
// Blank object for personal data Record with id and username included&lt;br /&gt;
			this.CurrentPerson = {id: idgen, name: {user: self}, age: 0};&lt;br /&gt;
			debuglog(PersonalDataDataBaseName);&lt;br /&gt;
			debuglog(this.CurrentPerson);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	// ADD MORE DOC&lt;br /&gt;
&lt;br /&gt;
	// EnqueuePDIO a PDIOLocalDatabase:User database access function with modes&lt;br /&gt;
	// Externally accessible wrapper for Enquire with current user / db preloaded&lt;br /&gt;
&lt;br /&gt;
	this.EnqueuePDIO = async function( sw, c1, c2, c3 ) {&lt;br /&gt;
		debuglog(&amp;quot;enquing pdio db &amp;quot; + PersonalDataDataBaseName + &amp;quot; with user &amp;quot; + JSON.stringify(this.CurrentPerson));&lt;br /&gt;
		var k = await Enquire( PersonalDataDataBaseName, this.CurrentPerson, sw, c1, c2, c3 );&lt;br /&gt;
		return k;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Enquire, a general purpose indexeddb update function with modes&lt;br /&gt;
&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
&lt;br /&gt;
	// Mode 'get record'&lt;br /&gt;
	// updates record given as argument&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
	&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
&lt;br /&gt;
	async function Enquire( pddbname, record, sqitch, control_1, control_2, control_3 ) {&lt;br /&gt;
		return new Promise(&lt;br /&gt;
			function(resolve, reject) {&lt;br /&gt;
&lt;br /&gt;
				var pddb = window.indexedDB.open(pddbname, 3);&lt;br /&gt;
				var inp_obj;&lt;br /&gt;
&lt;br /&gt;
				pddb.onerror = function() {  &lt;br /&gt;
				    console.log(&amp;quot;Warning: Access to IndexedDB for application has been rejected.&amp;quot;);&lt;br /&gt;
				};&lt;br /&gt;
&lt;br /&gt;
				// indexeddb internal mechanism for version tracking of schema&lt;br /&gt;
				pddb.onupgradeneeded = function() {&lt;br /&gt;
					console.log('upgrading database');&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var store = db.createObjectStore(pddbname, {keyPath: &amp;quot;id&amp;quot;});&lt;br /&gt;
					var index = store.createIndex(&amp;quot;NameIndex&amp;quot;, [&amp;quot;id&amp;quot;]);&lt;br /&gt;
						&lt;br /&gt;
				};&lt;br /&gt;
				// Database successfully opened function.&lt;br /&gt;
				pddb.onsuccess = function() {&lt;br /&gt;
					debuglog(pddb.result);&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var tx;&lt;br /&gt;
				&lt;br /&gt;
					if ( iOS ) {&lt;br /&gt;
						tx = db.transaction([pddbname], &amp;quot;readwrite&amp;quot;);&lt;br /&gt;
					} else {&lt;br /&gt;
						tx = db.transaction(pddbname, &amp;quot;readwrite&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
				&lt;br /&gt;
					var store = tx.objectStore(pddbname);&lt;br /&gt;
					var index = store.index(&amp;quot;NameIndex&amp;quot;);	&lt;br /&gt;
&lt;br /&gt;
					// Get the original record from the db...&lt;br /&gt;
					var getRecord;&lt;br /&gt;
					if ( iOS ) {&lt;br /&gt;
					 	getRecord = index.get(record.id);&lt;br /&gt;
					} else {&lt;br /&gt;
						getRecord = index.get([record.id]);&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					getRecord.onsuccess = function() {&lt;br /&gt;
							debuglog( &amp;quot;Record in database: \n &amp;lt;&amp;lt;&amp;quot;);&lt;br /&gt;
							debuglog( getRecord.result );&lt;br /&gt;
							debuglog( &amp;quot;&amp;gt;&amp;gt;&amp;quot;);&lt;br /&gt;
						// Essential recordAdd																													&lt;br /&gt;
						if ( sqitch === &amp;quot;aggressive push&amp;quot; ) {&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
							inp_obj = record;&lt;br /&gt;
							store.put( inp_obj );&lt;br /&gt;
							return inp_obj;&lt;br /&gt;
						} else if ( sqitch === &amp;quot;checkin&amp;quot; ) {&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
							if ( getRecord.result != undefined ) {&lt;br /&gt;
								debuglog(&amp;quot;getting from store&amp;quot;);&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
							} else {&lt;br /&gt;
								debuglog(&amp;quot;overriding whatever in there&amp;quot;);&lt;br /&gt;
								inp_obj = record;&lt;br /&gt;
								store.put(inp_obj);&lt;br /&gt;
							}&lt;br /&gt;
&lt;br /&gt;
						} else {&lt;br /&gt;
	// Methods manipulationg the actual record come here&lt;br /&gt;
	// Update &amp;amp; Remove from&lt;br /&gt;
							// If we got the record from store, use that version to be manipulated&lt;br /&gt;
							if ( getRecord.result !== undefined ) {		&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
								&lt;br /&gt;
								if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
									&lt;br /&gt;
									debuglog(&amp;quot;Getting record&amp;quot;);&lt;br /&gt;
									// we will return later&lt;br /&gt;
									&lt;br /&gt;
								} &lt;br /&gt;
&lt;br /&gt;
								// endof onsuccess&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								debuglog(&amp;quot;Record not found&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
								if ( sqitch === &amp;quot;update record&amp;quot; ) {&lt;br /&gt;
									// Update record will use supplied copy to update it&lt;br /&gt;
									inp_obj = record;&lt;br /&gt;
								} else {&lt;br /&gt;
									if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
										inp_obj = undefined;&lt;br /&gt;
									} else if ( sqitch === &amp;quot;remove from record&amp;quot; ) {&lt;br /&gt;
										inp_obj = record;&lt;br /&gt;
									} else {&lt;br /&gt;
										// any other method ...... would quit as record was not even foun&lt;br /&gt;
										return undefined;&lt;br /&gt;
									}&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
						} &lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;update record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
									if ( control_3 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
										if ( inp_obj[ control_1 ] == undefined ) { inp_obj[ control_1 ] = (isNaN( control_2 )) ? {} : [] };&lt;br /&gt;
										inp_obj[ control_1 ][ control_2 ] = control_3;	// =&amp;gt; &amp;quot;Bob&amp;quot;&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
									} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
										inp_obj[ control_1 ] = inp_obj[ control_1 ] || {};&lt;br /&gt;
										if ( Array.isArray( inp_obj[ control_1 ] ) ) {&lt;br /&gt;
											inp_obj[ control_1 ].push( control_2 );&lt;br /&gt;
										} else {&lt;br /&gt;
											inp_obj[ control_1 ] = control_2;&lt;br /&gt;
										}&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
&lt;br /&gt;
									}&lt;br /&gt;
								} else {&lt;br /&gt;
									// Only one control defined. We will return that part of the record, and change nothing&lt;br /&gt;
									inp_obj = inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								// There's not even control_1, we will just return the record itself&lt;br /&gt;
&lt;br /&gt;
							}&lt;br /&gt;
							debuglog(&amp;quot;return 3&amp;quot;)&lt;br /&gt;
							// return inp_obj;&lt;br /&gt;
&lt;br /&gt;
						};&lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;remove from record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
									&lt;br /&gt;
									if ( Array.isArray( inp_obj[ control_1 ] ) &amp;amp;&amp;amp; !isNaN( control_2 ) ) {&lt;br /&gt;
										inp_obj[ control_1 ].splice( control_2, 1 );&lt;br /&gt;
									} else {&lt;br /&gt;
										delete inp_obj[ control_1 ][ control_2 ];&lt;br /&gt;
									}&lt;br /&gt;
&lt;br /&gt;
								} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
&lt;br /&gt;
									delete inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
							debuglog(&amp;quot;putting object to store:&amp;quot;);&lt;br /&gt;
							debuglog(inp_obj);&lt;br /&gt;
							store.put(inp_obj);&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;import record&amp;quot; ) {&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								// Only import if control_1 is a non-empty object&lt;br /&gt;
								if ( ( !Array.isArray(control_1) ) &amp;amp;&amp;amp; ( Object.keys(control_1).length &amp;gt; 0 ) ) {&lt;br /&gt;
									 Object.keys(control_1).forEach( function( importkey ){&lt;br /&gt;
								 	        if (src.hasOwnProperty(importkey)) { inp_obj[importkey] = src[importkey] };&lt;br /&gt;
									 })&lt;br /&gt;
								store.put(inp_obj);&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
	// We are past all methodic code, Async return						&lt;br /&gt;
	&lt;br /&gt;
						resolve( inp_obj );&lt;br /&gt;
&lt;br /&gt;
					};&lt;br /&gt;
	&lt;br /&gt;
	// Indexeddb internal mechanism, close db&lt;br /&gt;
	&lt;br /&gt;
					tx.oncomplete = function() {&lt;br /&gt;
						debuglog(&amp;quot;return 1&amp;quot;)&lt;br /&gt;
						db.close();&lt;br /&gt;
					};&lt;br /&gt;
				};&lt;br /&gt;
				debuglog(&amp;quot;return 0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
	// End of promise&lt;br /&gt;
	&lt;br /&gt;
			}).then( function(result) {&lt;br /&gt;
				debuglog(&amp;quot;Mark 3&amp;quot;);&lt;br /&gt;
				debuglog(result);&lt;br /&gt;
				return result;&lt;br /&gt;
			});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function debuglog( l0g ){&lt;br /&gt;
		if ( Debug_switch ) {&lt;br /&gt;
			console.log( l0g );&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
};&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/WbProcessor.js&amp;diff=5295</id>
		<title>User:Abel/WbProcessor.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/WbProcessor.js&amp;diff=5295"/>
		<updated>2019-05-27T18:08:06Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// Wikibase Processor&lt;br /&gt;
console.log('wbprocessor loading');&lt;br /&gt;
&lt;br /&gt;
	function WikibaseProcessorContainer( universe, location ) {&lt;br /&gt;
&lt;br /&gt;
		Debug_switch = false;&lt;br /&gt;
&lt;br /&gt;
		this.main = interjson( checkdive( universe, location ));&lt;br /&gt;
		var the = this.main;&lt;br /&gt;
		&lt;br /&gt;
		/* The following is the main exposed function of the current Wb Processing class&lt;br /&gt;
			usage cases&lt;br /&gt;
&lt;br /&gt;
			to check the last value in a location given by a preceding array of internal paths to find, with the possibility of array layers between elements of array of paths: &lt;br /&gt;
			wbproc.checkentity( [ wbEStruct['instanceOfRelations'], wbEStruct['IDPropLoc'], wbEStruct['IDName'], 96 ] );&lt;br /&gt;
&lt;br /&gt;
			to return for example content of default value given by array of location paths, or check for existence of &lt;br /&gt;
			wbproc.checkentity( { default_value: [ wbEStruct['defaultValRelation'], wbEStruct['IDPropLoc'] ] } )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		*/&lt;br /&gt;
&lt;br /&gt;
		this.checkentity = function ( paths ) {&lt;br /&gt;
			if ( ( the !== undefined ) &amp;amp;&amp;amp; ( paths !== undefined ) ){&lt;br /&gt;
				return proceed( the, paths );&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// Exposed general wrapper for proceed for object other than what the class is originally instanced on, currently unused&lt;br /&gt;
		// Could be used to create a further function to cross check current object with another object 'universe' with another for example&lt;br /&gt;
&lt;br /&gt;
		this.xcontains = function ( unv, angle ) {&lt;br /&gt;
			if ( ( unv !== undefined ) &amp;amp;&amp;amp; ( angle !== undefined ) ){&lt;br /&gt;
				return proceed( unv, angle );&lt;br /&gt;
			};&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/* Exposed helper function to get Entity object of alien entity, if ever needed */&lt;br /&gt;
                &lt;br /&gt;
        this.EnqueueWB = async function( idk ) {&lt;br /&gt;
			var k = await wbqueue(idk);&lt;br /&gt;
			return k;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/* Private part of wb Entity getter */&lt;br /&gt;
&lt;br /&gt;
		async function wbqueue(id) {&lt;br /&gt;
			return new Promise(&lt;br /&gt;
				function(resolve, reject) {&lt;br /&gt;
					$.getJSON('/w/api.php?action=wbgetentities&amp;amp;format=json&amp;amp;ids=' + id, function(json) { &lt;br /&gt;
						var h = json.entities;&lt;br /&gt;
						resolve(h);&lt;br /&gt;
					})&lt;br /&gt;
				}).then( function(result) {&lt;br /&gt;
					debuglog(result);&lt;br /&gt;
					return result;&lt;br /&gt;
				});&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		// the list of private helper functions, could not be accessed from outside&lt;br /&gt;
		// helper function for descend into an object if key exists, otherwise stay at current level of object		&lt;br /&gt;
		function indexinterpolate(obj,i) { return  (obj[i] !== undefined) ? obj[i] : obj}; &lt;br /&gt;
		&lt;br /&gt;
		// helper function for checking a part of an array exists, if it doesn't, go undefined&lt;br /&gt;
		function indexcheck(obj,i) {  if ( obj !== undefined) { return ( obj[i] !== undefined ) ? obj[i] : undefined } };&lt;br /&gt;
		&lt;br /&gt;
		// dive selects matrix.a.b.c.d from the array called matrix and 'a.b.c.d' as string&lt;br /&gt;
		// 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.&lt;br /&gt;
		function dive(array, read){&lt;br /&gt;
			if ( array !== undefined ) {&lt;br /&gt;
				return (read + '').split('.').reduce(indexinterpolate, array);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		// Check returns matrix.a.b.c.d from 'array' ~ 'matrix' and 'read' ~ 'a.b.c.d' only if it exists all the way, otherwise go undefined&lt;br /&gt;
		function check(array, read){&lt;br /&gt;
			if ( array !== undefined ) {&lt;br /&gt;
				return (read + '').split('.').reduce(indexcheck, array);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// Main object / array processing instrument&lt;br /&gt;
		// Array can be a composition of objects and arrays &lt;br /&gt;
		// Read is the instructions, could be an array, or a single path, but for now it should be an object based on our inner convention, example:&lt;br /&gt;
		/* &lt;br /&gt;
			relational_id_list = { &lt;br /&gt;
				controller_id: [ wbEStructure['instanceOfRelations'], wbEStructure['IDPropLoc'], wbEStructure['IDName'], 96 ],&lt;br /&gt;
				personal_data_id: [ wbEStructure['subclassOfRelations'], wbEStructure['IDPropLoc'], wbEStructure['IDName'], 421 ],&lt;br /&gt;
				interface_button_id: [ wbEStructure ['instanceOfRelations'], wbEStructure['IDPropLoc'], wbEStructure['IDName'], 487 ]&lt;br /&gt;
			} &lt;br /&gt;
		*/&lt;br /&gt;
&lt;br /&gt;
		function proceed(array, read) {&lt;br /&gt;
			var ret_obj = {},&lt;br /&gt;
			temp_obj = array,&lt;br /&gt;
&lt;br /&gt;
			// If we encounter something seriously wrong we will just raise a red flag by setting this false, will check before returning this.&lt;br /&gt;
			success_o_meter = true,&lt;br /&gt;
&lt;br /&gt;
			// If all goes well, for each path checked, we will have a member in this&lt;br /&gt;
			future_instructional_return = [];&lt;br /&gt;
			&lt;br /&gt;
//|||||||||||||||||||||||||||||||||||||||||||||||||||||[ I N S T R U C T I O N S  C O N T R O L   ]||||||||||||||||||||||||||||||||||||||||||||||||||||||&lt;br /&gt;
&lt;br /&gt;
			// Init program, check if instructions are an object (not an array but has multiple keys) :&lt;br /&gt;
			// This is the main path of the function. Could be improved to have it for simple array of instructions&lt;br /&gt;
			if ( ( !Array.isArray(read) ) &amp;amp;&amp;amp; ( Object.keys(read).length &amp;gt; 0 ) ) {&lt;br /&gt;
				&lt;br /&gt;
				Object.keys(read).forEach( function(path) {&lt;br /&gt;
				debuglog(&amp;quot;instructions are an object, in path &amp;quot; + path);&lt;br /&gt;
&lt;br /&gt;
//||||||||||||||||||||||||||[ Check if elements of instruction object are arrays themselves ]||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||&lt;br /&gt;
					&lt;br /&gt;
					if ( Array.isArray (read[path]) ) {&lt;br /&gt;
&lt;br /&gt;
						// for each path, future_instructional_return will be filled with the future_return_partition after proceeding through that path&lt;br /&gt;
						var future_return_partition = temp_obj;&lt;br /&gt;
&lt;br /&gt;
						Object.keys(read[path]).forEach( function( path2 ) {&lt;br /&gt;
&lt;br /&gt;
							debuglog(&amp;quot;instructions are an array of arrays, going through &amp;quot; + read[ path ][ path2 ] );&lt;br /&gt;
							// for each step, see if it led anywhere other than where we were.&lt;br /&gt;
							if ( data_function( future_return_partition, read[ path ][ path2 ] ) != future_return_partition ){&lt;br /&gt;
								// if it did, proceed;&lt;br /&gt;
								future_return_partition = data_function( future_return_partition, read[ path ][ path2 ] );&lt;br /&gt;
							} else {&lt;br /&gt;
								// if it didn, raise flag&lt;br /&gt;
								success_o_meter = false;&lt;br /&gt;
							}&lt;br /&gt;
&lt;br /&gt;
//|||||||||||||||||||||||||||||||||||||||||||||||||||[   I N S T R U C T I O N S   C O N T R O L |||||||||||||||||||||||||||||||||||||||||||||||||||||||||&lt;br /&gt;
&lt;br /&gt;
						});&lt;br /&gt;
						//Now that we went through the path, lets see if everything was ok.&lt;br /&gt;
						if ( success_o_meter === true ) {&lt;br /&gt;
						// If yes, put the result of the travel 'future_return_partition' into 'future_instructional_return'&lt;br /&gt;
							&lt;br /&gt;
							debuglog(&amp;quot;arrived at&amp;quot;)&lt;br /&gt;
							debuglog(future_return_partition);&lt;br /&gt;
							future_instructional_return[path] = future_return_partition;&lt;br /&gt;
						} else {&lt;br /&gt;
&lt;br /&gt;
						// Otherwise let's put an undefined in there&lt;br /&gt;
							debuglog(&amp;quot;seeking derailed&amp;quot;);&lt;br /&gt;
							success_o_meter = true;&lt;br /&gt;
							future_instructional_return[path] = undefined;&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
					} &lt;br /&gt;
&lt;br /&gt;
//|||||||||||||||||| If instruction object element is not an array, lets just try to do that one step ||||||||||||||||||||||||||||||||||||||||||||||||||||||||&lt;br /&gt;
// Unused&lt;br /&gt;
					else {&lt;br /&gt;
												&lt;br /&gt;
						// INCLUDE step block with read[path] &lt;br /&gt;
						if ( data_function( temp_obj, read[ path ] ) !== temp_obj  ){&lt;br /&gt;
							future_instructional_return[path] = data_function( temp_obj, read[ path ] ) ;&lt;br /&gt;
						} else {&lt;br /&gt;
							// future_instructional_return.push( undefined );&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
					}&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				// Now that we have gone through all paths, make future return object into what we got&lt;br /&gt;
				temp_obj = future_instructional_return;&lt;br /&gt;
			} &lt;br /&gt;
&lt;br /&gt;
//||||||||||||[ If we are not in instruction object, let's see if we have an instruction array ]||||||||||||||||||||||||||||||||||||||||||||||||||||||||||&lt;br /&gt;
//Unused, this part could be improved&lt;br /&gt;
			else if ( Array.isArray(read) ) {&lt;br /&gt;
				// If so let's follow the array of instructions&lt;br /&gt;
				Object.keys( read ).forEach( function ( ect ) {&lt;br /&gt;
					if ( data_function( temp_obj, read[ ect ] ) !== temp_obj  ){&lt;br /&gt;
						&lt;br /&gt;
						temp_obj = data_function( temp_obj, read[ ect ] );&lt;br /&gt;
&lt;br /&gt;
					} else {&lt;br /&gt;
&lt;br /&gt;
						success_o_meter = false;&lt;br /&gt;
&lt;br /&gt;
					}&lt;br /&gt;
				});&lt;br /&gt;
			} &lt;br /&gt;
&lt;br /&gt;
//||||||||||||[ If we have a single instruction, let's try following that |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||&lt;br /&gt;
//Unused, this part could be improved&lt;br /&gt;
&lt;br /&gt;
			else {&lt;br /&gt;
				&lt;br /&gt;
				if ( data_function( temp_obj, read ) !== temp_obj  ){&lt;br /&gt;
	&lt;br /&gt;
					temp_obj = data_function( temp_obj, read );&lt;br /&gt;
&lt;br /&gt;
				} else {&lt;br /&gt;
&lt;br /&gt;
					success_o_meter = false;&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			&lt;br /&gt;
			// If we haven't got a not found signal along the way, let's try returning the object&lt;br /&gt;
&lt;br /&gt;
			if ( success_o_meter === true ) {&lt;br /&gt;
				return temp_obj;&lt;br /&gt;
			} else {&lt;br /&gt;
				return undefined;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
//|||||||||||||||||||||||||||||||||||||||||||||||||||||[   S T E P   B L O C K   ]||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||&lt;br /&gt;
&lt;br /&gt;
		// Function that takes 1 step. Proceed (along a path) uses this for each step.&lt;br /&gt;
&lt;br /&gt;
		function data_function ( temp_obj, moving ) {&lt;br /&gt;
			&lt;br /&gt;
			// we will return an array&lt;br /&gt;
			var future_temp_obj = [];&lt;br /&gt;
&lt;br /&gt;
			// Check if we are on an array level, &lt;br /&gt;
			if ( Array.isArray( temp_obj ) ) {&lt;br /&gt;
				debuglog(&amp;quot;data is on an array level&amp;quot;);&lt;br /&gt;
				Object.keys( temp_obj ).forEach( function ( ect ) {&lt;br /&gt;
					&lt;br /&gt;
					// if so, try proceeding in all directions.&lt;br /&gt;
					debuglog(&amp;quot;Within partition: &amp;quot; + ect );&lt;br /&gt;
					if ( checkdive( temp_obj[ ect ], moving ) !== undefined ) {&lt;br /&gt;
						future_temp_obj.push( checkdive( temp_obj[ ect ], moving ) );&lt;br /&gt;
					}&lt;br /&gt;
					// Put an element into the return array for each direction we could move into&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				temp_obj = future_temp_obj;&lt;br /&gt;
			&lt;br /&gt;
			} else {&lt;br /&gt;
&lt;br /&gt;
				// if we are not on an array level, proceed with the path&lt;br /&gt;
				&lt;br /&gt;
				debuglog(&amp;quot;data is on an objective level&amp;quot;);&lt;br /&gt;
				&lt;br /&gt;
				if ( checkdive( temp_obj, moving ) !== temp_obj ) {&lt;br /&gt;
					future_temp_obj = checkdive( temp_obj, moving );&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				if ( future_temp_obj !== undefined ){&lt;br /&gt;
					temp_obj = future_temp_obj;&lt;br /&gt;
				} else {&lt;br /&gt;
					debuglog('nothing to see here')&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			// NOTE this function works now but shows syntactic variance between the else branches&lt;br /&gt;
			// Rigorous testing recommended&lt;br /&gt;
&lt;br /&gt;
			return temp_obj;&lt;br /&gt;
		}&lt;br /&gt;
							&lt;br /&gt;
//|||||||||||||||||||||||||||||||||||||||||||||||||||||[  E N D   O F   S T E P   B L O C K    ]|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||&lt;br /&gt;
&lt;br /&gt;
// This function substitutes a bunch of try catches and also tries to dive into 'array' in different ways&lt;br /&gt;
&lt;br /&gt;
		function checkdive( array, read ){&lt;br /&gt;
&lt;br /&gt;
			// simple case, array is an object containing property 'read'&lt;br /&gt;
			&lt;br /&gt;
			if ( check(array, read) !== undefined) {&lt;br /&gt;
				return dive(array, read);&lt;br /&gt;
			} &lt;br /&gt;
			&lt;br /&gt;
			// array case, 'array' is an actual array, lets return an array of successful trials to dive into each direction&lt;br /&gt;
			&lt;br /&gt;
			if ( Array.isArray(array) ) {&lt;br /&gt;
				var potential_return = [];&lt;br /&gt;
				Object.keys(array).forEach( function(item){&lt;br /&gt;
					if ( check(array[item], read) !== undefined ) {&lt;br /&gt;
						potential_return.push( dive( array[item], read) );&lt;br /&gt;
					}&lt;br /&gt;
				});&lt;br /&gt;
				return potential_return;&lt;br /&gt;
			}&lt;br /&gt;
			&lt;br /&gt;
			// mystical case, 'what you have been seeking you had it all along... or at least you have it now'&lt;br /&gt;
			// This is for when you already at a value level, and are looking for that value.&lt;br /&gt;
			// Or when on an object level, and looking for that object&lt;br /&gt;
			// or when on an array level, and looking for that array :O &lt;br /&gt;
			&lt;br /&gt;
			if ( array === read ) {&lt;br /&gt;
				return read;&lt;br /&gt;
			}&lt;br /&gt;
			&lt;br /&gt;
			/* If we did this, it would probably open up a wormhole or a segfault, or that strange error message browsers give when they are maxed out&lt;br /&gt;
&lt;br /&gt;
			if (Object.keys( array ).length &amp;gt; 0 ){&lt;br /&gt;
				Object.keys( array ).forEach( function ( piece ) {&lt;br /&gt;
					if ( array[ piece ] === read ) { return read };&lt;br /&gt;
				});&lt;br /&gt;
			}&lt;br /&gt;
			*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// Try parsing json. If not a json, go void.&lt;br /&gt;
		this.rxjson = function( rx ) {&lt;br /&gt;
			return interjson( rx );&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		function interjson( obj ) {&lt;br /&gt;
			try {&lt;br /&gt;
				return JSON.parse( obj )&lt;br /&gt;
			} catch (e) {&lt;br /&gt;
			// if not JSON, do silly things&lt;br /&gt;
				debuglog('not a json ¯\_(ツ)_/¯');&lt;br /&gt;
			};&lt;br /&gt;
		} &lt;br /&gt;
&lt;br /&gt;
		// Heavyweight solution to suppress error messages. &lt;br /&gt;
&lt;br /&gt;
		function debuglog( l0g ){&lt;br /&gt;
			if ( Debug_switch ) {&lt;br /&gt;
				debuglog( l0g );&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/WbProcessor.js&amp;diff=5294</id>
		<title>User:Abel/WbProcessor.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/WbProcessor.js&amp;diff=5294"/>
		<updated>2019-05-27T18:07:40Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// Wikibase Processor&lt;br /&gt;
console.log('wbprocessor loading');&lt;br /&gt;
&lt;br /&gt;
	function WikibaseProcessorContainer( universe, location ) {&lt;br /&gt;
&lt;br /&gt;
		Debug_switch = false;&lt;br /&gt;
&lt;br /&gt;
		this.main = interjson( checkdive( universe, location ));&lt;br /&gt;
		var the = this.main;&lt;br /&gt;
		&lt;br /&gt;
		/* The following is the main exposed function of the current Wb Processing class&lt;br /&gt;
			usage cases&lt;br /&gt;
&lt;br /&gt;
			to check the last value in a location given by a preceding array of internal paths to find, with the possibility of array layers between elements of array of paths: &lt;br /&gt;
			wbproc.checkentity( [ wbEStruct['instanceOfRelations'], wbEStruct['IDPropLoc'], wbEStruct['IDName'], 96 ] );&lt;br /&gt;
&lt;br /&gt;
			to return for example content of default value given by array of location paths, or check for existence of &lt;br /&gt;
			wbproc.checkentity( { default_value: [ wbEStruct['defaultValRelation'], wbEStruct['IDPropLoc'] ] } )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		*/&lt;br /&gt;
&lt;br /&gt;
		this.checkentity = function ( paths ) {&lt;br /&gt;
			if ( ( the !== undefined ) &amp;amp;&amp;amp; ( paths !== undefined ) ){&lt;br /&gt;
				return proceed( the, paths );&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// Exposed general wrapper for proceed for object other than what the class is originally instanced on, currently unused&lt;br /&gt;
		// Could be used to create a further function to cross check current object with another object 'universe' with another for example&lt;br /&gt;
&lt;br /&gt;
		this.xcontains = function ( unv, angle ) {&lt;br /&gt;
			if ( ( unv !== undefined ) &amp;amp;&amp;amp; ( angle !== undefined ) ){&lt;br /&gt;
				return proceed( unv, angle );&lt;br /&gt;
			};&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/* Exposed helper function to get Entity object of alien entity, if ever needed */&lt;br /&gt;
                &lt;br /&gt;
        this.EnqueueWB = async function( idk ) {&lt;br /&gt;
			var k = await wbqueue(idk);&lt;br /&gt;
			return k;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/* Private part of wb Entity getter */&lt;br /&gt;
&lt;br /&gt;
		async function wbqueue(id) {&lt;br /&gt;
			return new Promise(&lt;br /&gt;
				function(resolve, reject) {&lt;br /&gt;
					$.getJSON('/w/api.php?action=wbgetentities&amp;amp;format=json&amp;amp;ids=' + id, function(json) { &lt;br /&gt;
						var h = json.entities;&lt;br /&gt;
						resolve(h);&lt;br /&gt;
					})&lt;br /&gt;
				}).then( function(result) {&lt;br /&gt;
					debuglog(result);&lt;br /&gt;
					return result;&lt;br /&gt;
				});&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		// the list of private helper functions, could not be accessed from outside&lt;br /&gt;
		// helper function for descend into an object if key exists, otherwise stay at current level of object		&lt;br /&gt;
		function indexinterpolate(obj,i) { return  (obj[i] !== undefined) ? obj[i] : obj}; &lt;br /&gt;
		&lt;br /&gt;
		// helper function for checking a part of an array exists, if it doesn't, go undefined&lt;br /&gt;
		function indexcheck(obj,i) {  if ( obj !== undefined) { return ( obj[i] !== undefined ) ? obj[i] : undefined } };&lt;br /&gt;
		&lt;br /&gt;
		// dive selects matrix.a.b.c.d from the array called matrix and 'a.b.c.d' as string&lt;br /&gt;
		// 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.&lt;br /&gt;
		function dive(array, read){&lt;br /&gt;
			if ( array !== undefined ) {&lt;br /&gt;
				return (read + '').split('.').reduce(indexinterpolate, array);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		// Check returns matrix.a.b.c.d from 'array' ~ 'matrix' and 'read' ~ 'a.b.c.d' only if it exists all the way, otherwise go undefined&lt;br /&gt;
		function check(array, read){&lt;br /&gt;
			if ( array !== undefined ) {&lt;br /&gt;
				return (read + '').split('.').reduce(indexcheck, array);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// Main object / array processing instrument&lt;br /&gt;
		// Array can be a composition of objects and arrays &lt;br /&gt;
		// Read is the instructions, could be an array, or a single path, but for now it should be an object based on our inner convention, example:&lt;br /&gt;
		/* &lt;br /&gt;
			relational_id_list = { &lt;br /&gt;
				controller_id: [ wbEStructure['instanceOfRelations'], wbEStructure['IDPropLoc'], wbEStructure['IDName'], 96 ],&lt;br /&gt;
				personal_data_id: [ wbEStructure['subclassOfRelations'], wbEStructure['IDPropLoc'], wbEStructure['IDName'], 421 ],&lt;br /&gt;
				interface_button_id: [ wbEStructure ['instanceOfRelations'], wbEStructure['IDPropLoc'], wbEStructure['IDName'], 487 ]&lt;br /&gt;
			} &lt;br /&gt;
		*/&lt;br /&gt;
&lt;br /&gt;
		function proceed(array, read) {&lt;br /&gt;
			var ret_obj = {},&lt;br /&gt;
			temp_obj = array,&lt;br /&gt;
&lt;br /&gt;
			// If we encounter something seriously wrong we will just raise a red flag by setting this false, will check before returning this.&lt;br /&gt;
			success_o_meter = true,&lt;br /&gt;
&lt;br /&gt;
			// If all goes well, for each path checked, we will have a member in this&lt;br /&gt;
			future_instructional_return = [];&lt;br /&gt;
			&lt;br /&gt;
//|||||||||||||||||||||||||||||||||||||||||||||||||||||[ I N S T R U C T I O N S  C O N T R O L   ]||||||||||||||||||||||||||||||||||||||||||||||||||||||&lt;br /&gt;
&lt;br /&gt;
			// Init program, check if instructions are an object (not an array but has multiple keys) :&lt;br /&gt;
			// This is the main path of the function. Could be improved to have it for simple array of instructions&lt;br /&gt;
			if ( ( !Array.isArray(read) ) &amp;amp;&amp;amp; ( Object.keys(read).length &amp;gt; 0 ) ) {&lt;br /&gt;
				&lt;br /&gt;
				Object.keys(read).forEach( function(path) {&lt;br /&gt;
				debuglog(&amp;quot;instructions are an object, in path &amp;quot; + path);&lt;br /&gt;
&lt;br /&gt;
//||||||||||||||||||||||||||[ Check if elements of instruction object are arrays themselves ]||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||&lt;br /&gt;
					&lt;br /&gt;
					if ( Array.isArray (read[path]) ) {&lt;br /&gt;
&lt;br /&gt;
						// for each path, future_instructional_return will be filled with the future_return_partition after proceeding through that path&lt;br /&gt;
						var future_return_partition = temp_obj;&lt;br /&gt;
&lt;br /&gt;
						Object.keys(read[path]).forEach( function( path2 ) {&lt;br /&gt;
&lt;br /&gt;
							debuglog(&amp;quot;instructions are an array of arrays, going through &amp;quot; + read[ path ][ path2 ] );&lt;br /&gt;
							// for each step, see if it led anywhere other than where we were.&lt;br /&gt;
							if ( data_function( future_return_partition, read[ path ][ path2 ] ) != future_return_partition ){&lt;br /&gt;
								// if it did, proceed;&lt;br /&gt;
								future_return_partition = data_function( future_return_partition, read[ path ][ path2 ] );&lt;br /&gt;
							} else {&lt;br /&gt;
								// if it didn, raise flag&lt;br /&gt;
								success_o_meter = false;&lt;br /&gt;
							}&lt;br /&gt;
&lt;br /&gt;
//|||||||||||||||||||||||||||||||||||||||||||||||||||[   I N S T R U C T I O N S   C O N T R O L |||||||||||||||||||||||||||||||||||||||||||||||||||||||||&lt;br /&gt;
&lt;br /&gt;
						});&lt;br /&gt;
						//Now that we went through the path, lets see if everything was ok.&lt;br /&gt;
						if ( success_o_meter === true ) {&lt;br /&gt;
						// If yes, put the result of the travel 'future_return_partition' into 'future_instructional_return'&lt;br /&gt;
							&lt;br /&gt;
							debuglog(&amp;quot;arrived at&amp;quot;)&lt;br /&gt;
							debuglog(future_return_partition);&lt;br /&gt;
							future_instructional_return[path] = future_return_partition;&lt;br /&gt;
						} else {&lt;br /&gt;
&lt;br /&gt;
						// Otherwise let's put an undefined in there&lt;br /&gt;
							debuglog(&amp;quot;seeking derailed&amp;quot;);&lt;br /&gt;
							success_o_meter = true;&lt;br /&gt;
							future_instructional_return[path] = undefined;&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
					} &lt;br /&gt;
&lt;br /&gt;
//|||||||||||||||||| If instruction object element is not an array, lets just try to do that one step ||||||||||||||||||||||||||||||||||||||||||||||||||||||||&lt;br /&gt;
// Unused&lt;br /&gt;
					else {&lt;br /&gt;
												&lt;br /&gt;
						// INCLUDE step block with read[path] &lt;br /&gt;
						if ( data_function( temp_obj, read[ path ] ) !== temp_obj  ){&lt;br /&gt;
							future_instructional_return[path] = data_function( temp_obj, read[ path ] ) ;&lt;br /&gt;
						} else {&lt;br /&gt;
							// future_instructional_return.push( undefined );&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
					}&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				// Now that we have gone through all paths, make future return object into what we got&lt;br /&gt;
				temp_obj = future_instructional_return;&lt;br /&gt;
			} &lt;br /&gt;
&lt;br /&gt;
//||||||||||||[ If we are not in instruction object, let's see if we have an instruction array ]||||||||||||||||||||||||||||||||||||||||||||||||||||||||||&lt;br /&gt;
//Unused, this part could be improved&lt;br /&gt;
			else if ( Array.isArray(read) ) {&lt;br /&gt;
				// If so let's follow the array of instructions&lt;br /&gt;
				Object.keys( read ).forEach( function ( ect ) {&lt;br /&gt;
					if ( data_function( temp_obj, read[ ect ] ) !== temp_obj  ){&lt;br /&gt;
						&lt;br /&gt;
						temp_obj = data_function( temp_obj, read[ ect ] );&lt;br /&gt;
&lt;br /&gt;
					} else {&lt;br /&gt;
&lt;br /&gt;
						success_o_meter = false;&lt;br /&gt;
&lt;br /&gt;
					}&lt;br /&gt;
				});&lt;br /&gt;
			} &lt;br /&gt;
&lt;br /&gt;
//||||||||||||[ If we have a single instruction, let's try following that |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||&lt;br /&gt;
//Unused, this part could be improved&lt;br /&gt;
&lt;br /&gt;
			else {&lt;br /&gt;
				&lt;br /&gt;
				if ( data_function( temp_obj, read ) !== temp_obj  ){&lt;br /&gt;
	&lt;br /&gt;
					temp_obj = data_function( temp_obj, read );&lt;br /&gt;
&lt;br /&gt;
				} else {&lt;br /&gt;
&lt;br /&gt;
					success_o_meter = false;&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			&lt;br /&gt;
			// If we haven't got a not found signal along the way, let's try returning the object&lt;br /&gt;
&lt;br /&gt;
			if ( success_o_meter === true ) {&lt;br /&gt;
				return temp_obj;&lt;br /&gt;
			} else {&lt;br /&gt;
				return undefined;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
//|||||||||||||||||||||||||||||||||||||||||||||||||||||[   S T E P   B L O C K   ]||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||&lt;br /&gt;
&lt;br /&gt;
		// Function that takes 1 step. Proceed (along a path) uses this for each step.&lt;br /&gt;
&lt;br /&gt;
		function data_function ( temp_obj, moving ) {&lt;br /&gt;
			&lt;br /&gt;
			// we will return an array&lt;br /&gt;
			var future_temp_obj = [];&lt;br /&gt;
&lt;br /&gt;
			// Check if we are on an array level, &lt;br /&gt;
			if ( Array.isArray( temp_obj ) ) {&lt;br /&gt;
				debuglog(&amp;quot;data is on an array level&amp;quot;);&lt;br /&gt;
				Object.keys( temp_obj ).forEach( function ( ect ) {&lt;br /&gt;
					&lt;br /&gt;
					// if so, try proceeding in all directions.&lt;br /&gt;
					debuglog(&amp;quot;Within partition: &amp;quot; + ect );&lt;br /&gt;
					if ( checkdive( temp_obj[ ect ], moving ) !== undefined ) {&lt;br /&gt;
						future_temp_obj.push( checkdive( temp_obj[ ect ], moving ) );&lt;br /&gt;
					}&lt;br /&gt;
					// Put an element into the return array for each direction we could move into&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				temp_obj = future_temp_obj;&lt;br /&gt;
			&lt;br /&gt;
			} else {&lt;br /&gt;
&lt;br /&gt;
				// if we are not on an array level, proceed with the path&lt;br /&gt;
				&lt;br /&gt;
				debuglog(&amp;quot;data is on an objective level&amp;quot;);&lt;br /&gt;
				&lt;br /&gt;
				if ( checkdive( temp_obj, moving ) !== temp_obj ) {&lt;br /&gt;
					future_temp_obj = checkdive( temp_obj, moving );&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				if ( future_temp_obj !== undefined ){&lt;br /&gt;
					temp_obj = future_temp_obj;&lt;br /&gt;
				} else {&lt;br /&gt;
					debuglog('nothing to see here')&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			// NOTE this function works now but shows syntactic variance between the else branches&lt;br /&gt;
			// Rigorous testing recommended&lt;br /&gt;
&lt;br /&gt;
			return temp_obj;&lt;br /&gt;
		}&lt;br /&gt;
							&lt;br /&gt;
//|||||||||||||||||||||||||||||||||||||||||||||||||||||[  E N D   O F   S T E P   B L O C K    ]|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||&lt;br /&gt;
&lt;br /&gt;
// This function substitutes a bunch of try catches and also tries to dive into 'array' in different ways&lt;br /&gt;
&lt;br /&gt;
		function checkdive( array, read ){&lt;br /&gt;
&lt;br /&gt;
			// simple case, array is an object containing property 'read'&lt;br /&gt;
			&lt;br /&gt;
			if ( check(array, read) !== undefined) {&lt;br /&gt;
				return dive(array, read);&lt;br /&gt;
			} &lt;br /&gt;
			&lt;br /&gt;
			// array case, 'array' is an actual array, lets return an array of successful trials to dive into each direction&lt;br /&gt;
			&lt;br /&gt;
			if ( Array.isArray(array) ) {&lt;br /&gt;
				var potential_return = [];&lt;br /&gt;
				Object.keys(array).forEach( function(item){&lt;br /&gt;
					if ( check(array[item], read) !== undefined ) {&lt;br /&gt;
						potential_return.push( dive( array[item], read) );&lt;br /&gt;
					}&lt;br /&gt;
				});&lt;br /&gt;
				return potential_return;&lt;br /&gt;
			}&lt;br /&gt;
			&lt;br /&gt;
			// mystical case, 'what you have been seeking you had it all along... or at least you have it now'&lt;br /&gt;
			// This is for when you already at a value level, and are looking for that value.&lt;br /&gt;
			// Or when on an object level, and looking for that object&lt;br /&gt;
			// or when on an array level, and looking for that array :O &lt;br /&gt;
			&lt;br /&gt;
			if ( array === read ) {&lt;br /&gt;
				return read;&lt;br /&gt;
			}&lt;br /&gt;
			&lt;br /&gt;
			/* If we did this, it would probably open up a wormhole or a segfault, or that strange error message browsers give when they are maxed out&lt;br /&gt;
&lt;br /&gt;
			if (Object.keys( array ).length &amp;gt; 0 ){&lt;br /&gt;
				Object.keys( array ).forEach( function ( piece ) {&lt;br /&gt;
					if ( array[ piece ] === read ) { return read };&lt;br /&gt;
				});&lt;br /&gt;
			}&lt;br /&gt;
			*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// Try parsing json. If not a json, go void.&lt;br /&gt;
		this.rxjson( rx ) {&lt;br /&gt;
			return interjson( rx );&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		function interjson( obj ) {&lt;br /&gt;
			try {&lt;br /&gt;
				return JSON.parse( obj )&lt;br /&gt;
			} catch (e) {&lt;br /&gt;
			// if not JSON, do silly things&lt;br /&gt;
				debuglog('not a json ¯\_(ツ)_/¯');&lt;br /&gt;
			};&lt;br /&gt;
		} &lt;br /&gt;
&lt;br /&gt;
		// Heavyweight solution to suppress error messages. &lt;br /&gt;
&lt;br /&gt;
		function debuglog( l0g ){&lt;br /&gt;
			if ( Debug_switch ) {&lt;br /&gt;
				debuglog( l0g );&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=5293</id>
		<title>User:Abel/OOInterface.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=5293"/>
		<updated>2019-05-27T18:07:21Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
		notify_porting();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['qIDPropName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
			ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
	&lt;br /&gt;
	function notify_porting() {&lt;br /&gt;
&lt;br /&gt;
		mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
			var button_import = new OO.ui.SelectFileWidget( { label: &amp;quot;Import Personal Data&amp;quot;, classes: [ 'pduimark' ] } ), &lt;br /&gt;
&lt;br /&gt;
				button_export = new OO.ui.ButtonWidget( { label: &amp;quot;Export Personal Data&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
&lt;br /&gt;
				button_import.on( 'change', function (event) {&lt;br /&gt;
&lt;br /&gt;
					if (window.webkitURL != null) {&lt;br /&gt;
						console.log(&amp;quot;loading file on webkit&amp;quot;)&lt;br /&gt;
					} else {&lt;br /&gt;
						console.log(&amp;quot;loading file non webkit&amp;quot;)&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					console.log( event );&lt;br /&gt;
					var input_object = event.target;&lt;br /&gt;
					readFileContent( input_object ).then( function(content) {&lt;br /&gt;
						var data = WikibaseProcessor.rxjson(content);&lt;br /&gt;
						indexedDBobject.EnqueuePDIO('import record', data);&lt;br /&gt;
					});&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			button_export.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
				var get_record = indexedDBobject.EnqueuePDIO('get record');&lt;br /&gt;
&lt;br /&gt;
				get_record.then( function(result) {&lt;br /&gt;
					console.log(&amp;quot;happening&amp;quot;);&lt;br /&gt;
					if ( result === undefined ) { window.alert(&amp;quot;No local data to export&amp;quot;) } else { &lt;br /&gt;
&lt;br /&gt;
						var filename_tosaveas = &amp;quot;pdiolocalexport_&amp;quot; + result.name.user + &amp;quot;_&amp;quot; + Date.now() + '.json';&lt;br /&gt;
						&lt;br /&gt;
						result.id = '';&lt;br /&gt;
						result.name.user = '';&lt;br /&gt;
						&lt;br /&gt;
						var export_to_text = JSON.stringify(result);&lt;br /&gt;
						var textFileAsBlob = new Blob([export_to_text], {type:'text/plain'});&lt;br /&gt;
						var downloadLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
						downloadLink.download = filename_tosaveas;&lt;br /&gt;
						if (window.webkitURL != null)&lt;br /&gt;
						{&lt;br /&gt;
							// Chrome allows the link to be clicked&lt;br /&gt;
							// without actually adding it to the DOM.&lt;br /&gt;
							downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);&lt;br /&gt;
						}&lt;br /&gt;
						else&lt;br /&gt;
						{&lt;br /&gt;
							// Firefox requires the link to be added to the DOM&lt;br /&gt;
							// before it can be clicked.&lt;br /&gt;
							downloadLink.href = window.URL.createObjectURL(textFileAsBlob);&lt;br /&gt;
							downloadLink.style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
							document.body.appendChild(downloadLink);&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
						downloadLink.click();&lt;br /&gt;
&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			mw.notify( $( button_import.$element ), { autoHide: false }  );&lt;br /&gt;
			mw.notify( $( button_export.$element ), { autoHide: false }  );&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=5292</id>
		<title>User:Abel/OOInterface.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=5292"/>
		<updated>2019-05-27T17:53:31Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
		notify_porting();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['qIDPropName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
			ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
	&lt;br /&gt;
	function notify_porting() {&lt;br /&gt;
&lt;br /&gt;
		mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
			var button_import = new OO.ui.SelectFileWidget( { label: &amp;quot;Import Personal Data&amp;quot;, classes: [ 'pduimark' ] } ), &lt;br /&gt;
&lt;br /&gt;
				button_export = new OO.ui.ButtonWidget( { label: &amp;quot;Export Personal Data&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
&lt;br /&gt;
				button_import.on( 'change', function (event) {&lt;br /&gt;
&lt;br /&gt;
					if (window.webkitURL != null) {&lt;br /&gt;
						console.log(&amp;quot;loading file on webkit&amp;quot;)&lt;br /&gt;
					} else {&lt;br /&gt;
						console.log(&amp;quot;loading file non webkit&amp;quot;)&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					console.log( event );&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			button_export.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
				var get_record = indexedDBobject.EnqueuePDIO('get record');&lt;br /&gt;
&lt;br /&gt;
				get_record.then( function(result) {&lt;br /&gt;
					console.log(&amp;quot;happening&amp;quot;);&lt;br /&gt;
					if ( result === undefined ) { window.alert(&amp;quot;No local data to export&amp;quot;) } else { &lt;br /&gt;
&lt;br /&gt;
						var filename_tosaveas = &amp;quot;pdiolocalexport_&amp;quot; + result.name.user + &amp;quot;_&amp;quot; + Date.now() + '.json';&lt;br /&gt;
						&lt;br /&gt;
						result.id = '';&lt;br /&gt;
						result.name.user = '';&lt;br /&gt;
						&lt;br /&gt;
						var export_to_text = JSON.stringify(result);&lt;br /&gt;
						var textFileAsBlob = new Blob([export_to_text], {type:'text/plain'});&lt;br /&gt;
						var downloadLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
						downloadLink.download = filename_tosaveas;&lt;br /&gt;
						if (window.webkitURL != null)&lt;br /&gt;
						{&lt;br /&gt;
							// Chrome allows the link to be clicked&lt;br /&gt;
							// without actually adding it to the DOM.&lt;br /&gt;
							downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);&lt;br /&gt;
						}&lt;br /&gt;
						else&lt;br /&gt;
						{&lt;br /&gt;
							// Firefox requires the link to be added to the DOM&lt;br /&gt;
							// before it can be clicked.&lt;br /&gt;
							downloadLink.href = window.URL.createObjectURL(textFileAsBlob);&lt;br /&gt;
							downloadLink.style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
							document.body.appendChild(downloadLink);&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
						downloadLink.click();&lt;br /&gt;
&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			mw.notify( $( button_import.$element ), { autoHide: false }  );&lt;br /&gt;
			mw.notify( $( button_export.$element ), { autoHide: false }  );&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5291</id>
		<title>User:Abel/PersonalData.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5291"/>
		<updated>2019-05-27T17:53:04Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// Indexeddb JavaScript &lt;br /&gt;
console.log('Indb loading');&lt;br /&gt;
&lt;br /&gt;
function IndexedDBContainer( ww	) {&lt;br /&gt;
&lt;br /&gt;
	// suppress console.log, switch to true for debug&lt;br /&gt;
	var Debug_switch = false;&lt;br /&gt;
	// seemingly the Safari engine uses a somewhat different implementation of arguments for db.transaction and index.get&lt;br /&gt;
	// because no browser on any mac / ios is allowed to use a different engine, rather than user agent, platform can be tested&lt;br /&gt;
	var iOS = !!navigator.platform &amp;amp;&amp;amp; /Macintosh|MacIntel|MacPPC|Mac68K|Mac|iPad|iPhone|iPod/.test(navigator.platform);&lt;br /&gt;
&lt;br /&gt;
	// deterministic hash generator for creating user id#s from usernames, should be replaced by something more functional (guaranteed to be transitively different)&lt;br /&gt;
	hashCode = function(s) {&lt;br /&gt;
		if ( s == undefined) {&lt;br /&gt;
			s = '00'&lt;br /&gt;
		}&lt;br /&gt;
		var h = 0, l = s.length, i = 0;&lt;br /&gt;
		if ( l &amp;gt; 0 )&lt;br /&gt;
			while (i &amp;lt; l)&lt;br /&gt;
				h = (h &amp;lt;&amp;lt; 5) - h + s.charCodeAt(i++) | 0;&lt;br /&gt;
			return h;&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
		if ( ww.user != undefined ) {&lt;br /&gt;
// if user exists in object passed to constructor, get username		&lt;br /&gt;
			var self = ww.user.getName();&lt;br /&gt;
// create userid by hashing username&lt;br /&gt;
			var idgen = hashCode(self);																										&lt;br /&gt;
			debuglog(idgen);&lt;br /&gt;
&lt;br /&gt;
// Take username for standard databasename format:&lt;br /&gt;
// Our current convention for personal databasename (separate dbname for each user)&lt;br /&gt;
			var PersonalDataDataBaseName = &amp;quot;PD.IO&amp;quot; + idgen + &amp;quot;Database&amp;quot;;&lt;br /&gt;
			// Use username in user to get up to date version of self&lt;br /&gt;
// Blank object for personal data Record with id and username included&lt;br /&gt;
			this.CurrentPerson = {id: idgen, name: {user: self}, age: 0};&lt;br /&gt;
			debuglog(PersonalDataDataBaseName);&lt;br /&gt;
			debuglog(this.CurrentPerson);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	// ADD MORE DOC&lt;br /&gt;
&lt;br /&gt;
	// EnqueuePDIO a PDIOLocalDatabase:User database access function with modes&lt;br /&gt;
	// Externally accessible wrapper for Enquire with current user / db preloaded&lt;br /&gt;
&lt;br /&gt;
	this.EnqueuePDIO = async function( sw, c1, c2, c3 ) {&lt;br /&gt;
		debuglog(&amp;quot;enquing pdio db &amp;quot; + PersonalDataDataBaseName + &amp;quot; with user &amp;quot; + JSON.stringify(this.CurrentPerson));&lt;br /&gt;
		var k = await Enquire( PersonalDataDataBaseName, this.CurrentPerson, sw, c1, c2, c3 );&lt;br /&gt;
		return k;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Enquire, a general purpose indexeddb update function with modes&lt;br /&gt;
&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
&lt;br /&gt;
	// Mode 'get record'&lt;br /&gt;
	// updates record given as argument&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
	&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
&lt;br /&gt;
	async function Enquire( pddbname, record, sqitch, control_1, control_2, control_3 ) {&lt;br /&gt;
		return new Promise(&lt;br /&gt;
			function(resolve, reject) {&lt;br /&gt;
&lt;br /&gt;
				var pddb = window.indexedDB.open(pddbname, 3);&lt;br /&gt;
				var inp_obj;&lt;br /&gt;
&lt;br /&gt;
				pddb.onerror = function() {  &lt;br /&gt;
				    console.log(&amp;quot;Warning: Access to IndexedDB for application has been rejected.&amp;quot;);&lt;br /&gt;
				};&lt;br /&gt;
&lt;br /&gt;
				// indexeddb internal mechanism for version tracking of schema&lt;br /&gt;
				pddb.onupgradeneeded = function() {&lt;br /&gt;
					console.log('upgrading database');&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var store = db.createObjectStore(pddbname, {keyPath: &amp;quot;id&amp;quot;});&lt;br /&gt;
					var index = store.createIndex(&amp;quot;NameIndex&amp;quot;, [&amp;quot;id&amp;quot;]);&lt;br /&gt;
						&lt;br /&gt;
				};&lt;br /&gt;
				// Database successfully opened function.&lt;br /&gt;
				pddb.onsuccess = function() {&lt;br /&gt;
					debuglog(pddb.result);&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var tx;&lt;br /&gt;
				&lt;br /&gt;
					if ( iOS ) {&lt;br /&gt;
						tx = db.transaction([pddbname], &amp;quot;readwrite&amp;quot;);&lt;br /&gt;
					} else {&lt;br /&gt;
						tx = db.transaction(pddbname, &amp;quot;readwrite&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
				&lt;br /&gt;
					var store = tx.objectStore(pddbname);&lt;br /&gt;
					var index = store.index(&amp;quot;NameIndex&amp;quot;);	&lt;br /&gt;
&lt;br /&gt;
					// Get the original record from the db...&lt;br /&gt;
					var getRecord;&lt;br /&gt;
					if ( iOS ) {&lt;br /&gt;
					 	getRecord = index.get(record.id);&lt;br /&gt;
					} else {&lt;br /&gt;
						getRecord = index.get([record.id]);&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					getRecord.onsuccess = function() {&lt;br /&gt;
							debuglog( &amp;quot;Record in database: \n &amp;lt;&amp;lt;&amp;quot;);&lt;br /&gt;
							debuglog( getRecord.result );&lt;br /&gt;
							debuglog( &amp;quot;&amp;gt;&amp;gt;&amp;quot;);&lt;br /&gt;
						// Essential recordAdd																													&lt;br /&gt;
						if ( sqitch === &amp;quot;aggressive push&amp;quot; ) {&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
							inp_obj = record;&lt;br /&gt;
							store.put( inp_obj );&lt;br /&gt;
							return inp_obj;&lt;br /&gt;
						} else if ( sqitch === &amp;quot;checkin&amp;quot; ) {&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
							if ( getRecord.result != undefined ) {&lt;br /&gt;
								debuglog(&amp;quot;getting from store&amp;quot;);&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
							} else {&lt;br /&gt;
								debuglog(&amp;quot;overriding whatever in there&amp;quot;);&lt;br /&gt;
								inp_obj = record;&lt;br /&gt;
								store.put(inp_obj);&lt;br /&gt;
							}&lt;br /&gt;
&lt;br /&gt;
						} else {&lt;br /&gt;
	// Methods manipulationg the actual record come here&lt;br /&gt;
	// Update &amp;amp; Remove from&lt;br /&gt;
							// If we got the record from store, use that version to be manipulated&lt;br /&gt;
							if ( getRecord.result !== undefined ) {		&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
								&lt;br /&gt;
								if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
									&lt;br /&gt;
									debuglog(&amp;quot;Getting record&amp;quot;);&lt;br /&gt;
									// we will return later&lt;br /&gt;
									&lt;br /&gt;
								} &lt;br /&gt;
&lt;br /&gt;
								// endof onsuccess&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								debuglog(&amp;quot;Record not found&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
								if ( sqitch === &amp;quot;update record&amp;quot; ) {&lt;br /&gt;
									// Update record will use supplied copy to update it&lt;br /&gt;
									inp_obj = record;&lt;br /&gt;
								} else {&lt;br /&gt;
									if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
										inp_obj = undefined;&lt;br /&gt;
									} else if ( sqitch === &amp;quot;remove from record&amp;quot; ) {&lt;br /&gt;
										inp_obj = record;&lt;br /&gt;
									} else {&lt;br /&gt;
										// any other method ...... would quit as record was not even foun&lt;br /&gt;
										return undefined;&lt;br /&gt;
									}&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
						} &lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;update record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
									if ( control_3 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
										if ( inp_obj[ control_1 ] == undefined ) { inp_obj[ control_1 ] = (isNaN( control_2 )) ? {} : [] };&lt;br /&gt;
										inp_obj[ control_1 ][ control_2 ] = control_3;	// =&amp;gt; &amp;quot;Bob&amp;quot;&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
									} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
										inp_obj[ control_1 ] = inp_obj[ control_1 ] || {};&lt;br /&gt;
										if ( Array.isArray( inp_obj[ control_1 ] ) ) {&lt;br /&gt;
											inp_obj[ control_1 ].push( control_2 );&lt;br /&gt;
										} else {&lt;br /&gt;
											inp_obj[ control_1 ] = control_2;&lt;br /&gt;
										}&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
&lt;br /&gt;
									}&lt;br /&gt;
								} else {&lt;br /&gt;
									// Only one control defined. We will return that part of the record, and change nothing&lt;br /&gt;
									inp_obj = inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								// There's not even control_1, we will just return the record itself&lt;br /&gt;
&lt;br /&gt;
							}&lt;br /&gt;
							debuglog(&amp;quot;return 3&amp;quot;)&lt;br /&gt;
							// return inp_obj;&lt;br /&gt;
&lt;br /&gt;
						};&lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;remove from record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
									&lt;br /&gt;
									if ( Array.isArray( inp_obj[ control_1 ] ) &amp;amp;&amp;amp; !isNaN( control_2 ) ) {&lt;br /&gt;
										inp_obj[ control_1 ].splice( control_2, 1 );&lt;br /&gt;
									} else {&lt;br /&gt;
										delete inp_obj[ control_1 ][ control_2 ];&lt;br /&gt;
									}&lt;br /&gt;
&lt;br /&gt;
								} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
&lt;br /&gt;
									delete inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
							debuglog(&amp;quot;putting object to store:&amp;quot;);&lt;br /&gt;
							debuglog(inp_obj);&lt;br /&gt;
							store.put(inp_obj);&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
	// We are past all methodic code, Async return						&lt;br /&gt;
	&lt;br /&gt;
						resolve( inp_obj );&lt;br /&gt;
&lt;br /&gt;
					};&lt;br /&gt;
	&lt;br /&gt;
	// Indexeddb internal mechanism, close db&lt;br /&gt;
	&lt;br /&gt;
					tx.oncomplete = function() {&lt;br /&gt;
						debuglog(&amp;quot;return 1&amp;quot;)&lt;br /&gt;
						db.close();&lt;br /&gt;
					};&lt;br /&gt;
				};&lt;br /&gt;
				debuglog(&amp;quot;return 0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
	// End of promise&lt;br /&gt;
	&lt;br /&gt;
			}).then( function(result) {&lt;br /&gt;
				debuglog(&amp;quot;Mark 3&amp;quot;);&lt;br /&gt;
				debuglog(result);&lt;br /&gt;
				return result;&lt;br /&gt;
			});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function debuglog( l0g ){&lt;br /&gt;
		if ( Debug_switch ) {&lt;br /&gt;
			console.log( l0g );&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
};&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5290</id>
		<title>User:Abel/PersonalData.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5290"/>
		<updated>2019-05-27T17:52:28Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
		notify_porting();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['qIDPropName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
			ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
	&lt;br /&gt;
	function notify_porting() {&lt;br /&gt;
&lt;br /&gt;
		mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
			var button_import = new OO.ui.SelectFileWidget( { label: &amp;quot;Import Personal Data&amp;quot;, classes: [ 'pduimark' ] } ), &lt;br /&gt;
&lt;br /&gt;
				button_export = new OO.ui.ButtonWidget( { label: &amp;quot;Export Personal Data&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
&lt;br /&gt;
				button_import.on( 'change', function (event) {&lt;br /&gt;
&lt;br /&gt;
					if (window.webkitURL != null) {&lt;br /&gt;
						console.log(&amp;quot;loading file on webkit&amp;quot;)&lt;br /&gt;
					} else {&lt;br /&gt;
						console.log(&amp;quot;loading file non webkit&amp;quot;)&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					console.log( event );&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			button_export.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
				var get_record = indexedDBobject.EnqueuePDIO('get record');&lt;br /&gt;
&lt;br /&gt;
				get_record.then( function(result) {&lt;br /&gt;
					console.log(&amp;quot;happening&amp;quot;);&lt;br /&gt;
					if ( result === undefined ) { window.alert(&amp;quot;No local data to export&amp;quot;) } else { &lt;br /&gt;
&lt;br /&gt;
						var filename_tosaveas = &amp;quot;pdiolocalexport_&amp;quot; + result.name.user + &amp;quot;_&amp;quot; + Date.now() + '.json';&lt;br /&gt;
						&lt;br /&gt;
						result.id = '';&lt;br /&gt;
						result.name.user = '';&lt;br /&gt;
						&lt;br /&gt;
						var export_to_text = JSON.stringify(result);&lt;br /&gt;
						var textFileAsBlob = new Blob([export_to_text], {type:'text/plain'});&lt;br /&gt;
						var downloadLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
						downloadLink.download = filename_tosaveas;&lt;br /&gt;
						if (window.webkitURL != null)&lt;br /&gt;
						{&lt;br /&gt;
							// Chrome allows the link to be clicked&lt;br /&gt;
							// without actually adding it to the DOM.&lt;br /&gt;
							downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);&lt;br /&gt;
						}&lt;br /&gt;
						else&lt;br /&gt;
						{&lt;br /&gt;
							// Firefox requires the link to be added to the DOM&lt;br /&gt;
							// before it can be clicked.&lt;br /&gt;
							downloadLink.href = window.URL.createObjectURL(textFileAsBlob);&lt;br /&gt;
							downloadLink.style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
							document.body.appendChild(downloadLink);&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
						downloadLink.click();&lt;br /&gt;
&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			mw.notify( $( button_import.$element ), { autoHide: false }  );&lt;br /&gt;
			mw.notify( $( button_export.$element ), { autoHide: false }  );&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=MediaWiki:Gadget-personaldata.js&amp;diff=5289</id>
		<title>MediaWiki:Gadget-personaldata.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=MediaWiki:Gadget-personaldata.js&amp;diff=5289"/>
		<updated>2019-05-27T17:46:21Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
		notify_porting();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['qIDPropName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
			ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
	&lt;br /&gt;
	function notify_porting() {&lt;br /&gt;
&lt;br /&gt;
		mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
			var button_import = new OO.ui.SelectFileWidget( { label: &amp;quot;Import Personal Data&amp;quot;, classes: [ 'pduimark' ] } ), &lt;br /&gt;
&lt;br /&gt;
				button_export = new OO.ui.ButtonWidget( { label: &amp;quot;Export Personal Data&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
&lt;br /&gt;
				button_import.on( 'change', function (event) {&lt;br /&gt;
&lt;br /&gt;
					if (window.webkitURL != null) {&lt;br /&gt;
						console.log(&amp;quot;loading file on webkit&amp;quot;)&lt;br /&gt;
					} else {&lt;br /&gt;
						console.log(&amp;quot;loading file non webkit&amp;quot;)&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					console.log( event );&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			button_export.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
				var get_record = indexedDBobject.EnqueuePDIO('get record');&lt;br /&gt;
&lt;br /&gt;
				get_record.then( function(result) {&lt;br /&gt;
					console.log(&amp;quot;happening&amp;quot;);&lt;br /&gt;
					if ( result === undefined ) { window.alert(&amp;quot;No local data to export&amp;quot;) } else { &lt;br /&gt;
&lt;br /&gt;
						var filename_tosaveas = &amp;quot;pdiolocalexport_&amp;quot; + result.name.user + &amp;quot;_&amp;quot; + Date.now() + '.json';&lt;br /&gt;
						&lt;br /&gt;
						result.id = '';&lt;br /&gt;
						result.name.user = '';&lt;br /&gt;
						&lt;br /&gt;
						var export_to_text = JSON.stringify(result);&lt;br /&gt;
						var textFileAsBlob = new Blob([export_to_text], {type:'text/plain'});&lt;br /&gt;
						var downloadLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
						downloadLink.download = filename_tosaveas;&lt;br /&gt;
						if (window.webkitURL != null)&lt;br /&gt;
						{&lt;br /&gt;
							// Chrome allows the link to be clicked&lt;br /&gt;
							// without actually adding it to the DOM.&lt;br /&gt;
							downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);&lt;br /&gt;
						}&lt;br /&gt;
						else&lt;br /&gt;
						{&lt;br /&gt;
							// Firefox requires the link to be added to the DOM&lt;br /&gt;
							// before it can be clicked.&lt;br /&gt;
							downloadLink.href = window.URL.createObjectURL(textFileAsBlob);&lt;br /&gt;
							downloadLink.style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
							document.body.appendChild(downloadLink);&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
						downloadLink.click();&lt;br /&gt;
&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			mw.notify( $( button_import.$element ), { autoHide: false }  );&lt;br /&gt;
			mw.notify( $( button_export.$element ), { autoHide: false }  );&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=MediaWiki:Development_of_SAR_service&amp;diff=5288</id>
		<title>MediaWiki:Development of SAR service</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=MediaWiki:Development_of_SAR_service&amp;diff=5288"/>
		<updated>2019-05-27T15:52:37Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= General information =&lt;br /&gt;
&lt;br /&gt;
* Contractor: [[User:Abel]]&lt;br /&gt;
* Reference: [[architecture of SAR service]]&lt;br /&gt;
* [https://docs.google.com/spreadsheets/d/1J-JxoldE10mKDJNilnE84Wb7ylMZ-B2ArxRiWzYXRz0/edit#gid=0 Logged hours] (request access)&lt;br /&gt;
&lt;br /&gt;
= General instructions =&lt;br /&gt;
* Read and constantly document [[architecture of SAR service]]&lt;br /&gt;
* Always document extensively (comments in code, for instance)&lt;br /&gt;
* Make sure you watch pages that are relevant (star)&lt;br /&gt;
* Be mindful of [https://www.mediawiki.org/wiki/Manual:Coding_conventions/JavaScript Javascript conventions] (within reason)&lt;br /&gt;
* '''Whenever using property or item numbers in code, define a new variable early in the code with that &amp;lt;name&amp;gt;_id locally, for example &amp;quot;controller_item_id = 96&amp;quot; (see {{Q|96}})'''  (this makes the code produced less dependent on which Wikibase instance we are using, as the numbers will change)&lt;br /&gt;
&lt;br /&gt;
= Blockers = &lt;br /&gt;
* Mailto url limits (mainly affected chrome on Windows), see [[How to send emails]]&lt;br /&gt;
&lt;br /&gt;
= Removed blockers = &lt;br /&gt;
* (solved) [https://www.mediawiki.org/wiki/Manual:$wgAllowUserJs user JS] not currently activated on wiki.personaldata.io (but this system can be tested on Wikidata)&lt;br /&gt;
&lt;br /&gt;
= To do =&lt;br /&gt;
The goal is to streamline the SAR process. There are many ways this could be made easier. If one looks at the generated requests, they miss some of the information, particularly identifiers for the individual requesting the data. We want to enable filling some data (like name or telephone number) only once, and then be able to make multiple requests. One way to do this is by using LocalStorage, but which data attributes to collect and where should be stored in the database itself. &lt;br /&gt;
&lt;br /&gt;
Specific instructions:&lt;br /&gt;
* Create a [[SAR tool testing page]], with a OOUI button tied to the mailto, generated through a new [[Template:ButtonMailtoAccess]]. &lt;br /&gt;
* Modify the SAR user script [[MediaWiki:Access.js]] so that this button appears instead.&lt;br /&gt;
* (needs clarification:) Above this button, add an OOUI entry field for first name and last name, dynamically affecting what is launched when clicking the button. If nothing is entered, have some code making explicit what should be entered. &lt;br /&gt;
* (needs clarification:) Starting a separate stream of work, at the top of {{Q|119}} (or rather all &amp;quot;instance of&amp;quot; &amp;quot;personal attribute&amp;quot;), add an entry field to store the phone number --or that attribute-- locally (using [https://www.mediawiki.org/wiki/ResourceLoader/Core_modules#mediawiki.storage LocalStorage])&lt;br /&gt;
* Implement an [[MediaWiki:InterfaceButton.js]] script, displaying a button based on data contained in an item (for instance: {{Q|488}}), and interacting with client-side storage (data stored in a key given by &amp;quot;concerns&amp;quot; field)&lt;br /&gt;
* Based on selector on &amp;quot;instance of&amp;quot; &amp;quot;interface button&amp;quot;, implemented in [[MediaWiki:Common.js]], make this button appear at the top of the &amp;quot;interface button&amp;quot; pages (by reusing [[MediaWiki:InterfaceButton.js]] of course).&lt;br /&gt;
&lt;br /&gt;
= Done =&lt;br /&gt;
* Modify the [[MediaWiki:Access.js]] code to follow the conventions above. &lt;br /&gt;
* Make sure the SAR popup only shows up selectively, for those items that are &amp;quot;instance of&amp;quot; &amp;quot;data controller&amp;quot; (here: [http://wiki.personaldata.io/wiki/Property:P3 P3]--{{Q|96}})&lt;br /&gt;
* Have a look at [https://www.mediawiki.org/wiki/OOUI OOUI]&lt;br /&gt;
&lt;br /&gt;
= To be tested = &lt;br /&gt;
* On any page on &amp;quot;instance of&amp;quot; &amp;quot;interface button&amp;quot; , test whether the save function to localstorage works ( whether input data persists after page reload / browser restart ). Cross platform/browser compatibility should include Firefox, Chrome under Android, Firefox, Chrome under Windows 10, Safari, Firefox, Chrome under MacOS and as well as under iOS&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=MediaWiki:Development_of_SAR_service&amp;diff=5286</id>
		<title>MediaWiki:Development of SAR service</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=MediaWiki:Development_of_SAR_service&amp;diff=5286"/>
		<updated>2019-05-27T15:49:51Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= General information =&lt;br /&gt;
&lt;br /&gt;
* Contractor: [[User:Abel]]&lt;br /&gt;
* Reference: [[architecture of SAR service]]&lt;br /&gt;
* [https://docs.google.com/spreadsheets/d/1J-JxoldE10mKDJNilnE84Wb7ylMZ-B2ArxRiWzYXRz0/edit#gid=0 Logged hours] (request access)&lt;br /&gt;
&lt;br /&gt;
= General instructions =&lt;br /&gt;
* Read and constantly document [[architecture of SAR service]]&lt;br /&gt;
* Always document extensively (comments in code, for instance)&lt;br /&gt;
* Make sure you watch pages that are relevant (star)&lt;br /&gt;
* Be mindful of [https://www.mediawiki.org/wiki/Manual:Coding_conventions/JavaScript Javascript conventions] (within reason)&lt;br /&gt;
* '''Whenever using property or item numbers in code, define a new variable early in the code with that &amp;lt;name&amp;gt;_id locally, for example &amp;quot;controller_item_id = 96&amp;quot; (see {{Q|96}})'''  (this makes the code produced less dependent on which Wikibase instance we are using, as the numbers will change)&lt;br /&gt;
&lt;br /&gt;
= Blockers = &lt;br /&gt;
* Mailto url limits (mainly affected chrome on Windows), see [[How to send emails]]&lt;br /&gt;
&lt;br /&gt;
= Removed blockers = &lt;br /&gt;
* (solved) [https://www.mediawiki.org/wiki/Manual:$wgAllowUserJs user JS] not currently activated on wiki.personaldata.io (but this system can be tested on Wikidata)&lt;br /&gt;
&lt;br /&gt;
= To do =&lt;br /&gt;
The goal is to streamline the SAR process. There are many ways this could be made easier. If one looks at the generated requests, they miss some of the information, particularly identifiers for the individual requesting the data. We want to enable filling some data (like name or telephone number) only once, and then be able to make multiple requests. One way to do this is by using LocalStorage, but which data attributes to collect and where should be stored in the database itself. &lt;br /&gt;
&lt;br /&gt;
Specific instructions:&lt;br /&gt;
* Create a [[SAR tool testing page]], with a OOUI button tied to the mailto, generated through a new [[Template:ButtonMailtoAccess]]. &lt;br /&gt;
* Modify the SAR user script [[MediaWiki:Access.js]] so that this button appears instead.&lt;br /&gt;
* (needs clarification:) Above this button, add an OOUI entry field for first name and last name, dynamically affecting what is launched when clicking the button. If nothing is entered, have some code making explicit what should be entered. &lt;br /&gt;
* (needs clarification:) Starting a separate stream of work, at the top of {{Q|119}} (or rather all &amp;quot;instance of&amp;quot; &amp;quot;personal attribute&amp;quot;), add an entry field to store the phone number --or that attribute-- locally (using [https://www.mediawiki.org/wiki/ResourceLoader/Core_modules#mediawiki.storage LocalStorage])&lt;br /&gt;
* Implement an [[MediaWiki:InterfaceButton.js]] script, displaying a button based on data contained in an item (for instance: {{Q|488}}), and interacting with client-side storage (data stored in a key given by &amp;quot;concerns&amp;quot; field)&lt;br /&gt;
* Based on selector on &amp;quot;instance of&amp;quot; &amp;quot;interface button&amp;quot;, implemented in [[MediaWiki:Common.js]], make this button appear at the top of the &amp;quot;interface button&amp;quot; pages (by reusing [[MediaWiki:InterfaceButton.js]] of course).&lt;br /&gt;
&lt;br /&gt;
= Done =&lt;br /&gt;
* Modify the [[MediaWiki:Access.js]] code to follow the conventions above. &lt;br /&gt;
* Make sure the SAR popup only shows up selectively, for those items that are &amp;quot;instance of&amp;quot; &amp;quot;data controller&amp;quot; (here: [http://wiki.personaldata.io/wiki/Property:P3 P3]--{{Q|96}})&lt;br /&gt;
* Have a look at [https://www.mediawiki.org/wiki/OOUI OOUI]&lt;br /&gt;
&lt;br /&gt;
= To be tested = &lt;br /&gt;
* On any page on &amp;quot;instance of&amp;quot; &amp;quot;interface button&amp;quot; , test whether the save function to localstorage works ( whether input data persists after page reload / browser restart )&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=5274</id>
		<title>User:Abel/OOInterface.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=5274"/>
		<updated>2019-05-27T15:30:15Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
		notify_porting();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['qIDPropName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
			ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
	&lt;br /&gt;
	function notify_porting() {&lt;br /&gt;
&lt;br /&gt;
		mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
			var button_import = new OO.ui.SelectFileWidget( { label: &amp;quot;Import Personal Data&amp;quot;, classes: [ 'pduimark' ] } ), &lt;br /&gt;
&lt;br /&gt;
				button_export = new OO.ui.ButtonWidget( { label: &amp;quot;Export Personal Data&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
&lt;br /&gt;
				button_import.on( 'change', function (event) {&lt;br /&gt;
&lt;br /&gt;
					if (window.webkitURL != null) {&lt;br /&gt;
						console.log(&amp;quot;loading file on webkit&amp;quot;)&lt;br /&gt;
					} else {&lt;br /&gt;
						console.log(&amp;quot;loading file non webkit&amp;quot;)&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					var imp_obj = JSON.parse( event.target.result );&lt;br /&gt;
					console.log( imp_obj );&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			button_export.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
				var get_record = indexedDBobject.EnqueuePDIO('get record');&lt;br /&gt;
&lt;br /&gt;
				get_record.then( function(result) {&lt;br /&gt;
					console.log(&amp;quot;happening&amp;quot;);&lt;br /&gt;
					if ( result === undefined ) { window.alert(&amp;quot;No local data to export&amp;quot;) } else { &lt;br /&gt;
&lt;br /&gt;
						var filename_tosaveas = &amp;quot;pdiolocalexport_&amp;quot; + result.name.user + &amp;quot;_&amp;quot; + Date.now() + '.json';&lt;br /&gt;
						&lt;br /&gt;
						result.id = '';&lt;br /&gt;
						result.name.user = '';&lt;br /&gt;
						&lt;br /&gt;
						var export_to_text = JSON.stringify(result);&lt;br /&gt;
						var textFileAsBlob = new Blob([export_to_text], {type:'text/plain'});&lt;br /&gt;
						var downloadLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
						downloadLink.download = filename_tosaveas;&lt;br /&gt;
						if (window.webkitURL != null)&lt;br /&gt;
						{&lt;br /&gt;
							// Chrome allows the link to be clicked&lt;br /&gt;
							// without actually adding it to the DOM.&lt;br /&gt;
							downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);&lt;br /&gt;
						}&lt;br /&gt;
						else&lt;br /&gt;
						{&lt;br /&gt;
							// Firefox requires the link to be added to the DOM&lt;br /&gt;
							// before it can be clicked.&lt;br /&gt;
							downloadLink.href = window.URL.createObjectURL(textFileAsBlob);&lt;br /&gt;
							downloadLink.style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
							document.body.appendChild(downloadLink);&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
						downloadLink.click();&lt;br /&gt;
&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			mw.notify( $( button_import.$element ), { autoHide: false }  );&lt;br /&gt;
			mw.notify( $( button_export.$element ), { autoHide: false }  );&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=5273</id>
		<title>User:Abel/OOInterface.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=5273"/>
		<updated>2019-05-27T15:28:57Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
		notify_porting();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['qIDPropName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
			ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
	&lt;br /&gt;
	function notify_porting() {&lt;br /&gt;
&lt;br /&gt;
		mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
			var button_import = new OO.ui.SelectFileWidget( { label: &amp;quot;Import Personal Data&amp;quot;, classes: [ 'pduimark' ] } ), &lt;br /&gt;
&lt;br /&gt;
				button_export = new OO.ui.ButtonWidget( { label: &amp;quot;Export Personal Data&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
&lt;br /&gt;
				button_import.on( 'change', function () {&lt;br /&gt;
&lt;br /&gt;
					if (window.webkitURL != null) {&lt;br /&gt;
						console.log(&amp;quot;loading file on webkit&amp;quot;)&lt;br /&gt;
					} else {&lt;br /&gt;
						console.log(&amp;quot;loading file non webkit&amp;quot;)&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					var imp_obj = JSON.parse( button_import.$content );&lt;br /&gt;
					console.log( imp_obj );&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			button_export.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
				var get_record = indexedDBobject.EnqueuePDIO('get record');&lt;br /&gt;
&lt;br /&gt;
				get_record.then( function(result) {&lt;br /&gt;
					console.log(&amp;quot;happening&amp;quot;);&lt;br /&gt;
					if ( result === undefined ) { window.alert(&amp;quot;No local data to export&amp;quot;) } else { &lt;br /&gt;
&lt;br /&gt;
						var filename_tosaveas = &amp;quot;pdiolocalexport_&amp;quot; + result.name.user + &amp;quot;_&amp;quot; + Date.now() + '.json';&lt;br /&gt;
						&lt;br /&gt;
						result.id = '';&lt;br /&gt;
						result.name.user = '';&lt;br /&gt;
						&lt;br /&gt;
						var export_to_text = JSON.stringify(result);&lt;br /&gt;
						var textFileAsBlob = new Blob([export_to_text], {type:'text/plain'});&lt;br /&gt;
						var downloadLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
						downloadLink.download = filename_tosaveas;&lt;br /&gt;
						if (window.webkitURL != null)&lt;br /&gt;
						{&lt;br /&gt;
							// Chrome allows the link to be clicked&lt;br /&gt;
							// without actually adding it to the DOM.&lt;br /&gt;
							downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);&lt;br /&gt;
						}&lt;br /&gt;
						else&lt;br /&gt;
						{&lt;br /&gt;
							// Firefox requires the link to be added to the DOM&lt;br /&gt;
							// before it can be clicked.&lt;br /&gt;
							downloadLink.href = window.URL.createObjectURL(textFileAsBlob);&lt;br /&gt;
							downloadLink.style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
							document.body.appendChild(downloadLink);&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
						downloadLink.click();&lt;br /&gt;
&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			mw.notify( $( button_import.$element ), { autoHide: false }  );&lt;br /&gt;
			mw.notify( $( button_export.$element ), { autoHide: false }  );&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=5271</id>
		<title>User:Abel/OOInterface.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=5271"/>
		<updated>2019-05-27T15:26:23Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
		notify_porting();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['qIDPropName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
			ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
	&lt;br /&gt;
	function notify_porting() {&lt;br /&gt;
&lt;br /&gt;
		mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
			var button_import = new OO.ui.SelectFileWidget( { label: &amp;quot;Import Personal Data&amp;quot;, classes: [ 'pduimark' ] } ), &lt;br /&gt;
&lt;br /&gt;
				button_export = new OO.ui.ButtonWidget( { label: &amp;quot;Export Personal Data&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
&lt;br /&gt;
				button_import.on( 'change', function () {&lt;br /&gt;
&lt;br /&gt;
					if (window.webkitURL != null) {&lt;br /&gt;
						console.log(&amp;quot;loading file on webkit&amp;quot;)&lt;br /&gt;
					} else {&lt;br /&gt;
						console.log(&amp;quot;loading file non webkit&amp;quot;)&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			button_export.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
				var get_record = indexedDBobject.EnqueuePDIO('get record');&lt;br /&gt;
&lt;br /&gt;
				get_record.then( function(result) {&lt;br /&gt;
					console.log(&amp;quot;happening&amp;quot;);&lt;br /&gt;
					if ( result === undefined ) { window.alert(&amp;quot;No local data to export&amp;quot;) } else { &lt;br /&gt;
&lt;br /&gt;
						var filename_tosaveas = &amp;quot;pdiolocalexport_&amp;quot; + result.name.user + &amp;quot;_&amp;quot; + Date.now() + '.json';&lt;br /&gt;
						&lt;br /&gt;
						result.id = '';&lt;br /&gt;
						result.name.user = '';&lt;br /&gt;
						&lt;br /&gt;
						var export_to_text = JSON.stringify(result);&lt;br /&gt;
						var textFileAsBlob = new Blob([export_to_text], {type:'text/plain'});&lt;br /&gt;
						var downloadLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
						downloadLink.download = filename_tosaveas;&lt;br /&gt;
						if (window.webkitURL != null)&lt;br /&gt;
						{&lt;br /&gt;
							// Chrome allows the link to be clicked&lt;br /&gt;
							// without actually adding it to the DOM.&lt;br /&gt;
							downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);&lt;br /&gt;
						}&lt;br /&gt;
						else&lt;br /&gt;
						{&lt;br /&gt;
							// Firefox requires the link to be added to the DOM&lt;br /&gt;
							// before it can be clicked.&lt;br /&gt;
							downloadLink.href = window.URL.createObjectURL(textFileAsBlob);&lt;br /&gt;
							downloadLink.style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
							document.body.appendChild(downloadLink);&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
						downloadLink.click();&lt;br /&gt;
&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			mw.notify( $( button_import.$element ), { autoHide: false }  );&lt;br /&gt;
			mw.notify( $( button_export.$element ), { autoHide: false }  );&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5258</id>
		<title>User:Abel/PersonalData.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5258"/>
		<updated>2019-05-27T15:04:26Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// Indexeddb JavaScript &lt;br /&gt;
console.log('Indb loading');&lt;br /&gt;
&lt;br /&gt;
function IndexedDBContainer( ww	) {&lt;br /&gt;
&lt;br /&gt;
	// suppress console.log, switch to true for debug&lt;br /&gt;
	var Debug_switch = false;&lt;br /&gt;
	// seemingly the Safari engine uses a somewhat different implementation of arguments for db.transaction and index.get&lt;br /&gt;
	// because no browser on any mac / ios is allowed to use a different engine, rather than user agent, platform can be tested&lt;br /&gt;
	var iOS = !!navigator.platform &amp;amp;&amp;amp; /Macintosh|MacIntel|MacPPC|Mac68K|Mac|iPad|iPhone|iPod/.test(navigator.platform);&lt;br /&gt;
&lt;br /&gt;
	// deterministic hash generator for creating user id#s from usernames, should be replaced by something more functional (guaranteed to be transitively different)&lt;br /&gt;
	hashCode = function(s) {&lt;br /&gt;
		if ( s == undefined) {&lt;br /&gt;
			s = '00'&lt;br /&gt;
		}&lt;br /&gt;
		var h = 0, l = s.length, i = 0;&lt;br /&gt;
		if ( l &amp;gt; 0 )&lt;br /&gt;
			while (i &amp;lt; l)&lt;br /&gt;
				h = (h &amp;lt;&amp;lt; 5) - h + s.charCodeAt(i++) | 0;&lt;br /&gt;
			return h;&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
		if ( ww.user != undefined ) {&lt;br /&gt;
// if user exists in object passed to constructor, get username		&lt;br /&gt;
			var self = ww.user.getName();&lt;br /&gt;
// create userid by hashing username&lt;br /&gt;
			var idgen = hashCode(self);																										&lt;br /&gt;
			debuglog(idgen);&lt;br /&gt;
&lt;br /&gt;
// Take username for standard databasename format:&lt;br /&gt;
// Our current convention for personal databasename (separate dbname for each user)&lt;br /&gt;
			var PersonalDataDataBaseName = &amp;quot;PD.IO&amp;quot; + idgen + &amp;quot;Database&amp;quot;;&lt;br /&gt;
			// Use username in user to get up to date version of self&lt;br /&gt;
// Blank object for personal data Record with id and username included&lt;br /&gt;
			this.CurrentPerson = {id: idgen, name: {user: self}, age: 0};&lt;br /&gt;
			debuglog(PersonalDataDataBaseName);&lt;br /&gt;
			debuglog(this.CurrentPerson);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	// ADD MORE DOC&lt;br /&gt;
&lt;br /&gt;
	// EnqueuePDIO a PDIOLocalDatabase:User database access function with modes&lt;br /&gt;
	// Externally accessible wrapper for Enquire with current user / db preloaded&lt;br /&gt;
&lt;br /&gt;
	this.EnqueuePDIO = async function( sw, c1, c2, c3 ) {&lt;br /&gt;
		debuglog(&amp;quot;enquing pdio db &amp;quot; + PersonalDataDataBaseName + &amp;quot; with user &amp;quot; + JSON.stringify(this.CurrentPerson));&lt;br /&gt;
		var k = await Enquire( PersonalDataDataBaseName, this.CurrentPerson, sw, c1, c2, c3 );&lt;br /&gt;
		return k;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Enquire, a general purpose indexeddb update function with modes&lt;br /&gt;
&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
&lt;br /&gt;
	// Mode 'get record'&lt;br /&gt;
	// updates record given as argument&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
	&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
&lt;br /&gt;
	async function Enquire( pddbname, record, sqitch, control_1, control_2, control_3 ) {&lt;br /&gt;
		return new Promise(&lt;br /&gt;
			function(resolve, reject) {&lt;br /&gt;
&lt;br /&gt;
				var pddb = window.indexedDB.open(pddbname, 3);&lt;br /&gt;
				var inp_obj;&lt;br /&gt;
&lt;br /&gt;
				pddb.onerror = function() {  &lt;br /&gt;
				    console.log(&amp;quot;Warning: Access to IndexedDB for application has been rejected.&amp;quot;);&lt;br /&gt;
				};&lt;br /&gt;
&lt;br /&gt;
				// indexeddb internal mechanism for version tracking of schema&lt;br /&gt;
				pddb.onupgradeneeded = function() {&lt;br /&gt;
					console.log('upgrading database');&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var store = db.createObjectStore(pddbname, {keyPath: &amp;quot;id&amp;quot;});&lt;br /&gt;
					var index = store.createIndex(&amp;quot;NameIndex&amp;quot;, [&amp;quot;id&amp;quot;]);&lt;br /&gt;
						&lt;br /&gt;
				};&lt;br /&gt;
				// Database successfully opened function.&lt;br /&gt;
				pddb.onsuccess = function() {&lt;br /&gt;
					debuglog(pddb.result);&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var tx;&lt;br /&gt;
				&lt;br /&gt;
					if ( iOS ) {&lt;br /&gt;
						tx = db.transaction([pddbname], &amp;quot;readwrite&amp;quot;);&lt;br /&gt;
					} else {&lt;br /&gt;
						tx = db.transaction(pddbname, &amp;quot;readwrite&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
				&lt;br /&gt;
					var store = tx.objectStore(pddbname);&lt;br /&gt;
					var index = store.index(&amp;quot;NameIndex&amp;quot;);	&lt;br /&gt;
&lt;br /&gt;
					// Get the original record from the db...&lt;br /&gt;
					var getRecord;&lt;br /&gt;
					if ( iOS ) {&lt;br /&gt;
					 	getRecord = index.get(record.id);&lt;br /&gt;
					} else {&lt;br /&gt;
						getRecord = index.get([record.id]);&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					getRecord.onsuccess = function() {&lt;br /&gt;
							debuglog( &amp;quot;Record in database: \n &amp;lt;&amp;lt;&amp;quot;);&lt;br /&gt;
							debuglog( getRecord.result );&lt;br /&gt;
							debuglog( &amp;quot;&amp;gt;&amp;gt;&amp;quot;);&lt;br /&gt;
						// Essential recordAdd																													&lt;br /&gt;
						if ( sqitch === &amp;quot;aggressive push&amp;quot; ) {&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
							inp_obj = record;&lt;br /&gt;
							store.put( inp_obj );&lt;br /&gt;
							return inp_obj;&lt;br /&gt;
						} else if ( sqitch === &amp;quot;checkin&amp;quot; ) {&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
							if ( getRecord.result != undefined ) {&lt;br /&gt;
								debuglog(&amp;quot;getting from store&amp;quot;);&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
							} else {&lt;br /&gt;
								debuglog(&amp;quot;overriding whatever in there&amp;quot;);&lt;br /&gt;
								inp_obj = record;&lt;br /&gt;
								store.put(inp_obj);&lt;br /&gt;
							}&lt;br /&gt;
&lt;br /&gt;
						} else {&lt;br /&gt;
	// Methods manipulationg the actual record come here&lt;br /&gt;
	// Update &amp;amp; Remove from&lt;br /&gt;
							// If we got the record from store, use that version to be manipulated&lt;br /&gt;
							if ( getRecord.result !== undefined ) {		&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
								&lt;br /&gt;
								if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
									&lt;br /&gt;
									debuglog(&amp;quot;Getting record&amp;quot;);&lt;br /&gt;
									// we will return later&lt;br /&gt;
									&lt;br /&gt;
								} &lt;br /&gt;
&lt;br /&gt;
								// endof onsuccess&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								debuglog(&amp;quot;Record not found&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
								if ( sqitch === &amp;quot;update record&amp;quot; ) {&lt;br /&gt;
									// Update record will use supplied copy to update it&lt;br /&gt;
									inp_obj = record;&lt;br /&gt;
								} else {&lt;br /&gt;
									if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
										inp_obj = undefined;&lt;br /&gt;
									} else if ( sqitch === &amp;quot;remove from record&amp;quot; ) {&lt;br /&gt;
										inp_obj = record;&lt;br /&gt;
									} else {&lt;br /&gt;
										// any other method ...... would quit as record was not even foun&lt;br /&gt;
										return undefined;&lt;br /&gt;
									}&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
						} &lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;update record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
									if ( control_3 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
										if ( inp_obj[ control_1 ] == undefined ) { inp_obj[ control_1 ] = (isNaN( control_2 )) ? {} : [] };&lt;br /&gt;
										inp_obj[ control_1 ][ control_2 ] = control_3;	// =&amp;gt; &amp;quot;Bob&amp;quot;&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
									} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
										inp_obj[ control_1 ] = inp_obj[ control_1 ] || {};&lt;br /&gt;
										if ( Array.isArray( inp_obj[ control_1 ] ) ) {&lt;br /&gt;
											inp_obj[ control_1 ].push( control_2 );&lt;br /&gt;
										} else {&lt;br /&gt;
											inp_obj[ control_1 ] = control_2;&lt;br /&gt;
										}&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
&lt;br /&gt;
									}&lt;br /&gt;
								} else {&lt;br /&gt;
									// Only one control defined. We will return that part of the record, and change nothing&lt;br /&gt;
									inp_obj = inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								// There's not even control_1, we will just return the record itself&lt;br /&gt;
&lt;br /&gt;
							}&lt;br /&gt;
							debuglog(&amp;quot;return 3&amp;quot;)&lt;br /&gt;
							// return inp_obj;&lt;br /&gt;
&lt;br /&gt;
						};&lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;remove from record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
									&lt;br /&gt;
									if ( Array.isArray( inp_obj[ control_1 ] ) &amp;amp;&amp;amp; !isNaN( control_2 ) ) {&lt;br /&gt;
										inp_obj[ control_1 ].splice( control_2, 1 );&lt;br /&gt;
									} else {&lt;br /&gt;
										delete inp_obj[ control_1 ][ control_2 ];&lt;br /&gt;
									}&lt;br /&gt;
&lt;br /&gt;
								} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
&lt;br /&gt;
									delete inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
							debuglog(&amp;quot;putting object to store:&amp;quot;);&lt;br /&gt;
							debuglog(inp_obj);&lt;br /&gt;
							store.put(inp_obj);&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
	// We are past all methodic code, Async return						&lt;br /&gt;
	&lt;br /&gt;
						resolve( inp_obj );&lt;br /&gt;
&lt;br /&gt;
					};&lt;br /&gt;
	&lt;br /&gt;
	// Indexeddb internal mechanism, close db&lt;br /&gt;
	&lt;br /&gt;
					tx.oncomplete = function() {&lt;br /&gt;
						debuglog(&amp;quot;return 1&amp;quot;)&lt;br /&gt;
						db.close();&lt;br /&gt;
					};&lt;br /&gt;
				};&lt;br /&gt;
				debuglog(&amp;quot;return 0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
	// End of promise&lt;br /&gt;
	&lt;br /&gt;
			}).then( function(result) {&lt;br /&gt;
				debuglog(&amp;quot;Mark 3&amp;quot;);&lt;br /&gt;
				debuglog(result);&lt;br /&gt;
				return result;&lt;br /&gt;
			});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function debuglog( l0g ){&lt;br /&gt;
		if ( Debug_switch ) {&lt;br /&gt;
			console.log( l0g );&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
};&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5249</id>
		<title>User:Abel/PersonalData.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5249"/>
		<updated>2019-05-27T14:46:11Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// Indexeddb JavaScript &lt;br /&gt;
console.log('Indb loading');&lt;br /&gt;
&lt;br /&gt;
function IndexedDBContainer( ww	) {&lt;br /&gt;
&lt;br /&gt;
	// suppress console.log, switch to true for debug&lt;br /&gt;
	var Debug_switch = true;&lt;br /&gt;
	var iOS = !!navigator.platform &amp;amp;&amp;amp; /Macintosh|MacIntel|MacPPC|Mac68K|Mac|iPad|iPhone|iPod/.test(navigator.platform);&lt;br /&gt;
&lt;br /&gt;
	// deterministic hash generator for creating user id#s from usernames, should be replaced by something more functional (guaranteed to be transitively different)&lt;br /&gt;
	hashCode = function(s) {&lt;br /&gt;
		if ( s == undefined) {&lt;br /&gt;
			s = '00'&lt;br /&gt;
		}&lt;br /&gt;
		var h = 0, l = s.length, i = 0;&lt;br /&gt;
		if ( l &amp;gt; 0 )&lt;br /&gt;
			while (i &amp;lt; l)&lt;br /&gt;
				h = (h &amp;lt;&amp;lt; 5) - h + s.charCodeAt(i++) | 0;&lt;br /&gt;
			return h;&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
		if ( ww.user != undefined ) {&lt;br /&gt;
// if user exists in object passed to constructor, get username		&lt;br /&gt;
			var self = ww.user.getName();&lt;br /&gt;
// create userid by hashing username&lt;br /&gt;
			var idgen = hashCode(self);																										&lt;br /&gt;
			debuglog(idgen);&lt;br /&gt;
&lt;br /&gt;
// Take username for standard databasename format:&lt;br /&gt;
// Our current convention for personal databasename (separate dbname for each user)&lt;br /&gt;
			var PersonalDataDataBaseName = &amp;quot;PD.IO&amp;quot; + idgen + &amp;quot;Database&amp;quot;;&lt;br /&gt;
			// Use username in user to get up to date version of self&lt;br /&gt;
// Blank object for personal data Record with id and username included&lt;br /&gt;
			this.CurrentPerson = {id: idgen, name: {user: self}, age: 0};&lt;br /&gt;
			debuglog(PersonalDataDataBaseName);&lt;br /&gt;
			debuglog(this.CurrentPerson);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	// ADD MORE DOC&lt;br /&gt;
&lt;br /&gt;
	// EnqueuePDIO a PDIOLocalDatabase:User database access function with modes&lt;br /&gt;
	// Externally accessible wrapper for Enquire with current user / db preloaded&lt;br /&gt;
&lt;br /&gt;
	this.EnqueuePDIO = async function( sw, c1, c2, c3 ) {&lt;br /&gt;
		debuglog(&amp;quot;enquing pdio db &amp;quot; + PersonalDataDataBaseName + &amp;quot; with user &amp;quot; + JSON.stringify(this.CurrentPerson));&lt;br /&gt;
		var k = await Enquire( PersonalDataDataBaseName, this.CurrentPerson, sw, c1, c2, c3 );&lt;br /&gt;
		return k;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Enquire, a general purpose indexeddb update function with modes&lt;br /&gt;
&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
&lt;br /&gt;
	// Mode 'get record'&lt;br /&gt;
	// updates record given as argument&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
	&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
&lt;br /&gt;
	async function Enquire( pddbname, record, sqitch, control_1, control_2, control_3 ) {&lt;br /&gt;
		return new Promise(&lt;br /&gt;
			function(resolve, reject) {&lt;br /&gt;
&lt;br /&gt;
				var pddb = window.indexedDB.open(pddbname, 3);&lt;br /&gt;
				var inp_obj;&lt;br /&gt;
&lt;br /&gt;
				pddb.onerror = function() {  &lt;br /&gt;
				    console.log(&amp;quot;Warning: Access to IndexedDB for application has been rejected.&amp;quot;);&lt;br /&gt;
				};&lt;br /&gt;
&lt;br /&gt;
				// indexeddb internal mechanism for version tracking of schema&lt;br /&gt;
				pddb.onupgradeneeded = function() {&lt;br /&gt;
					console.log('upgrading database');&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var store = db.createObjectStore(pddbname, {keyPath: &amp;quot;id&amp;quot;});&lt;br /&gt;
					var index = store.createIndex(&amp;quot;NameIndex&amp;quot;, [&amp;quot;id&amp;quot;]);&lt;br /&gt;
						&lt;br /&gt;
				};&lt;br /&gt;
				// Database successfully opened function.&lt;br /&gt;
				pddb.onsuccess = function() {&lt;br /&gt;
					debuglog(pddb.result);&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var tx;&lt;br /&gt;
				&lt;br /&gt;
					if ( iOS ) {&lt;br /&gt;
						tx = db.transaction([pddbname], &amp;quot;readwrite&amp;quot;);&lt;br /&gt;
					} else {&lt;br /&gt;
						tx = db.transaction(pddbname, &amp;quot;readwrite&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
				&lt;br /&gt;
					var store = tx.objectStore(pddbname);&lt;br /&gt;
					var index = store.index(&amp;quot;NameIndex&amp;quot;);	&lt;br /&gt;
&lt;br /&gt;
					// Get the original record from the db...&lt;br /&gt;
					var getRecord;&lt;br /&gt;
					if ( iOS ) {&lt;br /&gt;
					 	getRecord = index.get(record.id);&lt;br /&gt;
					} else {&lt;br /&gt;
						getRecord = index.get([record.id]);&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					getRecord.onsuccess = function() {&lt;br /&gt;
							debuglog( &amp;quot;Record in database: \n &amp;lt;&amp;lt;&amp;quot;);&lt;br /&gt;
							debuglog( getRecord.result );&lt;br /&gt;
							debuglog( &amp;quot;&amp;gt;&amp;gt;&amp;quot;);&lt;br /&gt;
						// Essential recordAdd																													&lt;br /&gt;
						if ( sqitch === &amp;quot;aggressive push&amp;quot; ) {&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
							inp_obj = record;&lt;br /&gt;
							store.put( inp_obj );&lt;br /&gt;
							return inp_obj;&lt;br /&gt;
						} else if ( sqitch === &amp;quot;checkin&amp;quot; ) {&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
							if ( getRecord.result != undefined ) {&lt;br /&gt;
								debuglog(&amp;quot;getting from store&amp;quot;);&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
							} else {&lt;br /&gt;
								debuglog(&amp;quot;overriding whatever in there&amp;quot;);&lt;br /&gt;
								inp_obj = record;&lt;br /&gt;
								store.put(inp_obj);&lt;br /&gt;
							}&lt;br /&gt;
&lt;br /&gt;
						} else {&lt;br /&gt;
	// Methods manipulationg the actual record come here&lt;br /&gt;
	// Update &amp;amp; Remove from&lt;br /&gt;
							// If we got the record from store, use that version to be manipulated&lt;br /&gt;
							if ( getRecord.result !== undefined ) {		&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
								&lt;br /&gt;
								if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
									&lt;br /&gt;
									debuglog(&amp;quot;Getting record&amp;quot;);&lt;br /&gt;
									// we will return later&lt;br /&gt;
									&lt;br /&gt;
								} &lt;br /&gt;
&lt;br /&gt;
								// endof onsuccess&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								debuglog(&amp;quot;Record not found&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
								if ( sqitch === &amp;quot;update record&amp;quot; ) {&lt;br /&gt;
									// Update record will use supplied copy to update it&lt;br /&gt;
									inp_obj = record;&lt;br /&gt;
								} else {&lt;br /&gt;
									if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
										inp_obj = undefined;&lt;br /&gt;
									} else if ( sqitch === &amp;quot;remove from record&amp;quot; ) {&lt;br /&gt;
										inp_obj = record;&lt;br /&gt;
									} else {&lt;br /&gt;
										// any other method ...... would quit as record was not even foun&lt;br /&gt;
										return undefined;&lt;br /&gt;
									}&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
						} &lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;update record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
									if ( control_3 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
										if ( inp_obj[ control_1 ] == undefined ) { inp_obj[ control_1 ] = (isNaN( control_2 )) ? {} : [] };&lt;br /&gt;
										inp_obj[ control_1 ][ control_2 ] = control_3;	// =&amp;gt; &amp;quot;Bob&amp;quot;&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
									} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
										inp_obj[ control_1 ] = inp_obj[ control_1 ] || {};&lt;br /&gt;
										if ( Array.isArray( inp_obj[ control_1 ] ) ) {&lt;br /&gt;
											inp_obj[ control_1 ].push( control_2 );&lt;br /&gt;
										} else {&lt;br /&gt;
											inp_obj[ control_1 ] = control_2;&lt;br /&gt;
										}&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
&lt;br /&gt;
									}&lt;br /&gt;
								} else {&lt;br /&gt;
									// Only one control defined. We will return that part of the record, and change nothing&lt;br /&gt;
									inp_obj = inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								// There's not even control_1, we will just return the record itself&lt;br /&gt;
&lt;br /&gt;
							}&lt;br /&gt;
							debuglog(&amp;quot;return 3&amp;quot;)&lt;br /&gt;
							// return inp_obj;&lt;br /&gt;
&lt;br /&gt;
						};&lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;remove from record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
									&lt;br /&gt;
									if ( Array.isArray( inp_obj[ control_1 ] ) &amp;amp;&amp;amp; !isNaN( control_2 ) ) {&lt;br /&gt;
										inp_obj[ control_1 ].splice( control_2, 1 );&lt;br /&gt;
									} else {&lt;br /&gt;
										delete inp_obj[ control_1 ][ control_2 ];&lt;br /&gt;
									}&lt;br /&gt;
&lt;br /&gt;
								} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
&lt;br /&gt;
									delete inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
							debuglog(&amp;quot;putting object to store:&amp;quot;);&lt;br /&gt;
							debuglog(inp_obj);&lt;br /&gt;
							store.put(inp_obj);&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
	// We are past all methodic code, Async return						&lt;br /&gt;
	&lt;br /&gt;
						resolve( inp_obj );&lt;br /&gt;
&lt;br /&gt;
					};&lt;br /&gt;
	&lt;br /&gt;
	// Indexeddb internal mechanism, close db&lt;br /&gt;
	&lt;br /&gt;
					tx.oncomplete = function() {&lt;br /&gt;
						debuglog(&amp;quot;return 1&amp;quot;)&lt;br /&gt;
						db.close();&lt;br /&gt;
					};&lt;br /&gt;
				};&lt;br /&gt;
				debuglog(&amp;quot;return 0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
	// End of promise&lt;br /&gt;
	&lt;br /&gt;
			}).then( function(result) {&lt;br /&gt;
				debuglog(&amp;quot;Mark 3&amp;quot;);&lt;br /&gt;
				debuglog(result);&lt;br /&gt;
				return result;&lt;br /&gt;
			});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function debuglog( l0g ){&lt;br /&gt;
		if ( Debug_switch ) {&lt;br /&gt;
			console.log( l0g );&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
};&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5243</id>
		<title>User:Abel/PersonalData.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5243"/>
		<updated>2019-05-27T14:37:14Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// Indexeddb JavaScript &lt;br /&gt;
console.log('Indb loading');&lt;br /&gt;
&lt;br /&gt;
function IndexedDBContainer( ww	) {&lt;br /&gt;
&lt;br /&gt;
	// suppress console.log, switch to true for debug&lt;br /&gt;
	var Debug_switch = true;&lt;br /&gt;
	var iOS = !!navigator.platform &amp;amp;&amp;amp; /Macintosh|MacIntel|MacPPC|Mac68K|Mac|iPad|iPhone|iPod/.test(navigator.platform);&lt;br /&gt;
&lt;br /&gt;
	// deterministic hash generator for creating user id#s from usernames, should be replaced by something more functional (guaranteed to be transitively different)&lt;br /&gt;
	hashCode = function(s) {&lt;br /&gt;
		if ( s == undefined) {&lt;br /&gt;
			s = '00'&lt;br /&gt;
		}&lt;br /&gt;
		var h = 0, l = s.length, i = 0;&lt;br /&gt;
		if ( l &amp;gt; 0 )&lt;br /&gt;
			while (i &amp;lt; l)&lt;br /&gt;
				h = (h &amp;lt;&amp;lt; 5) - h + s.charCodeAt(i++) | 0;&lt;br /&gt;
			return h;&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
		if ( ww.user != undefined ) {&lt;br /&gt;
// if user exists in object passed to constructor, get username		&lt;br /&gt;
			var self = ww.user.getName();&lt;br /&gt;
// create userid by hashing username&lt;br /&gt;
			var idgen = hashCode(self);																										&lt;br /&gt;
			debuglog(idgen);&lt;br /&gt;
&lt;br /&gt;
// Take username for standard databasename format:&lt;br /&gt;
// Our current convention for personal databasename (separate dbname for each user)&lt;br /&gt;
			var PersonalDataDataBaseName = &amp;quot;PD.IO&amp;quot; + idgen + &amp;quot;Database&amp;quot;;&lt;br /&gt;
			// Use username in user to get up to date version of self&lt;br /&gt;
// Blank object for personal data Record with id and username included&lt;br /&gt;
			this.CurrentPerson = {id: idgen, name: {user: self}, age: 0};&lt;br /&gt;
			debuglog(PersonalDataDataBaseName);&lt;br /&gt;
			debuglog(this.CurrentPerson);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	// ADD MORE DOC&lt;br /&gt;
&lt;br /&gt;
	// EnqueuePDIO a PDIOLocalDatabase:User database access function with modes&lt;br /&gt;
	// Externally accessible wrapper for Enquire with current user / db preloaded&lt;br /&gt;
&lt;br /&gt;
	this.EnqueuePDIO = async function( sw, c1, c2, c3 ) {&lt;br /&gt;
		debuglog(&amp;quot;enquing pdio db &amp;quot; + PersonalDataDataBaseName + &amp;quot; with user &amp;quot; + JSON.stringify(this.CurrentPerson));&lt;br /&gt;
		var k = await Enquire( PersonalDataDataBaseName, this.CurrentPerson, sw, c1, c2, c3 );&lt;br /&gt;
		return k;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Enquire, a general purpose indexeddb update function with modes&lt;br /&gt;
&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
&lt;br /&gt;
	// Mode 'get record'&lt;br /&gt;
	// updates record given as argument&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
	&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
&lt;br /&gt;
	async function Enquire( pddbname, record, sqitch, control_1, control_2, control_3 ) {&lt;br /&gt;
		return new Promise(&lt;br /&gt;
			function(resolve, reject) {&lt;br /&gt;
&lt;br /&gt;
				var pddb = window.indexedDB.open(pddbname, 3);&lt;br /&gt;
				var inp_obj;&lt;br /&gt;
&lt;br /&gt;
				pddb.onerror = function() {  &lt;br /&gt;
				    console.log(&amp;quot;Warning: Access to IndexedDB for application has been rejected.&amp;quot;);&lt;br /&gt;
				};&lt;br /&gt;
&lt;br /&gt;
				// indexeddb internal mechanism for version tracking of schema&lt;br /&gt;
				pddb.onupgradeneeded = function() {&lt;br /&gt;
					console.log('upgrading database');&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var store = db.createObjectStore(pddbname, {keyPath: &amp;quot;id&amp;quot;});&lt;br /&gt;
					var index;&lt;br /&gt;
						// shouldn't the index be the wiki.personaldata.io username? &lt;br /&gt;
						if ( iOS ) {&lt;br /&gt;
							index = db.store.createIndex(&amp;quot;NameIndex&amp;quot;, [&amp;quot;id&amp;quot;]);&lt;br /&gt;
						} else {&lt;br /&gt;
							index = store.createIndex(&amp;quot;NameIndex&amp;quot;, [&amp;quot;id&amp;quot;]);&lt;br /&gt;
						}&lt;br /&gt;
						&lt;br /&gt;
				};&lt;br /&gt;
				// Database successfully opened function.&lt;br /&gt;
				pddb.onsuccess = function() {&lt;br /&gt;
					debuglog(pddb.result);&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var tx;&lt;br /&gt;
				&lt;br /&gt;
					if ( iOS ) {&lt;br /&gt;
						tx = db.transaction([pddbname], &amp;quot;readwrite&amp;quot;);&lt;br /&gt;
					} else {&lt;br /&gt;
						tx = db.transaction(pddbname, &amp;quot;readwrite&amp;quot;);&lt;br /&gt;
					}&lt;br /&gt;
				&lt;br /&gt;
					var store = tx.objectStore(pddbname);&lt;br /&gt;
					var index = store.index(&amp;quot;NameIndex&amp;quot;);	&lt;br /&gt;
&lt;br /&gt;
					// Get the original record from the db...&lt;br /&gt;
					var getRecord = index.get(record.id);&lt;br /&gt;
&lt;br /&gt;
					getRecord.onsuccess = function() {&lt;br /&gt;
							debuglog( &amp;quot;Record in database: \n &amp;lt;&amp;lt;&amp;quot;);&lt;br /&gt;
							debuglog( getRecord.result );&lt;br /&gt;
							debuglog( &amp;quot;&amp;gt;&amp;gt;&amp;quot;);&lt;br /&gt;
						// Essential recordAdd																													&lt;br /&gt;
						if ( sqitch === &amp;quot;aggressive push&amp;quot; ) {&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
							inp_obj = record;&lt;br /&gt;
							store.put( inp_obj );&lt;br /&gt;
							return inp_obj;&lt;br /&gt;
						} else if ( sqitch === &amp;quot;checkin&amp;quot; ) {&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
							if ( getRecord.result != undefined ) {&lt;br /&gt;
								debuglog(&amp;quot;getting from store&amp;quot;);&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
							} else {&lt;br /&gt;
								debuglog(&amp;quot;overriding whatever in there&amp;quot;);&lt;br /&gt;
								inp_obj = record;&lt;br /&gt;
								store.put(inp_obj);&lt;br /&gt;
							}&lt;br /&gt;
&lt;br /&gt;
						} else {&lt;br /&gt;
	// Methods manipulationg the actual record come here&lt;br /&gt;
	// Update &amp;amp; Remove from&lt;br /&gt;
							// If we got the record from store, use that version to be manipulated&lt;br /&gt;
							if ( getRecord.result !== undefined ) {		&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
								&lt;br /&gt;
								if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
									&lt;br /&gt;
									debuglog(&amp;quot;Getting record&amp;quot;);&lt;br /&gt;
									// we will return later&lt;br /&gt;
									&lt;br /&gt;
								} &lt;br /&gt;
&lt;br /&gt;
								// endof onsuccess&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								debuglog(&amp;quot;Record not found&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
								if ( sqitch === &amp;quot;update record&amp;quot; ) {&lt;br /&gt;
									// Update record will use supplied copy to update it&lt;br /&gt;
									inp_obj = record;&lt;br /&gt;
								} else {&lt;br /&gt;
									if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
										inp_obj = undefined;&lt;br /&gt;
									} else if ( sqitch === &amp;quot;remove from record&amp;quot; ) {&lt;br /&gt;
										inp_obj = record;&lt;br /&gt;
									} else {&lt;br /&gt;
										// any other method ...... would quit as record was not even foun&lt;br /&gt;
										return undefined;&lt;br /&gt;
									}&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
						} &lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;update record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
									if ( control_3 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
										if ( inp_obj[ control_1 ] == undefined ) { inp_obj[ control_1 ] = (isNaN( control_2 )) ? {} : [] };&lt;br /&gt;
										inp_obj[ control_1 ][ control_2 ] = control_3;	// =&amp;gt; &amp;quot;Bob&amp;quot;&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
									} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
										inp_obj[ control_1 ] = inp_obj[ control_1 ] || {};&lt;br /&gt;
										if ( Array.isArray( inp_obj[ control_1 ] ) ) {&lt;br /&gt;
											inp_obj[ control_1 ].push( control_2 );&lt;br /&gt;
										} else {&lt;br /&gt;
											inp_obj[ control_1 ] = control_2;&lt;br /&gt;
										}&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
&lt;br /&gt;
									}&lt;br /&gt;
								} else {&lt;br /&gt;
									// Only one control defined. We will return that part of the record, and change nothing&lt;br /&gt;
									inp_obj = inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								// There's not even control_1, we will just return the record itself&lt;br /&gt;
&lt;br /&gt;
							}&lt;br /&gt;
							debuglog(&amp;quot;return 3&amp;quot;)&lt;br /&gt;
							// return inp_obj;&lt;br /&gt;
&lt;br /&gt;
						};&lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;remove from record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
									&lt;br /&gt;
									if ( Array.isArray( inp_obj[ control_1 ] ) &amp;amp;&amp;amp; !isNaN( control_2 ) ) {&lt;br /&gt;
										inp_obj[ control_1 ].splice( control_2, 1 );&lt;br /&gt;
									} else {&lt;br /&gt;
										delete inp_obj[ control_1 ][ control_2 ];&lt;br /&gt;
									}&lt;br /&gt;
&lt;br /&gt;
								} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
&lt;br /&gt;
									delete inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
							debuglog(&amp;quot;putting object to store:&amp;quot;);&lt;br /&gt;
							debuglog(inp_obj);&lt;br /&gt;
							store.put(inp_obj);&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
	// We are past all methodic code, Async return						&lt;br /&gt;
	&lt;br /&gt;
						resolve( inp_obj );&lt;br /&gt;
&lt;br /&gt;
					};&lt;br /&gt;
	&lt;br /&gt;
	// Indexeddb internal mechanism, close db&lt;br /&gt;
	&lt;br /&gt;
					tx.oncomplete = function() {&lt;br /&gt;
						debuglog(&amp;quot;return 1&amp;quot;)&lt;br /&gt;
						db.close();&lt;br /&gt;
					};&lt;br /&gt;
				};&lt;br /&gt;
				debuglog(&amp;quot;return 0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
	// End of promise&lt;br /&gt;
	&lt;br /&gt;
			}).then( function(result) {&lt;br /&gt;
				debuglog(&amp;quot;Mark 3&amp;quot;);&lt;br /&gt;
				debuglog(result);&lt;br /&gt;
				return result;&lt;br /&gt;
			});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function debuglog( l0g ){&lt;br /&gt;
		if ( Debug_switch ) {&lt;br /&gt;
			console.log( l0g );&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
};&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5220</id>
		<title>User:Abel/PersonalData.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5220"/>
		<updated>2019-05-27T13:53:06Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// Indexeddb JavaScript &lt;br /&gt;
console.log('Indb loading');&lt;br /&gt;
&lt;br /&gt;
function IndexedDBContainer( ww	) {&lt;br /&gt;
&lt;br /&gt;
	// suppress console.log, switch to true for debug&lt;br /&gt;
	var Debug_switch = true;&lt;br /&gt;
	&lt;br /&gt;
	// deterministic hash generator for creating user id#s from usernames, should be replaced by something more functional (guaranteed to be transitively different)&lt;br /&gt;
	hashCode = function(s) {&lt;br /&gt;
		if ( s == undefined) {&lt;br /&gt;
			s = '00'&lt;br /&gt;
		}&lt;br /&gt;
		var h = 0, l = s.length, i = 0;&lt;br /&gt;
		if ( l &amp;gt; 0 )&lt;br /&gt;
			while (i &amp;lt; l)&lt;br /&gt;
				h = (h &amp;lt;&amp;lt; 5) - h + s.charCodeAt(i++) | 0;&lt;br /&gt;
			return h;&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
		if ( ww.user != undefined ) {&lt;br /&gt;
// if user exists in object passed to constructor, get username		&lt;br /&gt;
			var self = ww.user.getName();&lt;br /&gt;
// create userid by hashing username&lt;br /&gt;
			var idgen = hashCode(self);																										&lt;br /&gt;
			debuglog(idgen);&lt;br /&gt;
&lt;br /&gt;
// Take username for standard databasename format:&lt;br /&gt;
// Our current convention for personal databasename (separate dbname for each user)&lt;br /&gt;
			var PersonalDataDataBaseName = &amp;quot;PD.IO&amp;quot; + idgen + &amp;quot;Database&amp;quot;;&lt;br /&gt;
			// Use username in user to get up to date version of self&lt;br /&gt;
// Blank object for personal data Record with id and username included&lt;br /&gt;
			this.CurrentPerson = {id: idgen, name: {user: self}, age: 0};&lt;br /&gt;
			debuglog(PersonalDataDataBaseName);&lt;br /&gt;
			debuglog(this.CurrentPerson);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	// ADD MORE DOC&lt;br /&gt;
&lt;br /&gt;
	// EnqueuePDIO a PDIOLocalDatabase:User database access function with modes&lt;br /&gt;
	// Externally accessible wrapper for Enquire with current user / db preloaded&lt;br /&gt;
&lt;br /&gt;
	this.EnqueuePDIO = async function( sw, c1, c2, c3 ) {&lt;br /&gt;
		debuglog(&amp;quot;enquing pdio db &amp;quot; + PersonalDataDataBaseName + &amp;quot; with user &amp;quot; + JSON.stringify(this.CurrentPerson));&lt;br /&gt;
		var k = await Enquire( PersonalDataDataBaseName, this.CurrentPerson, sw, c1, c2, c3 );&lt;br /&gt;
		return k;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Enquire, a general purpose indexeddb update function with modes&lt;br /&gt;
&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
&lt;br /&gt;
	// Mode 'get record'&lt;br /&gt;
	// updates record given as argument&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
	&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
&lt;br /&gt;
	async function Enquire( pddbname, record, sqitch, control_1, control_2, control_3 ) {&lt;br /&gt;
		return new Promise(&lt;br /&gt;
			function(resolve, reject) {&lt;br /&gt;
&lt;br /&gt;
				var pddb = window.indexedDB.open(pddbname, 3);&lt;br /&gt;
				var inp_obj;&lt;br /&gt;
&lt;br /&gt;
				pddb.onerror = function() {  &lt;br /&gt;
				    console.log(&amp;quot;Warning: Access to IndexedDB for application has been rejected.&amp;quot;);&lt;br /&gt;
				};&lt;br /&gt;
&lt;br /&gt;
				// indexeddb internal mechanism for version tracking of schema&lt;br /&gt;
				pddb.onupgradeneeded = function(evt) {&lt;br /&gt;
					console.log('upgrading database');&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var store = db.createObjectStore(pddbname, {keyPath: &amp;quot;id&amp;quot;});&lt;br /&gt;
&lt;br /&gt;
						// shouldn't the index be the wiki.personaldata.io username? &lt;br /&gt;
&lt;br /&gt;
						var index = db.store.createIndex(&amp;quot;NameIndex&amp;quot;, [&amp;quot;id&amp;quot;]);&lt;br /&gt;
				};&lt;br /&gt;
				// Database successfully opened function.&lt;br /&gt;
				pddb.onsuccess = function(xy) {&lt;br /&gt;
					debuglog(pddb.result);&lt;br /&gt;
					debuglog(xy);&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var tx = db.transaction([pddbname], &amp;quot;readwrite&amp;quot;);&lt;br /&gt;
					var store = tx.objectStore(pddbname);&lt;br /&gt;
					var index = store.index(&amp;quot;NameIndex&amp;quot;);	&lt;br /&gt;
&lt;br /&gt;
					// Get the original record from the db...&lt;br /&gt;
					var getRecord = index.get(record.id);&lt;br /&gt;
&lt;br /&gt;
					getRecord.onsuccess = function() {&lt;br /&gt;
							debuglog( &amp;quot;Record in database: \n &amp;lt;&amp;lt;&amp;quot;);&lt;br /&gt;
							debuglog( getRecord.result );&lt;br /&gt;
							debuglog( &amp;quot;&amp;gt;&amp;gt;&amp;quot;);&lt;br /&gt;
						// Essential recordAdd																													&lt;br /&gt;
						if ( sqitch === &amp;quot;aggressive push&amp;quot; ) {&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
							inp_obj = record;&lt;br /&gt;
							store.put( inp_obj );&lt;br /&gt;
							return inp_obj;&lt;br /&gt;
						} else if ( sqitch === &amp;quot;checkin&amp;quot; ) {&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
							if ( getRecord.result !== undefined ) {&lt;br /&gt;
								debuglog(&amp;quot;getting from store&amp;quot;);&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
							} else {&lt;br /&gt;
								debuglog(&amp;quot;overriding whatever in there&amp;quot;);&lt;br /&gt;
								inp_obj = record;&lt;br /&gt;
								store.put(inp_obj);&lt;br /&gt;
							}&lt;br /&gt;
&lt;br /&gt;
						} else {&lt;br /&gt;
	// Methods manipulationg the actual record come here&lt;br /&gt;
	// Update &amp;amp; Remove from&lt;br /&gt;
							// If we got the record from store, use that version to be manipulated&lt;br /&gt;
							if ( getRecord.result !== undefined ) {		&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
								&lt;br /&gt;
								if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
									&lt;br /&gt;
									debuglog(&amp;quot;Getting record&amp;quot;);&lt;br /&gt;
									// we will return later&lt;br /&gt;
									&lt;br /&gt;
								} &lt;br /&gt;
&lt;br /&gt;
								// endof onsuccess&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								debuglog(&amp;quot;Record not found&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
								if ( sqitch === &amp;quot;update record&amp;quot; ) {&lt;br /&gt;
									// Update record will use supplied copy to update it&lt;br /&gt;
									inp_obj = record;&lt;br /&gt;
								} else {&lt;br /&gt;
									if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
										inp_obj = undefined;&lt;br /&gt;
									} else {&lt;br /&gt;
										return undefined;&lt;br /&gt;
									}&lt;br /&gt;
									// Remove from record will quit as record was not even found&lt;br /&gt;
									&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
						} &lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;update record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
									if ( control_3 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
										if ( inp_obj[ control_1 ] == undefined ) { inp_obj[ control_1 ] = (isNaN( control_2 )) ? {} : [] };&lt;br /&gt;
										inp_obj[ control_1 ][ control_2 ] = control_3;	// =&amp;gt; &amp;quot;Bob&amp;quot;&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
									} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
										inp_obj[ control_1 ] = inp_obj[ control_1 ] || {};&lt;br /&gt;
										if ( Array.isArray( inp_obj[ control_1 ] ) ) {&lt;br /&gt;
											inp_obj[ control_1 ].push( control_2 );&lt;br /&gt;
										} else {&lt;br /&gt;
											inp_obj[ control_1 ] = control_2;&lt;br /&gt;
										}&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
&lt;br /&gt;
									}&lt;br /&gt;
								} else {&lt;br /&gt;
									// Only one control defined. We will return that part of the record, and change nothing&lt;br /&gt;
									inp_obj = inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								// There's not even control_1, we will just return the record itself&lt;br /&gt;
&lt;br /&gt;
							}&lt;br /&gt;
							debuglog(&amp;quot;return 3&amp;quot;)&lt;br /&gt;
							// return inp_obj;&lt;br /&gt;
&lt;br /&gt;
						};&lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;remove from record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
									&lt;br /&gt;
									if ( Array.isArray( inp_obj[ control_1 ] ) &amp;amp;&amp;amp; !isNaN( control_2 ) ) {&lt;br /&gt;
										inp_obj[ control_1 ].splice( control_2, 1 );&lt;br /&gt;
									} else {&lt;br /&gt;
										delete inp_obj[ control_1 ][ control_2 ];&lt;br /&gt;
									}&lt;br /&gt;
&lt;br /&gt;
								} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
&lt;br /&gt;
									delete inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
							debuglog(&amp;quot;putting object to store:&amp;quot;);&lt;br /&gt;
							debuglog(inp_obj);&lt;br /&gt;
							store.put(inp_obj);&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
	// We are past all methodic code, Async return						&lt;br /&gt;
	&lt;br /&gt;
						resolve( inp_obj );&lt;br /&gt;
&lt;br /&gt;
					};&lt;br /&gt;
	&lt;br /&gt;
	// Indexeddb internal mechanism, close db&lt;br /&gt;
	&lt;br /&gt;
					tx.oncomplete = function() {&lt;br /&gt;
						debuglog(&amp;quot;return 1&amp;quot;)&lt;br /&gt;
						db.close();&lt;br /&gt;
					};&lt;br /&gt;
				};&lt;br /&gt;
				debuglog(&amp;quot;return 0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
	// End of promise&lt;br /&gt;
	&lt;br /&gt;
			}).then( function(result) {&lt;br /&gt;
				debuglog(&amp;quot;Mark 3&amp;quot;);&lt;br /&gt;
				debuglog(result);&lt;br /&gt;
				return result;&lt;br /&gt;
			});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function debuglog( l0g ){&lt;br /&gt;
		if ( Debug_switch ) {&lt;br /&gt;
			console.log( l0g );&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
};&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5219</id>
		<title>User:Abel/PersonalData.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5219"/>
		<updated>2019-05-27T13:43:58Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// Indexeddb JavaScript &lt;br /&gt;
console.log('Indb loading');&lt;br /&gt;
&lt;br /&gt;
function IndexedDBContainer( ww	) {&lt;br /&gt;
&lt;br /&gt;
	// suppress console.log, switch to true for debug&lt;br /&gt;
	var Debug_switch = true;&lt;br /&gt;
	&lt;br /&gt;
	// deterministic hash generator for creating user id#s from usernames, should be replaced by something more functional (guaranteed to be transitively different)&lt;br /&gt;
	hashCode = function(s) {&lt;br /&gt;
		if ( s == undefined) {&lt;br /&gt;
			s = '00'&lt;br /&gt;
		}&lt;br /&gt;
		var h = 0, l = s.length, i = 0;&lt;br /&gt;
		if ( l &amp;gt; 0 )&lt;br /&gt;
			while (i &amp;lt; l)&lt;br /&gt;
				h = (h &amp;lt;&amp;lt; 5) - h + s.charCodeAt(i++) | 0;&lt;br /&gt;
			return h;&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
		if ( ww.user != undefined ) {&lt;br /&gt;
// if user exists in object passed to constructor, get username		&lt;br /&gt;
			var self = ww.user.getName();&lt;br /&gt;
// create userid by hashing username&lt;br /&gt;
			var idgen = hashCode(self);																										&lt;br /&gt;
			debuglog(idgen);&lt;br /&gt;
&lt;br /&gt;
// Take username for standard databasename format:&lt;br /&gt;
// Our current convention for personal databasename (separate dbname for each user)&lt;br /&gt;
			var PersonalDataDataBaseName = &amp;quot;PD.IO&amp;quot; + idgen + &amp;quot;Database&amp;quot;;&lt;br /&gt;
			// Use username in user to get up to date version of self&lt;br /&gt;
// Blank object for personal data Record with id and username included&lt;br /&gt;
			this.CurrentPerson = {id: idgen, name: {user: self}, age: 0};&lt;br /&gt;
			debuglog(PersonalDataDataBaseName);&lt;br /&gt;
			debuglog(this.CurrentPerson);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	// ADD MORE DOC&lt;br /&gt;
&lt;br /&gt;
	// EnqueuePDIO a PDIOLocalDatabase:User database access function with modes&lt;br /&gt;
	// Externally accessible wrapper for Enquire with current user / db preloaded&lt;br /&gt;
&lt;br /&gt;
	this.EnqueuePDIO = async function( sw, c1, c2, c3 ) {&lt;br /&gt;
		debuglog(&amp;quot;enquing pdio db &amp;quot; + PersonalDataDataBaseName + &amp;quot; with user &amp;quot; + JSON.stringify(this.CurrentPerson));&lt;br /&gt;
		var k = await Enquire( PersonalDataDataBaseName, this.CurrentPerson, sw, c1, c2, c3 );&lt;br /&gt;
		return k;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Enquire, a general purpose indexeddb update function with modes&lt;br /&gt;
&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
&lt;br /&gt;
	// Mode 'get record'&lt;br /&gt;
	// updates record given as argument&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
	&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
&lt;br /&gt;
	async function Enquire( pddbname, record, sqitch, control_1, control_2, control_3 ) {&lt;br /&gt;
		return new Promise(&lt;br /&gt;
			function(resolve, reject) {&lt;br /&gt;
&lt;br /&gt;
				var pddb = window.indexedDB.open(pddbname, 3);&lt;br /&gt;
				var inp_obj;&lt;br /&gt;
&lt;br /&gt;
				pddb.onerror = function() {  &lt;br /&gt;
				    console.log(&amp;quot;Warning: Access to IndexedDB for application has been rejected.&amp;quot;);&lt;br /&gt;
				};&lt;br /&gt;
&lt;br /&gt;
				// indexeddb internal mechanism for version tracking of schema&lt;br /&gt;
				pddb.onupgradeneeded = function(evt) {&lt;br /&gt;
					console.log('upgrading database');&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var store = db.createObjectStore(pddbname, {keyPath: &amp;quot;id&amp;quot;});&lt;br /&gt;
&lt;br /&gt;
						// shouldn't the index be the wiki.personaldata.io username? &lt;br /&gt;
&lt;br /&gt;
						var index = db.store.createIndex(&amp;quot;NameIndex&amp;quot;, [&amp;quot;id&amp;quot;]);&lt;br /&gt;
				};&lt;br /&gt;
				// Database successfully opened function.&lt;br /&gt;
				pddb.onsuccess = function(xy) {&lt;br /&gt;
					debuglog(pddb.result);&lt;br /&gt;
					debuglog(xy);&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var tx = db.transaction(pddbname, &amp;quot;readwrite&amp;quot;);&lt;br /&gt;
					var store = tx.objectStore(pddbname);&lt;br /&gt;
					var index = store.index(&amp;quot;NameIndex&amp;quot;);	&lt;br /&gt;
&lt;br /&gt;
					// Get the original record from the db...&lt;br /&gt;
					var getRecord = index.get([record.id]);&lt;br /&gt;
&lt;br /&gt;
					getRecord.onsuccess = function() {&lt;br /&gt;
							debuglog( &amp;quot;Record in database: \n &amp;lt;&amp;lt;&amp;quot;);&lt;br /&gt;
							debuglog( getRecord.result );&lt;br /&gt;
							debuglog( &amp;quot;&amp;gt;&amp;gt;&amp;quot;);&lt;br /&gt;
						// Essential recordAdd																													&lt;br /&gt;
						if ( sqitch === &amp;quot;aggressive push&amp;quot; ) {&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
							inp_obj = record;&lt;br /&gt;
							store.put( inp_obj );&lt;br /&gt;
							return inp_obj;&lt;br /&gt;
						} else if ( sqitch === &amp;quot;checkin&amp;quot; ) {&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
							if ( getRecord.result !== undefined ) {&lt;br /&gt;
								debuglog(&amp;quot;getting from store&amp;quot;);&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
							} else {&lt;br /&gt;
								debuglog(&amp;quot;overriding whatever in there&amp;quot;);&lt;br /&gt;
								inp_obj = record;&lt;br /&gt;
								store.put(inp_obj);&lt;br /&gt;
							}&lt;br /&gt;
&lt;br /&gt;
						} else {&lt;br /&gt;
	// Methods manipulationg the actual record come here&lt;br /&gt;
	// Update &amp;amp; Remove from&lt;br /&gt;
							// If we got the record from store, use that version to be manipulated&lt;br /&gt;
							if ( getRecord.result !== undefined ) {		&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
								&lt;br /&gt;
								if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
									&lt;br /&gt;
									debuglog(&amp;quot;Getting record&amp;quot;);&lt;br /&gt;
									// we will return later&lt;br /&gt;
									&lt;br /&gt;
								} &lt;br /&gt;
&lt;br /&gt;
								// endof onsuccess&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								debuglog(&amp;quot;Record not found&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
								if ( sqitch === &amp;quot;update record&amp;quot; ) {&lt;br /&gt;
									// Update record will use supplied copy to update it&lt;br /&gt;
									inp_obj = record;&lt;br /&gt;
								} else {&lt;br /&gt;
									if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
										inp_obj = undefined;&lt;br /&gt;
									} else {&lt;br /&gt;
										return undefined;&lt;br /&gt;
									}&lt;br /&gt;
									// Remove from record will quit as record was not even found&lt;br /&gt;
									&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
						} &lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;update record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
									if ( control_3 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
										if ( inp_obj[ control_1 ] == undefined ) { inp_obj[ control_1 ] = (isNaN( control_2 )) ? {} : [] };&lt;br /&gt;
										inp_obj[ control_1 ][ control_2 ] = control_3;	// =&amp;gt; &amp;quot;Bob&amp;quot;&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
									} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
										inp_obj[ control_1 ] = inp_obj[ control_1 ] || {};&lt;br /&gt;
										if ( Array.isArray( inp_obj[ control_1 ] ) ) {&lt;br /&gt;
											inp_obj[ control_1 ].push( control_2 );&lt;br /&gt;
										} else {&lt;br /&gt;
											inp_obj[ control_1 ] = control_2;&lt;br /&gt;
										}&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
&lt;br /&gt;
									}&lt;br /&gt;
								} else {&lt;br /&gt;
									// Only one control defined. We will return that part of the record, and change nothing&lt;br /&gt;
									inp_obj = inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								// There's not even control_1, we will just return the record itself&lt;br /&gt;
&lt;br /&gt;
							}&lt;br /&gt;
							debuglog(&amp;quot;return 3&amp;quot;)&lt;br /&gt;
							// return inp_obj;&lt;br /&gt;
&lt;br /&gt;
						};&lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;remove from record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
									&lt;br /&gt;
									if ( Array.isArray( inp_obj[ control_1 ] ) &amp;amp;&amp;amp; !isNaN( control_2 ) ) {&lt;br /&gt;
										inp_obj[ control_1 ].splice( control_2, 1 );&lt;br /&gt;
									} else {&lt;br /&gt;
										delete inp_obj[ control_1 ][ control_2 ];&lt;br /&gt;
									}&lt;br /&gt;
&lt;br /&gt;
								} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
&lt;br /&gt;
									delete inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
							store.put(inp_obj);&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
	// We are past all methodic code, Async return						&lt;br /&gt;
	&lt;br /&gt;
						resolve( inp_obj );&lt;br /&gt;
&lt;br /&gt;
					};&lt;br /&gt;
	&lt;br /&gt;
	// Indexeddb internal mechanism, close db&lt;br /&gt;
	&lt;br /&gt;
					tx.oncomplete = function() {&lt;br /&gt;
						debuglog(&amp;quot;return 1&amp;quot;)&lt;br /&gt;
						db.close();&lt;br /&gt;
					};&lt;br /&gt;
				};&lt;br /&gt;
				debuglog(&amp;quot;return 0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
	// End of promise&lt;br /&gt;
	&lt;br /&gt;
			}).then( function(result) {&lt;br /&gt;
				debuglog(&amp;quot;Mark 3&amp;quot;);&lt;br /&gt;
				debuglog(result);&lt;br /&gt;
				return result;&lt;br /&gt;
			});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function debuglog( l0g ){&lt;br /&gt;
		if ( Debug_switch ) {&lt;br /&gt;
			console.log( l0g );&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
};&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5218</id>
		<title>User:Abel/PersonalData.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5218"/>
		<updated>2019-05-27T13:42:26Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// Indexeddb JavaScript &lt;br /&gt;
console.log('Indb loading');&lt;br /&gt;
&lt;br /&gt;
function IndexedDBContainer( ww	) {&lt;br /&gt;
&lt;br /&gt;
	// suppress console.log, switch to true for debug&lt;br /&gt;
	var Debug_switch = false;&lt;br /&gt;
	&lt;br /&gt;
	// deterministic hash generator for creating user id#s from usernames, should be replaced by something more functional (guaranteed to be transitively different)&lt;br /&gt;
	hashCode = function(s) {&lt;br /&gt;
		if ( s == undefined) {&lt;br /&gt;
			s = '00'&lt;br /&gt;
		}&lt;br /&gt;
		var h = 0, l = s.length, i = 0;&lt;br /&gt;
		if ( l &amp;gt; 0 )&lt;br /&gt;
			while (i &amp;lt; l)&lt;br /&gt;
				h = (h &amp;lt;&amp;lt; 5) - h + s.charCodeAt(i++) | 0;&lt;br /&gt;
			return h;&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
		if ( ww.user != undefined ) {&lt;br /&gt;
// if user exists in object passed to constructor, get username		&lt;br /&gt;
			var self = ww.user.getName();&lt;br /&gt;
// create userid by hashing username&lt;br /&gt;
			var idgen = hashCode(self);																										&lt;br /&gt;
			debuglog(idgen);&lt;br /&gt;
&lt;br /&gt;
// Take username for standard databasename format:&lt;br /&gt;
// Our current convention for personal databasename (separate dbname for each user)&lt;br /&gt;
			var PersonalDataDataBaseName = &amp;quot;PD.IO&amp;quot; + idgen + &amp;quot;Database&amp;quot;;&lt;br /&gt;
			// Use username in user to get up to date version of self&lt;br /&gt;
// Blank object for personal data Record with id and username included&lt;br /&gt;
			this.CurrentPerson = {id: idgen, name: {user: self}, age: 0};&lt;br /&gt;
			debuglog(PersonalDataDataBaseName);&lt;br /&gt;
			debuglog(this.CurrentPerson);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	// ADD MORE DOC&lt;br /&gt;
&lt;br /&gt;
	// EnqueuePDIO a PDIOLocalDatabase:User database access function with modes&lt;br /&gt;
	// Externally accessible wrapper for Enquire with current user / db preloaded&lt;br /&gt;
&lt;br /&gt;
	this.EnqueuePDIO = async function( sw, c1, c2, c3 ) {&lt;br /&gt;
		debuglog(&amp;quot;enquing pdio db &amp;quot; + PersonalDataDataBaseName + &amp;quot; with user &amp;quot; + JSON.stringify(this.CurrentPerson));&lt;br /&gt;
		var k = await Enquire( PersonalDataDataBaseName, this.CurrentPerson, sw, c1, c2, c3 );&lt;br /&gt;
		return k;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Enquire, a general purpose indexeddb update function with modes&lt;br /&gt;
&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
&lt;br /&gt;
	// Mode 'get record'&lt;br /&gt;
	// updates record given as argument&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
	&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
&lt;br /&gt;
	async function Enquire( pddbname, record, sqitch, control_1, control_2, control_3 ) {&lt;br /&gt;
		return new Promise(&lt;br /&gt;
			function(resolve, reject) {&lt;br /&gt;
&lt;br /&gt;
				var pddb = window.indexedDB.open(pddbname, 3);&lt;br /&gt;
				var inp_obj;&lt;br /&gt;
&lt;br /&gt;
				pddb.onerror = function() {  &lt;br /&gt;
				    console.log(&amp;quot;Warning: Access to IndexedDB for application has been rejected.&amp;quot;);&lt;br /&gt;
				};&lt;br /&gt;
&lt;br /&gt;
				// indexeddb internal mechanism for version tracking of schema&lt;br /&gt;
				pddb.onupgradeneeded = function(evt) {&lt;br /&gt;
					console.log('upgrading database');&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var store = db.createObjectStore(pddbname, {keyPath: &amp;quot;id&amp;quot;});&lt;br /&gt;
&lt;br /&gt;
						// shouldn't the index be the wiki.personaldata.io username? &lt;br /&gt;
&lt;br /&gt;
						var index = db.store.createIndex(&amp;quot;NameIndex&amp;quot;, [&amp;quot;id&amp;quot;]);&lt;br /&gt;
				};&lt;br /&gt;
				// Database successfully opened function.&lt;br /&gt;
				pddb.onsuccess = function(xy) {&lt;br /&gt;
					debuglog(pddb.result);&lt;br /&gt;
					debuglog(xy);&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var tx = db.transaction(pddbname, &amp;quot;readwrite&amp;quot;);&lt;br /&gt;
					var store = tx.objectStore(pddbname);&lt;br /&gt;
					var index = store.index(&amp;quot;NameIndex&amp;quot;);	&lt;br /&gt;
&lt;br /&gt;
					// Get the original record from the db...&lt;br /&gt;
					var getRecord = index.get([record.id]);&lt;br /&gt;
&lt;br /&gt;
					getRecord.onsuccess = function() {&lt;br /&gt;
							debuglog( &amp;quot;Record in database: \n &amp;lt;&amp;lt;&amp;quot;);&lt;br /&gt;
							debuglog( getRecord.result );&lt;br /&gt;
							debuglog( &amp;quot;&amp;gt;&amp;gt;&amp;quot;);&lt;br /&gt;
						// Essential recordAdd																													&lt;br /&gt;
						if ( sqitch === &amp;quot;aggressive push&amp;quot; ) {&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
							inp_obj = record;&lt;br /&gt;
							store.put( inp_obj );&lt;br /&gt;
							return inp_obj;&lt;br /&gt;
						} else if ( sqitch === &amp;quot;checkin&amp;quot; ) {&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
							if ( getRecord.result !== undefined ) {&lt;br /&gt;
								debuglog(&amp;quot;getting from store&amp;quot;);&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
							} else {&lt;br /&gt;
								debuglog(&amp;quot;overriding whatever in there&amp;quot;);&lt;br /&gt;
								inp_obj = record;&lt;br /&gt;
								store.put(inp_obj);&lt;br /&gt;
							}&lt;br /&gt;
&lt;br /&gt;
						} else {&lt;br /&gt;
	// Methods manipulationg the actual record come here&lt;br /&gt;
	// Update &amp;amp; Remove from&lt;br /&gt;
							// If we got the record from store, use that version to be manipulated&lt;br /&gt;
							if ( getRecord.result !== undefined ) {		&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
								&lt;br /&gt;
								if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
									&lt;br /&gt;
									debuglog(&amp;quot;Getting record&amp;quot;);&lt;br /&gt;
									// we will return later&lt;br /&gt;
									&lt;br /&gt;
								} &lt;br /&gt;
&lt;br /&gt;
								// endof onsuccess&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								debuglog(&amp;quot;Record not found&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
								if ( sqitch === &amp;quot;update record&amp;quot; ) {&lt;br /&gt;
									// Update record will use supplied copy to update it&lt;br /&gt;
									inp_obj = record;&lt;br /&gt;
								} else {&lt;br /&gt;
									if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
										inp_obj = undefined;&lt;br /&gt;
									} else {&lt;br /&gt;
										return undefined;&lt;br /&gt;
									}&lt;br /&gt;
									// Remove from record will quit as record was not even found&lt;br /&gt;
									&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
						} &lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;update record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
									if ( control_3 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
										if ( inp_obj[ control_1 ] == undefined ) { inp_obj[ control_1 ] = (isNaN( control_2 )) ? {} : [] };&lt;br /&gt;
										inp_obj[ control_1 ][ control_2 ] = control_3;	// =&amp;gt; &amp;quot;Bob&amp;quot;&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
									} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
										inp_obj[ control_1 ] = inp_obj[ control_1 ] || {};&lt;br /&gt;
										if ( Array.isArray( inp_obj[ control_1 ] ) ) {&lt;br /&gt;
											inp_obj[ control_1 ].push( control_2 );&lt;br /&gt;
										} else {&lt;br /&gt;
											inp_obj[ control_1 ] = control_2;&lt;br /&gt;
										}&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
&lt;br /&gt;
									}&lt;br /&gt;
								} else {&lt;br /&gt;
									// Only one control defined. We will return that part of the record, and change nothing&lt;br /&gt;
									inp_obj = inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								// There's not even control_1, we will just return the record itself&lt;br /&gt;
&lt;br /&gt;
							}&lt;br /&gt;
							debuglog(&amp;quot;return 3&amp;quot;)&lt;br /&gt;
							// return inp_obj;&lt;br /&gt;
&lt;br /&gt;
						};&lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;remove from record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
									&lt;br /&gt;
									if ( Array.isArray( inp_obj[ control_1 ] ) &amp;amp;&amp;amp; !isNaN( control_2 ) ) {&lt;br /&gt;
										inp_obj[ control_1 ].splice( control_2, 1 );&lt;br /&gt;
									} else {&lt;br /&gt;
										delete inp_obj[ control_1 ][ control_2 ];&lt;br /&gt;
									}&lt;br /&gt;
&lt;br /&gt;
								} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
&lt;br /&gt;
									delete inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
							store.put(inp_obj);&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
	// We are past all methodic code, Async return						&lt;br /&gt;
	&lt;br /&gt;
						resolve( inp_obj );&lt;br /&gt;
&lt;br /&gt;
					};&lt;br /&gt;
	&lt;br /&gt;
	// Indexeddb internal mechanism, close db&lt;br /&gt;
	&lt;br /&gt;
					tx.oncomplete = function() {&lt;br /&gt;
						debuglog(&amp;quot;return 1&amp;quot;)&lt;br /&gt;
						db.close();&lt;br /&gt;
					};&lt;br /&gt;
				};&lt;br /&gt;
				debuglog(&amp;quot;return 0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
	// End of promise&lt;br /&gt;
	&lt;br /&gt;
			}).then( function(result) {&lt;br /&gt;
				debuglog(&amp;quot;Mark 3&amp;quot;);&lt;br /&gt;
				debuglog(result);&lt;br /&gt;
				return result;&lt;br /&gt;
			});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function debuglog( l0g ){&lt;br /&gt;
		if ( Debug_switch ) {&lt;br /&gt;
			console.log( l0g );&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
};&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5217</id>
		<title>User:Abel/PersonalData.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=5217"/>
		<updated>2019-05-27T13:40:56Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// Indexeddb JavaScript &lt;br /&gt;
console.log('Indb loading');&lt;br /&gt;
&lt;br /&gt;
function IndexedDBContainer( ww	) {&lt;br /&gt;
&lt;br /&gt;
	// suppress console.log, switch to true for debug&lt;br /&gt;
	var Debug_switch = false;&lt;br /&gt;
	&lt;br /&gt;
	// deterministic hash generator for creating user id#s from usernames, should be replaced by something more functional (guaranteed to be transitively different)&lt;br /&gt;
	hashCode = function(s) {&lt;br /&gt;
		if ( s == undefined) {&lt;br /&gt;
			s = '00'&lt;br /&gt;
		}&lt;br /&gt;
		var h = 0, l = s.length, i = 0;&lt;br /&gt;
		if ( l &amp;gt; 0 )&lt;br /&gt;
			while (i &amp;lt; l)&lt;br /&gt;
				h = (h &amp;lt;&amp;lt; 5) - h + s.charCodeAt(i++) | 0;&lt;br /&gt;
			return h;&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
		if ( ww.user != undefined ) {&lt;br /&gt;
// if user exists in object passed to constructor, get username		&lt;br /&gt;
			var self = ww.user.getName();&lt;br /&gt;
// create userid by hashing username&lt;br /&gt;
			var idgen = hashCode(self);																										&lt;br /&gt;
			debuglog(idgen);&lt;br /&gt;
&lt;br /&gt;
// Take username for standard databasename format:&lt;br /&gt;
// Our current convention for personal databasename (separate dbname for each user)&lt;br /&gt;
			var PersonalDataDataBaseName = &amp;quot;PD.IO&amp;quot; + idgen + &amp;quot;Database&amp;quot;;&lt;br /&gt;
			// Use username in user to get up to date version of self&lt;br /&gt;
// Blank object for personal data Record with id and username included&lt;br /&gt;
			this.CurrentPerson = {id: idgen, name: {user: self}, age: 0};&lt;br /&gt;
			debuglog(PersonalDataDataBaseName);&lt;br /&gt;
			debuglog(this.CurrentPerson);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	// ADD MORE DOC&lt;br /&gt;
&lt;br /&gt;
	// EnqueuePDIO a PDIOLocalDatabase:User database access function with modes&lt;br /&gt;
	// Externally accessible wrapper for Enquire with current user / db preloaded&lt;br /&gt;
&lt;br /&gt;
	this.EnqueuePDIO = async function( sw, c1, c2, c3 ) {&lt;br /&gt;
		debuglog(&amp;quot;enquing pdio db &amp;quot; + PersonalDataDataBaseName + &amp;quot; with user &amp;quot; + JSON.stringify(CurrentPerson));&lt;br /&gt;
		var k = await Enquire( PersonalDataDataBaseName, this.CurrentPerson, sw, c1, c2, c3 );&lt;br /&gt;
		return k;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Enquire, a general purpose indexeddb update function with modes&lt;br /&gt;
&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
&lt;br /&gt;
	// Mode 'get record'&lt;br /&gt;
	// updates record given as argument&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
	&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
&lt;br /&gt;
	async function Enquire( pddbname, record, sqitch, control_1, control_2, control_3 ) {&lt;br /&gt;
		return new Promise(&lt;br /&gt;
			function(resolve, reject) {&lt;br /&gt;
&lt;br /&gt;
				var pddb = window.indexedDB.open(pddbname, 3);&lt;br /&gt;
				var inp_obj;&lt;br /&gt;
&lt;br /&gt;
				pddb.onerror = function() {  &lt;br /&gt;
				    console.log(&amp;quot;Warning: Access to IndexedDB for application has been rejected.&amp;quot;);&lt;br /&gt;
				};&lt;br /&gt;
&lt;br /&gt;
				// indexeddb internal mechanism for version tracking of schema&lt;br /&gt;
				pddb.onupgradeneeded = function(evt) {&lt;br /&gt;
					console.log('upgrading database');&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var store = db.createObjectStore(pddbname, {keyPath: &amp;quot;id&amp;quot;});&lt;br /&gt;
&lt;br /&gt;
						// shouldn't the index be the wiki.personaldata.io username? &lt;br /&gt;
&lt;br /&gt;
						var index = db.store.createIndex(&amp;quot;NameIndex&amp;quot;, [&amp;quot;id&amp;quot;]);&lt;br /&gt;
				};&lt;br /&gt;
				// Database successfully opened function.&lt;br /&gt;
				pddb.onsuccess = function(xy) {&lt;br /&gt;
					debuglog(pddb.result);&lt;br /&gt;
					debuglog(xy);&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var tx = db.transaction(pddbname, &amp;quot;readwrite&amp;quot;);&lt;br /&gt;
					var store = tx.objectStore(pddbname);&lt;br /&gt;
					var index = store.index(&amp;quot;NameIndex&amp;quot;);	&lt;br /&gt;
&lt;br /&gt;
					// Get the original record from the db...&lt;br /&gt;
					var getRecord = index.get([record.id]);&lt;br /&gt;
&lt;br /&gt;
					getRecord.onsuccess = function() {&lt;br /&gt;
							debuglog( &amp;quot;Record in database: \n &amp;lt;&amp;lt;&amp;quot;);&lt;br /&gt;
							debuglog( getRecord.result );&lt;br /&gt;
							debuglog( &amp;quot;&amp;gt;&amp;gt;&amp;quot;);&lt;br /&gt;
						// Essential recordAdd																													&lt;br /&gt;
						if ( sqitch === &amp;quot;aggressive push&amp;quot; ) {&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
							inp_obj = record;&lt;br /&gt;
							store.put( inp_obj );&lt;br /&gt;
							return inp_obj;&lt;br /&gt;
						} else if ( sqitch === &amp;quot;checkin&amp;quot; ) {&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
							if ( getRecord.result !== undefined ) {&lt;br /&gt;
								debuglog(&amp;quot;getting from store&amp;quot;);&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
							} else {&lt;br /&gt;
								debuglog(&amp;quot;overriding whatever in there&amp;quot;);&lt;br /&gt;
								inp_obj = record;&lt;br /&gt;
								store.put(inp_obj);&lt;br /&gt;
							}&lt;br /&gt;
&lt;br /&gt;
						} else {&lt;br /&gt;
	// Methods manipulationg the actual record come here&lt;br /&gt;
	// Update &amp;amp; Remove from&lt;br /&gt;
							// If we got the record from store, use that version to be manipulated&lt;br /&gt;
							if ( getRecord.result !== undefined ) {		&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
								&lt;br /&gt;
								if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
									&lt;br /&gt;
									debuglog(&amp;quot;Getting record&amp;quot;);&lt;br /&gt;
									// we will return later&lt;br /&gt;
									&lt;br /&gt;
								} &lt;br /&gt;
&lt;br /&gt;
								// endof onsuccess&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								debuglog(&amp;quot;Record not found&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
								if ( sqitch === &amp;quot;update record&amp;quot; ) {&lt;br /&gt;
									// Update record will use supplied copy to update it&lt;br /&gt;
									inp_obj = record;&lt;br /&gt;
								} else {&lt;br /&gt;
									if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
										inp_obj = undefined;&lt;br /&gt;
									} else {&lt;br /&gt;
										return undefined;&lt;br /&gt;
									}&lt;br /&gt;
									// Remove from record will quit as record was not even found&lt;br /&gt;
									&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
						} &lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;update record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
									if ( control_3 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
										if ( inp_obj[ control_1 ] == undefined ) { inp_obj[ control_1 ] = (isNaN( control_2 )) ? {} : [] };&lt;br /&gt;
										inp_obj[ control_1 ][ control_2 ] = control_3;	// =&amp;gt; &amp;quot;Bob&amp;quot;&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
									} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
										inp_obj[ control_1 ] = inp_obj[ control_1 ] || {};&lt;br /&gt;
										if ( Array.isArray( inp_obj[ control_1 ] ) ) {&lt;br /&gt;
											inp_obj[ control_1 ].push( control_2 );&lt;br /&gt;
										} else {&lt;br /&gt;
											inp_obj[ control_1 ] = control_2;&lt;br /&gt;
										}&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
&lt;br /&gt;
									}&lt;br /&gt;
								} else {&lt;br /&gt;
									// Only one control defined. We will return that part of the record, and change nothing&lt;br /&gt;
									inp_obj = inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								// There's not even control_1, we will just return the record itself&lt;br /&gt;
&lt;br /&gt;
							}&lt;br /&gt;
							debuglog(&amp;quot;return 3&amp;quot;)&lt;br /&gt;
							// return inp_obj;&lt;br /&gt;
&lt;br /&gt;
						};&lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;remove from record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
									&lt;br /&gt;
									if ( Array.isArray( inp_obj[ control_1 ] ) &amp;amp;&amp;amp; !isNaN( control_2 ) ) {&lt;br /&gt;
										inp_obj[ control_1 ].splice( control_2, 1 );&lt;br /&gt;
									} else {&lt;br /&gt;
										delete inp_obj[ control_1 ][ control_2 ];&lt;br /&gt;
									}&lt;br /&gt;
&lt;br /&gt;
								} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
&lt;br /&gt;
									delete inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
							store.put(inp_obj);&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
	// We are past all methodic code, Async return						&lt;br /&gt;
	&lt;br /&gt;
						resolve( inp_obj );&lt;br /&gt;
&lt;br /&gt;
					};&lt;br /&gt;
	&lt;br /&gt;
	// Indexeddb internal mechanism, close db&lt;br /&gt;
	&lt;br /&gt;
					tx.oncomplete = function() {&lt;br /&gt;
						debuglog(&amp;quot;return 1&amp;quot;)&lt;br /&gt;
						db.close();&lt;br /&gt;
					};&lt;br /&gt;
				};&lt;br /&gt;
				debuglog(&amp;quot;return 0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
	// End of promise&lt;br /&gt;
	&lt;br /&gt;
			}).then( function(result) {&lt;br /&gt;
				debuglog(&amp;quot;Mark 3&amp;quot;);&lt;br /&gt;
				debuglog(result);&lt;br /&gt;
				return result;&lt;br /&gt;
			});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function debuglog( l0g ){&lt;br /&gt;
		if ( Debug_switch ) {&lt;br /&gt;
			console.log( l0g );&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
};&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=4950</id>
		<title>User:Abel/PersonalData.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=4950"/>
		<updated>2019-05-24T13:33:49Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// Indexeddb JavaScript &lt;br /&gt;
console.log('Indb loading');&lt;br /&gt;
&lt;br /&gt;
function IndexedDBContainer( ww	) {&lt;br /&gt;
&lt;br /&gt;
	// suppress console.log, switch to true for debug&lt;br /&gt;
	var Debug_switch = true;&lt;br /&gt;
	&lt;br /&gt;
	// deterministic hash generator for creating user id#s from usernames, should be replaced by something more functional (guaranteed to be transitively different)&lt;br /&gt;
	hashCode = function(s) {&lt;br /&gt;
		if ( s == undefined) {&lt;br /&gt;
			s = '00'&lt;br /&gt;
		}&lt;br /&gt;
		var h = 0, l = s.length, i = 0;&lt;br /&gt;
		if ( l &amp;gt; 0 )&lt;br /&gt;
			while (i &amp;lt; l)&lt;br /&gt;
				h = (h &amp;lt;&amp;lt; 5) - h + s.charCodeAt(i++) | 0;&lt;br /&gt;
			return h;&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
		if ( ww.user != undefined ) {&lt;br /&gt;
// if user exists in object passed to constructor, get username		&lt;br /&gt;
			var self = ww.user.getName();&lt;br /&gt;
// create userid by hashing username&lt;br /&gt;
			var idgen = hashCode(self);																										&lt;br /&gt;
			debuglog(idgen);&lt;br /&gt;
&lt;br /&gt;
// Take username for standard databasename format:&lt;br /&gt;
// Our current convention for personal databasename (separate dbname for each user)&lt;br /&gt;
			var PersonalDataDataBaseName = &amp;quot;PD.IO&amp;quot; + idgen + &amp;quot;Database&amp;quot;;&lt;br /&gt;
			// Use username in user to get up to date version of self&lt;br /&gt;
// Blank object for personal data Record with id and username included&lt;br /&gt;
			this.CurrentPerson = {id: idgen, name: {user: self}, age: 0};&lt;br /&gt;
			debuglog(PersonalDataDataBaseName);&lt;br /&gt;
			debuglog(this.CurrentPerson);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	// ADD MORE DOC&lt;br /&gt;
&lt;br /&gt;
	// EnqueuePDIO a PDIOLocalDatabase:User database access function with modes&lt;br /&gt;
	// Externally accessible wrapper for Enquire with current user / db preloaded&lt;br /&gt;
&lt;br /&gt;
	this.EnqueuePDIO = async function( sw, c1, c2, c3 ) {&lt;br /&gt;
		var k = await Enquire( PersonalDataDataBaseName, this.CurrentPerson, sw, c1, c2, c3 );&lt;br /&gt;
		return k;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Enquire, a general purpose indexeddb update function with modes&lt;br /&gt;
&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
&lt;br /&gt;
	// Mode 'get record'&lt;br /&gt;
	// updates record given as argument&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
	&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
&lt;br /&gt;
	async function Enquire( pddbname, record, sqitch, control_1, control_2, control_3 ) {&lt;br /&gt;
		return new Promise(&lt;br /&gt;
			function(resolve, reject) {&lt;br /&gt;
&lt;br /&gt;
				var pddb = window.indexedDB.open(pddbname, 3);&lt;br /&gt;
				var inp_obj;&lt;br /&gt;
&lt;br /&gt;
				// indexeddb internal mechanism for version tracking of schema&lt;br /&gt;
				pddb.onupgradeneeded = function() {&lt;br /&gt;
					console.log('upgrading database');&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var store = db.createObjectStore(pddbname, {keyPath: &amp;quot;id&amp;quot;});&lt;br /&gt;
&lt;br /&gt;
						// shouldn't the index be the wiki.personaldata.io username? &lt;br /&gt;
&lt;br /&gt;
						var index = store.createIndex(&amp;quot;NameIndex&amp;quot;, [&amp;quot;id&amp;quot;]);&lt;br /&gt;
				};&lt;br /&gt;
				// Database successfully opened function.&lt;br /&gt;
				pddb.onsuccess = function() {&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var tx = db.transaction(pddbname, &amp;quot;readwrite&amp;quot;);&lt;br /&gt;
					var store = tx.objectStore(pddbname);&lt;br /&gt;
					var index = store.index(&amp;quot;NameIndex&amp;quot;);	&lt;br /&gt;
&lt;br /&gt;
					// Get the original record from the db...&lt;br /&gt;
					var getRecord = index.get([record.id]);&lt;br /&gt;
&lt;br /&gt;
					getRecord.onsuccess = function() {&lt;br /&gt;
							debuglog( &amp;quot;Record found in database: \n &amp;lt;&amp;lt;&amp;quot;);&lt;br /&gt;
							debuglog( getRecord.result );&lt;br /&gt;
							debuglog( &amp;quot;&amp;gt;&amp;gt;&amp;quot;);&lt;br /&gt;
						// Essential recordAdd																													&lt;br /&gt;
						if ( sqitch === &amp;quot;aggressive push&amp;quot; ) {&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
							inp_obj = record;&lt;br /&gt;
							store.put( inp_obj );&lt;br /&gt;
							return inp_obj;&lt;br /&gt;
						} else if ( sqitch === &amp;quot;checkin&amp;quot; ) {&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
							if ( getRecord.result != undefined ) {&lt;br /&gt;
									debuglog(&amp;quot;getting from store&amp;quot;);&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
							} else {&lt;br /&gt;
								debuglog(&amp;quot;overriding whatever in there&amp;quot;);&lt;br /&gt;
								inp_obj = record;&lt;br /&gt;
								store.put(inp_obj);&lt;br /&gt;
							}&lt;br /&gt;
&lt;br /&gt;
						} else {&lt;br /&gt;
	// Methods manipulationg the actual record come here&lt;br /&gt;
	// Update &amp;amp; Remove from&lt;br /&gt;
							// If we got the record from store, use that version to be manipulated&lt;br /&gt;
							if ( getRecord.result != undefined ) {		&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
								&lt;br /&gt;
								if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
									&lt;br /&gt;
									debuglog(&amp;quot;Getting record&amp;quot;);&lt;br /&gt;
									// we will return later&lt;br /&gt;
									&lt;br /&gt;
								} &lt;br /&gt;
&lt;br /&gt;
								// endof onsuccess&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								debuglog(&amp;quot;Record not found&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
								if ( sqitch === &amp;quot;update record&amp;quot; ) {&lt;br /&gt;
									// Update record will use supplied copy to update it&lt;br /&gt;
									inp_obj = record;&lt;br /&gt;
								} else {&lt;br /&gt;
									if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
										inp_obj = undefined;&lt;br /&gt;
									} else {&lt;br /&gt;
										return undefined;&lt;br /&gt;
									}&lt;br /&gt;
									// Remove from record will quit as record was not even found&lt;br /&gt;
									&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
						} &lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;update record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
									if ( control_3 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
										if ( inp_obj[ control_1 ] == undefined ) { inp_obj[ control_1 ] = (isNaN( control_2 )) ? {} : [] };&lt;br /&gt;
										inp_obj[ control_1 ][ control_2 ] = control_3;	// =&amp;gt; &amp;quot;Bob&amp;quot;&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
									} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
										inp_obj[ control_1 ] = inp_obj[ control_1 ] || {};&lt;br /&gt;
										if ( Array.isArray( inp_obj[ control_1 ] ) ) {&lt;br /&gt;
											inp_obj[ control_1 ].push( control_2 );&lt;br /&gt;
										} else {&lt;br /&gt;
											inp_obj[ control_1 ] = control_2;&lt;br /&gt;
										}&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
&lt;br /&gt;
									}&lt;br /&gt;
								} else {&lt;br /&gt;
									// Only one control defined. We will return that part of the record, and change nothing&lt;br /&gt;
									inp_obj = inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								// There's not even control_1, we will just return the record itself&lt;br /&gt;
&lt;br /&gt;
							}&lt;br /&gt;
							debuglog(&amp;quot;return 3&amp;quot;)&lt;br /&gt;
							// return inp_obj;&lt;br /&gt;
&lt;br /&gt;
						};&lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;remove from record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
									&lt;br /&gt;
									if ( Array.isArray( inp_obj[ control_1 ] ) &amp;amp;&amp;amp; !isNaN( control_2 ) ) {&lt;br /&gt;
										inp_obj[ control_1 ].splice( control_2, 1 );&lt;br /&gt;
									} else {&lt;br /&gt;
										delete inp_obj[ control_1 ][ control_2 ];&lt;br /&gt;
									}&lt;br /&gt;
&lt;br /&gt;
								} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
&lt;br /&gt;
									delete inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
							store.put(inp_obj);&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
	// We are past all methodic code, Async return						&lt;br /&gt;
	&lt;br /&gt;
						resolve( inp_obj );&lt;br /&gt;
&lt;br /&gt;
					};&lt;br /&gt;
	&lt;br /&gt;
	// Indexeddb internal mechanism, close db&lt;br /&gt;
	&lt;br /&gt;
					tx.oncomplete = function() {&lt;br /&gt;
						debuglog(&amp;quot;return 1&amp;quot;)&lt;br /&gt;
						db.close();&lt;br /&gt;
					};&lt;br /&gt;
				};&lt;br /&gt;
				debuglog(&amp;quot;return 0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
	// End of promise&lt;br /&gt;
	&lt;br /&gt;
			}).then( function(result) {&lt;br /&gt;
				debuglog(&amp;quot;Mark 3&amp;quot;);&lt;br /&gt;
				debuglog(result);&lt;br /&gt;
				return result;&lt;br /&gt;
			});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function debuglog( l0g ){&lt;br /&gt;
		if ( Debug_switch ) {&lt;br /&gt;
			console.log( l0g );&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
};&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=4949</id>
		<title>User:Abel/PersonalData.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/PersonalData.js&amp;diff=4949"/>
		<updated>2019-05-24T13:25:30Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// Indexeddb JavaScript &lt;br /&gt;
console.log('Indb loading');&lt;br /&gt;
&lt;br /&gt;
function IndexedDBContainer( ww	) {&lt;br /&gt;
&lt;br /&gt;
	// suppress console.log, switch to true for debug&lt;br /&gt;
	var Debug_switch = false;&lt;br /&gt;
	&lt;br /&gt;
	// deterministic hash generator for creating user id#s from usernames, should be replaced by something more functional (guaranteed to be transitively different)&lt;br /&gt;
	hashCode = function(s) {&lt;br /&gt;
		if ( s == undefined) {&lt;br /&gt;
			s = '00'&lt;br /&gt;
		}&lt;br /&gt;
		var h = 0, l = s.length, i = 0;&lt;br /&gt;
		if ( l &amp;gt; 0 )&lt;br /&gt;
			while (i &amp;lt; l)&lt;br /&gt;
				h = (h &amp;lt;&amp;lt; 5) - h + s.charCodeAt(i++) | 0;&lt;br /&gt;
			return h;&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
		if ( ww.user != undefined ) {&lt;br /&gt;
// if user exists in object passed to constructor, get username		&lt;br /&gt;
			var self = ww.user.getName();&lt;br /&gt;
// create userid by hashing username&lt;br /&gt;
			var idgen = hashCode(self);																										&lt;br /&gt;
			debuglog(idgen);&lt;br /&gt;
&lt;br /&gt;
// Take username for standard databasename format:&lt;br /&gt;
// Our current convention for personal databasename (separate dbname for each user)&lt;br /&gt;
			var PersonalDataDataBaseName = &amp;quot;PD.IO&amp;quot; + idgen + &amp;quot;Database&amp;quot;;&lt;br /&gt;
			// Use username in user to get up to date version of self&lt;br /&gt;
// Blank object for personal data Record with id and username included&lt;br /&gt;
			this.CurrentPerson = {id: idgen, name: {user: self}, age: 0};&lt;br /&gt;
			debuglog(PersonalDataDataBaseName);&lt;br /&gt;
			debuglog(this.CurrentPerson);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	// ADD MORE DOC&lt;br /&gt;
&lt;br /&gt;
	// EnqueuePDIO a PDIOLocalDatabase:User database access function with modes&lt;br /&gt;
	// Externally accessible wrapper for Enquire with current user / db preloaded&lt;br /&gt;
&lt;br /&gt;
	this.EnqueuePDIO = async function( sw, c1, c2, c3 ) {&lt;br /&gt;
		var k = await Enquire( PersonalDataDataBaseName, this.CurrentPerson, sw, c1, c2, c3 );&lt;br /&gt;
		return k;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Enquire, a general purpose indexeddb update function with modes&lt;br /&gt;
&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
&lt;br /&gt;
	// Mode 'get record'&lt;br /&gt;
	// updates record given as argument&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
	&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
&lt;br /&gt;
	async function Enquire( pddbname, record, sqitch, control_1, control_2, control_3 ) {&lt;br /&gt;
		return new Promise(&lt;br /&gt;
			function(resolve, reject) {&lt;br /&gt;
&lt;br /&gt;
				var pddb = window.indexedDB.open(pddbname, 3);&lt;br /&gt;
				var inp_obj;&lt;br /&gt;
&lt;br /&gt;
				// indexeddb internal mechanism for version tracking of schema&lt;br /&gt;
				pddb.onupgradeneeded = function() {&lt;br /&gt;
					console.log('upgrading database');&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var store = db.createObjectStore(pddbname, {keyPath: &amp;quot;id&amp;quot;});&lt;br /&gt;
&lt;br /&gt;
						// shouldn't the index be the wiki.personaldata.io username? &lt;br /&gt;
&lt;br /&gt;
						var index = store.createIndex(&amp;quot;NameIndex&amp;quot;, [&amp;quot;id&amp;quot;]);&lt;br /&gt;
				};&lt;br /&gt;
				// Database successfully opened function.&lt;br /&gt;
				pddb.onsuccess = function() {&lt;br /&gt;
					var db = pddb.result;&lt;br /&gt;
					var tx = db.transaction(pddbname, &amp;quot;readwrite&amp;quot;);&lt;br /&gt;
					var store = tx.objectStore(pddbname);&lt;br /&gt;
					var index = store.index(&amp;quot;NameIndex&amp;quot;);	&lt;br /&gt;
&lt;br /&gt;
					// Get the original record from the db...&lt;br /&gt;
					var getRecord = index.get([record.id]);&lt;br /&gt;
&lt;br /&gt;
					getRecord.onsuccess = function() {&lt;br /&gt;
							debuglog( &amp;quot;Record found in database: \n &amp;lt;&amp;lt;&amp;quot;);&lt;br /&gt;
							debuglog( getRecord.result );&lt;br /&gt;
							debuglog( &amp;quot;&amp;gt;&amp;gt;&amp;quot;);&lt;br /&gt;
						// Essential recordAdd																													&lt;br /&gt;
						if ( sqitch === &amp;quot;aggressive push&amp;quot; ) {&lt;br /&gt;
	// Mode 'aggressive push':&lt;br /&gt;
	// parameter record is pushed to database, overwriting whatever is there&lt;br /&gt;
							inp_obj = record;&lt;br /&gt;
							store.put( inp_obj );&lt;br /&gt;
							return inp_obj;&lt;br /&gt;
						} else if ( sqitch === &amp;quot;checkin&amp;quot; ) {&lt;br /&gt;
	// Mode 'checkin':&lt;br /&gt;
	// record is retrieved from database, parameter record is pushed if not found&lt;br /&gt;
							if ( getRecord.result != undefined ) {&lt;br /&gt;
									debuglog(&amp;quot;getting from store&amp;quot;);&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
							} else {&lt;br /&gt;
								debuglog(&amp;quot;overriding whatever in there&amp;quot;);&lt;br /&gt;
								inp_obj = record;&lt;br /&gt;
								store.put(inp_obj);&lt;br /&gt;
							}&lt;br /&gt;
&lt;br /&gt;
						} else {&lt;br /&gt;
	// Methods manipulationg the actual record come here&lt;br /&gt;
	// Update &amp;amp; Remove from&lt;br /&gt;
							// If we got the record from store, use that version to be manipulated&lt;br /&gt;
							if ( getRecord.result != undefined ) {		&lt;br /&gt;
								inp_obj = getRecord.result;&lt;br /&gt;
								&lt;br /&gt;
								if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
									&lt;br /&gt;
									debuglog(&amp;quot;Getting record&amp;quot;);&lt;br /&gt;
									// we will return later&lt;br /&gt;
									&lt;br /&gt;
								} &lt;br /&gt;
&lt;br /&gt;
								// endof onsuccess&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								debuglog(&amp;quot;Record not found&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
								if ( sqitch === &amp;quot;update record&amp;quot; ) {&lt;br /&gt;
									// Update record will use supplied copy to update it&lt;br /&gt;
									inp_obj = record;&lt;br /&gt;
								} else {&lt;br /&gt;
									if ( sqitch === &amp;quot;get record&amp;quot; ) {&lt;br /&gt;
										inp_obj = undefined;&lt;br /&gt;
									} else {&lt;br /&gt;
										return undefined;&lt;br /&gt;
									}&lt;br /&gt;
									// Remove from record will quit as record was not even found&lt;br /&gt;
									&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
						} &lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;update record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
									if ( control_3 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2 field3&lt;br /&gt;
	// retrieve record, make record.field1.field2 = field3, push back&lt;br /&gt;
&lt;br /&gt;
										if ( inp_obj[ control_1 ] == undefined ) { inp_obj[ control_1 ] = (isNaN( control_2 )) ? {} : [] };&lt;br /&gt;
										inp_obj[ control_1 ][ control_2 ] = control_3;	// =&amp;gt; &amp;quot;Bob&amp;quot;&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
									} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'update record' field1 field2&lt;br /&gt;
	// retrieve record, make record.field1 = field2, push back&lt;br /&gt;
&lt;br /&gt;
										inp_obj[ control_1 ] = inp_obj[ control_1 ] || {};&lt;br /&gt;
										if ( Array.isArray( inp_obj[ control_1 ] ) ) {&lt;br /&gt;
											inp_obj[ control_1 ].push( control_2 );&lt;br /&gt;
										} else {&lt;br /&gt;
											inp_obj[ control_1 ] = control_2;&lt;br /&gt;
										}&lt;br /&gt;
										store.put(inp_obj);&lt;br /&gt;
&lt;br /&gt;
									}&lt;br /&gt;
								} else {&lt;br /&gt;
									// Only one control defined. We will return that part of the record, and change nothing&lt;br /&gt;
									inp_obj = inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							} else {&lt;br /&gt;
&lt;br /&gt;
								// There's not even control_1, we will just return the record itself&lt;br /&gt;
&lt;br /&gt;
							}&lt;br /&gt;
							debuglog(&amp;quot;return 3&amp;quot;)&lt;br /&gt;
							// return inp_obj;&lt;br /&gt;
&lt;br /&gt;
						};&lt;br /&gt;
&lt;br /&gt;
						if ( sqitch === &amp;quot;remove from record&amp;quot; ) { // Record Update															&lt;br /&gt;
							if ( control_1 != undefined ) {&lt;br /&gt;
								if ( control_2 != undefined ) {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 field2 &lt;br /&gt;
	// retrieve record, splice/delete record.field1.field2, push back&lt;br /&gt;
									&lt;br /&gt;
									if ( Array.isArray( inp_obj[ control_1 ] ) &amp;amp;&amp;amp; !isNaN( control_2 ) ) {&lt;br /&gt;
										inp_obj[ control_1 ].splice( control_2, 1 );&lt;br /&gt;
									} else {&lt;br /&gt;
										delete inp_obj[ control_1 ][ control_2 ];&lt;br /&gt;
									}&lt;br /&gt;
&lt;br /&gt;
								} else {&lt;br /&gt;
&lt;br /&gt;
	// Mode 'remove from record' field1 &lt;br /&gt;
	// retrieve record, splice/delete record.field1, push back&lt;br /&gt;
&lt;br /&gt;
									delete inp_obj[ control_1 ];&lt;br /&gt;
								}&lt;br /&gt;
							}&lt;br /&gt;
							store.put(inp_obj);&lt;br /&gt;
						}&lt;br /&gt;
&lt;br /&gt;
	// We are past all methodic code, Async return						&lt;br /&gt;
	&lt;br /&gt;
						resolve( inp_obj );&lt;br /&gt;
&lt;br /&gt;
					};&lt;br /&gt;
	&lt;br /&gt;
	// Indexeddb internal mechanism, close db&lt;br /&gt;
	&lt;br /&gt;
					tx.oncomplete = function() {&lt;br /&gt;
						debuglog(&amp;quot;return 1&amp;quot;)&lt;br /&gt;
						db.close();&lt;br /&gt;
					};&lt;br /&gt;
				};&lt;br /&gt;
				debuglog(&amp;quot;return 0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
	// End of promise&lt;br /&gt;
	&lt;br /&gt;
			}).then( function(result) {&lt;br /&gt;
				debuglog(&amp;quot;Mark 3&amp;quot;);&lt;br /&gt;
				debuglog(result);&lt;br /&gt;
				return result;&lt;br /&gt;
			});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function debuglog( l0g ){&lt;br /&gt;
		if ( Debug_switch ) {&lt;br /&gt;
			console.log( l0g );&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
};&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4948</id>
		<title>User:Abel/OOInterface.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4948"/>
		<updated>2019-05-24T13:20:55Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
		notify_porting();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['IDName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
			ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
	&lt;br /&gt;
	function notify_porting() {&lt;br /&gt;
&lt;br /&gt;
		mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
			var button_import = new OO.ui.SelectFileWidget ( { &lt;br /&gt;
					label: &amp;quot;Import Personal Data&amp;quot;, &lt;br /&gt;
					classes: [ 'pduimark' ] &lt;br /&gt;
				}), &lt;br /&gt;
&lt;br /&gt;
				button_export = new OO.ui.ButtonWidget( { label: &amp;quot;Export Personal Data&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
&lt;br /&gt;
				button_import.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
					if (window.webkitURL != null) {&lt;br /&gt;
						window.alert(&amp;quot;loading file on webkit&amp;quot;)&lt;br /&gt;
					} else {&lt;br /&gt;
						window.alert(&amp;quot;loading file non webkit&amp;quot;)&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			button_export.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
				var get_record = indexedDBobject.EnqueuePDIO('get record');&lt;br /&gt;
&lt;br /&gt;
				get_record.then( function(result) {&lt;br /&gt;
					console.log(&amp;quot;happening&amp;quot;);&lt;br /&gt;
					if ( result === undefined ) { window.alert(&amp;quot;No data to export&amp;quot;) } else { console.log(result) };&lt;br /&gt;
&lt;br /&gt;
					var filename_tosaveas = &amp;quot;pdiolocalexport_&amp;quot; + result.name.user + &amp;quot;_&amp;quot; + Date.now() + '.json';&lt;br /&gt;
					&lt;br /&gt;
					result.id = '';&lt;br /&gt;
					result.name.user = '';&lt;br /&gt;
					&lt;br /&gt;
					var export_to_text = JSON.stringify(result);&lt;br /&gt;
					var textFileAsBlob = new Blob([export_to_text], {type:'text/plain'});&lt;br /&gt;
					var downloadLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
					downloadLink.download = filename_tosaveas;&lt;br /&gt;
					if (window.webkitURL != null)&lt;br /&gt;
					{&lt;br /&gt;
						// Chrome allows the link to be clicked&lt;br /&gt;
						// without actually adding it to the DOM.&lt;br /&gt;
						downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						// Firefox requires the link to be added to the DOM&lt;br /&gt;
						// before it can be clicked.&lt;br /&gt;
						downloadLink.href = window.URL.createObjectURL(textFileAsBlob);&lt;br /&gt;
						downloadLink.style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
						document.body.appendChild(downloadLink);&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					downloadLink.click();&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			mw.notify( $( button_import.$element ), { autoHide: false }  );&lt;br /&gt;
			mw.notify( $( button_export.$element ), { autoHide: false }  );&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4947</id>
		<title>User:Abel/OOInterface.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4947"/>
		<updated>2019-05-24T13:18:41Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
		notify_porting();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['IDName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
			ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
	&lt;br /&gt;
	function notify_porting() {&lt;br /&gt;
&lt;br /&gt;
		mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
			var button_import = new OO.ui.SelectFileWidget ( { &lt;br /&gt;
					label: &amp;quot;Import Personal Data&amp;quot;, &lt;br /&gt;
					classes: [ 'pduimark' ] &lt;br /&gt;
				}), &lt;br /&gt;
&lt;br /&gt;
				button_export = new OO.ui.ButtonWidget( { label: &amp;quot;Export Personal Data&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
&lt;br /&gt;
				button_import.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
					if (window.webkitURL != null) {&lt;br /&gt;
						window.alert(&amp;quot;loading file on webkit&amp;quot;)&lt;br /&gt;
					} else {&lt;br /&gt;
						window.alert(&amp;quot;loading file non webkit&amp;quot;)&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			button_export.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
				var get_record = indexedDBobject.EnqueuePDIO('get record');&lt;br /&gt;
&lt;br /&gt;
				get_record.then( function(result) {&lt;br /&gt;
					if ( result === undefined ) { window.alert(&amp;quot;No data to export&amp;quot;) } else { console.log(result) };&lt;br /&gt;
&lt;br /&gt;
					var filename_tosaveas = &amp;quot;pdiolocalexport_&amp;quot; + result.name.user + &amp;quot;_&amp;quot; + Date.now() + '.json';&lt;br /&gt;
					&lt;br /&gt;
					result.id = '';&lt;br /&gt;
					result.name.user = '';&lt;br /&gt;
					&lt;br /&gt;
					var export_to_text = JSON.stringify(result);&lt;br /&gt;
					var textFileAsBlob = new Blob([export_to_text], {type:'text/plain'});&lt;br /&gt;
					var downloadLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
					downloadLink.download = filename_tosaveas;&lt;br /&gt;
					if (window.webkitURL != null)&lt;br /&gt;
					{&lt;br /&gt;
						// Chrome allows the link to be clicked&lt;br /&gt;
						// without actually adding it to the DOM.&lt;br /&gt;
						downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						// Firefox requires the link to be added to the DOM&lt;br /&gt;
						// before it can be clicked.&lt;br /&gt;
						downloadLink.href = window.URL.createObjectURL(textFileAsBlob);&lt;br /&gt;
						downloadLink.style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
						document.body.appendChild(downloadLink);&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					downloadLink.click();&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			mw.notify( $( button_import.$element ), { autoHide: false }  );&lt;br /&gt;
			mw.notify( $( button_export.$element ), { autoHide: false }  );&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4946</id>
		<title>User:Abel/OOInterface.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4946"/>
		<updated>2019-05-24T13:17:30Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
		notify_porting();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['IDName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
			ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
	&lt;br /&gt;
	function notify_porting() {&lt;br /&gt;
&lt;br /&gt;
		mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
			var button_import = new OO.ui.SelectFileWidget ( { &lt;br /&gt;
					label: &amp;quot;Import Personal Data&amp;quot;, &lt;br /&gt;
					classes: [ 'pduimark' ] &lt;br /&gt;
				}), &lt;br /&gt;
&lt;br /&gt;
				button_export = new OO.ui.ButtonWidget( { label: &amp;quot;Export Personal Data&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
&lt;br /&gt;
				button_import.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
					if (window.webkitURL != null) {&lt;br /&gt;
						window.alert(&amp;quot;loading file on webkit&amp;quot;)&lt;br /&gt;
					} else {&lt;br /&gt;
						window.alert(&amp;quot;loading file non webkit&amp;quot;)&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			button_export.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
				var get_record = indexedDBobject.EnqueuePDIO('get record');&lt;br /&gt;
&lt;br /&gt;
				get_record.then( function(result) {&lt;br /&gt;
					if ( get_record.result === undefined ) { window.alert(&amp;quot;No data to export&amp;quot;) };&lt;br /&gt;
&lt;br /&gt;
					var filename_tosaveas = &amp;quot;pdiolocalexport_&amp;quot; + result.name.user + &amp;quot;_&amp;quot; + Date.now() + '.json';&lt;br /&gt;
					&lt;br /&gt;
					result.id = '';&lt;br /&gt;
					result.name.user = '';&lt;br /&gt;
					&lt;br /&gt;
					var export_to_text = JSON.stringify(result);&lt;br /&gt;
					var textFileAsBlob = new Blob([export_to_text], {type:'text/plain'});&lt;br /&gt;
					var downloadLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
					downloadLink.download = filename_tosaveas;&lt;br /&gt;
					if (window.webkitURL != null)&lt;br /&gt;
					{&lt;br /&gt;
						// Chrome allows the link to be clicked&lt;br /&gt;
						// without actually adding it to the DOM.&lt;br /&gt;
						downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						// Firefox requires the link to be added to the DOM&lt;br /&gt;
						// before it can be clicked.&lt;br /&gt;
						downloadLink.href = window.URL.createObjectURL(textFileAsBlob);&lt;br /&gt;
						downloadLink.style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
						document.body.appendChild(downloadLink);&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					downloadLink.click();&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			mw.notify( $( button_import.$element ), { autoHide: false }  );&lt;br /&gt;
			mw.notify( $( button_export.$element ), { autoHide: false }  );&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4945</id>
		<title>User:Abel/OOInterface.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4945"/>
		<updated>2019-05-24T13:16:11Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
		notify_porting();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['IDName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
			ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
	&lt;br /&gt;
	function notify_porting() {&lt;br /&gt;
&lt;br /&gt;
		mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
			var button_import = new OO.ui.SelectFileWidget ( { &lt;br /&gt;
					label: &amp;quot;Import Personal Data&amp;quot;, &lt;br /&gt;
					classes: [ 'pduimark' ] &lt;br /&gt;
				}), &lt;br /&gt;
&lt;br /&gt;
				button_export = new OO.ui.ButtonWidget( { label: &amp;quot;Export Personal Data&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
&lt;br /&gt;
				button_import.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
					if (window.webkitURL != null) {&lt;br /&gt;
						window.alert(&amp;quot;loading file on webkit&amp;quot;)&lt;br /&gt;
					} else {&lt;br /&gt;
						window.alert(&amp;quot;loading file non webkit&amp;quot;)&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			button_export.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
				var get_record = indexedDBobject.EnqueuePDIO('get record');&lt;br /&gt;
&lt;br /&gt;
				get_record.then( function(result) {&lt;br /&gt;
					if ( result === undefined ) { window.alert(&amp;quot;No data to export&amp;quot;) };&lt;br /&gt;
&lt;br /&gt;
					var filename_tosaveas = &amp;quot;pdiolocalexport_&amp;quot; + result.name.user + &amp;quot;_&amp;quot; + Date.now() + '.json';&lt;br /&gt;
					&lt;br /&gt;
					result.id = '';&lt;br /&gt;
					result.name.user = '';&lt;br /&gt;
					&lt;br /&gt;
					var export_to_text = JSON.stringify(result);&lt;br /&gt;
					var textFileAsBlob = new Blob([export_to_text], {type:'text/plain'});&lt;br /&gt;
					var downloadLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
					downloadLink.download = filename_tosaveas;&lt;br /&gt;
					if (window.webkitURL != null)&lt;br /&gt;
					{&lt;br /&gt;
						// Chrome allows the link to be clicked&lt;br /&gt;
						// without actually adding it to the DOM.&lt;br /&gt;
						downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						// Firefox requires the link to be added to the DOM&lt;br /&gt;
						// before it can be clicked.&lt;br /&gt;
						downloadLink.href = window.URL.createObjectURL(textFileAsBlob);&lt;br /&gt;
						downloadLink.style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
						document.body.appendChild(downloadLink);&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					downloadLink.click();&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			mw.notify( $( button_import.$element ), { autoHide: false }  );&lt;br /&gt;
			mw.notify( $( button_export.$element ), { autoHide: false }  );&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4944</id>
		<title>User:Abel/OOInterface.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4944"/>
		<updated>2019-05-24T13:14:33Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
		notify_porting();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['IDName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
			ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
	&lt;br /&gt;
	function notify_porting() {&lt;br /&gt;
&lt;br /&gt;
		mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
			var button_import = new OO.ui.SelectFileWidget ( { &lt;br /&gt;
					label: &amp;quot;Import Personal Data&amp;quot;, &lt;br /&gt;
					classes: [ 'pduimark' ] &lt;br /&gt;
				}), &lt;br /&gt;
&lt;br /&gt;
				button_export = new OO.ui.ButtonWidget( { label: &amp;quot;Export Personal Data&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
&lt;br /&gt;
				button_import.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
				if (window.webkitURL != null) {&lt;br /&gt;
					alert(&amp;quot;loading file on webkit&amp;quot;)&lt;br /&gt;
				} else {&lt;br /&gt;
					alert(&amp;quot;loading file non webkit&amp;quot;)&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			button_export.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
				var get_record = indexedDBobject.EnqueuePDIO('get record');&lt;br /&gt;
&lt;br /&gt;
				get_record.then( function(result) {&lt;br /&gt;
					if ( result === undefined ) { alert(&amp;quot;No data to export&amp;quot;) };&lt;br /&gt;
&lt;br /&gt;
					var filename_tosaveas = &amp;quot;pdiolocalexport_&amp;quot; + result.name.user + &amp;quot;_&amp;quot; + Date.now() + '.json';&lt;br /&gt;
					&lt;br /&gt;
					result.id = '';&lt;br /&gt;
					result.name.user = '';&lt;br /&gt;
					&lt;br /&gt;
					var export_to_text = JSON.stringify(result);&lt;br /&gt;
					var textFileAsBlob = new Blob([export_to_text], {type:'text/plain'});&lt;br /&gt;
					var downloadLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
					downloadLink.download = filename_tosaveas;&lt;br /&gt;
					if (window.webkitURL != null)&lt;br /&gt;
					{&lt;br /&gt;
						// Chrome allows the link to be clicked&lt;br /&gt;
						// without actually adding it to the DOM.&lt;br /&gt;
						downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						// Firefox requires the link to be added to the DOM&lt;br /&gt;
						// before it can be clicked.&lt;br /&gt;
						downloadLink.href = window.URL.createObjectURL(textFileAsBlob);&lt;br /&gt;
						downloadLink.style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
						document.body.appendChild(downloadLink);&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					downloadLink.click();&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			mw.notify( $( button_import.$element ), { autoHide: false }  );&lt;br /&gt;
			mw.notify( $( button_export.$element ), { autoHide: false }  );&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4943</id>
		<title>User:Abel/OOInterface.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4943"/>
		<updated>2019-05-24T13:13:02Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
		notify_porting();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['IDName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
			ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
	&lt;br /&gt;
	function notify_porting() {&lt;br /&gt;
&lt;br /&gt;
		mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
			var button_import = new OO.ui.SelectFileWidget ( { &lt;br /&gt;
					label: &amp;quot;Import Personal Data&amp;quot;, &lt;br /&gt;
					classes: [ 'pduimark' ] &lt;br /&gt;
				}), &lt;br /&gt;
&lt;br /&gt;
				button_export = new OO.ui.ButtonWidget( { label: &amp;quot;Export Personal Data&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
&lt;br /&gt;
			button_import.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
				if (window.webkitURL != null) {&lt;br /&gt;
&lt;br /&gt;
				} else {&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			button_export.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
				var get_record = indexedDBobject.EnqueuePDIO('get record');&lt;br /&gt;
&lt;br /&gt;
				get_record.then( function(result) {&lt;br /&gt;
					if ( result === undefined ) { alert(&amp;quot;No data to export&amp;quot;) };&lt;br /&gt;
&lt;br /&gt;
					var filename_tosaveas = &amp;quot;pdiolocalexport_&amp;quot; + result.name.user + &amp;quot;_&amp;quot; + Date.now() + '.json';&lt;br /&gt;
					&lt;br /&gt;
					result.id = '';&lt;br /&gt;
					result.name.user = '';&lt;br /&gt;
					&lt;br /&gt;
					var export_to_text = JSON.stringify(result);&lt;br /&gt;
					var textFileAsBlob = new Blob([export_to_text], {type:'text/plain'});&lt;br /&gt;
					var downloadLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
					downloadLink.download = filename_tosaveas;&lt;br /&gt;
					if (window.webkitURL != null)&lt;br /&gt;
					{&lt;br /&gt;
						// Chrome allows the link to be clicked&lt;br /&gt;
						// without actually adding it to the DOM.&lt;br /&gt;
						downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);&lt;br /&gt;
					}&lt;br /&gt;
					else&lt;br /&gt;
					{&lt;br /&gt;
						// Firefox requires the link to be added to the DOM&lt;br /&gt;
						// before it can be clicked.&lt;br /&gt;
						downloadLink.href = window.URL.createObjectURL(textFileAsBlob);&lt;br /&gt;
						downloadLink.style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
						document.body.appendChild(downloadLink);&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					downloadLink.click();&lt;br /&gt;
&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			mw.notify( $( button_import.$element ), { autoHide: false }  );&lt;br /&gt;
			mw.notify( $( button_export.$element ), { autoHide: false }  );&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4942</id>
		<title>User:Abel/OOInterface.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4942"/>
		<updated>2019-05-24T13:00:11Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
		notify_porting();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['IDName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
			ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
	&lt;br /&gt;
	function notify_porting() {&lt;br /&gt;
		&lt;br /&gt;
		var button_import = new OO.ui.SelectFileInputWidget ( { &lt;br /&gt;
				label: &amp;quot;Import Personal Data&amp;quot;, &lt;br /&gt;
				useInputTag: true,&lt;br /&gt;
				classes: [ 'pduimark' ] &lt;br /&gt;
			}), &lt;br /&gt;
&lt;br /&gt;
			button_export = new OO.ui.ButtonWidget( { label: &amp;quot;Export Personal Data&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
&lt;br /&gt;
		button_import.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
			if (window.webkitURL != null) {&lt;br /&gt;
&lt;br /&gt;
			} else {&lt;br /&gt;
&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
		button_export.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
			var get_record = indexedDBobject.EnqueuePDIO('get record');&lt;br /&gt;
&lt;br /&gt;
			get_record.then( function(result) {&lt;br /&gt;
				if ( result === undefined ) { alert(&amp;quot;No data to export&amp;quot;) };&lt;br /&gt;
&lt;br /&gt;
				var filename_tosaveas = &amp;quot;pdiolocalexport_&amp;quot; + result.name.user + &amp;quot;_&amp;quot; + Date.now() + '.json';&lt;br /&gt;
				&lt;br /&gt;
				result.id = '';&lt;br /&gt;
				result.name.user = '';&lt;br /&gt;
				&lt;br /&gt;
				var export_to_text = JSON.stringify(result);&lt;br /&gt;
				var textFileAsBlob = new Blob([export_to_text], {type:'text/plain'});&lt;br /&gt;
				var downloadLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
				downloadLink.download = filename_tosaveas;&lt;br /&gt;
				if (window.webkitURL != null)&lt;br /&gt;
				{&lt;br /&gt;
					// Chrome allows the link to be clicked&lt;br /&gt;
					// without actually adding it to the DOM.&lt;br /&gt;
					downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					// Firefox requires the link to be added to the DOM&lt;br /&gt;
					// before it can be clicked.&lt;br /&gt;
					downloadLink.href = window.URL.createObjectURL(textFileAsBlob);&lt;br /&gt;
					downloadLink.style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
					document.body.appendChild(downloadLink);&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				downloadLink.click();&lt;br /&gt;
&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
		mw.notify( $( button_import.$element ), { autoHide: false }  );&lt;br /&gt;
		mw.notify( $( button_export.$element ), { autoHide: false }  );&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4941</id>
		<title>User:Abel/OOInterface.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4941"/>
		<updated>2019-05-24T12:47:57Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
		notify_porting();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['IDName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
			ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
	&lt;br /&gt;
	function notify_porting() {&lt;br /&gt;
		&lt;br /&gt;
		var button_import = new OO.ui.ButtonWidget( { label: &amp;quot;Import Personal Data&amp;quot;, classes: [ 'pduimark' ] } ), &lt;br /&gt;
			button_export = new OO.ui.ButtonWidget( { label: &amp;quot;Export Personal Data&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
&lt;br /&gt;
		button_import.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
		button_export.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
			var get_record = indexedDBobject.EnqueuePDIO('get record');&lt;br /&gt;
&lt;br /&gt;
			get_record.then( function(result) {&lt;br /&gt;
				if ( result === undefined ) { alert(&amp;quot;No data to export&amp;quot;) };&lt;br /&gt;
&lt;br /&gt;
				var filename_tosaveas = &amp;quot;pdiolocalexport_&amp;quot; + result.name.user + &amp;quot;_&amp;quot; + Date.now();&lt;br /&gt;
				&lt;br /&gt;
				result.id = '';&lt;br /&gt;
				result.name.user = '';&lt;br /&gt;
				&lt;br /&gt;
				var export_to_text = JSON.stringify(result);&lt;br /&gt;
				var textFileAsBlob = new Blob([export_to_text], {type:'text/plain'});&lt;br /&gt;
				var downloadLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
				downloadLink.download = filename_tosaveas;&lt;br /&gt;
				if (window.webkitURL != null)&lt;br /&gt;
				{&lt;br /&gt;
					// Chrome allows the link to be clicked&lt;br /&gt;
					// without actually adding it to the DOM.&lt;br /&gt;
					downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					// Firefox requires the link to be added to the DOM&lt;br /&gt;
					// before it can be clicked.&lt;br /&gt;
					downloadLink.href = window.URL.createObjectURL(textFileAsBlob);&lt;br /&gt;
					downloadLink.style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
					document.body.appendChild(downloadLink);&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				downloadLink.click();&lt;br /&gt;
&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
		mw.notify( $( button_import.$element ), { autoHide: false }  );&lt;br /&gt;
		mw.notify( $( button_export.$element ), { autoHide: false }  );&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4940</id>
		<title>User:Abel/OOInterface.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4940"/>
		<updated>2019-05-24T12:44:45Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
		notify_porting();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['IDName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
			ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
	&lt;br /&gt;
	function notify_porting() {&lt;br /&gt;
		&lt;br /&gt;
		var button_import = new OO.ui.ButtonWidget( { label: &amp;quot;Import Personal Data&amp;quot;, classes: [ 'pduimark' ] } ), &lt;br /&gt;
			button_export = new OO.ui.ButtonWidget( { label: &amp;quot;Export Personal Data&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
&lt;br /&gt;
		button_import.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
		button_export.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
			var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
			get_record.then( function(result) {&lt;br /&gt;
				var filename_tosaveas = &amp;quot;pdiolocalexport_&amp;quot; + result.name.user + &amp;quot;_&amp;quot; + Date.now();&lt;br /&gt;
				result.id = '';&lt;br /&gt;
				result.name.user = '';&lt;br /&gt;
				var export_to_text = JSON.stringify(result);&lt;br /&gt;
				var textFileAsBlob = new Blob([export_to_text], {type:'text/plain'});&lt;br /&gt;
				var downloadLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
				downloadLink.download = filename_tosaveas;&lt;br /&gt;
				if (window.webkitURL != null)&lt;br /&gt;
				{&lt;br /&gt;
					// Chrome allows the link to be clicked&lt;br /&gt;
					// without actually adding it to the DOM.&lt;br /&gt;
					downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					// Firefox requires the link to be added to the DOM&lt;br /&gt;
					// before it can be clicked.&lt;br /&gt;
					downloadLink.href = window.URL.createObjectURL(textFileAsBlob);&lt;br /&gt;
					downloadLink.style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
					document.body.appendChild(downloadLink);&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				downloadLink.click();&lt;br /&gt;
&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
		mw.notify( $( button_import.$element, '&amp;lt;br&amp;gt;', button_export.$element ) );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4939</id>
		<title>User:Abel/OOInterface.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4939"/>
		<updated>2019-05-24T12:42:37Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
		notify_porting();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['IDName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
			ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
	&lt;br /&gt;
	function notify_porting() {&lt;br /&gt;
		&lt;br /&gt;
		var button_import = new OO.ui.ButtonWidget( { label: &amp;quot;Import Personal Data&amp;quot;, classes: [ 'pduimark' ] } ), &lt;br /&gt;
			button_export = new OO.ui.ButtonWidget( { label: &amp;quot;Export Personal Data&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
&lt;br /&gt;
		button_import.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
		button_export.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
			var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
			get_record.then( function(result) {&lt;br /&gt;
				var filename_tosaveas = &amp;quot;pdiolocalexport_&amp;quot; + result.name.user + &amp;quot;_&amp;quot; + Date.now();&lt;br /&gt;
				result.id = '';&lt;br /&gt;
				result.name.user = '';&lt;br /&gt;
				var export_to_text = JSON.stringify(result);&lt;br /&gt;
				var textFileAsBlob = new Blob([export_to_text], {type:'text/plain'});&lt;br /&gt;
				var downloadLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
				downloadLink.download = filename_tosaveas;&lt;br /&gt;
				if (window.webkitURL != null)&lt;br /&gt;
				{&lt;br /&gt;
					// Chrome allows the link to be clicked&lt;br /&gt;
					// without actually adding it to the DOM.&lt;br /&gt;
					downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					// Firefox requires the link to be added to the DOM&lt;br /&gt;
					// before it can be clicked.&lt;br /&gt;
					downloadLink.href = window.URL.createObjectURL(textFileAsBlob);&lt;br /&gt;
					downloadLink.style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
					document.body.appendChild(downloadLink);&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				downloadLink.click();&lt;br /&gt;
&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
		mw.notify( $( button_import.$element + '&amp;lt;br&amp;gt;' + button_export.$element ) );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4938</id>
		<title>User:Abel/OOInterface.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4938"/>
		<updated>2019-05-24T12:40:57Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
		notify_porting();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['IDName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
			ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
	&lt;br /&gt;
	function notify_porting() {&lt;br /&gt;
		&lt;br /&gt;
		var button_import = new OO.ui.ButtonWidget( { label: &amp;quot;Import Personal Data&amp;quot;, classes: [ 'pduimark' ] } ), &lt;br /&gt;
			button_export = new OO.ui.ButtonWidget( { label: &amp;quot;Export Personal Data&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
&lt;br /&gt;
		button_import.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		button_export.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
			var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
			get_record.then( function(result) {&lt;br /&gt;
				var filename_tosaveas = &amp;quot;pdiolocalexport_&amp;quot; + result.name.user + &amp;quot;_&amp;quot; + Date.now();&lt;br /&gt;
				result.id = '';&lt;br /&gt;
				result.name.user = '';&lt;br /&gt;
				var export_to_text = JSON.stringify(result);&lt;br /&gt;
				var textFileAsBlob = new Blob([export_to_text], {type:'text/plain'});&lt;br /&gt;
				var downloadLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
				downloadLink.download = filename_tosaveas;&lt;br /&gt;
				if (window.webkitURL != null)&lt;br /&gt;
				{&lt;br /&gt;
					// Chrome allows the link to be clicked&lt;br /&gt;
					// without actually adding it to the DOM.&lt;br /&gt;
					downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					// Firefox requires the link to be added to the DOM&lt;br /&gt;
					// before it can be clicked.&lt;br /&gt;
					downloadLink.href = window.URL.createObjectURL(textFileAsBlob);&lt;br /&gt;
					downloadLink.style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
					document.body.appendChild(downloadLink);&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				downloadLink.click();&lt;br /&gt;
&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		mw.notify( $( button_import.$element + '&amp;lt;br&amp;gt;' + button_export.$element ) );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4937</id>
		<title>User:Abel/OOInterface.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4937"/>
		<updated>2019-05-24T12:37:25Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
		notify_porting();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['IDName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
			ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
	&lt;br /&gt;
	function notify_porting() {&lt;br /&gt;
		&lt;br /&gt;
		var button_import = new OO.ui.ButtonWidget( { label: &amp;quot;Import Personal Data&amp;quot;, classes: [ 'pduimark' ] } ), &lt;br /&gt;
			button_export = new OO.ui.ButtonWidget( { label: &amp;quot;Export Personal Data&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
&lt;br /&gt;
		button_import.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		button_export.on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
			var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
			get_record.then( function(result) {&lt;br /&gt;
				var filename_tosaveas = &amp;quot;pdiolocalexport_&amp;quot; + result.name.user + &amp;quot;_&amp;quot; + Date.now();&lt;br /&gt;
				result.id = '';&lt;br /&gt;
				result.name.user = '';&lt;br /&gt;
				var export_to_text = JSON.stringify(result);&lt;br /&gt;
				var textFileAsBlob = new Blob([export_to_text], {type:'text/plain'});&lt;br /&gt;
				var downloadLink = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
				downloadLink.download = filename_tosaveas;&lt;br /&gt;
				if (window.webkitURL != null)&lt;br /&gt;
				{&lt;br /&gt;
					// Chrome allows the link to be clicked&lt;br /&gt;
					// without actually adding it to the DOM.&lt;br /&gt;
					downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);&lt;br /&gt;
				}&lt;br /&gt;
				else&lt;br /&gt;
				{&lt;br /&gt;
					// Firefox requires the link to be added to the DOM&lt;br /&gt;
					// before it can be clicked.&lt;br /&gt;
					downloadLink.href = window.URL.createObjectURL(textFileAsBlob);&lt;br /&gt;
					downloadLink.style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
					document.body.appendChild(downloadLink);&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				downloadLink.click();&lt;br /&gt;
&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		mw.notify( $( button_import.$element + '&amp;lt;br&amp;gt;' + button_export.$element ) );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4927</id>
		<title>User:Abel/OOInterface.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4927"/>
		<updated>2019-05-24T11:36:40Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
		notify_porting();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['IDName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
		    ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
	&lt;br /&gt;
	function notify_porting() {&lt;br /&gt;
		&lt;br /&gt;
		var button_import = new OO.ui.ButtonWidget( { label: &amp;quot;Import local personal data from file&amp;quot;, classes: [ 'pduimark' ] } ), &lt;br /&gt;
			button_export = new OO.ui.ButtonWidget( { label: &amp;quot;Export local personal data to file &amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		mw.notify( $( button_import.$element , button_export.$element ) );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4926</id>
		<title>User:Abel/OOInterface.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4926"/>
		<updated>2019-05-24T11:33:53Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['IDName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
		    ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
	&lt;br /&gt;
	function notify_porting() {&lt;br /&gt;
		&lt;br /&gt;
		var button_import = new OO.ui.ButtonWidget( { label: &amp;quot;Import local personal data from file&amp;quot;, classes: [ 'pduimark' ] } ), &lt;br /&gt;
			button_export = new OO.ui.ButtonWidget( { label: &amp;quot;Export local personal data to file &amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		mw.notify( $( button_import.$element , button_export.$element ) );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4925</id>
		<title>User:Abel/OOInterface.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4925"/>
		<updated>2019-05-24T11:18:41Z</updated>

		<summary type="html">&lt;p&gt;Abel: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['IDName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('update record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
		    ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
	<entry>
		<id>https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4924</id>
		<title>User:Abel/OOInterface.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.personaldata.io/w/index.php?title=User:Abel/OOInterface.js&amp;diff=4924"/>
		<updated>2019-05-24T11:15:24Z</updated>

		<summary type="html">&lt;p&gt;Abel: Created page with &amp;quot;// License: GPL // User Interface Rendering  console.log('Interface handler loading');  function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) { 	 	this.rende...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// License: GPL&lt;br /&gt;
// User Interface Rendering &lt;br /&gt;
console.log('Interface handler loading');&lt;br /&gt;
&lt;br /&gt;
function InterfaceMediaContainer ( WikibaseProcessor, indexedDBobject ) {&lt;br /&gt;
	&lt;br /&gt;
	this.renderInterface = function( sqitch ) {&lt;br /&gt;
		switch( sqitch ) {&lt;br /&gt;
			case 'controller_id':&lt;br /&gt;
				controller_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'personal_data_id':&lt;br /&gt;
				pd_site_render();&lt;br /&gt;
				break;&lt;br /&gt;
			case 'interface_button_id':&lt;br /&gt;
				personal_data_edit_interface_render();&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	var button_save = [],&lt;br /&gt;
		button_remove = [],&lt;br /&gt;
		textInput = [];&lt;br /&gt;
&lt;br /&gt;
	async function controller_render(){&lt;br /&gt;
		console.log(&amp;quot;this function is done by the current page controller for now&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	async function pd_site_render(){&lt;br /&gt;
&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	async function personal_data_edit_interface_render(){&lt;br /&gt;
		clear_render();&lt;br /&gt;
		&lt;br /&gt;
		// Get concerns relation :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var concern_origin = WikibaseProcessor.checkentity( { this_concerns: [ WBEStructure['concernsRelation'], WBEStructure['IDPropLoc'], WBEStructure['IDName'] ] } )['this_concerns'][0];&lt;br /&gt;
&lt;br /&gt;
		// Get defval for entity :: Parts of this must be moved upstream, MAIN should know that this is the data the renderer will need and provide it &lt;br /&gt;
&lt;br /&gt;
		var default_value = WikibaseProcessor.checkentity( { default_value: [ WBEStructure['defaultValRelation'], WBEStructure['IDPropLoc'] ] } )['default_value'][0]; //defal&lt;br /&gt;
&lt;br /&gt;
		var get_record = indexedDBobject.EnqueuePDIO('get record');&lt;br /&gt;
&lt;br /&gt;
		get_record.then( function(result) {&lt;br /&gt;
&lt;br /&gt;
			mw.loader.using( 'oojs-ui-core' ).done( function () {&lt;br /&gt;
&lt;br /&gt;
				button_save = [],&lt;br /&gt;
				button_remove = [],&lt;br /&gt;
				textInput = [];&lt;br /&gt;
&lt;br /&gt;
				var extrafield = ( result[concern_origin] != undefined ) ? Object.keys(result[concern_origin]).length : 0;&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
				&lt;br /&gt;
				textInput[ extrafield ] = new OO.ui.TextInputWidget( { &lt;br /&gt;
						placeholder: default_value,&lt;br /&gt;
						classes: [ 'pduimark' ]&lt;br /&gt;
				} );&lt;br /&gt;
&lt;br /&gt;
				button_save[ extrafield ].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, extrafield, textInput[ extrafield ].value );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				$( '#mw-content-text' ).prepend( button_save[ extrafield ].$element );&lt;br /&gt;
				$( '#mw-content-text' ).prepend( textInput[ extrafield ].$element );&lt;br /&gt;
&lt;br /&gt;
				if ( extrafield &amp;gt; 0) {&lt;br /&gt;
					Object.keys( result[concern_origin] ).forEach( function(data) {&lt;br /&gt;
						button_save[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Save&amp;quot;, classes: [ 'pduimark' ]	} );&lt;br /&gt;
						button_remove[data] = new OO.ui.ButtonWidget( { label: &amp;quot;Delete&amp;quot;, classes: [ 'pduimark' ] } );&lt;br /&gt;
						textInput[data] = new OO.ui.TextInputWidget( { &lt;br /&gt;
							value: result[concern_origin][data],				///&lt;br /&gt;
							placeholder: default_value,&lt;br /&gt;
							classes: [ 'pduimark' ]&lt;br /&gt;
						} );&lt;br /&gt;
						button_save[data].on( 'click', function () {&lt;br /&gt;
&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('update record', concern_origin, data, textInput[ data ].value );&lt;br /&gt;
&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
&lt;br /&gt;
						button_remove[data].on( 'click', function () {&lt;br /&gt;
							indexedDBobject.EnqueuePDIO('remove from record', concern_origin, data );&lt;br /&gt;
							personal_data_edit_interface_render();&lt;br /&gt;
						});&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_remove[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( button_save[data].$element );&lt;br /&gt;
						$( '#mw-content-text' ).prepend( textInput[data].$element );&lt;br /&gt;
&lt;br /&gt;
					});&lt;br /&gt;
&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
	function clear_render() {&lt;br /&gt;
		var ifel = document.getElementsByClassName('pduimark');&lt;br /&gt;
		while( ifel[0] ) {&lt;br /&gt;
		    ifel[0].parentNode.removeChild(ifel[0]);&lt;br /&gt;
		};&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Abel</name></author>
	</entry>
</feed>