@@ -35,17 +35,26 @@ var VOID_ELEMENTS = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',
35
35
aria . widget . SourceCode = function ( ) {
36
36
this . location = new Array ( ) ;
37
37
this . code = new Array ( ) ;
38
+ this . exampleHeader = new Array ( ) ;
39
+ this . resources = new Array ( ) ;
38
40
} ;
39
41
40
42
/**
41
43
* Adds source code
42
44
*
45
+ * @param {string } locationId - ID of `code` element that will display the example html
46
+ * @param {string } codeID - ID of element containing only and all of the html used to render the example widget
47
+ * @param {string } exampleHeaderId - ID of header element under which the "Open in Codepen" button belongs
48
+ * @param {string } cssJsFilesId - ID of element containing links to all the relevent js and css files used for the example widget
49
+ *
43
50
* @method add
44
51
* @memberof aria.widget.SourceCode
45
52
*/
46
- aria . widget . SourceCode . prototype . add = function ( locationId , codeId ) {
53
+ aria . widget . SourceCode . prototype . add = function ( locationId , codeId , exampleHeaderId , cssJsFilesId ) {
47
54
this . location [ this . location . length ] = locationId ;
48
55
this . code [ this . code . length ] = codeId ;
56
+ this . exampleHeader [ this . exampleHeader . length ] = exampleHeaderId ;
57
+ this . resources [ this . resources . length ] = cssJsFilesId ;
49
58
} ;
50
59
51
60
/**
@@ -66,6 +75,11 @@ aria.widget.SourceCode.prototype.make = function () {
66
75
if ( sourceCodeNode . innerHTML . startsWith ( '<br>' ) ) {
67
76
sourceCodeNode . innerHTML = sourceCodeNode . innerHTML . replace ( '<br>' , '' ) ;
68
77
}
78
+
79
+ // Adds the "Open In CodePen" button by the example header
80
+ if ( this . exampleHeader [ i ] ) {
81
+ addOpenInCodePenForm ( i , this . exampleHeader [ i ] , this . code [ i ] , this . resources [ i ] ) ;
82
+ }
69
83
}
70
84
} ;
71
85
@@ -300,4 +314,96 @@ function indentLines (input, indentation) {
300
314
return lines . join ( '\n' ) ;
301
315
}
302
316
317
+ /**
318
+ * Creates and adds an "Open in CodePen" button
319
+ *
320
+ * @param {String } exampleIndex - the example number, if there are multiple examples
321
+ * @param {String } exampleHeaderId - the example header to place the button next to
322
+ * @param {String } exampleCodeId - the example html code
323
+ * @param {String } exampleFilesId - the element containing all relevent CSS and JS file
324
+ */
325
+ function addOpenInCodePenForm ( exampleIndex , exampleHeaderId , exampleCodeId , exampleFilesId ) {
326
+ var jsonInputId = 'codepen-data-ex-' + exampleIndex ;
327
+ var buttonId = exampleCodeId + '-codepenbutton'
328
+
329
+ var form = document . createElement ( 'form' ) ;
330
+ form . setAttribute ( 'action' , 'https://codepen.io/pen/define' ) ;
331
+ form . setAttribute ( 'method' , 'POST' ) ;
332
+ form . setAttribute ( 'target' , '_blank' ) ;
333
+
334
+ var input = document . createElement ( 'input' ) ;
335
+ input . setAttribute ( 'id' , jsonInputId ) ;
336
+ input . setAttribute ( 'type' , 'hidden' ) ;
337
+ input . setAttribute ( 'name' , 'data' ) ;
338
+
339
+ var button = document . createElement ( 'button' ) ;
340
+ button . innerText = 'Open In CodePen' ;
341
+
342
+ form . appendChild ( input ) ;
343
+ form . appendChild ( button ) ;
344
+
345
+ var exampleHeader = document . getElementById ( exampleHeaderId ) ;
346
+ exampleHeader . parentNode . insertBefore ( form , exampleHeader . nextSibling ) ;
347
+
348
+ // Correct the indentation for the example html
349
+ var indentedExampleHtml = document . getElementById ( exampleCodeId ) . innerHTML ;
350
+ indentedExampleHtml = indentedExampleHtml . replace ( / ^ \n + / , '' ) ;
351
+ var indentation = indentedExampleHtml . match ( / ^ \s + / ) [ 0 ] ;
352
+ var exampleHtml = indentedExampleHtml . replace ( new RegExp ( '^' + indentation , 'gm' ) , '' ) ;
353
+
354
+ var postJson = {
355
+ html : exampleHtml ,
356
+ css : '' ,
357
+ js : '' ,
358
+ head : '<base href="' + location . href + '">'
359
+ } ;
360
+
361
+ var totalFetchedFiles = 0 ;
362
+ var fileLinks = document . querySelectorAll ( '#' + exampleFilesId + ' a' ) ;
363
+
364
+ for ( let fileLink of fileLinks ) {
365
+
366
+ var request = new XMLHttpRequest ( ) ;
367
+
368
+ request . open ( 'GET' , fileLink . href , true ) ;
369
+ request . onload = function ( ) {
370
+ var href = this . responseURL ;
371
+ if ( this . status >= 200 && this . status < 400 ) {
372
+ if ( href . indexOf ( 'css' ) !== - 1 ) {
373
+ postJson . css = postJson . css . concat ( this . response ) ;
374
+ }
375
+ if ( href . indexOf ( 'js' ) !== - 1 ) {
376
+ postJson . js = postJson . js . concat ( this . response ) ;
377
+ }
378
+ totalFetchedFiles ++ ;
379
+ }
380
+ else {
381
+ hideButton ( buttonId , "Could not load resource: " + href ) ;
382
+ }
383
+ } ;
384
+ request . onerror = function ( ) {
385
+ hideButton ( buttonId , "Could not load resource: " + fileLink . href ) ;
386
+ } ;
387
+ request . send ( ) ;
388
+ }
389
+
390
+ var timerId = setInterval ( ( ) => {
391
+ console . log ( totalFetchedFiles ) ;
392
+ if ( totalFetchedFiles === fileLinks . length ) {
393
+ document . getElementById ( jsonInputId ) . value = JSON . stringify ( postJson ) ;
394
+ clearInterval ( timerId ) ;
395
+ }
396
+ } , 500 ) ;
397
+
398
+ setTimeout ( ( ) => {
399
+ clearInterval ( timerId ) ;
400
+ } , 10000 ) ;
401
+ }
402
+
403
+ function hideButton ( buttonId , errorMsg ) {
404
+ let button = document . querySelector ( buttonId ) ;
405
+ button . style . display = "none" ;
406
+ console . log ( "Removing 'Open in Codepen button'. " + errorMsg ) ;
407
+ }
408
+
303
409
var sourceCode = new aria . widget . SourceCode ( ) ;
0 commit comments