0

I want to transfer the INI file content uploaded by users to an object and compare this object data with the existing one. Example INI file content is look like this:

Name: Aesthetic
Author: Redon
CursorCentre: 1
CursorExpand: 0
SliderBallFlip: 0
Combo1: 145,229,103
Combo2: 255,213,128

However when I tried to get object itself it is working. But when I tried to get value by key it doesn't work. How can I get value by key in this example?

$(document).on('change','input[name=import]',function(e){
    var settings = {};
    var file = e.target.files[0];
    var reader = new FileReader();
    reader.onload = function(){
        var myText = reader.result;
        var myText = myText.split(/\r?\n/);
        $.each(myText, function(index, val) {
            var item = val.split(":");
            var itemkey = item[0];
            var itemval = $.trim(item[1]);
            settings[itemkey] = itemval;
        });
    }
    reader.readAsText(file);
    console.log(settings); // Works
    console.log(settings['Author']); // undefined
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="file" name="import" accept=".ini">
philos
  • 86
  • 7
  • 1
    I assume it's a timing problem. Where exactly in your code are you trying your console logging? It surely won't work outside your `reader.onload`function. – connexo Aug 03 '18 at 18:57
  • I tried logging both inside and outside of the change function and it didn't work. I also tried define object inside change function. It didn't work either. – philos Aug 03 '18 at 19:00
  • Read again. ^^^^ – connexo Aug 03 '18 at 19:11
  • `console.log(settings)` works outside onload function. So why `console.log(settings[key])` doesn't work on the same place? – philos Aug 03 '18 at 19:13
  • @philos Where do you add the property "Author" to the Object? – Unmitigated Aug 03 '18 at 19:22
  • @hev1 `settings[itemkey] = itemval;` after split them. Also not only "Author". All other keys in the INI file. – philos Aug 03 '18 at 19:30
  • @philos what is the *working* output of `console.log(settings); // Works` – Mark Aug 03 '18 at 20:04
  • @MarkMeyer [here](https://i.imgur.com/fEWE0NI.png) is the working output. – philos Aug 03 '18 at 20:11
  • It's not *actually* working. hover over the little blue "i" – Kevin B Aug 03 '18 at 20:14
  • @KevinB Little blue "i" showing for all objects in Chrome. It's a general thing. – philos Aug 03 '18 at 20:42
  • @philos As it should. Did you read the note behind the little i? – Kevin B Aug 03 '18 at 20:43
  • @KevinB Yes, I did. It's not something related to my question. – philos Aug 03 '18 at 20:57
  • Except... it is. "Value below was evaluated just now.". What it is telling you is the console didn't inspect the contents of the object until "just now", just now being the point in time you clicked to expand it. Which just so happened to be *after* the event that changes the object occurred, which happened some time *after* the console.logs did. Moving the console.logs into the event of course causes them to not hit the console until after the change occurs, thus making the direct log of a value work. – Kevin B Aug 03 '18 at 20:59
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/177382/discussion-between-philos-and-kevin-b). – philos Aug 03 '18 at 20:59

1 Answers1

2

Like @connexo suggested: it is a timing problem. In my slighty changed version I placed the two console.log inside the reader.onload-function and it works!

$(document).on('change','input[name=import]',function(e){
    var settings = {};
    var file = e.target.files[0];
    var reader = new FileReader();
    reader.onload = function(){
        var myText = reader.result;
        var myText = myText.split(/\r?\n/);
        $.each(myText, function(index, val) {
            var item = val.split(":");
            var itemkey = item[0];
            var itemval = $.trim(item[1]);
            settings[itemkey] = itemval;
        });
        console.log(settings); // really works
        console.log(settings['Author']); // works too!
    }
    reader.readAsText(file);
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="file" name="import" accept=".ini">

Note

When I say: "a timing problem" then that is strictly speaking not the whole truth. The object settings will only be available inside the $('document').on('change'...)-function, and only after reader.onload() has done its work. If you want to have the content stored in a global variable (for later reference, maybe by another function ...) then you need to place the var settings={}; outside of your $('document').on('change'...)-function or use something like window['settings']={}; or window.settings={};.

Carsten Massmann
  • 26,510
  • 2
  • 22
  • 43
  • @cars10m Thanks, it works! But It's really confusing, that I can retrieve whole data of object outside `reader.onload` but specific value by key. – philos Aug 03 '18 at 20:38