editor-view.js 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /* global grunionEditorView, tinyMCE, QTags, wp */
  2. ( function( $, wp, grunionEditorView ) {
  3. wp.mce = wp.mce || {};
  4. if ( 'undefined' === typeof wp.mce.views ) {
  5. return;
  6. }
  7. wp.mce.grunion_wp_view_renderer = {
  8. shortcode_string : 'contact-form',
  9. template : wp.template( 'grunion-contact-form' ),
  10. field_templates: {
  11. email : wp.template( 'grunion-field-email' ),
  12. telephone : wp.template( 'grunion-field-telephone' ),
  13. textarea : wp.template( 'grunion-field-textarea' ),
  14. radio : wp.template( 'grunion-field-radio' ),
  15. checkbox : wp.template( 'grunion-field-checkbox' ),
  16. 'checkbox-multiple' : wp.template( 'grunion-field-checkbox-multiple' ),
  17. select : wp.template( 'grunion-field-select' ),
  18. date : wp.template( 'grunion-field-date' ),
  19. text : wp.template( 'grunion-field-text' ),
  20. name : wp.template( 'grunion-field-text' ),
  21. url : wp.template( 'grunion-field-url' )
  22. },
  23. edit_template : wp.template( 'grunion-field-edit' ),
  24. editor_inline : wp.template( 'grunion-editor-inline' ),
  25. editor_option : wp.template( 'grunion-field-edit-option' ),
  26. getContent : function() {
  27. var content = this.shortcode.content,
  28. index = 0,
  29. field, named,
  30. body = '';
  31. // If it's the legacy `[contact-form /]` syntax, populate default fields.
  32. if ( ! content ) {
  33. content = grunionEditorView.default_form;
  34. }
  35. // Render the fields.
  36. while ( ( field = wp.shortcode.next( 'contact-field', content, index ) ) ) {
  37. index = field.index + field.content.length;
  38. named = field.shortcode.attrs.named;
  39. if ( ! named.type || ! this.field_templates[ named.type ] ) {
  40. named.type = 'text';
  41. }
  42. if ( named.required ) {
  43. named.required = grunionEditorView.labels.required_field_text;
  44. }
  45. if ( named.options && 'string' === typeof named.options ) {
  46. named.options = named.options.split( ',' );
  47. }
  48. body += this.field_templates[ named.type ]( named );
  49. }
  50. var options = {
  51. body : body,
  52. submit_button_text : grunionEditorView.labels.submit_button_text
  53. };
  54. return this.template( options );
  55. },
  56. edit: function( data, update_callback ) {
  57. var shortcode_data = wp.shortcode.next( this.shortcode_string, data ),
  58. shortcode = shortcode_data.shortcode,
  59. $tinyMCE_document = $( tinyMCE.activeEditor.getDoc() ),
  60. $view = $tinyMCE_document.find( '.wpview.wpview-wrap' ).filter( function() {
  61. return $( this ).attr( 'data-mce-selected' );
  62. } ),
  63. $editframe = $( '<iframe scrolling="no" class="inline-edit-contact-form" />' ),
  64. index = 0,
  65. named,
  66. fields = '',
  67. field;
  68. if ( ! shortcode.content ) {
  69. shortcode.content = grunionEditorView.default_form;
  70. }
  71. // Render the fields.
  72. while ( ( field = wp.shortcode.next( 'contact-field', shortcode.content, index ) ) ) {
  73. index = field.index + field.content.length;
  74. named = field.shortcode.attrs.named;
  75. if ( named.options && 'string' === typeof named.options ) {
  76. named.options = named.options.split( ',' );
  77. }
  78. fields += this.edit_template( named );
  79. }
  80. $editframe.on( 'checkheight', function() {
  81. var innerDoc = ( this.contentDocument ) ? this.contentDocument : this.contentWindow.document;
  82. this.style.height = '10px';
  83. this.style.height = ( 5 + innerDoc.body.scrollHeight ) + 'px';
  84. tinyMCE.activeEditor.execCommand( 'wpAutoResize' );
  85. } );
  86. $editframe.on( 'load', function() {
  87. var stylesheet_url = ( 1 === window.isRtl ) ? grunionEditorView.inline_editing_style_rtl : grunionEditorView.inline_editing_style,
  88. $stylesheet = $( '<link rel="stylesheet" href="' + stylesheet_url + '" />' ),
  89. $dashicons_css = $( '<link rel="stylesheet" href="' + grunionEditorView.dashicons_css_url + '" />' );
  90. $stylesheet.on( 'load', function() {
  91. $editframe.contents().find( 'body' ).css( 'visibility', 'visible' );
  92. $editframe.trigger( 'checkheight' );
  93. } );
  94. $editframe.contents().find( 'head' ).append( $stylesheet ).append( $dashicons_css );
  95. $editframe.contents().find( 'body' ).html( wp.mce.grunion_wp_view_renderer.editor_inline( {
  96. to : shortcode.attrs.named.to,
  97. subject : shortcode.attrs.named.subject,
  98. fields : fields
  99. } ) ).css( 'visibility', 'hidden' );
  100. $editframe.contents().find( 'input:first' ).focus();
  101. setTimeout( function(){
  102. $editframe.trigger( 'checkheight' );
  103. }, 250 );
  104. // Add a second timeout for super long forms racing, and to not slow it down for shorter forms unnecessarily.
  105. setTimeout( function(){
  106. $editframe.trigger( 'checkheight' );
  107. }, 500 );
  108. var $editfields = $editframe.contents().find( '.grunion-fields' ),
  109. $buttons = $editframe.contents().find( '.grunion-controls' );
  110. $editfields.sortable();
  111. // Now, add all the listeners!
  112. $editfields.on( 'change select', 'select[name=type]', function() {
  113. $( this ).closest( '.grunion-field-edit' )[ 0 ].className =
  114. 'card is-compact grunion-field-edit grunion-field-' + $( this ).val();
  115. $editframe.trigger( 'checkheight' );
  116. } );
  117. $editfields.on( 'click', '.delete-option', function( e ) {
  118. e.preventDefault();
  119. $( this ).closest( 'li' ).remove();
  120. $editframe.trigger( 'checkheight' );
  121. } );
  122. $editfields.on( 'click', '.add-option', function( e ) {
  123. var $new_option = $( wp.mce.grunion_wp_view_renderer.editor_option() );
  124. e.preventDefault();
  125. $( this ).closest( 'li' ).before( $new_option );
  126. $editframe.trigger( 'checkheight' );
  127. $new_option.find( 'input:first' ).focus();
  128. } );
  129. $editfields.on( 'click', '.delete-field', function( e ) {
  130. e.preventDefault();
  131. $( this ).closest( '.card' ).remove();
  132. $editframe.trigger( 'checkheight' );
  133. } );
  134. $buttons.find( 'input[name=submit]' ).on( 'click', function(){
  135. var new_data = shortcode;
  136. new_data.type = 'closed';
  137. new_data.attrs = {};
  138. new_data.content = '';
  139. $editfields.children().each( function() {
  140. var field_shortcode = {
  141. tag : 'contact-field',
  142. type : 'single',
  143. attrs : {
  144. label : $( this ).find( 'input[name=label]' ).val(),
  145. type : $( this ).find( 'select[name=type]' ).val()
  146. }
  147. },
  148. options = [];
  149. if ( $( this ).find( 'input[name=required]:checked' ).length ) {
  150. field_shortcode.attrs.required = '1';
  151. }
  152. $( this ).find( 'input[name=option]' ).each( function() {
  153. if ( $( this ).val() ) {
  154. options.push( $( this ).val() );
  155. }
  156. } );
  157. if ( options.length ) {
  158. field_shortcode.attrs.options = options.join( ',' );
  159. }
  160. new_data.content += wp.shortcode.string( field_shortcode );
  161. } );
  162. if ( $editframe.contents().find( 'input[name=to]' ).val() ) {
  163. new_data.attrs.to = $editframe.contents().find( 'input[name=to]' ).val();
  164. }
  165. if ( $editframe.contents().find( 'input[name=subject]' ).val() ) {
  166. new_data.attrs.subject = $editframe.contents().find( 'input[name=subject]' ).val();
  167. }
  168. update_callback( wp.shortcode.string( new_data ) );
  169. } );
  170. $buttons.find( 'input[name=cancel]' ).on( 'click', function() {
  171. update_callback( wp.shortcode.string( shortcode ) );
  172. } );
  173. $buttons.find( 'input[name=add-field]' ).on( 'click', function() {
  174. var $new_field = $( wp.mce.grunion_wp_view_renderer.edit_template( {} ) );
  175. $editfields.append( $new_field );
  176. $editfields.sortable( 'refresh' );
  177. $editframe.trigger( 'checkheight' );
  178. $new_field.find( 'input:first' ).focus();
  179. } );
  180. } );
  181. $view.html( $editframe );
  182. }
  183. };
  184. wp.mce.views.register( 'contact-form', wp.mce.grunion_wp_view_renderer );
  185. // Add the 'text' editor button.
  186. QTags.addButton(
  187. 'grunion_shortcode',
  188. grunionEditorView.labels.quicktags_label,
  189. function() {
  190. QTags.insertContent( '[contact-form]' + grunionEditorView.default_form + '[/contact-form]' );
  191. }
  192. );
  193. var $wp_content_wrap = $( '#wp-content-wrap' );
  194. $( '#insert-jetpack-contact-form' ).on( 'click', function( e ) {
  195. e.preventDefault();
  196. if ( $wp_content_wrap.hasClass( 'tmce-active' ) ) {
  197. tinyMCE.execCommand( 'grunion_add_form' );
  198. } else if ( $wp_content_wrap.hasClass( 'html-active' ) ) {
  199. QTags.insertContent( '[contact-form]' + grunionEditorView.default_form + '[/contact-form]' );
  200. } else {
  201. window.console.error( 'Neither TinyMCE nor QuickTags is active. Unable to insert form.' );
  202. }
  203. } );
  204. }( jQuery, wp, grunionEditorView ) );