Нет описания

widget-conditions.js 9.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /* global isRtl, widget_conditions_parent_pages, widget_conditions_data */
  2. jQuery( function ( $ ) {
  3. // Gutenberg 'widgets.php' screen.
  4. var widgets_shell = $( '#widgets-editor' );
  5. if ( 0 === widgets_shell.length ) {
  6. // Legacy 'widgets.php' screen + customizer.
  7. widgets_shell = $( 'div#widgets-right' );
  8. // For backwards compatibility
  9. if ( 0 === widgets_shell.length ) {
  10. widgets_shell = $( 'form#customize-controls' );
  11. }
  12. }
  13. function setWidgetMargin( $widget ) {
  14. var currentWidth, extra;
  15. if ( $( 'body' ).hasClass( 'wp-customizer' ) ) {
  16. // set the inside widget 2 top this way we can see the widget settings
  17. $widget.find( '.widget-inside' ).css( 'top', 0 );
  18. return;
  19. }
  20. if ( $widget.hasClass( 'expanded' ) ) {
  21. // The expanded widget must be at least 400px wide in order to
  22. // contain the visibility settings. IE wasn't handling the
  23. // margin-left value properly.
  24. if ( $widget.attr( 'style' ) ) {
  25. $widget.data( 'original-style', $widget.attr( 'style' ) );
  26. }
  27. currentWidth = $widget.width();
  28. if ( currentWidth < 400 ) {
  29. extra = 400 - currentWidth;
  30. if ( isRtl ) {
  31. $widget
  32. .css( 'position', 'relative' )
  33. .css( 'right', '-' + extra + 'px' )
  34. .css( 'width', '400px' );
  35. } else {
  36. $widget
  37. .css( 'position', 'relative' )
  38. .css( 'left', '-' + extra + 'px' )
  39. .css( 'width', '400px' );
  40. }
  41. }
  42. } else if ( $widget.data( 'original-style' ) ) {
  43. // Restore any original inline styles when visibility is toggled off.
  44. $widget.attr( 'style', $widget.data( 'original-style' ) ).data( 'original-style', null );
  45. } else {
  46. $widget.removeAttr( 'style' );
  47. }
  48. }
  49. function moveWidgetVisibilityButton( $widget ) {
  50. var $displayOptionsButton = $widget.find( 'a.display-options' ).first(),
  51. $relativeWidget = $widget.find( 'input.widget-control-save' );
  52. if ( 0 === $relativeWidget.length ) {
  53. // The save button doesn't exist in gutenberg widget editor, the conditional HTML ought to be displayed
  54. // last inside the widget options, so display the button before that.
  55. $relativeWidget = $widget.find( 'div.widget-conditional' );
  56. }
  57. $displayOptionsButton.insertBefore( $relativeWidget );
  58. // Widgets with no configurable options don't show the Save button's container.
  59. $displayOptionsButton
  60. .parent()
  61. .removeClass( 'widget-control-noform' )
  62. .find( '.spinner' )
  63. .remove()
  64. .css( 'float', 'left' )
  65. .prependTo( $displayOptionsButton.parent() );
  66. }
  67. $( '.widget' ).each( function () {
  68. moveWidgetVisibilityButton( $( this ) );
  69. } );
  70. $( document ).on( 'widget-added', function ( e, $widget ) {
  71. if ( $widget.find( 'div.widget-control-actions a.display-options' ).length === 0 ) {
  72. moveWidgetVisibilityButton( $widget );
  73. }
  74. } );
  75. widgets_shell.on( 'click.widgetconditions', 'a.add-condition', function ( e ) {
  76. var $condition = $( this ).closest( 'div.condition' ),
  77. $conditionClone = $condition
  78. .clone()
  79. .data( 'rule-major', '' )
  80. .data( 'rule-minor', '' )
  81. .data( 'has-children', '' )
  82. .insertAfter( $condition );
  83. e.preventDefault();
  84. $conditionClone.find( 'select.conditions-rule-major' ).val( '' );
  85. $conditionClone.find( 'select.conditions-rule-minor' ).html( '' ).attr( 'disabled' );
  86. $conditionClone
  87. .find( 'span.conditions-rule-has-children' )
  88. .hide()
  89. .find( 'input[type="checkbox"]' )
  90. .removeAttr( 'checked' );
  91. resetRuleIndexes( $conditionClone.closest( '.conditions' ) );
  92. } );
  93. widgets_shell.on( 'click.widgetconditions', 'a.display-options', function ( e ) {
  94. var $displayOptionsButton = $( this ),
  95. $widget = $displayOptionsButton.closest( 'div.widget' );
  96. e.preventDefault();
  97. $widget.find( 'div.widget-conditional' ).toggleClass( 'widget-conditional-hide' );
  98. $( this ).toggleClass( 'active' );
  99. $widget.toggleClass( 'expanded' );
  100. setWidgetMargin( $widget );
  101. if ( $( this ).hasClass( 'active' ) ) {
  102. $widget.find( 'input[name=widget-conditions-visible]' ).val( '1' );
  103. $widget.find( '.condition' ).each( function () {
  104. buildMinorConditions( $( this ) );
  105. } );
  106. } else {
  107. $widget.find( 'input[name=widget-conditions-visible]' ).val( '0' );
  108. }
  109. } );
  110. widgets_shell.on( 'click.widgetconditions', 'a.delete-condition', function ( e ) {
  111. var $condition = $( this ).closest( 'div.condition' );
  112. e.preventDefault();
  113. if ( $condition.is( ':first-child' ) && $condition.is( ':last-child' ) ) {
  114. $( this ).closest( 'div.widget' ).find( 'a.display-options' ).click();
  115. $condition.find( 'select.conditions-rule-major' ).val( '' ).change();
  116. } else {
  117. $condition.find( 'select.conditions-rule-major' ).change();
  118. $condition.detach();
  119. }
  120. resetRuleIndexes( $condition.closest( '.conditions' ) );
  121. } );
  122. widgets_shell.on( 'click.widgetconditions', 'div.widget-top', function () {
  123. var $widget = $( this ).closest( 'div.widget' ),
  124. $displayOptionsButton = $widget.find( 'a.display-options' );
  125. if ( $displayOptionsButton.hasClass( 'active' ) ) {
  126. $displayOptionsButton.attr( 'opened', 'true' );
  127. }
  128. if ( $displayOptionsButton.attr( 'opened' ) ) {
  129. $displayOptionsButton.removeAttr( 'opened' );
  130. $widget.toggleClass( 'expanded' );
  131. setWidgetMargin( $widget );
  132. }
  133. } );
  134. widgets_shell.on( 'change.widgetconditions', 'input.conditions-match-all', function () {
  135. $( this )
  136. .parents( '.widget-conditional' )
  137. .toggleClass( 'conjunction' )
  138. .toggleClass( 'intersection' );
  139. } );
  140. $( document ).on( 'change.widgetconditions', 'select.conditions-rule-major', function () {
  141. var $conditionsRuleMajor = $( this ),
  142. $conditionsRuleMinor = $conditionsRuleMajor.siblings( 'select.conditions-rule-minor:first' ),
  143. $conditionsRuleHasChildren = $conditionsRuleMajor.siblings(
  144. 'span.conditions-rule-has-children'
  145. ),
  146. $condition = $conditionsRuleMinor.closest( '.condition' );
  147. $condition.data( 'rule-minor', '' ).data( 'rule-major', $conditionsRuleMajor.val() );
  148. if ( $conditionsRuleMajor.val() ) {
  149. buildMinorConditions( $condition );
  150. } else {
  151. $conditionsRuleMajor
  152. .siblings( 'select.conditions-rule-minor' )
  153. .attr( 'disabled', 'disabled' )
  154. .html( '' );
  155. $conditionsRuleHasChildren.hide().find( 'input[type="checkbox"]' ).removeAttr( 'checked' );
  156. }
  157. } );
  158. $( document ).on( 'change.widgetconditions', 'select.conditions-rule-minor', function () {
  159. var $conditionsRuleMinor = $( this ),
  160. $conditionsRuleMajor = $conditionsRuleMinor.siblings( 'select.conditions-rule-major' ),
  161. $conditionsRuleHasChildren = $conditionsRuleMinor.siblings(
  162. 'span.conditions-rule-has-children'
  163. ),
  164. $condition = $conditionsRuleMinor.closest( '.condition' );
  165. $condition.data( 'rule-minor', $conditionsRuleMinor.val() );
  166. if ( $conditionsRuleMajor.val() === 'page' ) {
  167. if ( $conditionsRuleMinor.val() in widget_conditions_parent_pages ) {
  168. $conditionsRuleHasChildren.show();
  169. } else {
  170. $conditionsRuleHasChildren.hide().find( 'input[type="checkbox"]' ).removeAttr( 'checked' );
  171. }
  172. } else {
  173. $conditionsRuleHasChildren.hide().find( 'input[type="checkbox"]' ).removeAttr( 'checked' );
  174. }
  175. } );
  176. $( document ).on( 'widget-updated widget-synced', function ( e, widget ) {
  177. widget.find( '.condition' ).each( function () {
  178. buildMinorConditions( $( this ) );
  179. } );
  180. } );
  181. function buildMinorConditions( condition ) {
  182. var minor,
  183. hasChildren,
  184. majorData,
  185. i,
  186. j,
  187. key,
  188. val,
  189. _len,
  190. _jlen,
  191. subkey,
  192. subval,
  193. optgroup,
  194. select = condition.find( '.conditions-rule-minor' ).html( '' ),
  195. major = condition.data( 'rule-major' );
  196. // Disable the select, if major rule is empty or if it's a `post_type`.
  197. // "Post Type" rule has been removed in Jetpack 4.7, and
  198. // because it breaks all other rules we should `return`.
  199. if ( ! major || 'post_type' === major ) {
  200. select.attr( 'disabled', 'disabled' );
  201. return;
  202. }
  203. minor = condition.data( 'rule-minor' );
  204. hasChildren = condition.data( 'rule-has-children' );
  205. majorData = widget_conditions_data[ major ];
  206. for ( i = 0, _len = majorData.length; i < _len; i++ ) {
  207. key = majorData[ i ][ 0 ];
  208. val = majorData[ i ][ 1 ];
  209. if ( typeof val === 'object' ) {
  210. optgroup = $( '<optgroup/>' ).attr( 'label', key );
  211. for ( j = 0, _jlen = val.length; j < _jlen; j++ ) {
  212. subkey = majorData[ i ][ 1 ][ j ][ 0 ];
  213. subval = majorData[ i ][ 1 ][ j ][ 1 ];
  214. optgroup.append(
  215. $( '<option/>' )
  216. .val( subkey )
  217. .text( decodeEntities( subval.replace( /&nbsp;/g, '\xA0' ) ) )
  218. );
  219. }
  220. select.append( optgroup );
  221. } else {
  222. select.append(
  223. $( '<option/>' )
  224. .val( key )
  225. .text( decodeEntities( val.replace( /&nbsp;/g, '\xA0' ) ) )
  226. );
  227. }
  228. }
  229. select.removeAttr( 'disabled' );
  230. select.val( minor );
  231. if ( 'page' === major && minor in widget_conditions_parent_pages ) {
  232. select.siblings( 'span.conditions-rule-has-children' ).show();
  233. if ( hasChildren ) {
  234. select
  235. .siblings( 'span.conditions-rule-has-children' )
  236. .find( 'input[type="checkbox"]' )
  237. .attr( 'checked', 'checked' );
  238. }
  239. } else {
  240. select
  241. .siblings( 'span.conditions-rule-has-children' )
  242. .hide()
  243. .find( 'input[type="checkbox"]' )
  244. .removeAttr( 'checked' );
  245. }
  246. }
  247. function resetRuleIndexes( widget ) {
  248. var index = 0;
  249. widget
  250. .find( 'span.conditions-rule-has-children' )
  251. .find( 'input[type="checkbox"]' )
  252. .each( function () {
  253. $( this ).attr( 'name', 'conditions[page_children][' + index + ']' );
  254. index++;
  255. } );
  256. }
  257. function decodeEntities( encodedString ) {
  258. var textarea = document.createElement( 'textarea' );
  259. textarea.innerHTML = encodedString;
  260. return textarea.value;
  261. }
  262. } );