base.js 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. jQuery(document).ready(function() {
  2. jQuery('html').removeClass('no-js');
  3. if (window.SONATA_CONFIG.CONFIRM_EXIT) {
  4. jQuery('.sonata-ba-form form').confirmExit();
  5. }
  6. Admin.setup_select2(document);
  7. Admin.add_pretty_errors(document);
  8. Admin.add_filters(document);
  9. Admin.set_object_field_value(document);
  10. Admin.setup_collection_buttons(document);
  11. Admin.setup_per_page_switcher(document);
  12. Admin.setup_form_tabs_for_errors(document);
  13. Admin.setup_inline_form_errors(document);
  14. });
  15. jQuery(document).on('sonata-admin-append-form-element', function(e) {
  16. Admin.setup_select2(e.target);
  17. });
  18. var Admin = {
  19. setup_select2: function(subject) {
  20. if (window.SONATA_CONFIG && window.SONATA_CONFIG.USE_SELECT2 && window.Select2) {
  21. jQuery('select', subject).each(function() {
  22. var select = $(this);
  23. select.select2({
  24. width: 'resolve',
  25. minimumResultsForSearch: 10,
  26. allowClear: select.find('option[value=""]').length ? true : false
  27. });
  28. var popover = select.data('popover');
  29. if (undefined !== popover) {
  30. select
  31. .select2('container')
  32. .popover(popover.options)
  33. ;
  34. }
  35. });
  36. }
  37. },
  38. /**
  39. * render log message
  40. * @param mixed
  41. */
  42. log: function() {
  43. var msg = '[Sonata.Admin] ' + Array.prototype.join.call(arguments,', ');
  44. if (window.console && window.console.log) {
  45. window.console.log(msg);
  46. } else if (window.opera && window.opera.postError) {
  47. window.opera.postError(msg);
  48. }
  49. },
  50. /**
  51. * display related errors messages
  52. *
  53. * @param subject
  54. */
  55. add_pretty_errors: function(subject) {
  56. Admin.setup_select2(subject);
  57. jQuery('div.sonata-ba-field-error', subject).each(function(index, element) {
  58. var input = jQuery(':input', element);
  59. if (!input.length) {
  60. return;
  61. }
  62. var message = jQuery('div.sonata-ba-field-error-messages', element).html();
  63. jQuery('div.sonata-ba-field-error-messages', element).remove();
  64. if (!message || message.length == 0) {
  65. return;
  66. }
  67. var target = input,
  68. fieldShortDescription = input.closest('.field-container').find('.field-short-description')
  69. ;
  70. if (fieldShortDescription.length) {
  71. target = fieldShortDescription;
  72. }
  73. target.popover({
  74. content: message,
  75. trigger: 'hover',
  76. html: true,
  77. placement: 'right',
  78. template: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><div class="popover-content alert-error"><p></p></div></div></div>'
  79. });
  80. });
  81. },
  82. stopEvent: function(event) {
  83. // https://github.com/sonata-project/SonataAdminBundle/issues/151
  84. //if it is a standard browser use preventDefault otherwise it is IE then return false
  85. if(event.preventDefault) {
  86. event.preventDefault();
  87. } else {
  88. event.returnValue = false;
  89. }
  90. //if it is a standard browser get target otherwise it is IE then adapt syntax and get target
  91. if (typeof event.target != 'undefined') {
  92. targetElement = event.target;
  93. } else {
  94. targetElement = event.srcElement;
  95. }
  96. return targetElement;
  97. },
  98. add_filters: function(subject) {
  99. jQuery('div.filter_container .sonata-filter-option', subject).hide();
  100. jQuery('fieldset.filter_legend', subject).click(function(event) {
  101. jQuery('div.filter_container .sonata-filter-option', jQuery(event.target).parent()).toggle();
  102. });
  103. },
  104. /**
  105. * Change object field value
  106. * @param subject
  107. */
  108. set_object_field_value: function(subject) {
  109. this.log(jQuery('a.sonata-ba-edit-inline', subject));
  110. jQuery('a.sonata-ba-edit-inline', subject).click(function(event) {
  111. Admin.stopEvent(event);
  112. var subject = jQuery(this);
  113. jQuery.ajax({
  114. url: subject.attr('href'),
  115. type: 'POST',
  116. success: function(json) {
  117. if(json.status === "OK") {
  118. var elm = jQuery(subject).parent();
  119. elm.children().remove();
  120. // fix issue with html comment ...
  121. elm.html(jQuery(json.content.replace(/<!--[\s\S]*?-->/g, "")).html());
  122. elm.effect("highlight", {'color' : '#57A957'}, 2000);
  123. Admin.set_object_field_value(elm);
  124. } else {
  125. jQuery(subject).parent().effect("highlight", {'color' : '#C43C35'}, 2000);
  126. }
  127. }
  128. });
  129. });
  130. },
  131. setup_collection_buttons: function(subject) {
  132. jQuery(subject).on('click', '.sonata-collection-add', function(event) {
  133. Admin.stopEvent(event);
  134. var container = jQuery(this).closest('[data-prototype]');
  135. var proto = container.attr('data-prototype');
  136. var protoName = container.attr('data-prototype-name') || '__name__';
  137. // Set field id
  138. var idRegexp = new RegExp(container.attr('id')+'_'+protoName,'g');
  139. proto = proto.replace(idRegexp, container.attr('id')+'_'+(container.children().length - 1));
  140. // Set field name
  141. var parts = container.attr('id').split('_');
  142. var nameRegexp = new RegExp(parts[parts.length-1]+'\\]\\['+protoName,'g');
  143. proto = proto.replace(nameRegexp, parts[parts.length-1]+']['+(container.children().length - 1));
  144. jQuery(proto).insertBefore(jQuery(this).parent());
  145. jQuery(this).trigger('sonata-collection-item-added');
  146. });
  147. jQuery(subject).on('click', '.sonata-collection-delete', function(event) {
  148. Admin.stopEvent(event);
  149. jQuery(this).closest('.sonata-collection-row').remove();
  150. jQuery(this).trigger('sonata-collection-item-deleted');
  151. });
  152. },
  153. setup_per_page_switcher: function(subject) {
  154. jQuery('select.per-page').change(function(event) {
  155. jQuery('input[type=submit]').hide();
  156. window.top.location.href=this.options[this.selectedIndex].value;
  157. });
  158. },
  159. setup_form_tabs_for_errors: function(subject) {
  160. // Switch to first tab with server side validation errors on page load
  161. jQuery('form', subject).each(function() {
  162. Admin.show_form_first_tab_with_errors(jQuery(this), '.sonata-ba-field-error');
  163. });
  164. // Switch to first tab with HTML5 errors on form submit
  165. jQuery(subject)
  166. .on('click', 'form [type="submit"]', function() {
  167. Admin.show_form_first_tab_with_errors(jQuery(this).closest('form'), ':invalid');
  168. })
  169. .on('keypress', 'form [type="text"]', function(e) {
  170. if (13 === e.which) {
  171. Admin.show_form_first_tab_with_errors(jQuery(this), ':invalid');
  172. }
  173. })
  174. ;
  175. },
  176. show_form_first_tab_with_errors: function(form, errorSelector) {
  177. var tabs = form.find('.nav-tabs a'),
  178. firstTabWithErrors;
  179. tabs.each(function() {
  180. var id = jQuery(this).attr('href'),
  181. tab = jQuery(this),
  182. icon = tab.find('.has-errors');
  183. if (jQuery(id).find(errorSelector).length > 0) {
  184. // Only show first tab with errors
  185. if (!firstTabWithErrors) {
  186. tab.tab('show');
  187. firstTabWithErrors = tab;
  188. }
  189. icon.removeClass('hide');
  190. } else {
  191. icon.addClass('hide');
  192. }
  193. });
  194. },
  195. setup_inline_form_errors: function(subject) {
  196. var deleteCheckboxSelector = '.sonata-ba-field-inline-table [id$="_delete"][type="checkbox"]';
  197. jQuery(deleteCheckboxSelector, subject).each(function() {
  198. Admin.switch_inline_form_errors(jQuery(this));
  199. });
  200. $(subject).on('change', deleteCheckboxSelector, function() {
  201. Admin.switch_inline_form_errors(jQuery(this));
  202. });
  203. },
  204. /**
  205. * Disable inline form errors when the row is marked for deletion
  206. */
  207. switch_inline_form_errors: function(deleteCheckbox) {
  208. var row = deleteCheckbox.closest('.sonata-ba-field-inline-table'),
  209. errors = row.find('.sonata-ba-field-error-messages')
  210. ;
  211. if (deleteCheckbox.is(':checked')) {
  212. row
  213. .find('[required]')
  214. .removeAttr('required')
  215. .attr('data-required', 'required')
  216. ;
  217. errors.hide();
  218. } else {
  219. row
  220. .find('[data-required]')
  221. .attr('required', 'required')
  222. ;
  223. errors.show();
  224. }
  225. }
  226. };