undead 0.1.1 → 0.2.0

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.
@@ -0,0 +1,589 @@
1
+ var slice = [].slice,
2
+ indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
3
+ hasProp = {}.hasOwnProperty;
4
+
5
+ Poltergeist.WebPage = (function() {
6
+ var command, delegate, fn1, fn2, i, j, len, len1, ref, ref1;
7
+
8
+ WebPage.CALLBACKS = ['onConsoleMessage', 'onError', 'onLoadFinished', 'onInitialized', 'onLoadStarted', 'onResourceRequested', 'onResourceReceived', 'onResourceError', 'onNavigationRequested', 'onUrlChanged', 'onPageCreated', 'onClosing'];
9
+
10
+ WebPage.DELEGATES = ['open', 'sendEvent', 'uploadFile', 'release', 'render', 'renderBase64', 'goBack', 'goForward'];
11
+
12
+ WebPage.COMMANDS = ['currentUrl', 'find', 'nodeCall', 'documentSize', 'beforeUpload', 'afterUpload', 'clearLocalStorage'];
13
+
14
+ WebPage.EXTENSIONS = [];
15
+
16
+ function WebPage(_native) {
17
+ var callback, i, len, ref;
18
+ this._native = _native;
19
+ this._native || (this._native = require('webpage').create());
20
+ this.id = 0;
21
+ this.source = null;
22
+ this.closed = false;
23
+ this.state = 'default';
24
+ this.urlWhitelist = [];
25
+ this.urlBlacklist = [];
26
+ this.frames = [];
27
+ this.errors = [];
28
+ this._networkTraffic = {};
29
+ this._tempHeaders = {};
30
+ this._blockedUrls = [];
31
+ this._requestedResources = {};
32
+ ref = WebPage.CALLBACKS;
33
+ for (i = 0, len = ref.length; i < len; i++) {
34
+ callback = ref[i];
35
+ this.bindCallback(callback);
36
+ }
37
+ }
38
+
39
+ ref = WebPage.COMMANDS;
40
+ fn1 = function(command) {
41
+ return WebPage.prototype[command] = function() {
42
+ var args;
43
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
44
+ return this.runCommand(command, args);
45
+ };
46
+ };
47
+ for (i = 0, len = ref.length; i < len; i++) {
48
+ command = ref[i];
49
+ fn1(command);
50
+ }
51
+
52
+ ref1 = WebPage.DELEGATES;
53
+ fn2 = function(delegate) {
54
+ return WebPage.prototype[delegate] = function() {
55
+ return this._native[delegate].apply(this._native, arguments);
56
+ };
57
+ };
58
+ for (j = 0, len1 = ref1.length; j < len1; j++) {
59
+ delegate = ref1[j];
60
+ fn2(delegate);
61
+ }
62
+
63
+ WebPage.prototype.onInitializedNative = function() {
64
+ this.id += 1;
65
+ this.source = null;
66
+ this.injectAgent();
67
+ this.removeTempHeaders();
68
+ return this.setScrollPosition({
69
+ left: 0,
70
+ top: 0
71
+ });
72
+ };
73
+
74
+ WebPage.prototype.onClosingNative = function() {
75
+ this.handle = null;
76
+ return this.closed = true;
77
+ };
78
+
79
+ WebPage.prototype.onConsoleMessageNative = function(message) {
80
+ if (message === '__DOMContentLoaded') {
81
+ this.source = this._native.content;
82
+ return false;
83
+ } else {
84
+ return console.log(message);
85
+ }
86
+ };
87
+
88
+ WebPage.prototype.onLoadStartedNative = function() {
89
+ this.state = 'loading';
90
+ this.requestId = this.lastRequestId;
91
+ return this._requestedResources = {};
92
+ };
93
+
94
+ WebPage.prototype.onLoadFinishedNative = function(status) {
95
+ this.status = status;
96
+ this.state = 'default';
97
+ return this.source || (this.source = this._native.content);
98
+ };
99
+
100
+ WebPage.prototype.onErrorNative = function(message, stack) {
101
+ var stackString;
102
+ stackString = message;
103
+ stack.forEach(function(frame) {
104
+ stackString += "\n";
105
+ stackString += " at " + frame.file + ":" + frame.line;
106
+ if (frame["function"] && frame["function"] !== '') {
107
+ return stackString += " in " + frame["function"];
108
+ }
109
+ });
110
+ this.errors.push({
111
+ message: message,
112
+ stack: stackString
113
+ });
114
+ return true;
115
+ };
116
+
117
+ WebPage.prototype.onResourceRequestedNative = function(request, net) {
118
+ var abort, blacklisted, ref2, useWhitelist, whitelisted;
119
+ useWhitelist = this.urlWhitelist.length > 0;
120
+ whitelisted = this.urlWhitelist.some(function(whitelisted_url) {
121
+ return request.url.indexOf(whitelisted_url) !== -1;
122
+ });
123
+ blacklisted = this.urlBlacklist.some(function(blacklisted_url) {
124
+ return request.url.indexOf(blacklisted_url) !== -1;
125
+ });
126
+ abort = false;
127
+ if (useWhitelist && !whitelisted) {
128
+ abort = true;
129
+ }
130
+ if (blacklisted) {
131
+ abort = true;
132
+ }
133
+ if (abort) {
134
+ if (ref2 = request.url, indexOf.call(this._blockedUrls, ref2) < 0) {
135
+ this._blockedUrls.push(request.url);
136
+ }
137
+ net.abort();
138
+ } else {
139
+ this.lastRequestId = request.id;
140
+ if (this.normalizeURL(request.url) === this.redirectURL) {
141
+ this.redirectURL = null;
142
+ this.requestId = request.id;
143
+ }
144
+ this._networkTraffic[request.id] = {
145
+ request: request,
146
+ responseParts: [],
147
+ error: null
148
+ };
149
+ this._requestedResources[request.id] = request.url;
150
+ }
151
+ return true;
152
+ };
153
+
154
+ WebPage.prototype.onResourceReceivedNative = function(response) {
155
+ var ref2;
156
+ if ((ref2 = this._networkTraffic[response.id]) != null) {
157
+ ref2.responseParts.push(response);
158
+ }
159
+ if (response.stage === 'end') {
160
+ delete this._requestedResources[response.id];
161
+ }
162
+ if (this.requestId === response.id) {
163
+ if (response.redirectURL) {
164
+ this.redirectURL = this.normalizeURL(response.redirectURL);
165
+ } else {
166
+ this.statusCode = response.status;
167
+ this._responseHeaders = response.headers;
168
+ }
169
+ }
170
+ return true;
171
+ };
172
+
173
+ WebPage.prototype.onResourceErrorNative = function(errorResponse) {
174
+ var ref2;
175
+ if ((ref2 = this._networkTraffic[errorResponse.id]) != null) {
176
+ ref2.error = errorResponse;
177
+ }
178
+ delete this._requestedResources[errorResponse.id];
179
+ return true;
180
+ };
181
+
182
+ WebPage.prototype.injectAgent = function() {
183
+ var extension, k, len2, ref2;
184
+ if (this["native"]().evaluate(function() {
185
+ return typeof __poltergeist;
186
+ }) === "undefined") {
187
+ this["native"]().injectJs(phantom.libraryPath + "/agent.js");
188
+ ref2 = WebPage.EXTENSIONS;
189
+ for (k = 0, len2 = ref2.length; k < len2; k++) {
190
+ extension = ref2[k];
191
+ this["native"]().injectJs(extension);
192
+ }
193
+ return true;
194
+ }
195
+ return false;
196
+ };
197
+
198
+ WebPage.prototype.injectExtension = function(file) {
199
+ WebPage.EXTENSIONS.push(file);
200
+ return this["native"]().injectJs(file);
201
+ };
202
+
203
+ WebPage.prototype["native"] = function() {
204
+ if (this.closed) {
205
+ throw new Poltergeist.NoSuchWindowError;
206
+ } else {
207
+ return this._native;
208
+ }
209
+ };
210
+
211
+ WebPage.prototype.windowName = function() {
212
+ return this["native"]().windowName;
213
+ };
214
+
215
+ WebPage.prototype.keyCode = function(name) {
216
+ return this["native"]().event.key[name];
217
+ };
218
+
219
+ WebPage.prototype.keyModifierCode = function(names) {
220
+ var modifiers;
221
+ modifiers = this["native"]().event.modifier;
222
+ names = names.split(',').map((function(name) {
223
+ return modifiers[name];
224
+ }));
225
+ return names[0] | names[1];
226
+ };
227
+
228
+ WebPage.prototype.keyModifierKeys = function(names) {
229
+ return names.split(',').map((function(_this) {
230
+ return function(name) {
231
+ return _this.keyCode(name.charAt(0).toUpperCase() + name.substring(1));
232
+ };
233
+ })(this));
234
+ };
235
+
236
+ WebPage.prototype._waitState_until = function(state, callback, timeout, timeout_callback) {
237
+ var d;
238
+ if (this.state === state) {
239
+ return callback.call();
240
+ } else {
241
+ d = new Date();
242
+ if (d.getTime() > timeout) {
243
+ return timeout_callback.call();
244
+ } else {
245
+ return setTimeout(((function(_this) {
246
+ return function() {
247
+ return _this._waitState_until(state, callback, timeout, timeout_callback);
248
+ };
249
+ })(this)), 100);
250
+ }
251
+ }
252
+ };
253
+
254
+ WebPage.prototype.waitState = function(state, callback, max_wait, timeout_callback) {
255
+ var timeout;
256
+ if (max_wait == null) {
257
+ max_wait = 0;
258
+ }
259
+ if (this.state === state) {
260
+ return callback.call();
261
+ } else {
262
+ if (max_wait !== 0) {
263
+ timeout = (new Date).getTime() + (max_wait * 1000);
264
+ return setTimeout(((function(_this) {
265
+ return function() {
266
+ return _this._waitState_until(state, callback, timeout, timeout_callback);
267
+ };
268
+ })(this)), 100);
269
+ } else {
270
+ return setTimeout(((function(_this) {
271
+ return function() {
272
+ return _this.waitState(state, callback);
273
+ };
274
+ })(this)), 100);
275
+ }
276
+ }
277
+ };
278
+
279
+ WebPage.prototype.setHttpAuth = function(user, password) {
280
+ this["native"]().settings.userName = user;
281
+ this["native"]().settings.password = password;
282
+ return true;
283
+ };
284
+
285
+ WebPage.prototype.networkTraffic = function() {
286
+ return this._networkTraffic;
287
+ };
288
+
289
+ WebPage.prototype.clearNetworkTraffic = function() {
290
+ this._networkTraffic = {};
291
+ return true;
292
+ };
293
+
294
+ WebPage.prototype.blockedUrls = function() {
295
+ return this._blockedUrls;
296
+ };
297
+
298
+ WebPage.prototype.clearBlockedUrls = function() {
299
+ this._blockedUrls = [];
300
+ return true;
301
+ };
302
+
303
+ WebPage.prototype.openResourceRequests = function() {
304
+ var id, ref2, results, url;
305
+ ref2 = this._requestedResources;
306
+ results = [];
307
+ for (id in ref2) {
308
+ if (!hasProp.call(ref2, id)) continue;
309
+ url = ref2[id];
310
+ results.push(url);
311
+ }
312
+ return results;
313
+ };
314
+
315
+ WebPage.prototype.content = function() {
316
+ return this["native"]().frameContent;
317
+ };
318
+
319
+ WebPage.prototype.title = function() {
320
+ return this["native"]().frameTitle;
321
+ };
322
+
323
+ WebPage.prototype.frameUrl = function(frameNameOrId) {
324
+ var query;
325
+ query = function(frameNameOrId) {
326
+ var ref2;
327
+ return (ref2 = document.querySelector("iframe[name='" + frameNameOrId + "'], iframe[id='" + frameNameOrId + "']")) != null ? ref2.src : void 0;
328
+ };
329
+ return this.evaluate(query, frameNameOrId);
330
+ };
331
+
332
+ WebPage.prototype.clearErrors = function() {
333
+ this.errors = [];
334
+ return true;
335
+ };
336
+
337
+ WebPage.prototype.responseHeaders = function() {
338
+ var headers;
339
+ headers = {};
340
+ this._responseHeaders.forEach(function(item) {
341
+ return headers[item.name] = item.value;
342
+ });
343
+ return headers;
344
+ };
345
+
346
+ WebPage.prototype.cookies = function() {
347
+ return this["native"]().cookies;
348
+ };
349
+
350
+ WebPage.prototype.deleteCookie = function(name) {
351
+ return this["native"]().deleteCookie(name);
352
+ };
353
+
354
+ WebPage.prototype.viewportSize = function() {
355
+ return this["native"]().viewportSize;
356
+ };
357
+
358
+ WebPage.prototype.setViewportSize = function(size) {
359
+ return this["native"]().viewportSize = size;
360
+ };
361
+
362
+ WebPage.prototype.setZoomFactor = function(zoom_factor) {
363
+ return this["native"]().zoomFactor = zoom_factor;
364
+ };
365
+
366
+ WebPage.prototype.setPaperSize = function(size) {
367
+ return this["native"]().paperSize = size;
368
+ };
369
+
370
+ WebPage.prototype.scrollPosition = function() {
371
+ return this["native"]().scrollPosition;
372
+ };
373
+
374
+ WebPage.prototype.setScrollPosition = function(pos) {
375
+ return this["native"]().scrollPosition = pos;
376
+ };
377
+
378
+ WebPage.prototype.clipRect = function() {
379
+ return this["native"]().clipRect;
380
+ };
381
+
382
+ WebPage.prototype.setClipRect = function(rect) {
383
+ return this["native"]().clipRect = rect;
384
+ };
385
+
386
+ WebPage.prototype.elementBounds = function(selector) {
387
+ return this["native"]().evaluate(function(selector) {
388
+ return document.querySelector(selector).getBoundingClientRect();
389
+ }, selector);
390
+ };
391
+
392
+ WebPage.prototype.setUserAgent = function(userAgent) {
393
+ return this["native"]().settings.userAgent = userAgent;
394
+ };
395
+
396
+ WebPage.prototype.getCustomHeaders = function() {
397
+ return this["native"]().customHeaders;
398
+ };
399
+
400
+ WebPage.prototype.setCustomHeaders = function(headers) {
401
+ return this["native"]().customHeaders = headers;
402
+ };
403
+
404
+ WebPage.prototype.addTempHeader = function(header) {
405
+ var name, value;
406
+ for (name in header) {
407
+ value = header[name];
408
+ this._tempHeaders[name] = value;
409
+ }
410
+ return this._tempHeaders;
411
+ };
412
+
413
+ WebPage.prototype.removeTempHeaders = function() {
414
+ var allHeaders, name, ref2, value;
415
+ allHeaders = this.getCustomHeaders();
416
+ ref2 = this._tempHeaders;
417
+ for (name in ref2) {
418
+ value = ref2[name];
419
+ delete allHeaders[name];
420
+ }
421
+ return this.setCustomHeaders(allHeaders);
422
+ };
423
+
424
+ WebPage.prototype.pushFrame = function(name) {
425
+ var frame_no;
426
+ if (this["native"]().switchToFrame(name)) {
427
+ this.frames.push(name);
428
+ return true;
429
+ } else {
430
+ frame_no = this["native"]().evaluate(function(frame_name) {
431
+ var f, frames, idx;
432
+ frames = document.querySelectorAll("iframe, frame");
433
+ return ((function() {
434
+ var k, len2, results;
435
+ results = [];
436
+ for (idx = k = 0, len2 = frames.length; k < len2; idx = ++k) {
437
+ f = frames[idx];
438
+ if ((f != null ? f['name'] : void 0) === frame_name || (f != null ? f['id'] : void 0) === frame_name) {
439
+ results.push(idx);
440
+ }
441
+ }
442
+ return results;
443
+ })())[0];
444
+ }, name);
445
+ if ((frame_no != null) && this["native"]().switchToFrame(frame_no)) {
446
+ this.frames.push(name);
447
+ return true;
448
+ } else {
449
+ return false;
450
+ }
451
+ }
452
+ };
453
+
454
+ WebPage.prototype.popFrame = function() {
455
+ this.frames.pop();
456
+ return this["native"]().switchToParentFrame();
457
+ };
458
+
459
+ WebPage.prototype.dimensions = function() {
460
+ var scroll, viewport;
461
+ scroll = this.scrollPosition();
462
+ viewport = this.viewportSize();
463
+ return {
464
+ top: scroll.top,
465
+ bottom: scroll.top + viewport.height,
466
+ left: scroll.left,
467
+ right: scroll.left + viewport.width,
468
+ viewport: viewport,
469
+ document: this.documentSize()
470
+ };
471
+ };
472
+
473
+ WebPage.prototype.validatedDimensions = function() {
474
+ var dimensions, document;
475
+ dimensions = this.dimensions();
476
+ document = dimensions.document;
477
+ if (dimensions.right > document.width) {
478
+ dimensions.left = Math.max(0, dimensions.left - (dimensions.right - document.width));
479
+ dimensions.right = document.width;
480
+ }
481
+ if (dimensions.bottom > document.height) {
482
+ dimensions.top = Math.max(0, dimensions.top - (dimensions.bottom - document.height));
483
+ dimensions.bottom = document.height;
484
+ }
485
+ this.setScrollPosition({
486
+ left: dimensions.left,
487
+ top: dimensions.top
488
+ });
489
+ return dimensions;
490
+ };
491
+
492
+ WebPage.prototype.get = function(id) {
493
+ return new Poltergeist.Node(this, id);
494
+ };
495
+
496
+ WebPage.prototype.mouseEvent = function(name, x, y, button) {
497
+ if (button == null) {
498
+ button = 'left';
499
+ }
500
+ this.sendEvent('mousemove', x, y);
501
+ return this.sendEvent(name, x, y, button);
502
+ };
503
+
504
+ WebPage.prototype.evaluate = function() {
505
+ var args, fn;
506
+ fn = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
507
+ this.injectAgent();
508
+ return JSON.parse(this.sanitize(this["native"]().evaluate("function() { return PoltergeistAgent.stringify(" + (this.stringifyCall(fn, args)) + ") }")));
509
+ };
510
+
511
+ WebPage.prototype.sanitize = function(potential_string) {
512
+ if (typeof potential_string === "string") {
513
+ return potential_string.replace("\n", "\\n").replace("\r", "\\r");
514
+ } else {
515
+ return potential_string;
516
+ }
517
+ };
518
+
519
+ WebPage.prototype.execute = function() {
520
+ var args, fn;
521
+ fn = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
522
+ return this["native"]().evaluate("function() { " + (this.stringifyCall(fn, args)) + " }");
523
+ };
524
+
525
+ WebPage.prototype.stringifyCall = function(fn, args) {
526
+ if (args.length === 0) {
527
+ return "(" + (fn.toString()) + ")()";
528
+ } else {
529
+ return "(" + (fn.toString()) + ").apply(this, PoltergeistAgent.JSON.parse(" + (JSON.stringify(JSON.stringify(args))) + "))";
530
+ }
531
+ };
532
+
533
+ WebPage.prototype.bindCallback = function(name) {
534
+ var that;
535
+ that = this;
536
+ this["native"]()[name] = function() {
537
+ var result;
538
+ if (that[name + 'Native'] != null) {
539
+ result = that[name + 'Native'].apply(that, arguments);
540
+ }
541
+ if (result !== false && (that[name] != null)) {
542
+ return that[name].apply(that, arguments);
543
+ }
544
+ };
545
+ return true;
546
+ };
547
+
548
+ WebPage.prototype.runCommand = function(name, args) {
549
+ var method, result, selector;
550
+ result = this.evaluate(function(name, args) {
551
+ return __poltergeist.externalCall(name, args);
552
+ }, name, args);
553
+ if (result !== null) {
554
+ if (result.error != null) {
555
+ switch (result.error.message) {
556
+ case 'PoltergeistAgent.ObsoleteNode':
557
+ throw new Poltergeist.ObsoleteNode;
558
+ break;
559
+ case 'PoltergeistAgent.InvalidSelector':
560
+ method = args[0], selector = args[1];
561
+ throw new Poltergeist.InvalidSelector(method, selector);
562
+ break;
563
+ default:
564
+ throw new Poltergeist.BrowserError(result.error.message, result.error.stack);
565
+ }
566
+ } else {
567
+ return result.value;
568
+ }
569
+ }
570
+ };
571
+
572
+ WebPage.prototype.canGoBack = function() {
573
+ return this["native"]().canGoBack;
574
+ };
575
+
576
+ WebPage.prototype.canGoForward = function() {
577
+ return this["native"]().canGoForward;
578
+ };
579
+
580
+ WebPage.prototype.normalizeURL = function(url) {
581
+ var parser;
582
+ parser = document.createElement('a');
583
+ parser.href = url;
584
+ return parser.href;
585
+ };
586
+
587
+ return WebPage;
588
+
589
+ })();