retreaverjs-rails 0.0.12
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/Gruntfile.js +48 -0
- data/LICENSE +674 -0
- data/README.md +90 -0
- data/Rakefile +16 -0
- data/config/README +1 -0
- data/config/jsdocs.json +26 -0
- data/lib/retreaverjs/compile.rb +32 -0
- data/lib/retreaverjs/rails/version.rb +5 -0
- data/lib/retreaverjs/rails.rb +8 -0
- data/package.json +46 -0
- data/src/retreaver/base/base64.js +126 -0
- data/src/retreaver/base/cookies.js +59 -0
- data/src/retreaver/base/data.js +81 -0
- data/src/retreaver/base/helpers.js +55 -0
- data/src/retreaver/base/model.js +113 -0
- data/src/retreaver/base/request.js +215 -0
- data/src/retreaver/base/request_number.js +193 -0
- data/src/retreaver/cache.js +1 -0
- data/src/retreaver/callpixels.js +3 -0
- data/src/retreaver/campaign.js +108 -0
- data/src/retreaver/number.js +206 -0
- metadata +121 -0
@@ -0,0 +1,215 @@
|
|
1
|
+
(function () {
|
2
|
+
// Dependencies
|
3
|
+
var Base = window.Retreaver.Base;
|
4
|
+
var Cookies = window.Retreaver.Base.Cookies;
|
5
|
+
/**
|
6
|
+
* @constructor
|
7
|
+
* @memberof Retreaver.Base
|
8
|
+
* @param {String} options.http_prefix - The http type (http || https).
|
9
|
+
* @param {String} options.addr - The api hostname.
|
10
|
+
* @param {String} options.urlregex - The url regex validator.
|
11
|
+
*/
|
12
|
+
var Request = function (options) {
|
13
|
+
|
14
|
+
function initialize(options) {
|
15
|
+
// assert required keys and assign if valid
|
16
|
+
config = Base.assert_required_keys(options, 'http_prefix', 'addr', 'urlregex');
|
17
|
+
}
|
18
|
+
|
19
|
+
// INIT
|
20
|
+
var self = this;
|
21
|
+
var config = {};
|
22
|
+
|
23
|
+
/**
|
24
|
+
* Request data from the host
|
25
|
+
* @memberOf Retreaver.Base.Request
|
26
|
+
* @function getJSON
|
27
|
+
* @instance
|
28
|
+
* @param {String} request_url - The request uri
|
29
|
+
* @param {Object} payload - Post object
|
30
|
+
* @param {*} [callbacks] - Array or Function to be called after request
|
31
|
+
* @param {*} [context] - Context applied to callback
|
32
|
+
* @returns {Object} json
|
33
|
+
*/
|
34
|
+
self.getJSON = function (request_url, payload, callbacks, context) {
|
35
|
+
// ensure callbacks are an array
|
36
|
+
if (typeof(callbacks) == "function") callbacks = [callbacks];
|
37
|
+
if (typeof(context) === 'undefined') context = self;
|
38
|
+
// request
|
39
|
+
var request = function () {
|
40
|
+
self.apiRequest(request_url, function (data) {
|
41
|
+
// parse
|
42
|
+
response = JSON.parse(data);
|
43
|
+
// fire callbacks
|
44
|
+
for (var i in callbacks) {
|
45
|
+
if (typeof callbacks[i] == "function") callbacks[i].apply(context, [response]);
|
46
|
+
}
|
47
|
+
}, payload)
|
48
|
+
};
|
49
|
+
if (Base.ieVersion() == 6 || Base.ieVersion() == 7) {
|
50
|
+
with_ie_scripts(request);
|
51
|
+
} else {
|
52
|
+
request();
|
53
|
+
}
|
54
|
+
};
|
55
|
+
|
56
|
+
// This is an alias for now to show intent
|
57
|
+
self.postJSON = function () {
|
58
|
+
return self.getJSON.apply(this, arguments);
|
59
|
+
};
|
60
|
+
|
61
|
+
/**
|
62
|
+
* Request data from the host
|
63
|
+
* @memberOf Retreaver.Base.Request
|
64
|
+
* @function apiRequest
|
65
|
+
* @instance
|
66
|
+
* @param {String} request_url - The request uri
|
67
|
+
* @param {Array} callbackFunctions - Array of callback functions
|
68
|
+
* @param {Object} payload - Post object
|
69
|
+
* @returns {String} string
|
70
|
+
*/
|
71
|
+
self.apiRequest = function (request_uri, callbackFunctions, payload) {
|
72
|
+
// configure
|
73
|
+
var http_prefix = config['http_prefix'];
|
74
|
+
var addr = config['addr'];
|
75
|
+
var urlregex = eval(config['urlregex']);
|
76
|
+
var request_url = http_prefix + '://' + addr + request_uri;
|
77
|
+
// configure
|
78
|
+
|
79
|
+
if (payload && typeof(Cookies.get('CallPixels-vid')) !== 'undefined' && Cookies.get('CallPixels-vid') !== 'null') {
|
80
|
+
payload['visitor_id'] = Cookies.get('CallPixels-vid');
|
81
|
+
}
|
82
|
+
|
83
|
+
if (typeof(callbackFunctions) == "function") {
|
84
|
+
callbackFunctions = [callbackFunctions];
|
85
|
+
}
|
86
|
+
|
87
|
+
function ignored() {
|
88
|
+
}
|
89
|
+
|
90
|
+
function runCallbacks(response) {
|
91
|
+
for (var i in callbackFunctions) {
|
92
|
+
if (typeof callbackFunctions[i] == "function") callbackFunctions[i](response);
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
function forwardResponse() {
|
97
|
+
runCallbacks(xdr.responseText);
|
98
|
+
}
|
99
|
+
|
100
|
+
function sendXdm() {
|
101
|
+
// create the rpc request
|
102
|
+
var remote = http_prefix + '://' + addr + '/ie_provider';
|
103
|
+
var swf = http_prefix + '://' + addr + "/easyxdm.swf";
|
104
|
+
var rpc = eval('new window.easyXDM.Rpc({ remote: "' + remote + '", swf: "' + swf + '"},{remote: {request: {}}});');
|
105
|
+
|
106
|
+
rpc['request']({
|
107
|
+
url: ('/' + request_url.match(urlregex)[1]),
|
108
|
+
method: "POST",
|
109
|
+
data: payload
|
110
|
+
}, function (response) {
|
111
|
+
runCallbacks(response.data);
|
112
|
+
});
|
113
|
+
}
|
114
|
+
|
115
|
+
if (window.XDomainRequest) {
|
116
|
+
// IE >= 8
|
117
|
+
// 1. Create XDR object
|
118
|
+
var xdr = new XDomainRequest();
|
119
|
+
|
120
|
+
xdr.onload = forwardResponse; //alertLoaded;
|
121
|
+
xdr.onprogress = ignored;
|
122
|
+
xdr.onerror = ignored;
|
123
|
+
xdr.ontimeout = ignored;
|
124
|
+
xdr.timeout = 30000;
|
125
|
+
|
126
|
+
// 2. Open connection with server using GET method
|
127
|
+
if (payload) {
|
128
|
+
xdr.open("post", request_url);
|
129
|
+
xdr.send(self.buildPost(payload));
|
130
|
+
} else {
|
131
|
+
xdr.open("get", request_url);
|
132
|
+
xdr.send();
|
133
|
+
}
|
134
|
+
|
135
|
+
// 3. Send string data to server
|
136
|
+
|
137
|
+
} else if (Base.ieVersion() == 6 || Base.ieVersion() == 7) {
|
138
|
+
with_ie_scripts(sendXdm);
|
139
|
+
} else {
|
140
|
+
var request = new XMLHttpRequest;
|
141
|
+
|
142
|
+
if (payload) {
|
143
|
+
request.open("POST", request_url, false);
|
144
|
+
request.setRequestHeader("Content-Type", "application/json");
|
145
|
+
request.send(JSON.stringify(payload));
|
146
|
+
} else {
|
147
|
+
request.open("GET", request_url, false);
|
148
|
+
request.send();
|
149
|
+
}
|
150
|
+
|
151
|
+
runCallbacks(request.responseText);
|
152
|
+
}
|
153
|
+
};
|
154
|
+
|
155
|
+
function with_ie_scripts(callback) {
|
156
|
+
if (Retreaver['easyxdm_loaded']) {
|
157
|
+
callback();
|
158
|
+
} else {
|
159
|
+
self.loadScript(http_prefix + '://cdn.jsdelivr.net/easyxdm/2.4.17.1/easyXDM.min.js', function () {
|
160
|
+
self.loadScript(http_prefix + '://cdn.jsdelivr.net/easyxdm/2.4.17.1/json2.js', function () {
|
161
|
+
Retreaver['easyxdm_loaded'] = true;
|
162
|
+
callback();
|
163
|
+
});
|
164
|
+
});
|
165
|
+
}
|
166
|
+
};
|
167
|
+
|
168
|
+
self.buildPost = function (obj) {
|
169
|
+
var post_vars = '';
|
170
|
+
for (var k in obj) {
|
171
|
+
post_vars += k + "=" + obj[k] + '&';
|
172
|
+
}
|
173
|
+
return post_vars;
|
174
|
+
};
|
175
|
+
|
176
|
+
self.loadScript = function (scriptUrl, afterCallback) {
|
177
|
+
var firstScriptElement = document.getElementsByTagName('script')[0];
|
178
|
+
var scriptElement = document.createElement('script');
|
179
|
+
scriptElement.type = 'text/javascript';
|
180
|
+
scriptElement.async = false;
|
181
|
+
scriptElement.src = scriptUrl;
|
182
|
+
|
183
|
+
var ieLoadBugFix = function (scriptElement, callback) {
|
184
|
+
if (scriptElement.readyState == 'loaded' || scriptElement.readyState == 'complete') {
|
185
|
+
callback();
|
186
|
+
} else {
|
187
|
+
setTimeout(function () {
|
188
|
+
ieLoadBugFix(scriptElement, callback);
|
189
|
+
}, 100);
|
190
|
+
}
|
191
|
+
};
|
192
|
+
|
193
|
+
if (typeof afterCallback === "function") {
|
194
|
+
if (typeof scriptElement.addEventListener !== "undefined") {
|
195
|
+
scriptElement.addEventListener("load", afterCallback, false)
|
196
|
+
} else {
|
197
|
+
scriptElement.onreadystatechange = function () {
|
198
|
+
scriptElement.onreadystatechange = null;
|
199
|
+
ieLoadBugFix(scriptElement, afterCallback);
|
200
|
+
}
|
201
|
+
}
|
202
|
+
}
|
203
|
+
firstScriptElement.parentNode.insertBefore(scriptElement, firstScriptElement);
|
204
|
+
};
|
205
|
+
initialize(options);
|
206
|
+
self.config = config;
|
207
|
+
};
|
208
|
+
Request.connection = function () {
|
209
|
+
if (typeof window.Retreaver._connection === 'undefined') {
|
210
|
+
window.Retreaver._connection = new Retreaver.Base.Request({addr: 'api.retreaver.com', http_prefix: 'http', urlregex: "/\\/\\/[^\\/]*\\/(.*)/" });
|
211
|
+
}
|
212
|
+
return window.Retreaver._connection;
|
213
|
+
};
|
214
|
+
Retreaver.Base.Request = Request;
|
215
|
+
})();
|
@@ -0,0 +1,193 @@
|
|
1
|
+
(function () {
|
2
|
+
// Dependencies
|
3
|
+
var Base = Retreaver.Base;
|
4
|
+
var Cookies = Retreaver.Base.Cookies;
|
5
|
+
var Base64 = Retreaver.Base.Base64;
|
6
|
+
var Request = Retreaver.Base.Request;
|
7
|
+
/**
|
8
|
+
* @constructor
|
9
|
+
* @memberof Retreaver.Base
|
10
|
+
* @param {Object} options
|
11
|
+
* @param {String} options.campaign_key - The campaign uuid.
|
12
|
+
* @param {Object} options.tags - The tags to search for.
|
13
|
+
* @param {String} [options.default_number_replacement]
|
14
|
+
* @param {String} [options.message_replacement]
|
15
|
+
* @param {Array} [options.target_map]
|
16
|
+
* @param {Array} [options.target_map_cs]
|
17
|
+
* @param {String} [options.timer_offset]
|
18
|
+
* @param {String} [options.timer_offset_cs]
|
19
|
+
*/
|
20
|
+
var RequestNumber = function (options) {
|
21
|
+
|
22
|
+
function initialize(options) {
|
23
|
+
// assert required keys and assign if valid
|
24
|
+
config = Base.assert_required_keys(options, 'campaign_key');
|
25
|
+
}
|
26
|
+
|
27
|
+
// INIT
|
28
|
+
var self = this;
|
29
|
+
var config = {};
|
30
|
+
var resource_url = '/api/v1/numbers?';
|
31
|
+
|
32
|
+
/**
|
33
|
+
* Request the number
|
34
|
+
* @memberOf Retreaver.Base.RequestNumber
|
35
|
+
* @function perform
|
36
|
+
* @instance
|
37
|
+
* @param {Function} callback - Callback to fire after request
|
38
|
+
*/
|
39
|
+
self.perform = function (callback) {
|
40
|
+
if (typeof callback !== 'function') {
|
41
|
+
throw "ArgumentError: Expected to receive a callback function"
|
42
|
+
}
|
43
|
+
var request_url = resource_url + '&campaign_key=' + config['campaign_key'];
|
44
|
+
|
45
|
+
// append configs to url if provided
|
46
|
+
if (config['default_number_replacement']) {
|
47
|
+
request_url = request_url + "&default_number=" + config['default_number_replacement'];
|
48
|
+
}
|
49
|
+
if (config['message_replacement']) {
|
50
|
+
request_url = request_url + "&message=" + config['message_replacement'];
|
51
|
+
}
|
52
|
+
|
53
|
+
var body = new Object();
|
54
|
+
|
55
|
+
var uri = document.location.href;
|
56
|
+
|
57
|
+
body['u'] = Base64.encode(uri);
|
58
|
+
body['st'] = Base64.encode(tags_to_script_tags(config.number_matching_tags));
|
59
|
+
|
60
|
+
var ou = Cookies.get('CallPixels-ou');
|
61
|
+
if (getParts([document.location.href])['cpreset'] || !ou) {
|
62
|
+
Cookies.set('CallPixels-ou', body['u']);
|
63
|
+
} else {
|
64
|
+
body['ou'] = ou;
|
65
|
+
}
|
66
|
+
|
67
|
+
function sendGARequest(ga_acct, ga_cookies) {
|
68
|
+
body['ga'] = Base64.encode(ga_acct);
|
69
|
+
body['c'] = Base64.encode(JSON.stringify(ga_cookies));
|
70
|
+
Request.connection().getJSON(request_url, body, callback);
|
71
|
+
}
|
72
|
+
|
73
|
+
|
74
|
+
var ga_acct = 'FAILED';
|
75
|
+
|
76
|
+
try {
|
77
|
+
_gaq.push(function () {
|
78
|
+
ga_acct = eval('_gat._getTrackerByName()._getAccount()');
|
79
|
+
|
80
|
+
sendGARequest(ga_acct, getGACookies());
|
81
|
+
});
|
82
|
+
|
83
|
+
} catch (e) {
|
84
|
+
|
85
|
+
try {
|
86
|
+
ga(function (tracker) {
|
87
|
+
var clientId = tracker.get('clientId');
|
88
|
+
var allTrackers = eval('ga.getAll()');
|
89
|
+
ga_acct = allTrackers[0].get('trackingId');
|
90
|
+
|
91
|
+
var ga_cookies = {};
|
92
|
+
ga_cookies['__utma'] = clientId;
|
93
|
+
ga_cookies['mp'] = 'yes';
|
94
|
+
sendGARequest(ga_acct, ga_cookies);
|
95
|
+
});
|
96
|
+
|
97
|
+
} catch (f) {
|
98
|
+
// Post back with failed ga_acct.
|
99
|
+
Request.connection().getJSON(request_url, body, callback);
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
};
|
104
|
+
|
105
|
+
function getParts(urls) {
|
106
|
+
var all_parts = {};
|
107
|
+
for (var i = 0; i < urls.length; i++) {
|
108
|
+
var url_parts = getUrlParts(urls[i]);
|
109
|
+
for (var attrname in url_parts) {
|
110
|
+
all_parts[attrname] = url_parts[attrname];
|
111
|
+
}
|
112
|
+
}
|
113
|
+
return all_parts;
|
114
|
+
}
|
115
|
+
|
116
|
+
function getUrlParts(url) {
|
117
|
+
// url contains your data.
|
118
|
+
var objURL = new Object();
|
119
|
+
try {
|
120
|
+
//REGEX_1: /\?(.*)/
|
121
|
+
url = url.match(eval("/\\?(.*)/"))[0];
|
122
|
+
} catch (e) {
|
123
|
+
return objURL;
|
124
|
+
//Ignored
|
125
|
+
}
|
126
|
+
|
127
|
+
// Use the String::replace method to iterate over each
|
128
|
+
// name-value pair in the query string. Location.search
|
129
|
+
// gives us the query string (if it exists).
|
130
|
+
url.replace(
|
131
|
+
new RegExp("([^?=&]+)(=([^&]*))?", "g"),
|
132
|
+
|
133
|
+
// For each matched query string pair, add that
|
134
|
+
// pair to the URL struct using the pre-equals
|
135
|
+
// value as the key.
|
136
|
+
function ($0, $1, $2, $3) {
|
137
|
+
objURL[ $1.toLowerCase() ] = $3;
|
138
|
+
}
|
139
|
+
);
|
140
|
+
|
141
|
+
return objURL;
|
142
|
+
}
|
143
|
+
|
144
|
+
function getGACookies() {
|
145
|
+
var ga_cookies = ['__utma', '__utmb', '__utmc', '__utmz', '__utmv'];
|
146
|
+
var cookies = new Object();
|
147
|
+
for (var i in ga_cookies) {
|
148
|
+
var cookie_val = extractCookie(ga_cookies[i]);
|
149
|
+
|
150
|
+
if (cookie_val || i > 0) {
|
151
|
+
if (cookie_val) cookies[ga_cookies[i]] = cookie_val;
|
152
|
+
} else {
|
153
|
+
break;
|
154
|
+
}
|
155
|
+
}
|
156
|
+
return cookies;
|
157
|
+
}
|
158
|
+
|
159
|
+
function extractCookie(name) {
|
160
|
+
var regex = new RegExp(name + '=([^;]*)', 'g');
|
161
|
+
try {
|
162
|
+
return regex.exec(document.cookie)[1];
|
163
|
+
} catch (e) {
|
164
|
+
return false;
|
165
|
+
}
|
166
|
+
}
|
167
|
+
|
168
|
+
function findOne(all_parts, var_arr) {
|
169
|
+
for (var look_for in var_arr) {
|
170
|
+
for (var attrname in all_parts) {
|
171
|
+
if (attrname == var_arr[look_for]) {
|
172
|
+
return all_parts[attrname];
|
173
|
+
}
|
174
|
+
}
|
175
|
+
}
|
176
|
+
return false
|
177
|
+
}
|
178
|
+
|
179
|
+
initialize(options);
|
180
|
+
};
|
181
|
+
|
182
|
+
function tags_to_script_tags(tags) {
|
183
|
+
var script_tags = '';
|
184
|
+
for (var key in tags) {
|
185
|
+
var value = tags[key];
|
186
|
+
script_tags = script_tags + '&' + key + '=' + value
|
187
|
+
}
|
188
|
+
return script_tags;
|
189
|
+
}
|
190
|
+
|
191
|
+
Retreaver.Base.RequestNumber = RequestNumber;
|
192
|
+
})();
|
193
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
window.Retreaver.Cache = {};
|
@@ -0,0 +1,108 @@
|
|
1
|
+
(function () {
|
2
|
+
// Dependencies
|
3
|
+
var RequestNumber = Retreaver.Base.RequestNumber;
|
4
|
+
/**
|
5
|
+
* @constructor
|
6
|
+
* @memberOf Retreaver
|
7
|
+
* @param {Object} options
|
8
|
+
* @param {String} options.campaign_key - Campaign key
|
9
|
+
* @example
|
10
|
+
* var campaign = new Retreaver.Campaign({ campaign_key: '67d9fb1917ae8f4eaff36831b41788c3' });
|
11
|
+
*/
|
12
|
+
var Campaign = function (options) {
|
13
|
+
|
14
|
+
function initialize(data) {
|
15
|
+
// initialize data store
|
16
|
+
self.store(data);
|
17
|
+
}
|
18
|
+
|
19
|
+
var self = this;
|
20
|
+
self.type = 'campaigns';
|
21
|
+
self.primary_key('campaign_key');
|
22
|
+
self.numbers = [];
|
23
|
+
|
24
|
+
/**
|
25
|
+
* Fetch a campaign number.
|
26
|
+
* @memberOf Retreaver.Campaign
|
27
|
+
* @function request_number
|
28
|
+
* @instance
|
29
|
+
* @param {Object} tags - A collection of tags as key-value pairs. The number returned will match these tags.
|
30
|
+
* @param {getNumberCallback} callback - Callback fired if the request completes successfully.
|
31
|
+
* @param {Function} error_callback - Callback fired if the request raises an error.
|
32
|
+
* @example
|
33
|
+
* campaign.request_number({calling_about: 'support'}, function (number) {
|
34
|
+
* alert(number.get('number'))
|
35
|
+
* }, function(response){
|
36
|
+
* alert('something went wrong: ' + response);
|
37
|
+
* };
|
38
|
+
*/
|
39
|
+
self.request_number = function (tags, callback, error_callback) {
|
40
|
+
// if the first argument is a function, the user has decided to skip passing tags
|
41
|
+
// therefore cascade the arguments upwards so that everything works as expected
|
42
|
+
if (typeof(tags) === 'function'){
|
43
|
+
// argument 3 becomes argument 2
|
44
|
+
error_callback = callback;
|
45
|
+
// argument 2 becomes argument 1
|
46
|
+
callback = tags;
|
47
|
+
// argument 1 becomes an empty tags object
|
48
|
+
tags = {};
|
49
|
+
}
|
50
|
+
// assign the tags (this is important since it runs it through set_number_matching_tags)
|
51
|
+
self.set('number_matching_tags', tags);
|
52
|
+
// request the number
|
53
|
+
new RequestNumber(self.get('campaign_key', 'number_matching_tags')).perform(function (data) {
|
54
|
+
// did retreaver return a valid number?
|
55
|
+
if (typeof(data) !== 'undefined' && typeof(data.number) !== 'undefined' && data.number !== '') {
|
56
|
+
// initialize number
|
57
|
+
var number = new Retreaver.Number(data.number);
|
58
|
+
// call callback
|
59
|
+
callback.apply(self, [number]);
|
60
|
+
}
|
61
|
+
// otherwise fire the error callback
|
62
|
+
else if (typeof(error_callback) === 'function') {
|
63
|
+
error_callback.apply(self, [data]);
|
64
|
+
}
|
65
|
+
});
|
66
|
+
};
|
67
|
+
/**
|
68
|
+
* Retreaver.Campaign#request_number callback fired after the request completes.
|
69
|
+
* @callback getNumberCallback
|
70
|
+
* @param {Retreaver.Number} - The number that was returned
|
71
|
+
*/
|
72
|
+
|
73
|
+
self.numbers = function () {
|
74
|
+
var output = [];
|
75
|
+
if (typeof(Retreaver.Base.Data._store) !== 'undefined') {
|
76
|
+
// get numbers
|
77
|
+
var numbers = Retreaver.Base.Data._store['numbers'];
|
78
|
+
// present?
|
79
|
+
if (typeof(numbers) !== 'undefined') {
|
80
|
+
// collect numbers matching this campaign
|
81
|
+
for (var primary_key in numbers) {
|
82
|
+
var number = numbers[primary_key];
|
83
|
+
if (self.get('campaign_key') == number.campaign_key) {
|
84
|
+
output.push(new Retreaver.Number(number));
|
85
|
+
}
|
86
|
+
}
|
87
|
+
}
|
88
|
+
}
|
89
|
+
return output;
|
90
|
+
};
|
91
|
+
|
92
|
+
self.set_number_matching_tags = function (tags) {
|
93
|
+
if (typeof(tags) === 'string') {
|
94
|
+
tags = Retreaver.Number.extract_tags_from_string(tags);
|
95
|
+
}
|
96
|
+
if (tags && (typeof tags === "object") && !(tags instanceof Array)) {
|
97
|
+
return tags
|
98
|
+
}
|
99
|
+
else {
|
100
|
+
throw "ArgumentError: Expected number_matching_tags to be an object. eg: {tag: 'value'}";
|
101
|
+
}
|
102
|
+
};
|
103
|
+
|
104
|
+
initialize(options);
|
105
|
+
};
|
106
|
+
Campaign.prototype = new Retreaver.Base.Model();
|
107
|
+
Retreaver.Campaign = Campaign;
|
108
|
+
})();
|