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 | }); |
---|