[483] | 1 | define(["dojo/_base/lang", "dojo/_base/config", "dojo/ready", "dojo/_base/unload", |
---|
| 2 | "dojo/_base/sniff", "dojo/request", "dojo/json", "dojo/io-query", "dojo/request/script" |
---|
| 3 | ], function(lang, config, ready, unload, has, request, JSON, ioQuery, script){ |
---|
| 4 | |
---|
| 5 | var Analytics = function(){ |
---|
| 6 | // summary: |
---|
| 7 | // where we store data until we're ready to send it off. |
---|
| 8 | |
---|
| 9 | // the data queue; |
---|
| 10 | this._data = []; |
---|
| 11 | |
---|
| 12 | // id of messages for this session/page |
---|
| 13 | this._id = 1; |
---|
| 14 | |
---|
| 15 | // some default values |
---|
| 16 | this.sendInterval = config["sendInterval"] || 5000; |
---|
| 17 | this.inTransitRetry = config["inTransitRetry"] || 200; |
---|
| 18 | this.dataUrl = config["analyticsUrl"] || require.toUrl("dojox/analytics/logger/dojoxAnalytics.php"); |
---|
| 19 | this.sendMethod = config["sendMethod"] || "xhrPost"; |
---|
| 20 | this.maxRequestSize = has("ie") ? 2000 : config["maxRequestSize"] || 4000; |
---|
| 21 | |
---|
| 22 | // while we can go ahead and being logging as soon as this constructor is completed |
---|
| 23 | // we're not going to schedule pushing data to the server until after the page |
---|
| 24 | // has completed loading |
---|
| 25 | ready(this, "schedulePusher"); |
---|
| 26 | unload.addOnUnload(this, function(){ |
---|
| 27 | this.pushData(); |
---|
| 28 | }); |
---|
| 29 | }; |
---|
| 30 | |
---|
| 31 | lang.extend(Analytics, { |
---|
| 32 | schedulePusher: function(/* Int */interval){ |
---|
| 33 | // summary: |
---|
| 34 | // Schedule the data pushing routines to happen in interval ms |
---|
| 35 | setTimeout(lang.hitch(this, "checkData"), interval || this.sendInterval); |
---|
| 36 | }, |
---|
| 37 | |
---|
| 38 | addData: function(dataType, data){ |
---|
| 39 | // summary: |
---|
| 40 | // add data to the queue. Will be pusshed to the server on the next |
---|
| 41 | // data push |
---|
| 42 | |
---|
| 43 | if(arguments.length > 2){ |
---|
| 44 | // FIXME: var c = dojo._toArray(arguments) ? |
---|
| 45 | data = Array.prototype.slice.call(arguments,1); |
---|
| 46 | } |
---|
| 47 | |
---|
| 48 | this._data.push({ plugin: dataType, data: data }); |
---|
| 49 | }, |
---|
| 50 | |
---|
| 51 | checkData: function(){ |
---|
| 52 | // summary: |
---|
| 53 | // TODOC? |
---|
| 54 | if(this._inTransit){ |
---|
| 55 | this.schedulePusher(this.inTransitRetry); |
---|
| 56 | return; |
---|
| 57 | } |
---|
| 58 | |
---|
| 59 | if(this.pushData()){ return; } |
---|
| 60 | this.schedulePusher(); |
---|
| 61 | }, |
---|
| 62 | |
---|
| 63 | pushData: function(){ |
---|
| 64 | // summary: |
---|
| 65 | // pushes data to the server if any exists. If a push is done, return |
---|
| 66 | // the deferred after hooking up completion callbacks. If there is no data |
---|
| 67 | // to be pushed, return false; |
---|
| 68 | if(this._data.length){ |
---|
| 69 | // clear the queue |
---|
| 70 | this._inTransit = this._data; |
---|
| 71 | this._data = []; |
---|
| 72 | var promise; |
---|
| 73 | switch(this.sendMethod){ |
---|
| 74 | case "script": |
---|
| 75 | promise = script.get(this.getQueryPacket(), { |
---|
| 76 | preventCache: 1, |
---|
| 77 | callbackParamName: "callback" |
---|
| 78 | }); |
---|
| 79 | break; |
---|
| 80 | case "xhrPost": |
---|
| 81 | default: |
---|
| 82 | promise = request.post(this.dataUrl, { |
---|
| 83 | data:{ |
---|
| 84 | id: this._id++, |
---|
| 85 | data: JSON.stringify(this._inTransit) |
---|
| 86 | } |
---|
| 87 | }); |
---|
| 88 | break; |
---|
| 89 | } |
---|
| 90 | promise.then(lang.hitch(this, "onPushComplete")); |
---|
| 91 | return promise; |
---|
| 92 | } |
---|
| 93 | return false; |
---|
| 94 | }, |
---|
| 95 | |
---|
| 96 | getQueryPacket: function(){ |
---|
| 97 | // TODOC |
---|
| 98 | while(true){ |
---|
| 99 | var content = { |
---|
| 100 | id: this._id++, |
---|
| 101 | data: JSON.stringify(this._inTransit) |
---|
| 102 | }; |
---|
| 103 | |
---|
| 104 | // FIXME would like a much better way to get the query down to length |
---|
| 105 | var query = this.dataUrl + '?' + ioQuery.objectToQuery(content); |
---|
| 106 | if(query.length > this.maxRequestSize){ |
---|
| 107 | this._data.unshift(this._inTransit.pop()); |
---|
| 108 | this._split = 1; |
---|
| 109 | }else{ |
---|
| 110 | return query; |
---|
| 111 | } |
---|
| 112 | } |
---|
| 113 | }, |
---|
| 114 | |
---|
| 115 | onPushComplete: function(results){ |
---|
| 116 | // summary: |
---|
| 117 | // If our data push was successfully, remove the _inTransit data and schedule the next |
---|
| 118 | // parser run. |
---|
| 119 | if(this._inTransit){ |
---|
| 120 | delete this._inTransit; |
---|
| 121 | } |
---|
| 122 | |
---|
| 123 | if(this._data.length > 0){ |
---|
| 124 | this.schedulePusher(this.inTransitRetry); |
---|
| 125 | }else{ |
---|
| 126 | this.schedulePusher(); |
---|
| 127 | } |
---|
| 128 | } |
---|
| 129 | }); |
---|
| 130 | |
---|
| 131 | // create the analytics singleton |
---|
| 132 | return lang.setObject("dojox.analytics",new Analytics()); |
---|
| 133 | }); |
---|