Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serialize JavaScript's navigator object

I'm creating a page to help diagnose the problem our users are experiencing with our web pages (you know, asking a user "What browser are you using?" usually leads to "Internet").

This page already submits to me all the HTTP headers and now I'm trying to have JavaScript give some more informations, so I thought it would be great to have the user's navigator JavaScript object and I started looking how to serialize it so I can submit it through a form.

The problem is I'm not able to serialize the navigator object using any JSON library I know of, everyone returns an empty object (?!), so I decided to write an ad-hoc serializer.

You can find the code here:

<!DOCTYPE html>
<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js" type="text/javascript"></script>
        <script type="text/javascript">
            function serialize (object) {
                var type = typeof object;
                if (object === null) {
                    return '"nullValue"';
                }
                if (type == 'string' || type === 'number' || type === 'boolean') {
                    return '"' + object + '"';
                }
                else if (type === 'function') {
                    return '"functionValue"';
                }
                else if (type === 'object') {
                    var output = '{';
                    for (var item in object) {
                        if (item !== 'enabledPlugin') {
                            output += '"' + item + '":' + serialize(object[item]) + ',';
                        }
                    }
                    return output.replace(/\,$/, '') + '}';
                }
                else if (type === 'undefined') {
                    return '"undefinedError"';
                }
                else {
                    return '"unknownTypeError"';
                }
            };
            $(document).ready(function () {
                $('#navigator').text(serialize(navigator));
            });
        </script>
        <style type="text/css">
            #navigator {
                font-family: monospaced;
            }
        </style>
        <title>Serialize</title>
    </head>
    <body>
        <h1>Serialize</h1>
        <p id="navigator"></p>
    </body>
</html>

This code seems to work perfectly in Firefox, Opera, Chrome and Safari but (obviously) doesn't work in Internet Explorer (at least version 8.0), it complains that "Property or method not supported by the object" at line for (var item in object) {.

Do you have any hint on how to fix the code or how to reach the goal (serialize the navigator object) by other means?


Solution (v 2.0):

Replace

for (var item in object) {
    if (item !== 'enabledPlugin') {
        output += '"' + item + '":' + serialize(object[item]) + ',';
    }
}

with

for (var item in object) {
    try {
        if (item !== 'enabledPlugin') {
            output += '"' + item + '":' + serialize(object[item]) + ',';
        }
    }
    catch (e) {
    }
}

and it works.

like image 723
Albireo Avatar asked Feb 11 '11 14:02

Albireo


2 Answers

Try putting it inside a new object

var _navigator = {};
for (var i in navigator) _navigator[i] = navigator[i];

And then serialize it (maybe using some JSON library if the browser doesn't have native JSON API, I use json2.js):

$('#navigator').text(JSON.stringify(_navigator));

Edit: It seems that Internet Explorer doesn't allow navigator.plugins and navigator.mimeTypes to be iterated over, so this works:

var _navigator = {};
for (var i in navigator) _navigator[i] = navigator[i];

delete _navigator.plugins;
delete _navigator.mimeTypes;

$('#navigator').text(JSON.stringify(_navigator));
like image 67
Thai Avatar answered Oct 03 '22 04:10

Thai


JSON in accepted answer contains only top level elements. Check this out https://jsfiddle.net/j1zb7qm0/ - _navigator.connection is empty. I've wrote a small func to collect all nested properties:

function recur(obj) {
  var result = {}, _tmp;
  for (var i in obj) {
    // enabledPlugin is too nested, also skip functions
    if (i === 'enabledPlugin' || typeof obj[i] === 'function') {
        continue;
    } else if (typeof obj[i] === 'object') {
        // get props recursively
        _tmp = recur(obj[i]);
        // if object is not {}
        if (Object.keys(_tmp).length) {
            result[i] = _tmp;
        }
    } else {
        // string, number or boolean
        result[i] = obj[i];
    }
  }
  return result;
}

You can use it like this var _navigator = recur(navigator) or create your own wrapper. In fact you can use it to iterate over and copy any nested object.

like image 24
vladkras Avatar answered Oct 03 '22 02:10

vladkras