AJAX/JSON
epikTrash
- javascript
3 molily
Hallo ich habe ein Problem mit einem Javascript: Ich möchte beim Ausführen einer Funktion getMail(1); im onload Bereich des HTML Dokuments eine Funtkion ausführen, die eine Datei "header/1/" läd in der sich ein JSON Objekt befindet. Beim Ausführen passiert nichts. Es gibt auch keine Fehler in den Fehlerkonsolen von FF 4 und Opera 11.01. Der Funktionsaufruf schein bei der Funktion addMail() zu scheitern, da dort die if Bedingung nicht erfüllt wird. index.htm:
<!DOCTYPE html>
<head>
<title>möp</title>
<script type="text/javascript" src="json_sans_eval.js"></script>
<script type="text/javascript" src="tmpjs.js"></script>
</head>
<body onload="getMail(1);">
<div>
<div id="nav">
</div>
<div id="mailwrapper"></div>
</div>
</body>
</html>
tmpjs.js:
<!--
function getXmlHttpRequestObject() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else if(window.ActiveXObject) {
return new ActiveXObject("Microsoft.XMLHTTP");
} else {
alert("Dein Browser unterstützt keine XmlHttpRequest Objekte. Besser du wechselst auf Firefox oder Opera.<br />Your browser doesn't support the XmlHttpRequest object. Better upgrade to Firefox or Opera.");
}
}
var receiveReq = getXmlHttpRequestObject();
var mailArray = new Array();
mailArray[0] = '';
function handleContent() {
if (receiveReq.readyState == 4) {
document.getElementById('mailwrapper').innerHTML = receiveReq.responseText;
}
}
function showContent(id) {
if (receiveReq.readyState == 4 || receiveReq.readyState == 0) {
receiveReq.open("GET", 'content/'+id+'/', true);
receiveReq.onreadystatechange = handleContent;
receiveReq.send(null);
}
}
function addMail(id) {
if (receiveReq.readyState == 4) {
mailArray[id] = jsonParse(receiveReq.responseText);
refreshMails;
}
}
function deleteMail(id) {
mailArray[id] = '';
refreshMails;
}
function getMail(id) {
if (receiveReq.readyState == 4 || receiveReq.readyState == 0) {
receiveReq.open("GET", 'header/'+id+'/', true);
receiveReq.onreadystatechange = addMail(id);
receiveReq.send(null);
}
}
function refreshMails() {
var returnVar = '';
for(var i = mailArray.length; i > 0; --i) {
if(mailArray[i] != '') {
returnVar += '<a href="javascript:showContent('+mailArray[i].id+')"><div id="'+mailArray[i].id+'" class="element"><div class="top"><div class="name">'+mailArray[i].from+'</div><div class="time">'+mailArray[i].time+'</div></div><div class="bottom">'+mailArray[i].subject+'</div></div></a>';
}
}
document.getElementById('nav').innerHTML = returnVar;
}
function rateMail(id, rate) { /* TODO */
refreshMails;
}
-->
json_sans_eval.js:
// This source code is free for use in the public domain.
// NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
// http://code.google.com/p/json-sans-eval/
/**
* Parses a string of well-formed JSON text.
*
* If the input is not well-formed, then behavior is undefined, but it is
* deterministic and is guaranteed not to modify any object other than its
* return value.
*
* This does not use `eval` so is less likely to have obscure security bugs than
* json2.js.
* It is optimized for speed, so is much faster than json_parse.js.
*
* This library should be used whenever security is a concern (when JSON may
* come from an untrusted source), speed is a concern, and erroring on malformed
* JSON is *not* a concern.
*
* Pros Cons
* +-----------------------+-----------------------+
* json_sans_eval.js | Fast, secure | Not validating |
* +-----------------------+-----------------------+
* json_parse.js | Validating, secure | Slow |
* +-----------------------+-----------------------+
* json2.js | Fast, some validation | Potentially insecure |
* +-----------------------+-----------------------+
*
* json2.js is very fast, but potentially insecure since it calls `eval` to
* parse JSON data, so an attacker might be able to supply strange JS that
* looks like JSON, but that executes arbitrary javascript.
* If you do have to use json2.js with untrusted data, make sure you keep
* your version of json2.js up to date so that you get patches as they're
* released.
*
* @param {string} json per RFC 4627
* @param {function (this:Object, string, *):*} opt_reviver optional function
* that reworks JSON objects post-parse per Chapter 15.12 of EcmaScript3.1.
* If supplied, the function is called with a string key, and a value.
* The value is the property of 'this'. The reviver should return
* the value to use in its place. So if dates were serialized as
* {@code { "type": "Date", "time": 1234 }}, then a reviver might look like
* {@code
* function (key, value) {
* if (value && typeof value === 'object' && 'Date' === value.type) {
* return new Date(value.time);
* } else {
* return value;
* }
* }}.
* If the reviver returns {@code undefined} then the property named by key
* will be deleted from its container.
* {@code this} is bound to the object containing the specified property.
* @return {Object|Array}
* @author Mike Samuel <mikesamuel@gmail.com>
*/
var jsonParse = (function () {
var number
= '(?:-?\\b(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\\b)';
var oneChar = '(?:[^\\0-\\x08\\x0a-\\x1f\"\\\\]'
+ '|\\\\(?:[\"/\\\\bfnrt]|u[0-9A-Fa-f]{4}))';
var string = '(?:\"' + oneChar + '*\")';
// Will match a value in a well-formed JSON file.
// If the input is not well-formed, may match strangely, but not in an unsafe
// way.
// Since this only matches value tokens, it does not match whitespace, colons,
// or commas.
var jsonToken = new RegExp(
'(?:false|true|null|[\\{\\}\\[\\]]'
+ '|' + number
+ '|' + string
+ ')', 'g');
// Matches escape sequences in a string literal
var escapeSequence = new RegExp('\\\\(?:([^u])|u(.{4}))', 'g');
// Decodes escape sequences in object literals
var escapes = {
'"': '"',
'/': '/',
'\\': '\\',
'b': '\b',
'f': '\f',
'n': '\n',
'r': '\r',
't': '\t'
};
function unescapeOne(_, ch, hex) {
return ch ? escapes[ch] : String.fromCharCode(parseInt(hex, 16));
}
// A non-falsy value that coerces to the empty string when used as a key.
var EMPTY_STRING = new String('');
var SLASH = '\\';
// Constructor to use based on an open token.
var firstTokenCtors = { '{': Object, '[': Array };
var hop = Object.hasOwnProperty;
return function (json, opt_reviver) {
// Split into tokens
var toks = json.match(jsonToken);
// Construct the object to return
var result;
var tok = toks[0];
var topLevelPrimitive = false;
if ('{' === tok) {
result = {};
} else if ('[' === tok) {
result = [];
} else {
// The RFC only allows arrays or objects at the top level, but the JSON.parse
// defined by the EcmaScript 5 draft does allow strings, booleans, numbers, and null
// at the top level.
result = [];
topLevelPrimitive = true;
}
// If undefined, the key in an object key/value record to use for the next
// value parsed.
var key;
// Loop over remaining tokens maintaining a stack of uncompleted objects and
// arrays.
var stack = [result];
for (var i = 1 - topLevelPrimitive, n = toks.length; i < n; ++i) {
tok = toks[i];
var cont;
switch (tok.charCodeAt(0)) {
default: // sign or digit
cont = stack[0];
cont[key || cont.length] = +(tok);
key = void 0;
break;
case 0x22: // '"'
tok = tok.substring(1, tok.length - 1);
if (tok.indexOf(SLASH) !== -1) {
tok = tok.replace(escapeSequence, unescapeOne);
}
cont = stack[0];
if (!key) {
if (cont instanceof Array) {
key = cont.length;
} else {
key = tok || EMPTY_STRING; // Use as key for next value seen.
break;
}
}
cont[key] = tok;
key = void 0;
break;
case 0x5b: // '['
cont = stack[0];
stack.unshift(cont[key || cont.length] = []);
key = void 0;
break;
case 0x5d: // ']'
stack.shift();
break;
case 0x66: // 'f'
cont = stack[0];
cont[key || cont.length] = false;
key = void 0;
break;
case 0x6e: // 'n'
cont = stack[0];
cont[key || cont.length] = null;
key = void 0;
break;
case 0x74: // 't'
cont = stack[0];
cont[key || cont.length] = true;
key = void 0;
break;
case 0x7b: // '{'
cont = stack[0];
stack.unshift(cont[key || cont.length] = {});
key = void 0;
break;
case 0x7d: // '}'
stack.shift();
break;
}
}
// Fail if we've got an uncompleted object.
if (topLevelPrimitive) {
if (stack.length !== 1) { throw new Error(); }
result = result[0];
} else {
if (stack.length) { throw new Error(); }
}
if (opt_reviver) {
// Based on walk as implemented in http://www.json.org/json2.js
var walk = function (holder, key) {
var value = holder[key];
if (value && typeof value === 'object') {
var toDelete = null;
for (var k in value) {
if (hop.call(value, k) && value !== holder) {
// Recurse to properties first. This has the effect of causing
// the reviver to be called on the object graph depth-first.
// Since 'this' is bound to the holder of the property, the
// reviver can access sibling properties of k including ones
// that have not yet been revived.
// The value returned by the reviver is used in place of the
// current value of property k.
// If it returns undefined then the property is deleted.
var v = walk(value, k);
if (v !== void 0) {
value[k] = v;
} else {
// Deleting properties inside the loop has vaguely defined
// semantics in ES3 and ES3.1.
if (!toDelete) { toDelete = []; }
toDelete.push(k);
}
}
}
if (toDelete) {
for (var i = toDelete.length; --i >= 0;) {
delete value[toDelete[i]];
}
}
}
return opt_reviver.call(holder, key, value);
};
result = walk({ '': result }, '');
}
return result;
};
})();
in der Datei auf Pfad 'header/1/' befindet sich folgender Inhalt: {"from": "webteam@asf.de","subject": "Willkommen 122","time": "17:39"}
Danke, wenn jemand weiß, warum (receiveReq.readyState == 4) ind der Funktion addMail immer falsch ist.
Lg epikTrash
receiveReq.onreadystatechange = addMail(id);
Traditionelles Event-Handling
Häufiger Fehler: Handler-Funktion direkt aufrufen
Du rufst hier die Handlerfunktion in dem Moment auf, wo du eigentlich den readystatechange-Handler registrieren willst.
Als Handler wird der *Rückgabewert* des Funktionsaufrufs addMail(1) verwendet. Der ist undefined, also findet keine Event-Überwachung statt.
Du musst hier eine Funktion zuweisen. Wenn du Parameter übergeben willst, dann mit einer weiteren Funktion:
receiveReq.onreadystatechange = function () {
addMail(id);
};
json_sans_eval.js:
Dieser JSON-Parser ist veraltet. Aktuelle Browser haben längst native Parser. Die sind am schnellsten und sichersten. Nimm daher lieber json2.js bzw. json_parse.js.
* This library should be used whenever security is a concern (when JSON may
* come from an untrusted source), speed is a concern, and erroring on malformed
* JSON is *not* a concern.
Das trifft auf deinen Anwendungsfall anscheinend nicht zu.
Ich denke nicht, dass der Geschwindigkeitsaspekt in deinem Fall ins Gewicht fällt.
Mathias