Commit 8877515f 8877515fa5311ae80adfba79d0bf7bcfb7d527a0 by Nicolas Perriault

introducing client-side utils :)

1 parent bbd5410c
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);
......