callpixelsjs-rails 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +674 -0
- data/README.md +90 -0
- data/lib/callpixelsjs/rails/version.rb +5 -0
- data/lib/callpixelsjs/rails.rb +8 -0
- data/vendor/assets/javascripts/callpixels.js +1126 -0
- data/vendor/assets/javascripts/callpixels.min.js +2 -0
- metadata +92 -0
|
@@ -0,0 +1,1126 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
// ensure namespace is present
|
|
3
|
+
if (typeof window.Callpixels === 'undefined') window.Callpixels = {};
|
|
4
|
+
var Base = {};
|
|
5
|
+
// define helpers
|
|
6
|
+
Base.assert_required_keys = function () {
|
|
7
|
+
var args = Array.prototype.slice.call(arguments);
|
|
8
|
+
var object = args.shift();
|
|
9
|
+
for (var i = 0; i < args.length; i++) {
|
|
10
|
+
var key = args[i];
|
|
11
|
+
if (typeof object === 'undefined' || typeof object[key] === 'undefined') {
|
|
12
|
+
throw "ArgumentError: Required keys are not defined: " + args.join(', ');
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return object;
|
|
16
|
+
};
|
|
17
|
+
Base.merge = function (obj1, obj2) {
|
|
18
|
+
for (var p in obj2) {
|
|
19
|
+
try {
|
|
20
|
+
if (obj2[p].constructor == Object) {
|
|
21
|
+
obj1[p] = Base.merge(obj1[p], obj2[p]);
|
|
22
|
+
} else {
|
|
23
|
+
obj1[p] = obj2[p];
|
|
24
|
+
}
|
|
25
|
+
} catch (e) {
|
|
26
|
+
obj1[p] = obj2[p];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return obj1;
|
|
30
|
+
};
|
|
31
|
+
Base.isArray = function (arg) {
|
|
32
|
+
return Object.prototype.toString.call(arg) === '[object Array]';
|
|
33
|
+
};
|
|
34
|
+
Base.ieVersion = function () {
|
|
35
|
+
if (Base._ieVersion == null) {
|
|
36
|
+
Base._ieVersion = (function () {
|
|
37
|
+
var v = 3,
|
|
38
|
+
div = document.createElement('div'),
|
|
39
|
+
all = div.getElementsByTagName('i');
|
|
40
|
+
|
|
41
|
+
while (
|
|
42
|
+
div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
|
|
43
|
+
all[0]
|
|
44
|
+
) {
|
|
45
|
+
}
|
|
46
|
+
return v > 4 ? v : false;
|
|
47
|
+
}());
|
|
48
|
+
}
|
|
49
|
+
if (Base._ieVersion == 6 || Base._ieVersion == 7) {
|
|
50
|
+
if (Callpixels['easyxdm_loaded'] == null) Callpixels['easyxdm_loaded'] = false;
|
|
51
|
+
}
|
|
52
|
+
return Base._ieVersion;
|
|
53
|
+
};
|
|
54
|
+
Callpixels.Base = Base;
|
|
55
|
+
})();;// https://github.com/evertton/cookiejs
|
|
56
|
+
(function (f) {
|
|
57
|
+
var a = function (b, c, d) {
|
|
58
|
+
return 1 === arguments.length ? a.get(b) : a.set(b, c, d)
|
|
59
|
+
};
|
|
60
|
+
a._document = document;
|
|
61
|
+
a._navigator = navigator;
|
|
62
|
+
a.defaults = {path: "/"};
|
|
63
|
+
a.get = function (b) {
|
|
64
|
+
a._cachedDocumentCookie !== a._document.cookie && a._renewCache();
|
|
65
|
+
return a._cache[b]
|
|
66
|
+
};
|
|
67
|
+
a.set = function (b, c, d) {
|
|
68
|
+
d = a._getExtendedOptions(d);
|
|
69
|
+
a._document.cookie = a._generateCookieString(b, c, d);
|
|
70
|
+
return a
|
|
71
|
+
};
|
|
72
|
+
a._getExtendedOptions = function (b) {
|
|
73
|
+
return{path: b && b.path || a.defaults.path, domain: b && b.domain || a.defaults.domain, secure: b && b.secure !== f ? b.secure :
|
|
74
|
+
a.defaults.secure}
|
|
75
|
+
};
|
|
76
|
+
a._isValidDate = function (a) {
|
|
77
|
+
return"[object Date]" === Object.prototype.toString.call(a) && !isNaN(a.getTime())
|
|
78
|
+
};
|
|
79
|
+
a._generateCookieString = function (a, c, d) {
|
|
80
|
+
a = encodeURIComponent(a);
|
|
81
|
+
c = (c + "").replace(/[^!#$&-+\--:<-\[\]-~]/g, encodeURIComponent);
|
|
82
|
+
d = d || {};
|
|
83
|
+
a = a + "=" + c + (d.path ? ";path=" + d.path : "");
|
|
84
|
+
a += d.domain ? ";domain=" + d.domain : "";
|
|
85
|
+
return a += d.secure ? ";secure" : ""
|
|
86
|
+
};
|
|
87
|
+
a._getCookieObjectFromString = function (b) {
|
|
88
|
+
var c = {};
|
|
89
|
+
b = b ? b.split("; ") : [];
|
|
90
|
+
for (var d = 0; d < b.length; d++) {
|
|
91
|
+
var e = a._getKeyValuePairFromCookieString(b[d]);
|
|
92
|
+
c[e.key] === f && (c[e.key] = e.value)
|
|
93
|
+
}
|
|
94
|
+
return c
|
|
95
|
+
};
|
|
96
|
+
a._getKeyValuePairFromCookieString = function (a) {
|
|
97
|
+
var c = a.indexOf("="), c = 0 > c ? a.length : c;
|
|
98
|
+
return{key: decodeURIComponent(a.substr(0, c)), value: decodeURIComponent(a.substr(c + 1))}
|
|
99
|
+
};
|
|
100
|
+
a._renewCache = function () {
|
|
101
|
+
a._cache = a._getCookieObjectFromString(a._document.cookie);
|
|
102
|
+
a._cachedDocumentCookie = a._document.cookie
|
|
103
|
+
};
|
|
104
|
+
a._areEnabled = function () {
|
|
105
|
+
return a._navigator.cookieEnabled || "1" === a.set("cookies.js", 1).get("cookies.js")
|
|
106
|
+
};
|
|
107
|
+
a.enabled = a._areEnabled();
|
|
108
|
+
"function" === typeof define &&
|
|
109
|
+
define.amd ? define(function () {
|
|
110
|
+
return a
|
|
111
|
+
}) : "undefined" !== typeof exports ? ("undefined" !== typeof module && module.exports && (exports = module.exports = a), exports.Cookies = a) : a;
|
|
112
|
+
Callpixels.Base.Cookies = a;
|
|
113
|
+
})();;// http://www.webtoolkit.info/javascript-base64.html#.U-qwzYBdUwQ
|
|
114
|
+
(function () {
|
|
115
|
+
var Base64 = {
|
|
116
|
+
_keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
|
|
117
|
+
};
|
|
118
|
+
// public method for encoding
|
|
119
|
+
Base64.encode = function (input) {
|
|
120
|
+
var output = "";
|
|
121
|
+
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
|
|
122
|
+
var i = 0;
|
|
123
|
+
|
|
124
|
+
input = Base64._utf8_encode(input);
|
|
125
|
+
|
|
126
|
+
while (i < input.length) {
|
|
127
|
+
|
|
128
|
+
chr1 = input.charCodeAt(i++);
|
|
129
|
+
chr2 = input.charCodeAt(i++);
|
|
130
|
+
chr3 = input.charCodeAt(i++);
|
|
131
|
+
|
|
132
|
+
enc1 = chr1 >> 2;
|
|
133
|
+
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
|
|
134
|
+
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
|
|
135
|
+
enc4 = chr3 & 63;
|
|
136
|
+
|
|
137
|
+
if (isNaN(chr2)) {
|
|
138
|
+
enc3 = enc4 = 64;
|
|
139
|
+
} else if (isNaN(chr3)) {
|
|
140
|
+
enc4 = 64;
|
|
141
|
+
}
|
|
142
|
+
output = output +
|
|
143
|
+
Base64._keyStr.charAt(enc1) + Base64._keyStr.charAt(enc2) +
|
|
144
|
+
Base64._keyStr.charAt(enc3) + Base64._keyStr.charAt(enc4);
|
|
145
|
+
|
|
146
|
+
}
|
|
147
|
+
return output;
|
|
148
|
+
};
|
|
149
|
+
Base64.decode = function (input) {
|
|
150
|
+
var output = "";
|
|
151
|
+
var chr1, chr2, chr3;
|
|
152
|
+
var enc1, enc2, enc3, enc4;
|
|
153
|
+
var i = 0;
|
|
154
|
+
|
|
155
|
+
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
|
|
156
|
+
|
|
157
|
+
while (i < input.length) {
|
|
158
|
+
|
|
159
|
+
enc1 = Base64._keyStr.indexOf(input.charAt(i++));
|
|
160
|
+
enc2 = Base64._keyStr.indexOf(input.charAt(i++));
|
|
161
|
+
enc3 = Base64._keyStr.indexOf(input.charAt(i++));
|
|
162
|
+
enc4 = Base64._keyStr.indexOf(input.charAt(i++));
|
|
163
|
+
|
|
164
|
+
chr1 = (enc1 << 2) | (enc2 >> 4);
|
|
165
|
+
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
|
166
|
+
chr3 = ((enc3 & 3) << 6) | enc4;
|
|
167
|
+
|
|
168
|
+
output = output + String.fromCharCode(chr1);
|
|
169
|
+
|
|
170
|
+
if (enc3 != 64) {
|
|
171
|
+
output = output + String.fromCharCode(chr2);
|
|
172
|
+
}
|
|
173
|
+
if (enc4 != 64) {
|
|
174
|
+
output = output + String.fromCharCode(chr3);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
output = Base64._utf8_decode(output);
|
|
180
|
+
|
|
181
|
+
return output;
|
|
182
|
+
};
|
|
183
|
+
Base64._utf8_encode = function (string) {
|
|
184
|
+
//REGEX_2: /\r\n/g NEWLINE: "\n"
|
|
185
|
+
string = string.replace(eval("/\\r\\n/g"),eval("String('\\n')"));
|
|
186
|
+
var utftext = "";
|
|
187
|
+
|
|
188
|
+
for (var n = 0; n < string.length; n++) {
|
|
189
|
+
|
|
190
|
+
var c = string.charCodeAt(n);
|
|
191
|
+
|
|
192
|
+
if (c < 128) {
|
|
193
|
+
utftext += String.fromCharCode(c);
|
|
194
|
+
}
|
|
195
|
+
else if ((c > 127) && (c < 2048)) {
|
|
196
|
+
utftext += String.fromCharCode((c >> 6) | 192);
|
|
197
|
+
utftext += String.fromCharCode((c & 63) | 128);
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
utftext += String.fromCharCode((c >> 12) | 224);
|
|
201
|
+
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
|
|
202
|
+
utftext += String.fromCharCode((c & 63) | 128);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return utftext;
|
|
208
|
+
};
|
|
209
|
+
Base64._utf8_decode = function (utftext) {
|
|
210
|
+
var string = "";
|
|
211
|
+
var i = 0;
|
|
212
|
+
var c = c1 = c2 = 0;
|
|
213
|
+
|
|
214
|
+
while (i < utftext.length) {
|
|
215
|
+
|
|
216
|
+
c = utftext.charCodeAt(i);
|
|
217
|
+
|
|
218
|
+
if (c < 128) {
|
|
219
|
+
string += String.fromCharCode(c);
|
|
220
|
+
i++;
|
|
221
|
+
}
|
|
222
|
+
else if ((c > 191) && (c < 224)) {
|
|
223
|
+
c2 = utftext.charCodeAt(i + 1);
|
|
224
|
+
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
|
|
225
|
+
i += 2;
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
c2 = utftext.charCodeAt(i + 1);
|
|
229
|
+
c3 = utftext.charCodeAt(i + 2);
|
|
230
|
+
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
|
|
231
|
+
i += 3;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
}
|
|
235
|
+
return string;
|
|
236
|
+
};
|
|
237
|
+
Callpixels.Base.Base64 = Base64;
|
|
238
|
+
})();;(function () {
|
|
239
|
+
// Dependencies
|
|
240
|
+
var Base = Callpixels.Base;
|
|
241
|
+
/**
|
|
242
|
+
* @constructor
|
|
243
|
+
* @memberof Callpixels.Base
|
|
244
|
+
* @param {Object} config - Configuration hash
|
|
245
|
+
* @param {String} config.type - The data type
|
|
246
|
+
* @param {Numeric} config.primary_key - The primary_key
|
|
247
|
+
*/
|
|
248
|
+
var Data = function (config) {
|
|
249
|
+
|
|
250
|
+
function initialize() {
|
|
251
|
+
Base.assert_required_keys(config, 'type', 'primary_key');
|
|
252
|
+
if (typeof Callpixels.Base.Data._store[config.type] === 'undefined') {
|
|
253
|
+
Callpixels.Base.Data._store[config.type] = {};
|
|
254
|
+
}
|
|
255
|
+
if (typeof Callpixels.Base.Data._store[config.type][config.primary_key] === 'undefined') {
|
|
256
|
+
Callpixels.Base.Data._store[config.type][config.primary_key] = {};
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
var self = this;
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Request data from the host
|
|
264
|
+
* @memberOf Callpixels.Base.Data
|
|
265
|
+
* @function get
|
|
266
|
+
* @instance
|
|
267
|
+
* @param {String} key - The key to retrieve
|
|
268
|
+
* @returns {*}
|
|
269
|
+
*/
|
|
270
|
+
self.get = function () {
|
|
271
|
+
var output = {};
|
|
272
|
+
if (typeof arguments[0] === 'undefined') {
|
|
273
|
+
output = Callpixels.Base.Data._store[config.type][config.primary_key];
|
|
274
|
+
} else if (arguments.length === 1) {
|
|
275
|
+
output = Callpixels.Base.Data._store[config.type][config.primary_key][arguments[0]];
|
|
276
|
+
} else {
|
|
277
|
+
for (var i = 0; i < arguments.length; i++) {
|
|
278
|
+
var key = arguments[i];
|
|
279
|
+
output[key] = Callpixels.Base.Data._store[config.type][config.primary_key][key];
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return output;
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Request data from the host
|
|
287
|
+
* @memberOf Callpixels.Base.Data
|
|
288
|
+
* @function set
|
|
289
|
+
* @instance
|
|
290
|
+
* @param {String} key - The key to retrieve
|
|
291
|
+
* @param {String} value - The value to assign
|
|
292
|
+
* @returns {*}
|
|
293
|
+
*/
|
|
294
|
+
self.set = function (key, value) {
|
|
295
|
+
Callpixels.Base.Data._store[config.type][config.primary_key][key] = value;
|
|
296
|
+
return value;
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Merge data
|
|
301
|
+
* @memberOf Callpixels.Base.Data
|
|
302
|
+
* @function set
|
|
303
|
+
* @instance
|
|
304
|
+
* @param {String} object - The object to merge
|
|
305
|
+
* @returns {*}
|
|
306
|
+
*/
|
|
307
|
+
self.merge = function (object) {
|
|
308
|
+
for (var key in object) {
|
|
309
|
+
Callpixels.Base.Data._store[config.type][config.primary_key][key] = object[key];
|
|
310
|
+
}
|
|
311
|
+
return object;
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
initialize();
|
|
315
|
+
};
|
|
316
|
+
Data._store = {};
|
|
317
|
+
Callpixels.Base.Data = Data;
|
|
318
|
+
})();;(function () {
|
|
319
|
+
// Dependencies
|
|
320
|
+
var Base = Callpixels.Base;
|
|
321
|
+
var Data = Callpixels.Base.Data;
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* @constructor
|
|
325
|
+
* @memberof Callpixels.Base
|
|
326
|
+
*/
|
|
327
|
+
var Model = function () {
|
|
328
|
+
|
|
329
|
+
this.api_host_uri = '/api/v1/';
|
|
330
|
+
this.type = 'model';
|
|
331
|
+
|
|
332
|
+
this.primary_key = function (primary_key) {
|
|
333
|
+
return Model.primary_key(this.type, primary_key);
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
this.store = function (data) {
|
|
337
|
+
// do we have data to store?
|
|
338
|
+
if (typeof(data) !== 'undefined') {
|
|
339
|
+
// does the data contain the required primary_key?
|
|
340
|
+
var key = this.primary_key();
|
|
341
|
+
if (typeof(data[key]) === 'undefined') {
|
|
342
|
+
throw("ArgumentError: Expected to receive primary_key " + key);
|
|
343
|
+
}
|
|
344
|
+
// has a store been initialized?
|
|
345
|
+
else if (typeof(this._store) === 'undefined') {
|
|
346
|
+
this._store = new Callpixels.Base.Data({type: this.type, primary_key: data[key] });
|
|
347
|
+
}
|
|
348
|
+
// merge the data
|
|
349
|
+
this._store.merge(data);
|
|
350
|
+
// update visitor is token present
|
|
351
|
+
Model.update_visitor_id(data);
|
|
352
|
+
}
|
|
353
|
+
return this._store;
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
this.get_data = function (path, callback) {
|
|
357
|
+
return this.connection().getJSON(this.api_host_uri + path, null, [Model.update, callback], this);
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
this.post_data = function (path, data, callback) {
|
|
361
|
+
return this.connection().postJSON(this.api_host_uri + path, data, [Model.update, callback], this);
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
this.set = function () {
|
|
365
|
+
if (typeof(this["set_" + arguments[0]]) === 'function') {
|
|
366
|
+
arguments[1] = this["set_" + arguments[0]].apply(this, [arguments[1]]);
|
|
367
|
+
}
|
|
368
|
+
return this._store.set.apply(this, arguments);
|
|
369
|
+
};
|
|
370
|
+
this.get = function () {
|
|
371
|
+
return this._store.get.apply(this, arguments);
|
|
372
|
+
};
|
|
373
|
+
this.connection = function () {
|
|
374
|
+
return Callpixels.Base.Request.connection();
|
|
375
|
+
};
|
|
376
|
+
};
|
|
377
|
+
Model.inflections = {
|
|
378
|
+
'number': 'numbers',
|
|
379
|
+
'campaign': 'campaigns'
|
|
380
|
+
};
|
|
381
|
+
Model.update = function (data) {
|
|
382
|
+
for (var key in data) {
|
|
383
|
+
var type = key;
|
|
384
|
+
var value = data[key];
|
|
385
|
+
if (typeof Model.inflections[key] !== 'undefined') {
|
|
386
|
+
type = Model.inflections[key];
|
|
387
|
+
}
|
|
388
|
+
if (typeof Data._store[type] !== 'undefined') {
|
|
389
|
+
if (Base.isArray(value)) {
|
|
390
|
+
for (var i = 0; i < value.length; i++) {
|
|
391
|
+
Model.update_record(type, value[i]);
|
|
392
|
+
}
|
|
393
|
+
} else {
|
|
394
|
+
Model.update_record(type, value[i]);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
return data;
|
|
399
|
+
};
|
|
400
|
+
Model.update_record = function (type, record) {
|
|
401
|
+
// update visitor is token present
|
|
402
|
+
Model.update_visitor_id(record);
|
|
403
|
+
// update data store
|
|
404
|
+
if (typeof record.id !== 'undefined') {
|
|
405
|
+
var primary_key = Model.primary_key(type);
|
|
406
|
+
for (var key in record) {
|
|
407
|
+
Callpixels.Base.Data._store[type][record[primary_key]][key] = record[key];
|
|
408
|
+
}
|
|
409
|
+
return true
|
|
410
|
+
} else {
|
|
411
|
+
return false
|
|
412
|
+
}
|
|
413
|
+
return record;
|
|
414
|
+
};
|
|
415
|
+
Model.update_visitor_id = function (record) {
|
|
416
|
+
if (typeof(record) !== 'undefined' && typeof(record.visitor_id) !== 'undefined') {
|
|
417
|
+
Callpixels.Base.Cookies.set('CallPixels-vid', record.visitor_id);
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
Model.primary_key = function (type, primary_key) {
|
|
421
|
+
if (typeof(Model.primary_keys) === 'undefined') Model.primary_keys = {};
|
|
422
|
+
// default key
|
|
423
|
+
if (typeof(Model.primary_keys[type]) === 'undefined') Model.primary_keys[type] = 'id';
|
|
424
|
+
// assign key if passed
|
|
425
|
+
if (typeof(primary_key) !== 'undefined') Model.primary_keys[type] = primary_key;
|
|
426
|
+
// return value
|
|
427
|
+
return Model.primary_keys[type];
|
|
428
|
+
}
|
|
429
|
+
Callpixels.Base.Model = Model;
|
|
430
|
+
})();;(function () {
|
|
431
|
+
// Dependencies
|
|
432
|
+
var Base = window.Callpixels.Base;
|
|
433
|
+
var Cookies = window.Callpixels.Base.Cookies;
|
|
434
|
+
/**
|
|
435
|
+
* @constructor
|
|
436
|
+
* @memberof Callpixels.Base
|
|
437
|
+
* @param {String} options.http_prefix - The http type (http || https).
|
|
438
|
+
* @param {String} options.addr - The api hostname.
|
|
439
|
+
* @param {String} options.urlregex - The url regex validator.
|
|
440
|
+
*/
|
|
441
|
+
var Request = function (options) {
|
|
442
|
+
|
|
443
|
+
function initialize(options) {
|
|
444
|
+
// assert required keys and assign if valid
|
|
445
|
+
config = Base.assert_required_keys(options, 'http_prefix', 'addr', 'urlregex');
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// INIT
|
|
449
|
+
var self = this;
|
|
450
|
+
var config = {};
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Request data from the host
|
|
454
|
+
* @memberOf Callpixels.Base.Request
|
|
455
|
+
* @function getJSON
|
|
456
|
+
* @instance
|
|
457
|
+
* @param {String} request_url - The request uri
|
|
458
|
+
* @param {Object} payload - Post object
|
|
459
|
+
* @param {*} [callbacks] - Array or Function to be called after request
|
|
460
|
+
* @param {*} [context] - Context applied to callback
|
|
461
|
+
* @returns {Object} json
|
|
462
|
+
*/
|
|
463
|
+
self.getJSON = function (request_url, payload, callbacks, context) {
|
|
464
|
+
// ensure callbacks are an array
|
|
465
|
+
if (typeof(callbacks) == "function") callbacks = [callbacks];
|
|
466
|
+
if (typeof(context) === 'undefined') context = self;
|
|
467
|
+
// request
|
|
468
|
+
var request = function () {
|
|
469
|
+
self.apiRequest(request_url, function (data) {
|
|
470
|
+
// parse
|
|
471
|
+
response = JSON.parse(data);
|
|
472
|
+
// fire callbacks
|
|
473
|
+
for (var i in callbacks) {
|
|
474
|
+
if (typeof callbacks[i] == "function") callbacks[i].apply(context, [response]);
|
|
475
|
+
}
|
|
476
|
+
}, payload)
|
|
477
|
+
};
|
|
478
|
+
if (Base.ieVersion() == 6 || Base.ieVersion() == 7) {
|
|
479
|
+
with_ie_scripts(request);
|
|
480
|
+
} else {
|
|
481
|
+
request();
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
// This is an alias for now to show intent
|
|
486
|
+
self.postJSON = function () {
|
|
487
|
+
return self.getJSON.apply(this, arguments);
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Request data from the host
|
|
492
|
+
* @memberOf Callpixels.Base.Request
|
|
493
|
+
* @function apiRequest
|
|
494
|
+
* @instance
|
|
495
|
+
* @param {String} request_url - The request uri
|
|
496
|
+
* @param {Array} callbackFunctions - Array of callback functions
|
|
497
|
+
* @param {Object} payload - Post object
|
|
498
|
+
* @returns {String} string
|
|
499
|
+
*/
|
|
500
|
+
self.apiRequest = function (request_uri, callbackFunctions, payload) {
|
|
501
|
+
// configure
|
|
502
|
+
var http_prefix = config['http_prefix'];
|
|
503
|
+
var addr = config['addr'];
|
|
504
|
+
var urlregex = eval(config['urlregex']);
|
|
505
|
+
var request_url = http_prefix + '://' + addr + request_uri;
|
|
506
|
+
// configure
|
|
507
|
+
|
|
508
|
+
if (payload && typeof(Cookies.get('CallPixels-vid')) !== 'undefined' && Cookies.get('CallPixels-vid') !== 'null') {
|
|
509
|
+
payload['visitor_id'] = Cookies.get('CallPixels-vid');
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
if (typeof(callbackFunctions) == "function") {
|
|
513
|
+
callbackFunctions = [callbackFunctions];
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
function ignored() {
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
function runCallbacks(response) {
|
|
520
|
+
for (var i in callbackFunctions) {
|
|
521
|
+
if (typeof callbackFunctions[i] == "function") callbackFunctions[i](response);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
function forwardResponse() {
|
|
526
|
+
runCallbacks(xdr.responseText);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
function sendXdm() {
|
|
530
|
+
// create the rpc request
|
|
531
|
+
var remote = http_prefix + '://' + addr + '/ie_provider';
|
|
532
|
+
var swf = http_prefix + '://' + addr + "/easyxdm.swf";
|
|
533
|
+
var rpc = eval('new window.easyXDM.Rpc({ remote: "' + remote + '", swf: "' + swf + '"},{remote: {request: {}}});');
|
|
534
|
+
|
|
535
|
+
rpc['request']({
|
|
536
|
+
url: ('/' + request_url.match(urlregex)[1]),
|
|
537
|
+
method: "POST",
|
|
538
|
+
data: payload
|
|
539
|
+
}, function (response) {
|
|
540
|
+
runCallbacks(response.data);
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
if (window.XDomainRequest) {
|
|
545
|
+
// IE >= 8
|
|
546
|
+
// 1. Create XDR object
|
|
547
|
+
var xdr = new XDomainRequest();
|
|
548
|
+
|
|
549
|
+
xdr.onload = forwardResponse; //alertLoaded;
|
|
550
|
+
xdr.onprogress = ignored;
|
|
551
|
+
xdr.onerror = ignored;
|
|
552
|
+
xdr.ontimeout = ignored;
|
|
553
|
+
xdr.timeout = 30000;
|
|
554
|
+
|
|
555
|
+
// 2. Open connection with server using GET method
|
|
556
|
+
if (payload) {
|
|
557
|
+
xdr.open("post", request_url);
|
|
558
|
+
xdr.send(self.buildPost(payload));
|
|
559
|
+
} else {
|
|
560
|
+
xdr.open("get", request_url);
|
|
561
|
+
xdr.send();
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// 3. Send string data to server
|
|
565
|
+
|
|
566
|
+
} else if (Base.ieVersion() == 6 || Base.ieVersion() == 7) {
|
|
567
|
+
with_ie_scripts(sendXdm);
|
|
568
|
+
} else {
|
|
569
|
+
var request = new XMLHttpRequest;
|
|
570
|
+
|
|
571
|
+
if (payload) {
|
|
572
|
+
request.open("POST", request_url, false);
|
|
573
|
+
request.setRequestHeader("Content-Type", "application/json");
|
|
574
|
+
request.send(JSON.stringify(payload));
|
|
575
|
+
} else {
|
|
576
|
+
request.open("GET", request_url, false);
|
|
577
|
+
request.send();
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
if (request.status === 200) {
|
|
581
|
+
runCallbacks(request.responseText);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
};
|
|
585
|
+
|
|
586
|
+
function with_ie_scripts(callback) {
|
|
587
|
+
if (Callpixels['easyxdm_loaded']) {
|
|
588
|
+
callback();
|
|
589
|
+
} else {
|
|
590
|
+
self.loadScript(http_prefix + '://cdn.jsdelivr.net/easyxdm/2.4.17.1/easyXDM.min.js', function () {
|
|
591
|
+
self.loadScript(http_prefix + '://cdn.jsdelivr.net/easyxdm/2.4.17.1/json2.js', function () {
|
|
592
|
+
Callpixels['easyxdm_loaded'] = true;
|
|
593
|
+
callback();
|
|
594
|
+
});
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
};
|
|
598
|
+
|
|
599
|
+
self.buildPost = function (obj) {
|
|
600
|
+
var post_vars = '';
|
|
601
|
+
for (var k in obj) {
|
|
602
|
+
post_vars += k + "=" + obj[k] + '&';
|
|
603
|
+
}
|
|
604
|
+
return post_vars;
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
self.loadScript = function (scriptUrl, afterCallback) {
|
|
608
|
+
var firstScriptElement = document.getElementsByTagName('script')[0];
|
|
609
|
+
var scriptElement = document.createElement('script');
|
|
610
|
+
scriptElement.type = 'text/javascript';
|
|
611
|
+
scriptElement.async = false;
|
|
612
|
+
scriptElement.src = scriptUrl;
|
|
613
|
+
|
|
614
|
+
var ieLoadBugFix = function (scriptElement, callback) {
|
|
615
|
+
if (scriptElement.readyState == 'loaded' || scriptElement.readyState == 'complete') {
|
|
616
|
+
callback();
|
|
617
|
+
} else {
|
|
618
|
+
setTimeout(function () {
|
|
619
|
+
ieLoadBugFix(scriptElement, callback);
|
|
620
|
+
}, 100);
|
|
621
|
+
}
|
|
622
|
+
};
|
|
623
|
+
|
|
624
|
+
if (typeof afterCallback === "function") {
|
|
625
|
+
if (typeof scriptElement.addEventListener !== "undefined") {
|
|
626
|
+
scriptElement.addEventListener("load", afterCallback, false)
|
|
627
|
+
} else {
|
|
628
|
+
scriptElement.onreadystatechange = function () {
|
|
629
|
+
scriptElement.onreadystatechange = null;
|
|
630
|
+
ieLoadBugFix(scriptElement, afterCallback);
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
firstScriptElement.parentNode.insertBefore(scriptElement, firstScriptElement);
|
|
635
|
+
};
|
|
636
|
+
initialize(options);
|
|
637
|
+
self.config = config;
|
|
638
|
+
};
|
|
639
|
+
Request.connection = function () {
|
|
640
|
+
if (typeof window.Callpixels._connection === 'undefined') {
|
|
641
|
+
window.Callpixels._connection = new Callpixels.Base.Request({addr: 'callpixels.com', http_prefix: 'http', urlregex: "/\\/\\/[^\\/]*\\/(.*)/" });
|
|
642
|
+
}
|
|
643
|
+
return window.Callpixels._connection;
|
|
644
|
+
};
|
|
645
|
+
Callpixels.Base.Request = Request;
|
|
646
|
+
})();;(function () {
|
|
647
|
+
// Dependencies
|
|
648
|
+
var Base = Callpixels.Base;
|
|
649
|
+
var Cookies = Callpixels.Base.Cookies;
|
|
650
|
+
var Base64 = Callpixels.Base.Base64;
|
|
651
|
+
var Request = Callpixels.Base.Request;
|
|
652
|
+
/**
|
|
653
|
+
* @constructor
|
|
654
|
+
* @memberof Callpixels.Base
|
|
655
|
+
* @param {Object} options
|
|
656
|
+
* @param {String} options.campaign_key - The campaign uuid.
|
|
657
|
+
* @param {Object} options.tags - The tags to search for.
|
|
658
|
+
* @param {String} [options.default_number_replacement]
|
|
659
|
+
* @param {String} [options.message_replacement]
|
|
660
|
+
* @param {Array} [options.target_map]
|
|
661
|
+
* @param {Array} [options.target_map_cs]
|
|
662
|
+
* @param {String} [options.timer_offset]
|
|
663
|
+
* @param {String} [options.timer_offset_cs]
|
|
664
|
+
*/
|
|
665
|
+
var RequestNumber = function (options) {
|
|
666
|
+
|
|
667
|
+
function initialize(options) {
|
|
668
|
+
// assert required keys and assign if valid
|
|
669
|
+
config = Base.assert_required_keys(options, 'campaign_key');
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// INIT
|
|
673
|
+
var self = this;
|
|
674
|
+
var config = {};
|
|
675
|
+
var resource_url = '/api/v1/numbers?';
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* Request the number
|
|
679
|
+
* @memberOf Callpixels.Base.RequestNumber
|
|
680
|
+
* @function perform
|
|
681
|
+
* @instance
|
|
682
|
+
* @param {Function} callback - Callback to fire after request
|
|
683
|
+
*/
|
|
684
|
+
self.perform = function (callback) {
|
|
685
|
+
if (typeof callback !== 'function') {
|
|
686
|
+
throw "ArgumentError: Expected to receive a callback function"
|
|
687
|
+
}
|
|
688
|
+
var request_url = resource_url + '&campaign_key=' + config['campaign_key'];
|
|
689
|
+
|
|
690
|
+
// append configs to url if provided
|
|
691
|
+
if (config['default_number_replacement']) {
|
|
692
|
+
request_url = request_url + "&default_number=" + config['default_number_replacement'];
|
|
693
|
+
}
|
|
694
|
+
if (config['message_replacement']) {
|
|
695
|
+
request_url = request_url + "&message=" + config['message_replacement'];
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
var body = new Object();
|
|
699
|
+
|
|
700
|
+
var uri = document.location.href;
|
|
701
|
+
|
|
702
|
+
body['u'] = Base64.encode(uri);
|
|
703
|
+
body['st'] = Base64.encode(tags_to_script_tags(config.number_matching_tags));
|
|
704
|
+
|
|
705
|
+
var ou = Cookies.get('CallPixels-ou');
|
|
706
|
+
if (getParts([document.location.href])['cpreset'] || !ou) {
|
|
707
|
+
Cookies.set('CallPixels-ou', body['u']);
|
|
708
|
+
} else {
|
|
709
|
+
body['ou'] = ou;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
function sendGARequest(ga_acct, ga_cookies) {
|
|
713
|
+
body['ga'] = Base64.encode(ga_acct);
|
|
714
|
+
body['c'] = Base64.encode(JSON.stringify(ga_cookies));
|
|
715
|
+
Request.connection().getJSON(request_url, body, callback);
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
|
|
719
|
+
var ga_acct = 'FAILED';
|
|
720
|
+
|
|
721
|
+
try {
|
|
722
|
+
_gaq.push(function () {
|
|
723
|
+
ga_acct = eval('_gat._getTrackerByName()._getAccount()');
|
|
724
|
+
|
|
725
|
+
sendGARequest(ga_acct, getGACookies());
|
|
726
|
+
});
|
|
727
|
+
|
|
728
|
+
} catch (e) {
|
|
729
|
+
|
|
730
|
+
try {
|
|
731
|
+
ga(function (tracker) {
|
|
732
|
+
var clientId = tracker.get('clientId');
|
|
733
|
+
var allTrackers = eval('ga.getAll()');
|
|
734
|
+
ga_acct = allTrackers[0].get('trackingId');
|
|
735
|
+
|
|
736
|
+
var ga_cookies = {};
|
|
737
|
+
ga_cookies['__utma'] = clientId;
|
|
738
|
+
ga_cookies['mp'] = 'yes';
|
|
739
|
+
sendGARequest(ga_acct, ga_cookies);
|
|
740
|
+
});
|
|
741
|
+
|
|
742
|
+
} catch (f) {
|
|
743
|
+
// Post back with failed ga_acct.
|
|
744
|
+
Request.connection().getJSON(request_url, body, callback);
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
};
|
|
749
|
+
|
|
750
|
+
function getParts(urls) {
|
|
751
|
+
var all_parts = {};
|
|
752
|
+
for (var i = 0; i < urls.length; i++) {
|
|
753
|
+
var url_parts = getUrlParts(urls[i]);
|
|
754
|
+
for (var attrname in url_parts) {
|
|
755
|
+
all_parts[attrname] = url_parts[attrname];
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
return all_parts;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
function getUrlParts(url) {
|
|
762
|
+
// url contains your data.
|
|
763
|
+
var objURL = new Object();
|
|
764
|
+
try {
|
|
765
|
+
//REGEX_1: /\?(.*)/
|
|
766
|
+
url = url.match(eval("/\\?(.*)/"))[0];
|
|
767
|
+
} catch (e) {
|
|
768
|
+
return objURL;
|
|
769
|
+
//Ignored
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
// Use the String::replace method to iterate over each
|
|
773
|
+
// name-value pair in the query string. Location.search
|
|
774
|
+
// gives us the query string (if it exists).
|
|
775
|
+
url.replace(
|
|
776
|
+
new RegExp("([^?=&]+)(=([^&]*))?", "g"),
|
|
777
|
+
|
|
778
|
+
// For each matched query string pair, add that
|
|
779
|
+
// pair to the URL struct using the pre-equals
|
|
780
|
+
// value as the key.
|
|
781
|
+
function ($0, $1, $2, $3) {
|
|
782
|
+
objURL[ $1.toLowerCase() ] = $3;
|
|
783
|
+
}
|
|
784
|
+
);
|
|
785
|
+
|
|
786
|
+
return objURL;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
function getGACookies() {
|
|
790
|
+
var ga_cookies = ['__utma', '__utmb', '__utmc', '__utmz', '__utmv'];
|
|
791
|
+
var cookies = new Object();
|
|
792
|
+
for (var i in ga_cookies) {
|
|
793
|
+
var cookie_val = extractCookie(ga_cookies[i]);
|
|
794
|
+
|
|
795
|
+
if (cookie_val || i > 0) {
|
|
796
|
+
if (cookie_val) cookies[ga_cookies[i]] = cookie_val;
|
|
797
|
+
} else {
|
|
798
|
+
break;
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
return cookies;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
function extractCookie(name) {
|
|
805
|
+
var regex = new RegExp(name + '=([^;]*)', 'g');
|
|
806
|
+
try {
|
|
807
|
+
return regex.exec(document.cookie)[1];
|
|
808
|
+
} catch (e) {
|
|
809
|
+
return false;
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
function findOne(all_parts, var_arr) {
|
|
814
|
+
for (var look_for in var_arr) {
|
|
815
|
+
for (var attrname in all_parts) {
|
|
816
|
+
if (attrname == var_arr[look_for]) {
|
|
817
|
+
return all_parts[attrname];
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
return false
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
initialize(options);
|
|
825
|
+
};
|
|
826
|
+
|
|
827
|
+
function tags_to_script_tags(tags) {
|
|
828
|
+
var script_tags = '';
|
|
829
|
+
for (var key in tags) {
|
|
830
|
+
var value = tags[key];
|
|
831
|
+
script_tags = script_tags + '&' + key + '=' + value
|
|
832
|
+
}
|
|
833
|
+
return script_tags;
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
Callpixels.Base.RequestNumber = RequestNumber;
|
|
837
|
+
})();
|
|
838
|
+
|
|
839
|
+
;window.Callpixels.Cache = {};;(function () {
|
|
840
|
+
// Dependencies
|
|
841
|
+
var Base = Callpixels.Base;
|
|
842
|
+
/**
|
|
843
|
+
* @constructor
|
|
844
|
+
* @memberOf Callpixels
|
|
845
|
+
* @param {Object} attributes - Attributes
|
|
846
|
+
* @property {Object} attributes
|
|
847
|
+
* @property {Number} attributes.id - The CallPixels internal number ID.
|
|
848
|
+
* @property {String} attributes.formatted_number - Nationally formatted phone number.
|
|
849
|
+
* @property {String} attributes.number - E.164 formatted phone number.
|
|
850
|
+
* @property {String} attributes.plain_number - The unformatted phone number digits.
|
|
851
|
+
* @property {Boolean} attributes.target_open - Whether there is an open, available target.
|
|
852
|
+
*/
|
|
853
|
+
Callpixels.Number = function (options) {
|
|
854
|
+
|
|
855
|
+
var self = this;
|
|
856
|
+
self.type = 'numbers';
|
|
857
|
+
|
|
858
|
+
function initialize(data) {
|
|
859
|
+
self.store(data);
|
|
860
|
+
self.set('is_active', 'true');
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
/**
|
|
864
|
+
* Add tags to a number.
|
|
865
|
+
* @memberOf Callpixels.Number
|
|
866
|
+
* @function add_tags
|
|
867
|
+
* @instance
|
|
868
|
+
* @param {Object} tags - A collection of tags {key: 'value', tag2: 'value2'}
|
|
869
|
+
* @param {Function} callback - Callback that will be fired after request.
|
|
870
|
+
* @throws Will throw an error if attempting to modify tags on a number that doesn't belong to a number pool
|
|
871
|
+
* with per-visitor numbers enabled.
|
|
872
|
+
*/
|
|
873
|
+
self.add_tags = function (tags, callback) {
|
|
874
|
+
ensure_is_per_visitor();
|
|
875
|
+
self.post_data('numbers/tag', tags_payload(tags), callback);
|
|
876
|
+
};
|
|
877
|
+
|
|
878
|
+
/**
|
|
879
|
+
* Remove tags from a number.
|
|
880
|
+
* @memberOf Callpixels.Number
|
|
881
|
+
* @function remove_tags
|
|
882
|
+
* @instance
|
|
883
|
+
* @param {Object} tags - A collection of tags {key: 'value', tag2: 'value2'}
|
|
884
|
+
* @param {Function} callback - Callback that will be fired after request.
|
|
885
|
+
* @throws Will throw an error if attempting to modify tags on a number that doesn't belong to a number pool
|
|
886
|
+
* with per-visitor numbers enabled.
|
|
887
|
+
*/
|
|
888
|
+
self.remove_tags = function (tags, callback) {
|
|
889
|
+
ensure_is_per_visitor();
|
|
890
|
+
self.post_data('numbers/untag', tags_payload(tags), callback);
|
|
891
|
+
};
|
|
892
|
+
|
|
893
|
+
/**
|
|
894
|
+
* Removes all tags with given keys from a number.
|
|
895
|
+
* @memberOf Callpixels.Number
|
|
896
|
+
* @function remove_tags_by_keys
|
|
897
|
+
* @instance
|
|
898
|
+
* @param {Array} keys - An array of keys to remove. eg: ['key1', 'key2']
|
|
899
|
+
* @param {Function} callback - Callback that will be fired after request.
|
|
900
|
+
* @throws Will throw an error if attempting to modify tags on a number that doesn't belong to a number pool
|
|
901
|
+
* with per-visitor numbers enabled.
|
|
902
|
+
*/
|
|
903
|
+
self.remove_tags_by_keys = function (keys, callback) {
|
|
904
|
+
ensure_is_per_visitor();
|
|
905
|
+
if (typeof(keys) === 'string') keys = keys.split(',');
|
|
906
|
+
var payload = {
|
|
907
|
+
tag_keys: keys,
|
|
908
|
+
ids: [ get('id') ],
|
|
909
|
+
campaign_key: get('campaign_key')
|
|
910
|
+
};
|
|
911
|
+
self.post_data('numbers/untag/keys', payload, callback);
|
|
912
|
+
};
|
|
913
|
+
|
|
914
|
+
/**
|
|
915
|
+
* Clear all tags from a number.
|
|
916
|
+
* @memberOf Callpixels.Number
|
|
917
|
+
* @function clear_tags
|
|
918
|
+
* @instance
|
|
919
|
+
* @param {Function} callback - Callback that will be fired after request.
|
|
920
|
+
* @throws Will throw an error if attempting to modify tags on a number that doesn't belong to a number pool
|
|
921
|
+
* with per-visitor numbers enabled.
|
|
922
|
+
*/
|
|
923
|
+
self.clear_tags = function (callback) {
|
|
924
|
+
ensure_is_per_visitor();
|
|
925
|
+
var payload = {
|
|
926
|
+
ids: [ get('id') ],
|
|
927
|
+
campaign_key: get('campaign_key'),
|
|
928
|
+
all: 'true'
|
|
929
|
+
};
|
|
930
|
+
self.post_data('numbers/untag', payload, callback);
|
|
931
|
+
};
|
|
932
|
+
|
|
933
|
+
/**
|
|
934
|
+
* Release number back to pool.
|
|
935
|
+
* @memberOf Callpixels.Number
|
|
936
|
+
* @function release
|
|
937
|
+
* @instance
|
|
938
|
+
*/
|
|
939
|
+
self.release = function () {
|
|
940
|
+
self.set('is_active', 'false');
|
|
941
|
+
};
|
|
942
|
+
|
|
943
|
+
/**
|
|
944
|
+
* Start a call immediately by having a campaign target dial the visitor.
|
|
945
|
+
* @memberOf Callpixels.Number
|
|
946
|
+
* @function initiate_call
|
|
947
|
+
* @instance
|
|
948
|
+
* @param {String} dial - The number to call.
|
|
949
|
+
* @param {Object} payload - A collection of tags as key-value pairs and optional secure override properties.
|
|
950
|
+
* @param {string} [payload.target_map] - A string mapping a placeholder number to a phone number.
|
|
951
|
+
* @param {string} [payload.target_map_cs] - A SHA1 checksum of the target_map concatenated with your CallPixels API
|
|
952
|
+
* key.
|
|
953
|
+
* @param {number} [payload.timer_offset] - Number of seconds to offset the "connect" duration timers by.
|
|
954
|
+
* @param {string} [payload.timer_offset_cs] - An SHA1 checksum of the timer_offset concatenated with your
|
|
955
|
+
* CallPixels API key.
|
|
956
|
+
* @param {(string|number)} [payload.*] - Key value pairs treated as tags.
|
|
957
|
+
* @param {Function} callback - Callback that will be fired after request.
|
|
958
|
+
* @example
|
|
959
|
+
* number.initiate_call('4166686980', {company_name: 'CallPixels'}, function (call) {
|
|
960
|
+
* alert('Call started with UUID ' + call.uuid)
|
|
961
|
+
* });
|
|
962
|
+
*/
|
|
963
|
+
self.initiate_call = function (dial, payload, callback) {
|
|
964
|
+
if (typeof(payload) === 'undefined') payload = {};
|
|
965
|
+
// assign dial to payload
|
|
966
|
+
payload.dial = dial;
|
|
967
|
+
// merge payload into payload
|
|
968
|
+
payload = Base.merge(self.get('id', 'campaign_key'), payload);
|
|
969
|
+
// post the payload
|
|
970
|
+
self.post_data('numbers/initiate_call', payload, callback);
|
|
971
|
+
};
|
|
972
|
+
|
|
973
|
+
function tags_payload(tags) {
|
|
974
|
+
if (typeof(tags) === 'string') tags = Callpixels.Number.extract_tags_from_string(tags);
|
|
975
|
+
return {
|
|
976
|
+
tag_values: tags,
|
|
977
|
+
ids: [ get('id') ],
|
|
978
|
+
campaign_key: get('campaign_key')
|
|
979
|
+
};
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
function get(key) {
|
|
983
|
+
return self.get(key);
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
function ensure_is_per_visitor() {
|
|
987
|
+
if (self.get('is_per_visitor') === false) {
|
|
988
|
+
throw "Error: Tried to add tags to non per-visitor number.";
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
initialize(options);
|
|
993
|
+
};
|
|
994
|
+
|
|
995
|
+
Callpixels.Number.extract_tags_from_string = function (tags) {
|
|
996
|
+
var output = {};
|
|
997
|
+
var tags = tags.split(",");
|
|
998
|
+
for (var i = 0; i < tags.length; i++) {
|
|
999
|
+
var tag = tags[i].split(":");
|
|
1000
|
+
output[tag[0]] = tag[1]
|
|
1001
|
+
}
|
|
1002
|
+
return output;
|
|
1003
|
+
};
|
|
1004
|
+
|
|
1005
|
+
Callpixels.Number.prototype = new Callpixels.Base.Model();
|
|
1006
|
+
|
|
1007
|
+
function ping_active_numbers(callback) {
|
|
1008
|
+
if (typeof(Callpixels.Base.Data._store) !== 'undefined') {
|
|
1009
|
+
// get numbers
|
|
1010
|
+
var numbers = Callpixels.Base.Data._store['numbers'];
|
|
1011
|
+
// for each number
|
|
1012
|
+
if (typeof(numbers) !== 'undefined') {
|
|
1013
|
+
// group number_ids by campaign_key
|
|
1014
|
+
var grouped = {};
|
|
1015
|
+
for (var primary_key in numbers) {
|
|
1016
|
+
var number = numbers[primary_key];
|
|
1017
|
+
if (number.is_active === 'true') {
|
|
1018
|
+
if (typeof(grouped[number.campaign_key]) === 'undefined') grouped[number.campaign_key] = [];
|
|
1019
|
+
grouped[number.campaign_key].push(number.id);
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
// ping each group of number_ids
|
|
1023
|
+
for (var campaign_key in grouped) {
|
|
1024
|
+
var payload = {
|
|
1025
|
+
campaign_key: campaign_key,
|
|
1026
|
+
ids: grouped[campaign_key]
|
|
1027
|
+
};
|
|
1028
|
+
Callpixels.Base.Request.connection().postJSON('/api/v1/numbers/ping', payload, [Callpixels.Base.Model.update, callback], this);
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
// call recursively
|
|
1033
|
+
setTimeout(ping_active_numbers, 15000);
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
// always ping active numbers
|
|
1037
|
+
ping_active_numbers();
|
|
1038
|
+
|
|
1039
|
+
})();;(function () {
|
|
1040
|
+
// Dependencies
|
|
1041
|
+
var RequestNumber = Callpixels.Base.RequestNumber;
|
|
1042
|
+
/**
|
|
1043
|
+
* @constructor
|
|
1044
|
+
* @memberOf Callpixels
|
|
1045
|
+
* @param {Object} options
|
|
1046
|
+
* @param {String} options.campaign_key - Campaign key
|
|
1047
|
+
* @example
|
|
1048
|
+
* var campaign = new Callpixels.Campaign({ campaign_key: '67d9fb1917ae8f4eaff36831b41788c3' });
|
|
1049
|
+
*/
|
|
1050
|
+
var Campaign = function (options) {
|
|
1051
|
+
|
|
1052
|
+
function initialize(data) {
|
|
1053
|
+
// initialize data store
|
|
1054
|
+
self.store(data);
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
var self = this;
|
|
1058
|
+
self.type = 'campaigns';
|
|
1059
|
+
self.primary_key('campaign_key');
|
|
1060
|
+
self.numbers = [];
|
|
1061
|
+
|
|
1062
|
+
/**
|
|
1063
|
+
* Fetch a campaign number.
|
|
1064
|
+
* @memberOf Callpixels.Campaign
|
|
1065
|
+
* @function request_number
|
|
1066
|
+
* @instance
|
|
1067
|
+
* @param {Object} tags - A collection of tags as key-value pairs. The number returned will match these tags.
|
|
1068
|
+
* @param {getNumberCallback} callback - Callback fired after the request completes.
|
|
1069
|
+
* @example
|
|
1070
|
+
* campaign.request_number({calling_about: 'support'}, function (number) {
|
|
1071
|
+
* alert(number.get('number'))
|
|
1072
|
+
* });
|
|
1073
|
+
*/
|
|
1074
|
+
self.request_number = function (tags, callback) {
|
|
1075
|
+
// assign the tags (this is important since it runs it through set_number_matching_tags)
|
|
1076
|
+
self.set('number_matching_tags', tags);
|
|
1077
|
+
// request the number
|
|
1078
|
+
new RequestNumber(self.get('campaign_key', 'number_matching_tags')).perform(function (data) {
|
|
1079
|
+
// initialize number
|
|
1080
|
+
var number = new Callpixels.Number(data.number);
|
|
1081
|
+
// call callback
|
|
1082
|
+
callback.apply(self, [number]);
|
|
1083
|
+
});
|
|
1084
|
+
};
|
|
1085
|
+
/**
|
|
1086
|
+
* Callpixels.Campaign#request_number callback fired after the request completes.
|
|
1087
|
+
* @callback getNumberCallback
|
|
1088
|
+
* @param {Callpixels.Number} - The number that was returned
|
|
1089
|
+
*/
|
|
1090
|
+
|
|
1091
|
+
self.numbers = function () {
|
|
1092
|
+
var output = [];
|
|
1093
|
+
if (typeof(Callpixels.Base.Data._store) !== 'undefined') {
|
|
1094
|
+
// get numbers
|
|
1095
|
+
var numbers = Callpixels.Base.Data._store['numbers'];
|
|
1096
|
+
// present?
|
|
1097
|
+
if (typeof(numbers) !== 'undefined') {
|
|
1098
|
+
// collect numbers matching this campaign
|
|
1099
|
+
for (var primary_key in numbers) {
|
|
1100
|
+
var number = numbers[primary_key];
|
|
1101
|
+
if (self.get('campaign_key') == number.campaign_key) {
|
|
1102
|
+
output.push(new Callpixels.Number(number));
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
return output;
|
|
1108
|
+
};
|
|
1109
|
+
|
|
1110
|
+
self.set_number_matching_tags = function (tags) {
|
|
1111
|
+
if (typeof(tags) === 'string') {
|
|
1112
|
+
tags = Callpixels.Number.extract_tags_from_string(tags);
|
|
1113
|
+
}
|
|
1114
|
+
if (tags && (typeof tags === "object") && !(tags instanceof Array)) {
|
|
1115
|
+
return tags
|
|
1116
|
+
}
|
|
1117
|
+
else {
|
|
1118
|
+
throw "ArgumentError: Expected number_matching_tags to be an object. eg: {tag: 'value'}";
|
|
1119
|
+
}
|
|
1120
|
+
};
|
|
1121
|
+
|
|
1122
|
+
initialize(options);
|
|
1123
|
+
};
|
|
1124
|
+
Campaign.prototype = new Callpixels.Base.Model();
|
|
1125
|
+
Callpixels.Campaign = Campaign;
|
|
1126
|
+
})();
|