@@ -459,7 +459,9 @@ $(".panel-default .panel-heading").click(function() {
459459 var decodedHeader = window . decode ( parts [ 0 ] ) ;
460460
461461 try {
462+ headerEditor . off ( 'change' , refreshTokenEditor ) ;
462463 selectDetectedAlgorithm ( JSON . parse ( decodedHeader . result ) . alg ) ;
464+ headerEditor . on ( 'change' , refreshTokenEditor ) ;
463465 } catch ( e ) {
464466 console . error ( 'Invalid header decoded' ) ;
465467 }
@@ -776,16 +778,14 @@ $(".panel-default .panel-heading").click(function() {
776778
777779 var qs ;
778780 var d ;
779- if ( document . location . search ) {
780- qs = document . location . search . slice ( 1 ) ;
781- d = { } ;
782- qs = qs . split ( '&' ) ;
783- qs . forEach ( function ( kv ) { kv = kv . split ( '=' ) ; d [ kv [ 0 ] ] = kv [ 1 ] ; } ) ;
784- if ( d . value ) {
785- tokenEditor . setValue ( decodeURIComponent ( d . value ) ) ;
786- return ;
787- }
788- }
781+
782+ loadFromStorage ( function ( jwt ) {
783+ lastRestoredToken = jwt || defaultTokens . hs256 . token ;
784+
785+ tokenEditor . setValue (
786+ lastRestoredToken
787+ ) ;
788+ } ) ;
789789
790790 if ( document . location . hash ) {
791791 qs = document . location . hash . slice ( 1 ) ;
@@ -800,25 +800,107 @@ $(".panel-default .panel-heading").click(function() {
800800
801801 if ( d . id_token ) {
802802 tokenEditor . setValue ( decodeURIComponent ( d . id_token ) ) ;
803- return ;
804803 }
805804
806805 if ( d . access_token ) {
807806 tokenEditor . setValue ( decodeURIComponent ( d . access_token ) ) ;
808- return ;
809807 }
810808 }
811809
812- loadFromStorage ( function ( jwt ) {
813- lastRestoredToken = jwt || defaultTokens . hs256 . token ;
810+ if ( document . location . search ) {
811+ qs = document . location . search . slice ( 1 ) ;
812+ d = { } ;
813+ qs = qs . split ( '&' ) ;
814+ qs . forEach ( function ( kv ) {
815+ kv = kv . split ( '=' ) ;
816+ d [ kv [ 0 ] ] = kv [ 1 ] ;
817+ } ) ;
818+ if ( d . publicKey ) {
819+ var publicKey = $ ( '.jwt-signature textarea[name="public-key"]' ) ;
820+ publicKey . val ( decodeURIComponent ( d . publicKey ) ) ;
821+ validateKey . apply ( publicKey ) ;
822+ }
823+ if ( d . value ) {
824+ tokenEditor . setValue ( decodeURIComponent ( d . value ) ) ;
825+ }
826+ if ( d . token ) {
827+ tokenEditor . setValue ( decodeURIComponent ( d . token ) ) ;
828+ }
814829
815- tokenEditor . setValue (
816- lastRestoredToken
817- ) ;
818- } ) ;
830+
831+ }
832+
833+ function copyTokenLink ( ) {
834+ var algorithm = $ ( 'input[name="algorithm"]' ) . filter ( ':checked' ) . val ( ) ;
835+
836+ var url = 'https://jwt.io/#debugger-io?' ;
837+ url += 'token=' + encodeURIComponent ( getTrimmedValue ( tokenEditor ) ) ;
838+ if ( algorithm . indexOf ( 'HS' ) === - 1 ) {
839+ var publicKey = $ ( '.jwt-signature textarea[name="public-key"]' ) ;
840+ url += '&publicKey=' + encodeURIComponent ( publicKey . val ( ) ) ;
841+ }
842+
843+ copyTextToClipboard ( url ) ;
844+ }
845+
846+ $ ( '.validation-status.js-signature' ) . on ( 'click' , copyTokenLink ) ;
819847
820848} ( ) ) ;
821849
850+ // https://stackoverflow.com/questions/400212/how-do-i-copy-to-the-clipboard-in-javascript
851+ function copyTextToClipboard ( text ) {
852+ var textArea = document . createElement ( "textarea" ) ;
853+
854+ //
855+ // *** This styling is an extra step which is likely not required. ***
856+ //
857+ // Why is it here? To ensure:
858+ // 1. the element is able to have focus and selection.
859+ // 2. if element was to flash render it has minimal visual impact.
860+ // 3. less flakyness with selection and copying which **might** occur if
861+ // the textarea element is not visible.
862+ //
863+ // The likelihood is the element won't even render, not even a flash,
864+ // so some of these are just precautions. However in IE the element
865+ // is visible whilst the popup box asking the user for permission for
866+ // the web page to copy to the clipboard.
867+ //
868+
869+ // Place in top-left corner of screen regardless of scroll position.
870+ textArea . style . position = 'fixed' ;
871+ textArea . style . top = 0 ;
872+ textArea . style . left = 0 ;
873+
874+ // Ensure it has a small width and height. Setting to 1px / 1em
875+ // doesn't work as this gives a negative w/h on some browsers.
876+ textArea . style . width = '2em' ;
877+ textArea . style . height = '2em' ;
878+
879+ // We don't need padding, reducing the size if it does flash render.
880+ textArea . style . padding = 0 ;
881+
882+ // Clean up any borders.
883+ textArea . style . border = 'none' ;
884+ textArea . style . outline = 'none' ;
885+ textArea . style . boxShadow = 'none' ;
886+
887+ // Avoid flash of white box if rendered for any reason.
888+ textArea . style . background = 'transparent' ;
889+
890+ textArea . value = text ;
891+
892+ document . body . appendChild ( textArea ) ;
893+
894+ textArea . select ( ) ;
895+
896+ try {
897+ document . execCommand ( 'copy' ) ;
898+ } catch ( err ) {
899+ console . error ( err ) ;
900+ }
901+
902+ document . body . removeChild ( textArea ) ;
903+ }
822904
823905//TIMESTAMP
824906( function ( ) {
@@ -840,7 +922,10 @@ $(".debugger-jwt .algorithm select").change(function() {
840922} ) ;
841923
842924
843- $ ( ".debugger-jwt .algorithm select" ) . change ( function ( ) { var a = $ ( '.debugger-jwt .algorithm input[value="' + $ ( this ) . val ( ) + '"]' ) ; a . prop ( "checked" , ! 0 ) ; } ) ;
925+ $ ( ".debugger-jwt .algorithm select" ) . change ( function ( ) {
926+ var a = $ ( '.debugger-jwt .algorithm input[value="' + $ ( this ) . val ( ) + '"]' ) ;
927+ a . prop ( "checked" , ! 0 ) ;
928+ } ) ;
844929// end 07012015
845930
846931$ ( ".debugger-jwt .token-type select" ) . change ( function ( ) {
0 commit comments