admin-sharing.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. /* jshint onevar: false, smarttabs: true */
  2. /* global sharing_loading_icon */
  3. (function($) {
  4. $( document ).ready(function() {
  5. function enable_share_button() {
  6. $( '.preview a.sharing-anchor' ).unbind( 'mouseenter mouseenter' ).hover( function() {
  7. if ( $( this ).data( 'hasappeared' ) !== true ) {
  8. var item = $( '.sharing-hidden .inner' );
  9. var original = $( this ).parents( 'li' );
  10. // Create a timer to make the area appear if the mouse hovers for a period
  11. var timer = setTimeout( function() {
  12. $( item ).css( {
  13. left: $( original ).position().left + 'px',
  14. top: $( original ).position().top + $( original ).height() + 3 + 'px'
  15. } ).slideDown( 200, function() {
  16. // Mark the item as have being appeared by the hover
  17. $( original ).data( 'hasappeared', true ).data( 'hasoriginal', true ).data( 'hasitem', false );
  18. // Remove all special handlers
  19. $( item ).mouseleave( handler_item_leave ).mouseenter( handler_item_enter );
  20. $( original ).mouseleave( handler_original_leave ).mouseenter( handler_original_enter );
  21. // Add a special handler to quickly close the item
  22. $( original ).click( close_it );
  23. } );
  24. // The following handlers take care of the mouseenter/mouseleave for the share button and the share area - if both are left then we close the share area
  25. var handler_item_leave = function() {
  26. $( original ).data( 'hasitem', false );
  27. if ( $( original ).data( 'hasoriginal' ) === false ) {
  28. var timer = setTimeout( close_it, 800 );
  29. $( original ).data( 'timer2', timer );
  30. }
  31. };
  32. var handler_item_enter = function() {
  33. $( original ).data( 'hasitem', true );
  34. clearTimeout( $( original ).data( 'timer2' ) );
  35. };
  36. var handler_original_leave = function() {
  37. $( original ).data( 'hasoriginal', false );
  38. if ( $( original ).data( 'hasitem' ) === false ) {
  39. var timer = setTimeout( close_it, 800 );
  40. $( original ).data( 'timer2', timer );
  41. }
  42. };
  43. var handler_original_enter = function() {
  44. $( original ).data( 'hasoriginal', true );
  45. clearTimeout( $( original ).data( 'timer2' ) );
  46. };
  47. var close_it = function() {
  48. item.slideUp( 200 );
  49. // Clear all hooks
  50. $( original ).unbind( 'mouseleave', handler_original_leave ).unbind( 'mouseenter', handler_original_enter );
  51. $( item ).unbind( 'mouseleave', handler_item_leave ).unbind( 'mouseenter', handler_item_leave );
  52. $( original ).data( 'hasappeared', false );
  53. $( original ).unbind( 'click', close_it );
  54. return false;
  55. };
  56. }, 200 );
  57. // Remember the timer so we can detect it on the mouseout
  58. $( this ).data( 'timer', timer );
  59. }
  60. }, function() {
  61. // Mouse out - remove any timer
  62. clearTimeout( $( this ).data( 'timer' ) );
  63. $( this ).data( 'timer', false );
  64. } );
  65. }
  66. function update_preview() {
  67. var button_style = $( '#button_style' ).val();
  68. // Clear the live preview
  69. $( '#live-preview ul.preview li' ).remove();
  70. // Add label
  71. if ( $( '#save-enabled-shares input[name=visible]' ).val() || $( '#save-enabled-shares input[name=hidden]' ).val() ) {
  72. $( '#live-preview ul.preview' ).append( $( '#live-preview ul.archive .sharing-label' ).clone() );
  73. }
  74. // Re-insert all the enabled items
  75. $( 'ul.services-enabled li' ).each( function() {
  76. if ( $( this ).hasClass( 'service' ) ) {
  77. var service = $( this ).attr( 'id' );
  78. $( '#live-preview ul.preview' ).append( $( '#live-preview ul.archive li.preview-' + service ).clone() );
  79. }
  80. } );
  81. // Add any hidden items
  82. if ( $( '#save-enabled-shares input[name=hidden]' ).val() ) {
  83. // Add share button
  84. $( '#live-preview ul.preview' ).append( $( '#live-preview ul.archive .share-more' ).parent().clone() );
  85. $( '.sharing-hidden ul li' ).remove();
  86. // Add hidden items into the inner panel
  87. $( 'ul.services-hidden li' ).each( function( /*pos, item*/ ) {
  88. if ( $( this ).hasClass( 'service' ) ) {
  89. var service = $( this ).attr( 'id' );
  90. $( '.sharing-hidden .inner ul' ).append( $( '#live-preview ul.archive .preview-' + service ).clone() );
  91. }
  92. } );
  93. enable_share_button();
  94. }
  95. $( '#live-preview div.sharedaddy' ).removeClass( 'sd-social-icon' );
  96. $( '#live-preview li.advanced' ).removeClass( 'no-icon' );
  97. // Button style
  98. if ( 'icon' === button_style ) {
  99. $( '#live-preview ul.preview div span, .sharing-hidden .inner ul div span' ).html( ' ' ).parent().addClass( 'no-text' );
  100. $( '#live-preview div.sharedaddy' ).addClass( 'sd-social-icon' );
  101. } else if ( 'official' === button_style ) {
  102. $( '#live-preview ul.preview .advanced, .sharing-hidden .inner ul .advanced' ).each( function( /*i*/ ) {
  103. if ( !$( this ).hasClass( 'preview-press-this' ) &&
  104. !$( this ).hasClass( 'preview-email' ) &&
  105. !$( this ).hasClass( 'preview-print' ) &&
  106. !$( this ).hasClass( 'preview-telegram' ) &&
  107. !$( this ).hasClass( 'preview-jetpack-whatsapp' ) &&
  108. !$( this ).hasClass( 'share-custom' ) ) {
  109. $( this ).find( '.option a span' ).html( '' ).parent().removeClass( 'sd-button' ).parent().attr( 'class', 'option option-smart-on' );
  110. }
  111. } );
  112. } else if ( 'text' === button_style ) {
  113. $( '#live-preview li.advanced' ).addClass( 'no-icon' );
  114. }
  115. }
  116. window.sharing_option_changed = function() {
  117. var item = this;
  118. // Loading icon
  119. $( this ).parents( 'li:first' ).css( 'backgroundImage', 'url("' + sharing_loading_icon + '")' );
  120. // Save
  121. $( this ).parents( 'form' ).ajaxSubmit( function( response ) {
  122. if ( response.indexOf( '<!---' ) >= 0 ) {
  123. var button = response.substring( 0, response.indexOf( '<!--->' ) );
  124. var preview = response.substring( response.indexOf( '<!--->' ) + 6 );
  125. if ( $( item ).is( ':submit' ) === true ) {
  126. // Update the DOM using a bit of cut/paste technology
  127. $( item ).parents( 'li:first' ).replaceWith( button );
  128. }
  129. $( '#live-preview ul.archive li.preview-' + $( item ).parents( 'form' ).find( 'input[name=service]' ).val() ).replaceWith( preview );
  130. }
  131. // Update preview
  132. update_preview();
  133. // Restore the icon
  134. $( item ).parents( 'li:first' ).removeAttr( 'style' );
  135. } );
  136. if ( $( item ).is( ':submit' ) === true ) {
  137. return false;
  138. }
  139. return true;
  140. };
  141. function showExtraOptions( service ) {
  142. jQuery( '.' + service + '-extra-options' ).css( { backgroundColor: '#ffffcc' } ).fadeIn();
  143. }
  144. function hideExtraOptions( service ) {
  145. jQuery( '.' + service + '-extra-options' ).fadeOut( 'slow' );
  146. }
  147. function save_services() {
  148. $( '#enabled-services h3 img' ).show();
  149. // Toggle various dividers/help texts
  150. if ( $( '#enabled-services ul.services-enabled li.service' ).length > 0 ) {
  151. $( '#drag-instructions' ).hide();
  152. }
  153. else {
  154. $( '#drag-instructions' ).show();
  155. }
  156. if ( $( '#enabled-services li.service' ).length > 0 ) {
  157. $( '#live-preview .services h2' ).hide();
  158. }
  159. else {
  160. $( '#live-preview .services h2' ).show();
  161. }
  162. // Gather the modules
  163. var visible = [], hidden = [];
  164. $( 'ul.services-enabled li' ).each( function() {
  165. if ( $( this ).hasClass( 'service' ) ) {
  166. // Ready for saving
  167. visible[visible.length] = $( this ).attr( 'id' );
  168. showExtraOptions( $( this ).attr( 'id' ) );
  169. }
  170. } );
  171. $( 'ul.services-available li' ).each( function() {
  172. if ( $( this ).hasClass( 'service' ) ) {
  173. hideExtraOptions( $( this ).attr( 'id' ) );
  174. }
  175. } );
  176. $( 'ul.services-hidden li' ).each( function() {
  177. if ( $( this ).hasClass( 'service' ) ) {
  178. // Ready for saving
  179. hidden[hidden.length] = $( this ).attr( 'id' );
  180. showExtraOptions( $( this ).attr( 'id' ) );
  181. }
  182. } );
  183. // Set the hidden element values
  184. $( '#save-enabled-shares input[name=visible]' ).val( visible.join( ',' ) );
  185. $( '#save-enabled-shares input[name=hidden]' ).val( hidden.join( ',' ) );
  186. update_preview();
  187. // Save it
  188. $( '#save-enabled-shares' ).ajaxSubmit( function() {
  189. $( '#enabled-services h3 img' ).hide();
  190. } );
  191. }
  192. $( '#enabled-services .services ul' ).sortable( {
  193. receive: function( /*event, ui*/ ) {
  194. save_services();
  195. },
  196. stop: function() {
  197. save_services();
  198. $( 'li.service' ).enableSelection(); // Fixes a problem with Chrome
  199. },
  200. over: function( /*event, ui*/ ) {
  201. $( this ).find( 'ul' ).addClass( 'dropping' );
  202. // Ensure the 'end-fix' is at the end
  203. $( '#enabled-services li.end-fix' ).remove();
  204. $( '#enabled-services ul' ).append( '<li class="end-fix"></li>' );
  205. },
  206. out: function( /*event, ui*/ ) {
  207. $( this ).find( 'ul' ).removeClass( 'dropping' );
  208. // Ensure the 'end-fix' is at the end
  209. $( '#enabled-services li.end-fix' ).remove();
  210. $( '#enabled-services ul' ).append( '<li class="end-fix"></li>' );
  211. },
  212. helper: function( event, ui ) {
  213. ui.find( '.advanced-form' ).hide();
  214. return ui.clone();
  215. },
  216. start: function( /*event, ui*/ ) {
  217. // Make sure that the advanced section is closed
  218. $( '.advanced-form' ).hide();
  219. $( 'li.service' ).disableSelection(); // Fixes a problem with Chrome
  220. },
  221. placeholder: 'dropzone',
  222. opacity: 0.8,
  223. delay: 150,
  224. forcePlaceholderSize: true,
  225. items: 'li',
  226. connectWith: '#available-services ul, #enabled-services .services ul',
  227. cancel: '.advanced-form'
  228. } );
  229. $( '#available-services ul' ).sortable( {
  230. opacity: 0.8,
  231. delay: 150,
  232. cursor: 'move',
  233. connectWith: '#enabled-services .services ul',
  234. placeholder: 'dropzone',
  235. forcePlaceholderSize: true,
  236. start: function() {
  237. $( '.advanced-form' ).hide();
  238. }
  239. } );
  240. // Accessibility keyboard shortcurts
  241. $( '.service' ).on( 'keydown', function ( e ) {
  242. // Reposition if one of the directional keys is pressed
  243. switch ( e.keyCode ) {
  244. case 13: keyboardDragDrop( $( this ) ); break; // Enter
  245. case 32: keyboardDragDrop( $( this ) ); break; // Space
  246. case 37: keyboardChangeOrder( $( this ), 'left' ); break; // Left
  247. case 39: keyboardChangeOrder( $( this ), 'right' ); break; // Right
  248. default: return true; // Exit and bubble
  249. }
  250. e.preventDefault();
  251. });
  252. function keyboardChangeOrder( $this, dir ) {
  253. var thisParent = $this.parent(),
  254. thisParentsChildren = thisParent.find( 'li' ),
  255. thisPosition = thisParentsChildren.index( $this ) + 1,
  256. totalChildren = thisParentsChildren.length - 1,
  257. thisService;
  258. // No need to be able to sort order for the "Available Services" section
  259. if ( thisParent.hasClass( 'services-available' ) ) {
  260. return;
  261. }
  262. if ( 'left' === dir ) {
  263. if ( 1 === thisPosition ) {
  264. return;
  265. }
  266. // Find service to left
  267. var prevSibling = $this.prev();
  268. // Detach this service from DOM
  269. thisService = $this.detach();
  270. // Move it to the appropriate area and add focus back to service
  271. prevSibling.before( thisService );
  272. // Add focus
  273. prevSibling.prev().focus();
  274. }
  275. if ( 'right' === dir ) {
  276. if ( thisPosition === totalChildren ) {
  277. return;
  278. }
  279. // Find service to left
  280. var nextSibling = $this.next();
  281. // Detach this service from DOM
  282. thisService = $this.detach();
  283. // Move it to the appropriate area and add focus back to service
  284. nextSibling.after( thisService );
  285. // Add focus
  286. nextSibling.next().focus();
  287. }
  288. //Save changes
  289. save_services();
  290. }
  291. function keyboardDragDrop( $this ) {
  292. var dropzone,
  293. thisParent = $this.parent();
  294. // Rotate through 3 available dropzones
  295. if ( thisParent.hasClass( 'services-available' ) ) {
  296. dropzone = 'services-enabled';
  297. } else if ( thisParent.hasClass( 'services-enabled' ) ) {
  298. dropzone = 'services-hidden';
  299. } else {
  300. dropzone = 'services-available';
  301. }
  302. // Detach this service from DOM
  303. var thisService = $this.detach();
  304. // Move it to the appropriate area and add focus back to service
  305. $( '.' + dropzone ).prepend( thisService ).find( 'li:first-child' ).focus();
  306. //Save changes
  307. save_services();
  308. }
  309. // Live preview 'hidden' button
  310. $( '.preview-hidden a' ).click( function() {
  311. $( this ).parent().find( '.preview' ).toggle();
  312. return false;
  313. } );
  314. // Add service
  315. $( '#new-service form' ).ajaxForm( {
  316. beforeSubmit: function() {
  317. $( '#new-service-form .error' ).hide();
  318. $( '#new-service-form img' ).show();
  319. $( '#new-service-form input[type=submit]' ).prop( 'disabled', true );
  320. },
  321. success: function( response ) {
  322. $( '#new-service-form img' ).hide();
  323. if ( ( '' + response ) === '1' ) {
  324. $( '#new-service-form .inerror' ).removeClass( 'inerror' ).addClass( 'error' );
  325. $( '#new-service-form .error' ).show();
  326. $( '#new-service-form input[type=submit]' ).prop( 'disabled', false );
  327. }
  328. else {
  329. document.location.reload();
  330. }
  331. }
  332. }
  333. );
  334. function init_handlers() {
  335. $( '#services-config a.remove' ).unbind( 'click' ).click( function() {
  336. var form = $( this ).parent().next();
  337. // Loading icon
  338. $( this ).parents( 'li:first' ).css( 'backgroundImage', 'url("' + sharing_loading_icon + '")' );
  339. // Save
  340. form.ajaxSubmit( function( /*response*/ ) {
  341. // Remove the item
  342. form.parents( 'li:first' ).fadeOut( function() {
  343. $( this ).remove();
  344. // Update preview
  345. update_preview();
  346. } );
  347. } );
  348. return false;
  349. } );
  350. }
  351. $( '#button_style' ).change( function() {
  352. update_preview();
  353. return true;
  354. } ).change();
  355. $( 'input[name=sharing_label]' ).blur( function() {
  356. $('#live-preview h3.sd-title').text( $( '<div/>' ).text( $( this ).val() ).html() );
  357. } );
  358. init_handlers();
  359. enable_share_button();
  360. } );
  361. })( jQuery );