introducing client-side utils :)
Showing
1 changed file
with
91 additions
and
46 deletions
1 | /*! | 1 | /*! |
2 | * Casper is a navigator for PhantomJS - http://github.com/n1k0/casperjs | 2 | * Casper is a navigation utility for PhantomJS - http://github.com/n1k0/casperjs |
3 | * | 3 | * |
4 | * Copyright (c) 2011 Nicolas Perriault | 4 | * Copyright (c) 2011 Nicolas Perriault |
5 | * | 5 | * |
... | @@ -89,41 +89,7 @@ | ... | @@ -89,41 +89,7 @@ |
89 | */ | 89 | */ |
90 | base64encode: function(url) { | 90 | base64encode: function(url) { |
91 | return result = this.evaluate(function() { | 91 | return result = this.evaluate(function() { |
92 | function encode(str) { | 92 | return __utils__.encode(__utils__.getBinary('%url%')); |
93 | var CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | ||
94 | var out = "", i = 0, len = str.length, c1, c2, c3; | ||
95 | while (i < len) { | ||
96 | c1 = str.charCodeAt(i++) & 0xff; | ||
97 | if (i == len) { | ||
98 | out += CHARS.charAt(c1 >> 2); | ||
99 | out += CHARS.charAt((c1 & 0x3) << 4); | ||
100 | out += "=="; | ||
101 | break; | ||
102 | } | ||
103 | c2 = str.charCodeAt(i++); | ||
104 | if (i == len) { | ||
105 | out += CHARS.charAt(c1 >> 2); | ||
106 | out += CHARS.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)); | ||
107 | out += CHARS.charAt((c2 & 0xF) << 2); | ||
108 | out += "="; | ||
109 | break; | ||
110 | } | ||
111 | c3 = str.charCodeAt(i++); | ||
112 | out += CHARS.charAt(c1 >> 2); | ||
113 | out += CHARS.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)); | ||
114 | out += CHARS.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6)); | ||
115 | out += CHARS.charAt(c3 & 0x3F); | ||
116 | } | ||
117 | return out; | ||
118 | } | ||
119 | function getBinary(url) { | ||
120 | var xhr = new XMLHttpRequest(); | ||
121 | xhr.open("GET", url, false); | ||
122 | xhr.overrideMimeType("text/plain; charset=x-user-defined"); | ||
123 | xhr.send(null); | ||
124 | return xhr.responseText; | ||
125 | } | ||
126 | return encode(getBinary('%url%')); | ||
127 | }, { | 93 | }, { |
128 | url: url | 94 | url: url |
129 | }); | 95 | }); |
... | @@ -263,16 +229,7 @@ | ... | @@ -263,16 +229,7 @@ |
263 | * @see WebPage#evaluate | 229 | * @see WebPage#evaluate |
264 | */ | 230 | */ |
265 | evaluate: function(fn, replacements) { | 231 | evaluate: function(fn, replacements) { |
266 | if (replacements && typeof replacements === "object") { | 232 | return this.page.evaluate(replaceFunctionPlaceholders(fn, replacements)); |
267 | fn = fn.toString(); | ||
268 | for (var p in replacements) { | ||
269 | var match = '%' + p + '%'; | ||
270 | do { | ||
271 | fn = fn.replace(match, replacements[p]); | ||
272 | } while(fn.indexOf(match) !== -1); | ||
273 | } | ||
274 | } | ||
275 | return this.page.evaluate(fn); | ||
276 | }, | 233 | }, |
277 | 234 | ||
278 | /** | 235 | /** |
... | @@ -478,6 +435,60 @@ | ... | @@ -478,6 +435,60 @@ |
478 | }; | 435 | }; |
479 | 436 | ||
480 | /** | 437 | /** |
438 | * Casper client-side helpers. | ||
439 | */ | ||
440 | phantom.Casper.ClientUtils = function() { | ||
441 | /** | ||
442 | * Base64 encodes a string, even binary ones. Succeeds where | ||
443 | * window.btoa() fails. | ||
444 | * | ||
445 | * @param string str | ||
446 | * @return string | ||
447 | */ | ||
448 | this.encode = function(str) { | ||
449 | var CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | ||
450 | var out = "", i = 0, len = str.length, c1, c2, c3; | ||
451 | while (i < len) { | ||
452 | c1 = str.charCodeAt(i++) & 0xff; | ||
453 | if (i == len) { | ||
454 | out += CHARS.charAt(c1 >> 2); | ||
455 | out += CHARS.charAt((c1 & 0x3) << 4); | ||
456 | out += "=="; | ||
457 | break; | ||
458 | } | ||
459 | c2 = str.charCodeAt(i++); | ||
460 | if (i == len) { | ||
461 | out += CHARS.charAt(c1 >> 2); | ||
462 | out += CHARS.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)); | ||
463 | out += CHARS.charAt((c2 & 0xF) << 2); | ||
464 | out += "="; | ||
465 | break; | ||
466 | } | ||
467 | c3 = str.charCodeAt(i++); | ||
468 | out += CHARS.charAt(c1 >> 2); | ||
469 | out += CHARS.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)); | ||
470 | out += CHARS.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6)); | ||
471 | out += CHARS.charAt(c3 & 0x3F); | ||
472 | } | ||
473 | return out; | ||
474 | }; | ||
475 | |||
476 | /** | ||
477 | * Retrieves string contents from a binary file behind an url. | ||
478 | * | ||
479 | * @param string url | ||
480 | * @return string | ||
481 | */ | ||
482 | this.getBinary = function(url) { | ||
483 | var xhr = new XMLHttpRequest(); | ||
484 | xhr.open("GET", url, false); | ||
485 | xhr.overrideMimeType("text/plain; charset=x-user-defined"); | ||
486 | xhr.send(null); | ||
487 | return xhr.responseText; | ||
488 | }; | ||
489 | }; | ||
490 | |||
491 | /** | ||
481 | * Creates a new WebPage instance for Casper use. | 492 | * Creates a new WebPage instance for Casper use. |
482 | * | 493 | * |
483 | * @param Casper casper A Casper instance | 494 | * @param Casper casper A Casper instance |
... | @@ -505,6 +516,19 @@ | ... | @@ -505,6 +516,19 @@ |
505 | } | 516 | } |
506 | } | 517 | } |
507 | } | 518 | } |
519 | // Client utils injection | ||
520 | var injected = page.evaluate(replaceFunctionPlaceholders(function() { | ||
521 | eval("var ClientUtils = " + decodeURIComponent("%utils%")); | ||
522 | __utils__ = new ClientUtils(); | ||
523 | return __utils__ instanceof ClientUtils; | ||
524 | }, { | ||
525 | utils: encodeURIComponent(phantom.Casper.ClientUtils.toString()) | ||
526 | })); | ||
527 | if (!injected) { | ||
528 | casper.log('Failed to inject Casper client-side utilities!', "debug"); | ||
529 | } else { | ||
530 | casper.log('Successfully injected Casper client-side utilities', "debug"); | ||
531 | } | ||
508 | casper.loadInProgress = false; | 532 | casper.loadInProgress = false; |
509 | }; | 533 | }; |
510 | page.onResourceReceived = function(resource) { | 534 | page.onResourceReceived = function(resource) { |
... | @@ -536,4 +560,25 @@ | ... | @@ -536,4 +560,25 @@ |
536 | } | 560 | } |
537 | return obj1; | 561 | return obj1; |
538 | } | 562 | } |
563 | |||
564 | /** | ||
565 | * Replaces a function string contents with placeholders provided by an | ||
566 | * Object. | ||
567 | * | ||
568 | * @param function fn The function | ||
569 | * @param object replacements Object containing placeholder replacements | ||
570 | * @return string A function string representation | ||
571 | */ | ||
572 | function replaceFunctionPlaceholders(fn, replacements) { | ||
573 | if (replacements && typeof replacements === "object") { | ||
574 | fn = fn.toString(); | ||
575 | for (var p in replacements) { | ||
576 | var match = '%' + p + '%'; | ||
577 | do { | ||
578 | fn = fn.replace(match, replacements[p]); | ||
579 | } while(fn.indexOf(match) !== -1); | ||
580 | } | ||
581 | } | ||
582 | return fn; | ||
583 | } | ||
539 | })(phantom); | 584 | })(phantom); | ... | ... |
-
Please register or sign in to post a comment