isc_analytics 0.5 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/vendor/assets/javascripts/isc_analytics/session/index.js +1 -0
- data/vendor/assets/javascripts/isc_analytics/session/session-0.4.js +414 -0
- data/vendor/assets/javascripts/isc_analytics/yepnope/css_prefix.js +21 -0
- data/vendor/assets/javascripts/isc_analytics/yepnope/index.js +2 -0
- data/vendor/assets/javascripts/isc_analytics/yepnope/yepnope.js +546 -0
- metadata +6 -1
@@ -0,0 +1 @@
|
|
1
|
+
//= require_tree .
|
@@ -0,0 +1,414 @@
|
|
1
|
+
/**
|
2
|
+
* session.js 0.4.1
|
3
|
+
* (c) 2012 Iain, CodeJoust
|
4
|
+
* session.js is freely distributable under the MIT license.
|
5
|
+
* Portions of session.js are inspired or borrowed from Underscore.js, and quirksmode.org demo javascript.
|
6
|
+
* This version uses google's jsapi library for location services.
|
7
|
+
* For details, see: https://github.com/codejoust/session.js
|
8
|
+
*/
|
9
|
+
(function(win, doc, nav){
|
10
|
+
// Changing the API Version invalidates olde cookies with previous api version tags.
|
11
|
+
var API_VERSION = 0.4;
|
12
|
+
|
13
|
+
// Settings: defaults
|
14
|
+
var options = {
|
15
|
+
// Use the HTML5 Geolocation API
|
16
|
+
// this ONLY returns lat & long, no city/address
|
17
|
+
use_html5_location: false,
|
18
|
+
// Attempts to use IPInfoDB if provided a valid key
|
19
|
+
// Get a key at http://ipinfodb.com/register.php
|
20
|
+
ipinfodb_key: false,
|
21
|
+
// Leaving true allows for fallback for both
|
22
|
+
// the HTML5 location and the IPInfoDB
|
23
|
+
gapi_location: true,
|
24
|
+
// Name of the location cookie (set blank to disable cookie)
|
25
|
+
// - WARNING: different providers use the same cookie
|
26
|
+
// - if switching providers, remember to use another cookie or provide checks for old cookies
|
27
|
+
location_cookie: "location",
|
28
|
+
// Location cookie expiration in hours
|
29
|
+
location_cookie_timeout: 5,
|
30
|
+
// Session expiration in days
|
31
|
+
session_timeout: 32,
|
32
|
+
// Session cookie name (set blank to disable cookie)
|
33
|
+
session_cookie: "first_session"
|
34
|
+
};
|
35
|
+
|
36
|
+
// Session object
|
37
|
+
var SessionRunner = function(){
|
38
|
+
// Helper for querying.
|
39
|
+
// Usage: session.current_session.referrer_info.hostname.contains(['github.com','news.ycombinator.com'])
|
40
|
+
String.prototype.contains = function(other_str){
|
41
|
+
if (typeof(other_str) === 'string'){
|
42
|
+
return (this.indexOf(other_str) !== -1); }
|
43
|
+
for (var i = 0; i < other_str.length; i++){
|
44
|
+
if (this.indexOf(other_str[i]) !== -1){ return true; } }
|
45
|
+
return false; }
|
46
|
+
// Merge options
|
47
|
+
if (win.session && win.session.options) {
|
48
|
+
for (option in win.session.options){
|
49
|
+
options[option] = win.session.options[option]; }
|
50
|
+
}
|
51
|
+
// Modules to run
|
52
|
+
// If the module has arguments,
|
53
|
+
// it _needs_ to return a callback function.
|
54
|
+
var unloaded_modules = {
|
55
|
+
api_version: API_VERSION,
|
56
|
+
locale: modules.locale(),
|
57
|
+
current_session: modules.session(),
|
58
|
+
original_session: modules.session(
|
59
|
+
options.session_cookie,
|
60
|
+
options.session_timeout * 24 * 60 * 60 * 1000),
|
61
|
+
browser: modules.browser(),
|
62
|
+
plugins: modules.plugins(),
|
63
|
+
time: modules.time(),
|
64
|
+
device: modules.device()
|
65
|
+
};
|
66
|
+
// Location switch
|
67
|
+
if (options.use_html5_location){
|
68
|
+
unloaded_modules.location = modules.html5_location();
|
69
|
+
} else if (options.ipinfodb_key){
|
70
|
+
unloaded_modules.location = modules.ipinfodb_location(options.ipinfodb_key);
|
71
|
+
} else if (options.gapi_location){
|
72
|
+
unloaded_modules.location = modules.gapi_location();
|
73
|
+
}
|
74
|
+
// Cache win.session.start
|
75
|
+
if (win.session && win.session.start){
|
76
|
+
var start = win.session.start;
|
77
|
+
}
|
78
|
+
// Set up checking, if all modules are ready
|
79
|
+
var asynchs = 0, module, result,
|
80
|
+
check_asynch = function(){
|
81
|
+
if (asynchs === 0){
|
82
|
+
// Run start calback
|
83
|
+
if (start){ start(win.session); }
|
84
|
+
}
|
85
|
+
};
|
86
|
+
win.session = {};
|
87
|
+
// Run asynchronous methods
|
88
|
+
for (var name in unloaded_modules){
|
89
|
+
module = unloaded_modules[name];
|
90
|
+
if (typeof module === "function"){
|
91
|
+
try {
|
92
|
+
module(function(data){
|
93
|
+
win.session[name] = data;
|
94
|
+
asynchs--;
|
95
|
+
check_asynch();
|
96
|
+
});
|
97
|
+
asynchs++;
|
98
|
+
} catch(err){
|
99
|
+
if (win.console && typeof(console.log) === "function"){
|
100
|
+
console.log(err); }
|
101
|
+
}
|
102
|
+
} else {
|
103
|
+
win.session[name] = module;
|
104
|
+
} }
|
105
|
+
check_asynch();
|
106
|
+
};
|
107
|
+
|
108
|
+
|
109
|
+
// Browser (and OS) detection
|
110
|
+
var browser = {
|
111
|
+
detect: function(){
|
112
|
+
return {
|
113
|
+
browser: this.search(this.data.browser),
|
114
|
+
version: this.search(nav.userAgent) || this.search(nav.appVersion),
|
115
|
+
os: this.search(this.data.os)
|
116
|
+
} },
|
117
|
+
search: function(data) {
|
118
|
+
if (typeof data === "object"){
|
119
|
+
// search for string match
|
120
|
+
for(var i = 0; i < data.length; i++) {
|
121
|
+
var dataString = data[i].string,
|
122
|
+
dataProp = data[i].prop;
|
123
|
+
this.version_string = data[i].versionSearch || data[i].identity;
|
124
|
+
if (dataString){
|
125
|
+
if (dataString.indexOf(data[i].subString) != -1){
|
126
|
+
return data[i].identity;
|
127
|
+
}
|
128
|
+
} else if (dataProp){
|
129
|
+
return data[i].identity;
|
130
|
+
}
|
131
|
+
}
|
132
|
+
} else {
|
133
|
+
// search for version number
|
134
|
+
var index = data.indexOf(this.version_string);
|
135
|
+
if (index == -1) return;
|
136
|
+
return parseFloat(data.substr(index + this.version_string.length + 1));
|
137
|
+
}
|
138
|
+
},
|
139
|
+
data: {
|
140
|
+
browser: [
|
141
|
+
{ string: nav.userAgent, subString: "Chrome", identity: "Chrome" },
|
142
|
+
{ string: nav.userAgent, subString: "OmniWeb", versionSearch: "OmniWeb/", identity: "OmniWeb" },
|
143
|
+
{ string: nav.vendor, subString: "Apple", identity: "Safari", versionSearch: "Version" },
|
144
|
+
{ prop: win.opera, identity: "Opera", versionSearch: "Version" },
|
145
|
+
{ string: nav.vendor, subString: "iCab",identity: "iCab" },
|
146
|
+
{ string: nav.vendor, subString: "KDE", identity: "Konqueror" },
|
147
|
+
{ string: nav.userAgent, subString: "Firefox", identity: "Firefox" },
|
148
|
+
{ string: nav.vendor, subString: "Camino", identity: "Camino" },
|
149
|
+
{ string: nav.userAgent, subString: "Netscape", identity: "Netscape" },
|
150
|
+
{ string: nav.userAgent, subString: "MSIE", identity: "Explorer", versionSearch: "MSIE" },
|
151
|
+
{ string: nav.userAgent, subString: "Gecko", identity: "Mozilla", versionSearch: "rv" },
|
152
|
+
{ string: nav.userAgent, subString: "Mozilla", identity: "Netscape", versionSearch: "Mozilla" }
|
153
|
+
],
|
154
|
+
os: [
|
155
|
+
{ string: nav.platform, subString: "Win", identity: "Windows" },
|
156
|
+
{ string: nav.platform, subString: "Mac", identity: "Mac" },
|
157
|
+
{ string: nav.userAgent, subString: "iPhone", identity: "iPhone/iPod" },
|
158
|
+
{ string: nav.userAgent, subString: "iPad", identitiy: "iPad" },
|
159
|
+
{ string: nav.platform, subString: "Linux", identity: "Linux" },
|
160
|
+
{ string: nav.userAgent, subString: "Android", identity: "Android" }
|
161
|
+
]}
|
162
|
+
};
|
163
|
+
|
164
|
+
var modules = {
|
165
|
+
browser: function(){
|
166
|
+
return browser.detect();
|
167
|
+
},
|
168
|
+
time: function(){
|
169
|
+
// split date and grab timezone estimation.
|
170
|
+
// timezone estimation: http://www.onlineaspect.com/2007/06/08/auto-detect-a-time-zone-with-javascript/
|
171
|
+
var d1 = new Date(), d2 = new Date();
|
172
|
+
d1.setMonth(0); d1.setDate(1); d2.setMonth(6); d2.setDate(1);
|
173
|
+
return({tz_offset: -(new Date().getTimezoneOffset()) / 60, observes_dst: (d1.getTimezoneOffset() !== d2.getTimezoneOffset()) });
|
174
|
+
// Gives a browser estimation, not guaranteed to be correct.
|
175
|
+
},
|
176
|
+
locale: function() {
|
177
|
+
var lang = (
|
178
|
+
nav.language ||
|
179
|
+
nav.browserLanguage ||
|
180
|
+
nav.systemLanguage ||
|
181
|
+
nav.userLanguage
|
182
|
+
).split("-");
|
183
|
+
if (lang.length == 2){
|
184
|
+
return { country: lang[1].toLowerCase(), lang: lang[0].toLowerCase() };
|
185
|
+
} else if (lang) {
|
186
|
+
return {lang: lang[0].toLowerCase(), country: null };
|
187
|
+
} else { return{lang: null, country: null }; }
|
188
|
+
},
|
189
|
+
device: function() {
|
190
|
+
var device = {
|
191
|
+
screen: {
|
192
|
+
width: screen.width,
|
193
|
+
height: screen.height
|
194
|
+
}
|
195
|
+
};
|
196
|
+
var html = doc.documentElement,
|
197
|
+
body = doc.getElementsByTagName("body")[0];
|
198
|
+
device.viewport = {
|
199
|
+
width: win.innerWidth || html.clientWidth || body.clientWidth,
|
200
|
+
height: win.innerHeight || html.clientHeight || body.clientHeight
|
201
|
+
};
|
202
|
+
device.is_tablet = !!nav.userAgent.match(/(iPad|SCH-I800|xoom|kindle)/i);
|
203
|
+
device.is_phone = !device.isTablet && !!nav.userAgent.match(/(iPhone|iPod|blackberry|android 0.5|htc|lg|midp|mmp|mobile|nokia|opera mini|palm|pocket|psp|sgh|smartphone|symbian|treo mini|Playstation Portable|SonyEricsson|Samsung|MobileExplorer|PalmSource|Benq|Windows Phone|Windows Mobile|IEMobile|Windows CE|Nintendo Wii)/i);
|
204
|
+
device.is_mobile = (device.is_tablet || device.is_phone);
|
205
|
+
return device;
|
206
|
+
},
|
207
|
+
plugins: function(){
|
208
|
+
var check_plugin = function(name){
|
209
|
+
if (nav.plugins){
|
210
|
+
var plugin, i = 0, length = nav.plugins.length;
|
211
|
+
for (; i < length; i++ ){
|
212
|
+
plugin = nav.plugins[i];
|
213
|
+
if (plugin && plugin.name && plugin.name.toLowerCase().indexOf(name) !== -1){
|
214
|
+
return true;
|
215
|
+
} }
|
216
|
+
return false;
|
217
|
+
} return false;
|
218
|
+
}
|
219
|
+
return {
|
220
|
+
flash: check_plugin("flash"),
|
221
|
+
silverlight: check_plugin("silverlight"),
|
222
|
+
java: check_plugin("java"),
|
223
|
+
quicktime: check_plugin("quicktime")
|
224
|
+
};
|
225
|
+
},
|
226
|
+
session: function (cookie, expires){
|
227
|
+
var session = util.get_obj(cookie);
|
228
|
+
if (session == null){
|
229
|
+
session = {
|
230
|
+
visits: 1,
|
231
|
+
start: new Date().getTime(), last_visit: new Date().getTime(),
|
232
|
+
url: win.location.href, path: win.location.pathname,
|
233
|
+
referrer: doc.referrer, referrer_info: util.parse_url(doc.referrer),
|
234
|
+
search: { engine: null, query: null }
|
235
|
+
};
|
236
|
+
var search_engines = [
|
237
|
+
{ name: "Google", host: "google", query: "q" },
|
238
|
+
{ name: "Bing", host: "bing.com", query: "q" },
|
239
|
+
{ name: "Yahoo", host: "search.yahoo", query: "p" },
|
240
|
+
{ name: "AOL", host: "search.aol", query: "q" },
|
241
|
+
{ name: "Ask", host: "ask.com", query: "q" },
|
242
|
+
{ name: "Baidu", host: "baidu.com", query: "wd" }
|
243
|
+
], length = search_engines.length,
|
244
|
+
engine, match, i = 0,
|
245
|
+
fallbacks = 'q query term p wd query text'.split(' ');
|
246
|
+
for (i = 0; i < length; i++){
|
247
|
+
engine = search_engines[i];
|
248
|
+
if (session.referrer_info.host.indexOf(engine.host) !== -1){
|
249
|
+
session.search.engine = engine.name;
|
250
|
+
session.search.query = session.referrer_info.query[engine.query];
|
251
|
+
session.search.terms = session.search.query ? session.search.query.split(" ") : null;
|
252
|
+
break;
|
253
|
+
}
|
254
|
+
}
|
255
|
+
if (session.search.engine === null && session.referrer_info.search.length > 1){
|
256
|
+
for (i = 0; i < fallbacks.length; i++){
|
257
|
+
var terms = session.referrer_info.query[fallbacks[i]];
|
258
|
+
if (terms){
|
259
|
+
session.search.engine = "Unknown";
|
260
|
+
session.search.query = terms; session.search.terms = terms.split(" ");
|
261
|
+
break;
|
262
|
+
}
|
263
|
+
}
|
264
|
+
}
|
265
|
+
} else {
|
266
|
+
session.last_visit = new Date().getTime();
|
267
|
+
session.visits++;
|
268
|
+
}
|
269
|
+
util.set_cookie(cookie, util.package_obj(session), expires);
|
270
|
+
return session;
|
271
|
+
},
|
272
|
+
html5_location: function(){
|
273
|
+
return function(callback){
|
274
|
+
nav.geolocation.getCurrentPosition(function(pos){
|
275
|
+
pos.source = 'html5';
|
276
|
+
callback(pos);
|
277
|
+
}, function(err) {
|
278
|
+
if (options.gapi_location){
|
279
|
+
modules.gapi_location()(callback);
|
280
|
+
} else {
|
281
|
+
callback({error: true, source: 'html5'}); }
|
282
|
+
});
|
283
|
+
};
|
284
|
+
},
|
285
|
+
gapi_location: function(){
|
286
|
+
return function(callback){
|
287
|
+
var location = util.get_obj(options.location_cookie);
|
288
|
+
if (!location || location.source !== 'google'){
|
289
|
+
win.gloader_ready = function() {
|
290
|
+
if ("google" in win){
|
291
|
+
if (win.google.loader.ClientLocation){
|
292
|
+
win.google.loader.ClientLocation.source = "google";
|
293
|
+
callback(win.google.loader.ClientLocation);
|
294
|
+
} else {
|
295
|
+
callback({error: true, source: "google"});
|
296
|
+
}
|
297
|
+
util.set_cookie(
|
298
|
+
options.location_cookie,
|
299
|
+
util.package_obj(win.google.loader.ClientLocation),
|
300
|
+
options.location_cookie_timeout * 60 * 60 * 1000);
|
301
|
+
}}
|
302
|
+
util.embed_script("https://www.google.com/jsapi?callback=gloader_ready");
|
303
|
+
} else {
|
304
|
+
callback(location);
|
305
|
+
}}
|
306
|
+
},
|
307
|
+
ipinfodb_location: function(api_key){
|
308
|
+
return function (callback){
|
309
|
+
var location_cookie = util.get_obj(options.location_cookie);
|
310
|
+
if (location_cookie && location_cookie.source === 'ipinfodb'){ callback(location_cookie); }
|
311
|
+
win.ipinfocb = function(data){
|
312
|
+
if (data.statusCode === "OK"){
|
313
|
+
data.source = "ipinfodb";
|
314
|
+
util.set_cookie(
|
315
|
+
options.location_cookie,
|
316
|
+
util.package_obj(data),
|
317
|
+
options.location_cookie * 60 * 60 * 1000);
|
318
|
+
callback(data);
|
319
|
+
} else {
|
320
|
+
if (options.gapi_location){ return modules.gapi_location()(callback); }
|
321
|
+
else { callback({error: true, source: "ipinfodb", message: data.statusMessage}); }
|
322
|
+
}}
|
323
|
+
util.embed_script("http://api.ipinfodb.com/v3/ip-city/?key=" + api_key + "&format=json&callback=ipinfocb");
|
324
|
+
}}
|
325
|
+
};
|
326
|
+
|
327
|
+
// Utilities
|
328
|
+
var util = {
|
329
|
+
parse_url: function(url_str){
|
330
|
+
var a = doc.createElement("a"), query = {};
|
331
|
+
a.href = url_str; query_str = a.search.substr(1);
|
332
|
+
// Disassemble query string
|
333
|
+
if (query_str != ''){
|
334
|
+
var pairs = query_str.split("&"), i = 0,
|
335
|
+
length = pairs.length, parts;
|
336
|
+
for (; i < length; i++){
|
337
|
+
parts = pairs[i].split("=");
|
338
|
+
if (parts.length === 2){
|
339
|
+
query[parts[0]] = decodeURI(parts[1]); }
|
340
|
+
}
|
341
|
+
}
|
342
|
+
return {
|
343
|
+
host: a.host,
|
344
|
+
path: a.pathname,
|
345
|
+
protocol: a.protocol,
|
346
|
+
port: a.port === '' ? 80 : a.port,
|
347
|
+
search: a.search,
|
348
|
+
query: query }
|
349
|
+
},
|
350
|
+
set_cookie: function(cname, value, expires, options){ // from jquery.cookie.js
|
351
|
+
if (!doc.cookie || !cname || !value){ return null; }
|
352
|
+
if (!options){ var options = {}; }
|
353
|
+
if (value === null || value === undefined){ expires = -1; }
|
354
|
+
if (expires){ options.expires = (new Date().getTime()) + expires; }
|
355
|
+
return (document.cookie = [
|
356
|
+
encodeURIComponent(cname), '=',
|
357
|
+
encodeURIComponent(String(value)),
|
358
|
+
options.expires ? '; expires=' + new Date(options.expires).toUTCString() : '', // use expires attribute, max-age is not supported by IE
|
359
|
+
options.path ? '; path=' + options.path : '',
|
360
|
+
options.domain ? '; domain=' + options.domain : '',
|
361
|
+
(win.location && win.location.protocol === 'https:') ? '; secure' : ''
|
362
|
+
].join(''));
|
363
|
+
},
|
364
|
+
get_cookie: function(cookie_name, result){ // from jquery.cookie.js
|
365
|
+
return (result = new RegExp('(?:^|; )' + encodeURIComponent(cookie_name) + '=([^;]*)').exec(document.cookie)) ? decodeURIComponent(result[1]) : null;
|
366
|
+
},
|
367
|
+
embed_script: function(url){
|
368
|
+
var element = doc.createElement("script");
|
369
|
+
element.type = "text/javascript";
|
370
|
+
element.src = url;
|
371
|
+
doc.getElementsByTagName("body")[0].appendChild(element);
|
372
|
+
},
|
373
|
+
package_obj: function (obj){
|
374
|
+
obj.version = API_VERSION;
|
375
|
+
var ret = JSON.stringify(obj);
|
376
|
+
delete obj.version; return ret;
|
377
|
+
},
|
378
|
+
get_obj: function(cookie_name){
|
379
|
+
var obj;
|
380
|
+
try { obj = JSON.parse(util.get_cookie(cookie_name)); } catch(e){};
|
381
|
+
if (obj && obj.version == API_VERSION){
|
382
|
+
delete obj.version; return obj;
|
383
|
+
}
|
384
|
+
}
|
385
|
+
};
|
386
|
+
|
387
|
+
// JSON
|
388
|
+
var JSON = {
|
389
|
+
parse: (win.JSON && win.JSON.parse) || function(data){
|
390
|
+
if (typeof data !== "string" || !data){ return null; }
|
391
|
+
return (new Function("return " + data))();
|
392
|
+
},
|
393
|
+
stringify: (win.JSON && win.JSON.stringify) || function(object){
|
394
|
+
var type = typeof object;
|
395
|
+
if (type !== "object" || object === null) {
|
396
|
+
if (type === "string"){ return '"' + object + '"'; }
|
397
|
+
} else {
|
398
|
+
var k, v, json = [],
|
399
|
+
isArray = (object && object.constructor === Array);
|
400
|
+
for (k in object ) {
|
401
|
+
v = object[k]; type = typeof v;
|
402
|
+
if (type === "string")
|
403
|
+
v = '"' + v + '"';
|
404
|
+
else if (type === "object" && v !== null)
|
405
|
+
v = this.stringify(v);
|
406
|
+
json.push((isArray ? "" : '"' + k + '":') + v);
|
407
|
+
}
|
408
|
+
return (isArray ? "[" : "{") + json.join(",") + (isArray ? "]" : "}");
|
409
|
+
} } };
|
410
|
+
|
411
|
+
// Initialize SessionRunner
|
412
|
+
SessionRunner();
|
413
|
+
|
414
|
+
})(window, document, navigator);
|
@@ -0,0 +1,21 @@
|
|
1
|
+
/**
|
2
|
+
* Yepnope CSS Force prefix
|
3
|
+
*
|
4
|
+
* Use a combination of any prefix, and they should work
|
5
|
+
* Usage: ['css!genStyles.php?234', 'normal-styles.css' ]
|
6
|
+
*
|
7
|
+
* Official Yepnope Plugin
|
8
|
+
*
|
9
|
+
* WTFPL License
|
10
|
+
*
|
11
|
+
* by Alex Sexton | AlexSexton@gmail.com
|
12
|
+
*/
|
13
|
+
( function ( yepnope ) {
|
14
|
+
// add each prefix
|
15
|
+
yepnope.addPrefix( 'css', function ( resource ) {
|
16
|
+
// Set the force flag
|
17
|
+
resource.forceCSS = true;
|
18
|
+
//carry on
|
19
|
+
return resource;
|
20
|
+
} );
|
21
|
+
} )( this.yepnope );
|
@@ -0,0 +1,546 @@
|
|
1
|
+
/*yepnope1.0.2|WTFPL*/
|
2
|
+
// yepnope.js
|
3
|
+
// Version - 1.0.2
|
4
|
+
//
|
5
|
+
// by
|
6
|
+
// Alex Sexton - @SlexAxton - AlexSexton[at]gmail.com
|
7
|
+
// Ralph Holzmann - @ralphholzmann - ralphholzmann[at]gmail.com
|
8
|
+
//
|
9
|
+
// http://yepnopejs.com/
|
10
|
+
// https://github.com/SlexAxton/yepnope.js/
|
11
|
+
//
|
12
|
+
// Tri-license - WTFPL | MIT | BSD
|
13
|
+
//
|
14
|
+
// Please minify before use.
|
15
|
+
// Also available as Modernizr.load via the Modernizr Project
|
16
|
+
//
|
17
|
+
( function ( window, doc, undef ) {
|
18
|
+
|
19
|
+
var docElement = doc.documentElement,
|
20
|
+
sTimeout = window.setTimeout,
|
21
|
+
firstScript = doc.getElementsByTagName( 'script' )[ 0 ],
|
22
|
+
toString = {}.toString,
|
23
|
+
execStack = [],
|
24
|
+
started = 0,
|
25
|
+
// Before you get mad about browser sniffs, please read:
|
26
|
+
// https://github.com/Modernizr/Modernizr/wiki/Undetectables
|
27
|
+
// If you have a better solution, we are actively looking to solve the problem
|
28
|
+
isGecko = ( 'MozAppearance' in docElement.style ),
|
29
|
+
isGeckoLTE18 = isGecko && !! doc.createRange().compareNode,
|
30
|
+
isGeckoGT18 = isGecko && ! isGeckoLTE18,
|
31
|
+
insBeforeObj = isGeckoLTE18 ? docElement : firstScript.parentNode,
|
32
|
+
// Thanks to @jdalton for showing us this opera detection (by way of @kangax) (and probably @miketaylr too, or whatever...)
|
33
|
+
isOpera = window.opera && toString.call( window.opera ) == '[object Opera]',
|
34
|
+
isWebkit = ( 'webkitAppearance' in docElement.style ),
|
35
|
+
isNewerWebkit = isWebkit && 'async' in doc.createElement('script'),
|
36
|
+
strJsElem = isGecko ? 'object' : ( isOpera || isNewerWebkit ) ? 'img' : 'script',
|
37
|
+
strCssElem = isWebkit ? 'img' : strJsElem,
|
38
|
+
isArray = Array.isArray || function ( obj ) {
|
39
|
+
return toString.call( obj ) == '[object Array]';
|
40
|
+
},
|
41
|
+
isObject = function ( obj ) {
|
42
|
+
return Object(obj) === obj;
|
43
|
+
},
|
44
|
+
isString = function ( s ) {
|
45
|
+
return typeof s == 'string';
|
46
|
+
},
|
47
|
+
isFunction = function ( fn ) {
|
48
|
+
return toString.call( fn ) == '[object Function]';
|
49
|
+
},
|
50
|
+
globalFilters = [],
|
51
|
+
prefixes = {},
|
52
|
+
handler,
|
53
|
+
yepnope;
|
54
|
+
|
55
|
+
/* Loader helper functions */
|
56
|
+
function isFileReady ( readyState ) {
|
57
|
+
// Check to see if any of the ways a file can be ready are available as properties on the file's element
|
58
|
+
return ( ! readyState || readyState == 'loaded' || readyState == 'complete' );
|
59
|
+
}
|
60
|
+
|
61
|
+
function execWhenReady () {
|
62
|
+
var execStackReady = 1,
|
63
|
+
i = -1;
|
64
|
+
|
65
|
+
// Loop through the stack of scripts in the cue and execute them when all scripts in a group are ready
|
66
|
+
while ( execStack.length - ++i ) {
|
67
|
+
if ( execStack[ i ].s && ! ( execStackReady = execStack[ i ].r ) ) {
|
68
|
+
// As soon as we encounter a script that isn't ready, stop looking for more
|
69
|
+
break;
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
// If we've set the stack as ready in the loop, make it happen here
|
74
|
+
execStackReady && executeStack();
|
75
|
+
|
76
|
+
}
|
77
|
+
|
78
|
+
// Takes a preloaded js obj (changes in different browsers) and injects it into the head
|
79
|
+
// in the appropriate order
|
80
|
+
function injectJs ( oldObj ) {
|
81
|
+
var script = doc.createElement( 'script' ),
|
82
|
+
done;
|
83
|
+
|
84
|
+
script.src = oldObj.s;
|
85
|
+
|
86
|
+
// Bind to load events
|
87
|
+
script.onreadystatechange = script.onload = function () {
|
88
|
+
|
89
|
+
if ( ! done && isFileReady( script.readyState ) ) {
|
90
|
+
|
91
|
+
// Set done to prevent this function from being called twice.
|
92
|
+
done = 1;
|
93
|
+
execWhenReady();
|
94
|
+
|
95
|
+
// Handle memory leak in IE
|
96
|
+
script.onload = script.onreadystatechange = null;
|
97
|
+
}
|
98
|
+
};
|
99
|
+
|
100
|
+
// 404 Fallback
|
101
|
+
sTimeout( function () {
|
102
|
+
if ( ! done ) {
|
103
|
+
done = 1;
|
104
|
+
execWhenReady();
|
105
|
+
}
|
106
|
+
}, yepnope.errorTimeout );
|
107
|
+
|
108
|
+
// Inject script into to document
|
109
|
+
// or immediately callback if we know there
|
110
|
+
// was previously a timeout error
|
111
|
+
oldObj.e ? script.onload() : firstScript.parentNode.insertBefore( script, firstScript );
|
112
|
+
}
|
113
|
+
|
114
|
+
// Takes a preloaded css obj (changes in different browsers) and injects it into the head
|
115
|
+
// in the appropriate order
|
116
|
+
// Many credits to John Hann (@unscriptable) for a lot of the ideas here - found in the css! plugin for RequireJS
|
117
|
+
function injectCss ( oldObj ) {
|
118
|
+
|
119
|
+
// Create stylesheet link
|
120
|
+
var link = doc.createElement( 'link' ),
|
121
|
+
done;
|
122
|
+
|
123
|
+
// Add attributes
|
124
|
+
link.href = oldObj.s;
|
125
|
+
link.rel = 'stylesheet';
|
126
|
+
link.type = 'text/css';
|
127
|
+
|
128
|
+
// Poll for changes in webkit and gecko
|
129
|
+
if ( ! oldObj.e && ( isWebkit || isGecko ) ) {
|
130
|
+
// A self executing function with a sTimeout poll to call itself
|
131
|
+
// again until the css file is added successfully
|
132
|
+
var poll = function ( link ) {
|
133
|
+
sTimeout( function () {
|
134
|
+
// Don't run again if we're already done
|
135
|
+
if ( ! done ) {
|
136
|
+
try {
|
137
|
+
// In supporting browsers, we can see the length of the cssRules of the file go up
|
138
|
+
if ( link.sheet.cssRules.length ) {
|
139
|
+
// Then turn off the poll
|
140
|
+
done = 1;
|
141
|
+
// And execute a function to execute callbacks when all dependencies are met
|
142
|
+
execWhenReady();
|
143
|
+
}
|
144
|
+
// otherwise, wait another interval and try again
|
145
|
+
else {
|
146
|
+
poll( link );
|
147
|
+
}
|
148
|
+
}
|
149
|
+
catch ( ex ) {
|
150
|
+
// In the case that the browser does not support the cssRules array (cross domain)
|
151
|
+
// just check the error message to see if it's a security error
|
152
|
+
if ( ( ex.code == 1e3 ) || ( ex.message == 'security' || ex.message == 'denied' ) ) {
|
153
|
+
// if it's a security error, that means it loaded a cross domain file, so stop the timeout loop
|
154
|
+
done = 1;
|
155
|
+
// and execute a check to see if we can run the callback(s) immediately after this function ends
|
156
|
+
sTimeout( function () {
|
157
|
+
execWhenReady();
|
158
|
+
}, 0 );
|
159
|
+
}
|
160
|
+
// otherwise, continue to poll
|
161
|
+
else {
|
162
|
+
poll( link );
|
163
|
+
}
|
164
|
+
}
|
165
|
+
}
|
166
|
+
}, 0 );
|
167
|
+
};
|
168
|
+
poll( link );
|
169
|
+
|
170
|
+
}
|
171
|
+
// Onload handler for IE and Opera
|
172
|
+
else {
|
173
|
+
// In browsers that allow the onload event on link tags, just use it
|
174
|
+
link.onload = function () {
|
175
|
+
if ( ! done ) {
|
176
|
+
// Set our flag to complete
|
177
|
+
done = 1;
|
178
|
+
// Check to see if we can call the callback
|
179
|
+
sTimeout( function () {
|
180
|
+
execWhenReady();
|
181
|
+
}, 0 );
|
182
|
+
}
|
183
|
+
};
|
184
|
+
|
185
|
+
// if we shouldn't inject due to error or settings, just call this right away
|
186
|
+
oldObj.e && link.onload();
|
187
|
+
}
|
188
|
+
|
189
|
+
// 404 Fallback
|
190
|
+
sTimeout( function () {
|
191
|
+
if ( ! done ) {
|
192
|
+
done = 1;
|
193
|
+
execWhenReady();
|
194
|
+
}
|
195
|
+
}, yepnope.errorTimeout );
|
196
|
+
|
197
|
+
// Inject CSS
|
198
|
+
// only inject if there are no errors, and we didn't set the no inject flag ( oldObj.e )
|
199
|
+
! oldObj.e && firstScript.parentNode.insertBefore( link, firstScript );
|
200
|
+
}
|
201
|
+
|
202
|
+
function executeStack ( ) {
|
203
|
+
// shift an element off of the stack
|
204
|
+
var i = execStack.shift();
|
205
|
+
started = 1;
|
206
|
+
|
207
|
+
// if a is truthy and the first item in the stack has an src
|
208
|
+
if ( i ) {
|
209
|
+
// if it's a script, inject it into the head with no type attribute
|
210
|
+
if ( i.t ) {
|
211
|
+
// Inject after a timeout so FF has time to be a jerk about it and
|
212
|
+
// not double load (ignore the cache)
|
213
|
+
sTimeout( function () {
|
214
|
+
i.t == 'c' ? injectCss( i ) : injectJs( i );
|
215
|
+
}, 0 );
|
216
|
+
}
|
217
|
+
// Otherwise, just call the function and potentially run the stack
|
218
|
+
else {
|
219
|
+
i();
|
220
|
+
execWhenReady();
|
221
|
+
}
|
222
|
+
}
|
223
|
+
else {
|
224
|
+
// just reset out of recursive mode
|
225
|
+
started = 0;
|
226
|
+
}
|
227
|
+
}
|
228
|
+
|
229
|
+
function preloadFile ( elem, url, type, splicePoint, docElement, dontExec ) {
|
230
|
+
|
231
|
+
// Create appropriate element for browser and type
|
232
|
+
var preloadElem = doc.createElement( elem ),
|
233
|
+
done = 0,
|
234
|
+
stackObject = {
|
235
|
+
t: type, // type
|
236
|
+
s: url, // src
|
237
|
+
//r: 0, // ready
|
238
|
+
e : dontExec // set to true if we don't want to reinject
|
239
|
+
};
|
240
|
+
|
241
|
+
function onload () {
|
242
|
+
|
243
|
+
// If the script/css file is loaded
|
244
|
+
if ( ! done && isFileReady( preloadElem.readyState ) ) {
|
245
|
+
|
246
|
+
// Set done to prevent this function from being called twice.
|
247
|
+
stackObject.r = done = 1;
|
248
|
+
|
249
|
+
! started && execWhenReady();
|
250
|
+
|
251
|
+
// Handle memory leak in IE
|
252
|
+
preloadElem.onload = preloadElem.onreadystatechange = null;
|
253
|
+
sTimeout(function(){ insBeforeObj.removeChild( preloadElem ) }, 0);
|
254
|
+
}
|
255
|
+
}
|
256
|
+
|
257
|
+
// Just set the src and the data attributes so we don't have differentiate between elem types
|
258
|
+
preloadElem.src = preloadElem.data = url;
|
259
|
+
|
260
|
+
// Don't let it show up visually
|
261
|
+
! isGeckoLTE18 && ( preloadElem.style.display = 'none' );
|
262
|
+
preloadElem.width = preloadElem.height = '0';
|
263
|
+
|
264
|
+
|
265
|
+
// Only if we have a type to add should we set the type attribute (a real script has no type)
|
266
|
+
if ( elem != 'object' ) {
|
267
|
+
preloadElem.type = type;
|
268
|
+
}
|
269
|
+
|
270
|
+
// Attach handlers for all browsers
|
271
|
+
preloadElem.onload = preloadElem.onreadystatechange = onload;
|
272
|
+
|
273
|
+
// If it's an image
|
274
|
+
if ( elem == 'img' ) {
|
275
|
+
// Use the onerror callback as the 'completed' indicator
|
276
|
+
preloadElem.onerror = onload;
|
277
|
+
}
|
278
|
+
// Otherwise, if it's a script element
|
279
|
+
else if ( elem == 'script' ) {
|
280
|
+
// handle errors on script elements when we can
|
281
|
+
preloadElem.onerror = function () {
|
282
|
+
stackObject.e = stackObject.r = 1;
|
283
|
+
executeStack();
|
284
|
+
};
|
285
|
+
}
|
286
|
+
|
287
|
+
// inject the element into the stack depending on if it's
|
288
|
+
// in the middle of other scripts or not
|
289
|
+
execStack.splice( splicePoint, 0, stackObject );
|
290
|
+
|
291
|
+
// The only place these can't go is in the <head> element, since objects won't load in there
|
292
|
+
// so we have two options - insert before the head element (which is hard to assume) - or
|
293
|
+
// insertBefore technically takes null/undefined as a second param and it will insert the element into
|
294
|
+
// the parent last. We try the head, and it automatically falls back to undefined.
|
295
|
+
insBeforeObj.insertBefore( preloadElem, isGeckoLTE18 ? null : firstScript );
|
296
|
+
|
297
|
+
// If something fails, and onerror doesn't fire,
|
298
|
+
// continue after a timeout.
|
299
|
+
sTimeout( function () {
|
300
|
+
if ( ! done ) {
|
301
|
+
// Remove the node from the dom
|
302
|
+
insBeforeObj.removeChild( preloadElem );
|
303
|
+
// Set it to ready to move on
|
304
|
+
// indicate that this had a timeout error on our stack object
|
305
|
+
stackObject.r = stackObject.e = done = 1;
|
306
|
+
// Continue on
|
307
|
+
execWhenReady();
|
308
|
+
}
|
309
|
+
}, yepnope.errorTimeout );
|
310
|
+
}
|
311
|
+
|
312
|
+
function load ( resource, type, dontExec ) {
|
313
|
+
|
314
|
+
var elem = ( type == 'c' ? strCssElem : strJsElem );
|
315
|
+
|
316
|
+
// If this method gets hit multiple times, we should flag
|
317
|
+
// that the execution of other threads should halt.
|
318
|
+
started = 0;
|
319
|
+
|
320
|
+
// We'll do 'j' for js and 'c' for css, yay for unreadable minification tactics
|
321
|
+
type = type || 'j';
|
322
|
+
if ( isString( resource ) ) {
|
323
|
+
// if the resource passed in here is a string, preload the file
|
324
|
+
preloadFile( elem, resource, type, this.i++, docElement, dontExec );
|
325
|
+
} else {
|
326
|
+
// Otherwise it's a resource object and we can splice it into the app at the current location
|
327
|
+
execStack.splice( this.i++, 0, resource );
|
328
|
+
execStack.length == 1 && executeStack();
|
329
|
+
}
|
330
|
+
|
331
|
+
// OMG is this jQueries? For chaining...
|
332
|
+
return this;
|
333
|
+
}
|
334
|
+
|
335
|
+
// return the yepnope object with a fresh loader attached
|
336
|
+
function getYepnope () {
|
337
|
+
var y = yepnope;
|
338
|
+
y.loader = {
|
339
|
+
load: load,
|
340
|
+
i : 0
|
341
|
+
};
|
342
|
+
return y;
|
343
|
+
}
|
344
|
+
|
345
|
+
/* End loader helper functions */
|
346
|
+
// Yepnope Function
|
347
|
+
yepnope = function ( needs ) {
|
348
|
+
|
349
|
+
var i,
|
350
|
+
need,
|
351
|
+
// start the chain as a plain instance
|
352
|
+
chain = this.yepnope.loader;
|
353
|
+
|
354
|
+
function satisfyPrefixes ( url ) {
|
355
|
+
// split all prefixes out
|
356
|
+
var parts = url.split( '!' ),
|
357
|
+
gLen = globalFilters.length,
|
358
|
+
origUrl = parts.pop(),
|
359
|
+
pLen = parts.length,
|
360
|
+
res = {
|
361
|
+
url : origUrl,
|
362
|
+
// keep this one static for callback variable consistency
|
363
|
+
origUrl : origUrl,
|
364
|
+
prefixes : parts
|
365
|
+
},
|
366
|
+
mFunc,
|
367
|
+
j;
|
368
|
+
|
369
|
+
// loop through prefixes
|
370
|
+
// if there are none, this automatically gets skipped
|
371
|
+
for ( j = 0; j < pLen; j++ ) {
|
372
|
+
mFunc = prefixes[ parts[ j ] ];
|
373
|
+
if ( mFunc ) {
|
374
|
+
res = mFunc( res );
|
375
|
+
}
|
376
|
+
}
|
377
|
+
|
378
|
+
// Go through our global filters
|
379
|
+
for ( j = 0; j < gLen; j++ ) {
|
380
|
+
res = globalFilters[ j ]( res );
|
381
|
+
}
|
382
|
+
|
383
|
+
// return the final url
|
384
|
+
return res;
|
385
|
+
}
|
386
|
+
|
387
|
+
function loadScriptOrStyle ( input, callback, chain, index, testResult ) {
|
388
|
+
// run through our set of prefixes
|
389
|
+
var resource = satisfyPrefixes( input ),
|
390
|
+
autoCallback = resource.autoCallback;
|
391
|
+
|
392
|
+
// if no object is returned or the url is empty/0 just exit the load
|
393
|
+
if ( resource.bypass ) {
|
394
|
+
return;
|
395
|
+
}
|
396
|
+
|
397
|
+
// Determine callback, if any
|
398
|
+
if ( callback ) {
|
399
|
+
callback = isFunction( callback ) ? callback : callback[ input ] || callback[ index ] || callback[ ( input.split( '/' ).pop().split( '?' )[ 0 ] ) ];
|
400
|
+
}
|
401
|
+
|
402
|
+
// if someone is overriding all normal functionality
|
403
|
+
if ( resource.instead ) {
|
404
|
+
return resource.instead( input, callback, chain, index, testResult );
|
405
|
+
}
|
406
|
+
else {
|
407
|
+
|
408
|
+
chain.load( resource.url, ( ( resource.forceCSS || ( ! resource.forceJS && /css$/.test( resource.url ) ) ) ) ? 'c' : undef, resource.noexec );
|
409
|
+
|
410
|
+
// If we have a callback, we'll start the chain over
|
411
|
+
if ( isFunction( callback ) || isFunction( autoCallback ) ) {
|
412
|
+
// Call getJS with our current stack of things
|
413
|
+
chain.load( function () {
|
414
|
+
// Hijack yepnope and restart index counter
|
415
|
+
getYepnope();
|
416
|
+
// Call our callbacks with this set of data
|
417
|
+
callback && callback( resource.origUrl, testResult, index );
|
418
|
+
autoCallback && autoCallback( resource.origUrl, testResult, index );
|
419
|
+
} );
|
420
|
+
}
|
421
|
+
}
|
422
|
+
}
|
423
|
+
|
424
|
+
function loadFromTestObject ( testObject, chain ) {
|
425
|
+
var testResult = !! testObject.test,
|
426
|
+
group = testResult ? testObject.yep : testObject.nope,
|
427
|
+
always = testObject.load || testObject.both,
|
428
|
+
callback = testObject.callback,
|
429
|
+
callbackKey;
|
430
|
+
|
431
|
+
// Reusable function for dealing with the different input types
|
432
|
+
// NOTE:: relies on closures to keep 'chain' up to date, a bit confusing, but
|
433
|
+
// much smaller than the functional equivalent in this case.
|
434
|
+
function handleGroup ( needGroup ) {
|
435
|
+
// If it's a string
|
436
|
+
if ( isString( needGroup ) ) {
|
437
|
+
// Just load the script of style
|
438
|
+
loadScriptOrStyle( needGroup, callback, chain, 0, testResult );
|
439
|
+
}
|
440
|
+
// See if we have an object. Doesn't matter if it's an array or a key/val hash
|
441
|
+
// Note:: order cannot be guaranteed on an key value object with multiple elements
|
442
|
+
// since the for-in does not preserve order. Arrays _should_ go in order though.
|
443
|
+
else if ( isObject( needGroup ) ) {
|
444
|
+
for ( callbackKey in needGroup ) {
|
445
|
+
// Safari 2 does not have hasOwnProperty, but not worth the bytes for a shim
|
446
|
+
// patch if needed. Kangax has a nice shim for it. Or just remove the check
|
447
|
+
// and promise not to extend the object prototype.
|
448
|
+
if ( needGroup.hasOwnProperty( callbackKey ) ) {
|
449
|
+
loadScriptOrStyle( needGroup[ callbackKey ], callback, chain, callbackKey, testResult );
|
450
|
+
}
|
451
|
+
}
|
452
|
+
}
|
453
|
+
}
|
454
|
+
|
455
|
+
// figure out what this group should do
|
456
|
+
handleGroup( group );
|
457
|
+
|
458
|
+
// Run our loader on the load/both group too
|
459
|
+
handleGroup( always );
|
460
|
+
|
461
|
+
// Fire complete callback
|
462
|
+
if ( testObject.complete ) {
|
463
|
+
chain.load( testObject.complete );
|
464
|
+
}
|
465
|
+
|
466
|
+
}
|
467
|
+
|
468
|
+
// Someone just decides to load a single script or css file as a string
|
469
|
+
if ( isString( needs ) ) {
|
470
|
+
loadScriptOrStyle( needs, 0, chain, 0 );
|
471
|
+
}
|
472
|
+
// Normal case is likely an array of different types of loading options
|
473
|
+
else if ( isArray( needs ) ) {
|
474
|
+
// go through the list of needs
|
475
|
+
for( i = 0; i < needs.length; i++ ) {
|
476
|
+
need = needs[ i ];
|
477
|
+
|
478
|
+
// if it's a string, just load it
|
479
|
+
if ( isString( need ) ) {
|
480
|
+
loadScriptOrStyle( need, 0, chain, 0 );
|
481
|
+
}
|
482
|
+
// if it's an array, call our function recursively
|
483
|
+
else if ( isArray( need ) ) {
|
484
|
+
yepnope( need );
|
485
|
+
}
|
486
|
+
// if it's an object, use our modernizr logic to win
|
487
|
+
else if ( isObject( need ) ) {
|
488
|
+
loadFromTestObject( need, chain );
|
489
|
+
}
|
490
|
+
}
|
491
|
+
}
|
492
|
+
// Allow a single object to be passed in
|
493
|
+
else if ( isObject( needs ) ) {
|
494
|
+
loadFromTestObject( needs, chain );
|
495
|
+
}
|
496
|
+
};
|
497
|
+
|
498
|
+
// This publicly exposed function is for allowing
|
499
|
+
// you to add functionality based on prefixes on the
|
500
|
+
// string files you add. 'css!' is a builtin prefix
|
501
|
+
//
|
502
|
+
// The arguments are the prefix (not including the !) as a string
|
503
|
+
// and
|
504
|
+
// A callback function. This function is passed a resource object
|
505
|
+
// that can be manipulated and then returned. (like middleware. har.)
|
506
|
+
//
|
507
|
+
// Examples of this can be seen in the officially supported ie prefix
|
508
|
+
yepnope.addPrefix = function ( prefix, callback ) {
|
509
|
+
prefixes[ prefix ] = callback;
|
510
|
+
};
|
511
|
+
|
512
|
+
// A filter is a global function that every resource
|
513
|
+
// object that passes through yepnope will see. You can
|
514
|
+
// of course conditionally choose to modify the resource objects
|
515
|
+
// or just pass them along. The filter function takes the resource
|
516
|
+
// object and is expected to return one.
|
517
|
+
//
|
518
|
+
// The best example of a filter is the 'autoprotocol' officially
|
519
|
+
// supported filter
|
520
|
+
yepnope.addFilter = function ( filter ) {
|
521
|
+
globalFilters.push( filter );
|
522
|
+
};
|
523
|
+
|
524
|
+
// Default error timeout to 10sec - modify to alter
|
525
|
+
yepnope.errorTimeout = 1e4;
|
526
|
+
|
527
|
+
// Webreflection readystate hack
|
528
|
+
// safe for jQuery 1.4+ ( i.e. don't use yepnope with jQuery 1.3.2 )
|
529
|
+
// if the readyState is null and we have a listener
|
530
|
+
if ( doc.readyState == null && doc.addEventListener ) {
|
531
|
+
// set the ready state to loading
|
532
|
+
doc.readyState = 'loading';
|
533
|
+
// call the listener
|
534
|
+
doc.addEventListener( 'DOMContentLoaded', handler = function () {
|
535
|
+
// Remove the listener
|
536
|
+
doc.removeEventListener( 'DOMContentLoaded', handler, 0 );
|
537
|
+
// Set it to ready
|
538
|
+
doc.readyState = 'complete';
|
539
|
+
}, 0 );
|
540
|
+
}
|
541
|
+
|
542
|
+
// Attach loader &
|
543
|
+
// Leak it
|
544
|
+
window.yepnope = getYepnope();
|
545
|
+
|
546
|
+
} )( this, this.document );
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: isc_analytics
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 0.5.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -81,6 +81,11 @@ files:
|
|
81
81
|
- lib/isc_analytics/services.rb
|
82
82
|
- lib/isc_analytics/tags.rb
|
83
83
|
- lib/isc_analytics.rb
|
84
|
+
- vendor/assets/javascripts/isc_analytics/session/index.js
|
85
|
+
- vendor/assets/javascripts/isc_analytics/session/session-0.4.js
|
86
|
+
- vendor/assets/javascripts/isc_analytics/yepnope/css_prefix.js
|
87
|
+
- vendor/assets/javascripts/isc_analytics/yepnope/index.js
|
88
|
+
- vendor/assets/javascripts/isc_analytics/yepnope/yepnope.js
|
84
89
|
- Rakefile
|
85
90
|
- Gemfile
|
86
91
|
- README.md
|