PageRenderTime 27ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/system/cms/themes/pyrocms/js/scripts.js

https://gitlab.com/hashrocket/pyrocms
JavaScript | 484 lines | 326 code | 87 blank | 71 comment | 29 complexity | f27d04e5761e1b1099978b3fdcfccf9e MD5 | raw file
Possible License(s): BSD-3-Clause, MIT
  1. /*
  2. Author: PyroCMS Dev Team
  3. */
  4. /**
  5. * Pyro object
  6. *
  7. * The Pyro object is the foundation of all PyroUI enhancements
  8. */
  9. // It may already be defined in metadata partial
  10. if (typeof(pyro) == 'undefined') {
  11. var pyro = {};
  12. }
  13. jQuery(function($) {
  14. // Set up an object for caching things
  15. pyro.cache = {
  16. // set this up for the slug generator
  17. url_titles : {}
  18. }
  19. /**
  20. * Overload the json converter to avoid error when json is null or empty.
  21. */
  22. $.ajaxSetup({
  23. //allowEmpty: true,
  24. converters: {
  25. 'text json': function(text) {
  26. var json = jQuery.parseJSON(text);
  27. if (!jQuery.ajaxSettings.allowEmpty == true && (json == null || jQuery.isEmptyObject(json)))
  28. {
  29. jQuery.error('The server is not responding correctly, please try again later.');
  30. }
  31. return json;
  32. }
  33. },
  34. data: {
  35. csrf_hash_name: $.cookie(pyro.csrf_cookie_name)
  36. }
  37. });
  38. /**
  39. * This initializes all JS goodness
  40. */
  41. pyro.init = function() {
  42. // Select menu for smaller screens
  43. $("<select />").appendTo("nav#primary");
  44. // Create default option "Menu"
  45. $("<option />", {
  46. "selected": "selected",
  47. "value" : "",
  48. "text" : "Menu"
  49. }).appendTo("nav#primary select");
  50. // Populate dropdown with menu items
  51. $("nav#primary a").each(function() {
  52. var el = $(this);
  53. $("<option />", {
  54. "value" : el.attr("href"),
  55. "text" : el.text()
  56. }).appendTo("nav#primary select");
  57. });
  58. $("nav#primary select").change(function() {
  59. window.location = $(this).find("option:selected").val();
  60. });
  61. $('.topbar ul li:not(#dashboard-link)').hoverIntent({
  62. sensitivity: 7,
  63. interval: 75,
  64. over: function(){ $(this).find('ul:first:hidden').css({visibility: "visible", display: "none"}).slideDown(400) },
  65. timeout: 0,
  66. out: function(){ $(this).parent().find('ul').slideUp(400) }
  67. });
  68. // Add class to dropdowns for styling
  69. $(".topbar ul li:has(ul)").children("a").addClass("menu");
  70. // Add the close link to all alert boxes
  71. $('.alert').livequery(function(){
  72. $(this).prepend('<a href="#" class="close">x</a>');
  73. });
  74. // Close the notifications when the close link is clicked
  75. $('a.close').live('click', function(e){
  76. e.preventDefault();
  77. $(this).fadeTo(200, 0); // This is a hack so that the close link fades out in IE
  78. $(this).parent().fadeTo(200, 0);
  79. $(this).parent().slideUp(400, function(){
  80. $(window).trigger('notification-closed');
  81. $(this).remove();
  82. });
  83. });
  84. $("#datepicker").datepicker({dateFormat: 'yy-mm-dd'});
  85. // Fade in the notifications
  86. $('.alert').livequery(function(){
  87. $(this).fadeIn('slow', function(){
  88. $(window).trigger('notification-complete');
  89. });
  90. });
  91. // Check all checkboxes in container table or grid
  92. $(".check-all").live('click', function () {
  93. var check_all = $(this),
  94. all_checkbox = $(this).is('.grid-check-all')
  95. ? $(this).parents(".list-items").find(".grid input[type='checkbox']")
  96. : $(this).parents("table").find("tbody input[type='checkbox']");
  97. all_checkbox.each(function () {
  98. if (check_all.is(":checked") && ! $(this).is(':checked'))
  99. {
  100. $(this).click();
  101. }
  102. else if ( ! check_all.is(":checked") && $(this).is(':checked'))
  103. {
  104. $(this).click();
  105. }
  106. });
  107. // Check all?
  108. $(".table_action_buttons .btn").prop('disabled', false);
  109. });
  110. // Table action buttons start out as disabled
  111. $(".table_action_buttons .btn").prop('disabled', true);
  112. // Enable/Disable table action buttons
  113. $('input[name="action_to[]"], .check-all').live('click', function () {
  114. if( $('input[name="action_to[]"]:checked, .check-all:checked').length >= 1 ){
  115. $(".table_action_buttons .btn").prop('disabled', false);
  116. } else {
  117. $(".table_action_buttons .btn").prop('disabled', true);
  118. }
  119. });
  120. // Confirmation
  121. $('a.confirm').live('click', function(e){
  122. e.preventDefault();
  123. var href = $(this).attr('href'),
  124. removemsg = $(this).attr('title');
  125. if (confirm(removemsg || pyro.lang.dialog_message))
  126. {
  127. $(this).trigger('click-confirmed');
  128. if ($.data(this, 'stop-click')){
  129. $.data(this, 'stop-click', false);
  130. return;
  131. }
  132. window.location.replace(href);
  133. }
  134. });
  135. //use a confirm dialog on "delete many" buttons
  136. $(':submit.confirm').live('click', function(e, confirmation){
  137. if (confirmation)
  138. {
  139. return true;
  140. }
  141. e.preventDefault();
  142. var removemsg = $(this).attr('title');
  143. if (confirm(removemsg || pyro.lang.dialog_message))
  144. {
  145. $(this).trigger('click-confirmed');
  146. if ($(this).data('stop-click')){
  147. $(this).data('stop-click', false);
  148. return;
  149. }
  150. $(this).trigger('click', true);
  151. }
  152. });
  153. // Table zerbra striping
  154. $("tbody tr:nth-child(even)").livequery(function () {
  155. $(this).addClass("alt");
  156. });
  157. $('#main, .tabs').livequery(function () {
  158. $(this).tabs();
  159. $(this).tabs('paging', { cycle: true, follow: false } );
  160. });
  161. $('#tabs').livequery(function () {
  162. $(this).tabs({
  163. // This allows for the Back button to work.
  164. select: function(event, ui) {
  165. parent.location.hash = ui.tab.hash;
  166. },
  167. load: function(event, ui) {
  168. confirm_links();
  169. confirm_buttons();
  170. }
  171. });
  172. });
  173. var current_module = $('#page-header h1 a').text();
  174. // Colorbox modal window
  175. $('a[rel=modal], a.modal').livequery(function() {
  176. $(this).colorbox({
  177. width: "60%",
  178. maxHeight: "90%",
  179. current: current_module + " {current} / {total}",
  180. onComplete: function(){ pyro.chosen() }
  181. });
  182. });
  183. $('a[data-inline-modal]').livequery(function() {
  184. var element_id = $(this).attr('data-inline-modal');
  185. $(this).colorbox({
  186. width: "60%",
  187. maxHeight: "90%",
  188. inline: true,
  189. href: element_id,
  190. current: current_module + " {current} / {total}",
  191. onComplete: function(){ pyro.chosen() }
  192. });
  193. });
  194. $('a[rel="modal-large"], a.modal-large').livequery(function() {
  195. $(this).colorbox({
  196. width: "90%",
  197. height: "95%",
  198. iframe: true,
  199. scrolling: false,
  200. current: current_module + " {current} / {total}",
  201. onComplete: function(){ pyro.chosen() }
  202. });
  203. });
  204. };
  205. pyro.clear_notifications = function()
  206. {
  207. $('.alert .close').click();
  208. return pyro;
  209. };
  210. pyro.add_notification = function(notification, options, callback)
  211. {
  212. var defaults = {
  213. clear : true,
  214. ref : '#content-body',
  215. method : 'prepend'
  216. }, opt;
  217. // extend options
  218. opt = $.isPlainObject(options) ? $.extend(defaults, options) : defaults;
  219. // clear old notifications
  220. opt.clear && pyro.clear_notifications();
  221. // display current notifications
  222. $(opt.ref)[opt.method](notification);
  223. // call callback
  224. $(window).one('notification-complete', function(){
  225. callback && callback();
  226. });
  227. return pyro;
  228. };
  229. // Used by Pages and Navigation and is available for third-party add-ons.
  230. // Module must load jquery/jquery.ui.nestedSortable.js and jquery/jquery.cooki.js
  231. pyro.sort_tree = function($item_list, $url, $cookie, data_callback, post_sort_callback, sortable_opts)
  232. {
  233. // set options or create a empty object to merge with defaults
  234. sortable_opts = sortable_opts || {};
  235. // collapse all ordered lists but the top level
  236. $item_list.find('ul').children().hide();
  237. // this gets ran again after drop
  238. var refresh_tree = function() {
  239. // add the minus icon to all parent items that now have visible children
  240. $item_list.find('li:has(li:visible)').removeClass().addClass('minus');
  241. // add the plus icon to all parent items with hidden children
  242. $item_list.find('li:has(li:hidden)').removeClass().addClass('plus');
  243. // Remove any empty ul elements
  244. $('.plus, .minus').find('ul').not(':has(li)').remove();
  245. // remove the class if the child was removed
  246. $item_list.find("li:not(:has(ul li))").removeClass();
  247. // call the post sort callback
  248. post_sort_callback && post_sort_callback();
  249. }
  250. refresh_tree();
  251. // set the icons properly on parents restored from cookie
  252. $($.cookie($cookie)).has('ul').toggleClass('minus plus');
  253. // show the parents that were open on last visit
  254. $($.cookie($cookie)).children('ul').children().show();
  255. // show/hide the children when clicking on an <li>
  256. $item_list.find('li').live('click', function()
  257. {
  258. $(this).children('ul').children().slideToggle('fast');
  259. $(this).has('ul').toggleClass('minus plus');
  260. var items = [];
  261. // get all of the open parents
  262. $item_list.find('li.minus:visible').each(function(){ items.push('#' + this.id) });
  263. // save open parents in the cookie
  264. $.cookie($cookie, items.join(', '), { expires: 1 });
  265. return false;
  266. });
  267. // Defaults for nestedSortable
  268. var default_opts = {
  269. delay: 100,
  270. disableNesting: 'no-nest',
  271. forcePlaceholderSize: true,
  272. handle: 'div',
  273. helper: 'clone',
  274. items: 'li',
  275. opacity: .4,
  276. placeholder: 'placeholder',
  277. tabSize: 25,
  278. listType: 'ul',
  279. tolerance: 'pointer',
  280. toleranceElement: '> div',
  281. update: function(event, ui) {
  282. post = {};
  283. // create the array using the toHierarchy method
  284. post.order = $item_list.nestedSortable('toHierarchy');
  285. // pass to third-party devs and let them return data to send along
  286. if (data_callback) {
  287. post.data = data_callback(event, ui);
  288. }
  289. // Refresh UI (no more timeout needed)
  290. refresh_tree();
  291. $.post(SITE_URL + $url, post );
  292. }
  293. };
  294. // init nestedSortable with options
  295. $item_list.nestedSortable($.extend({}, default_opts, sortable_opts));
  296. }
  297. pyro.chosen = function()
  298. {
  299. // Chosen
  300. $('select:not(.skip)').livequery(function(){
  301. $(this).addClass('chzn').trigger("liszt:updated");
  302. $(".chzn").chosen();
  303. // This is a workaround for Chosen's visibility bug. In short if a select
  304. // is inside a hidden element Chosen sets the width to 0. This iterates through
  305. // the 0 width selects and sets a fixed width.
  306. $('.chzn-container').each(function(i, ele){
  307. if ($(ele).width() == 0) {
  308. $(ele).css('width', '236px');
  309. $(ele).find('.chzn-drop').css('width', '234px');
  310. $(ele).find('.chzn-search input').css('width', '200px');
  311. $(ele).find('.search-field input').css('width', '225px');
  312. }
  313. });
  314. });
  315. }
  316. // Create a clean slug from whatever garbage is in the title field
  317. pyro.generate_slug = function(input_form, output_form, space_character, disallow_dashes)
  318. {
  319. space_character = space_character || '-';
  320. $(input_form).slugify({ slug: output_form, type: space_character });
  321. }
  322. $(document).ajaxError(function(e, jqxhr, settings, exception) {
  323. pyro.add_notification($('<div class="alert error">'+exception+'</div>'));
  324. });
  325. $(document).ready(function() {
  326. pyro.init();
  327. pyro.chosen();
  328. });
  329. //close colorbox only when cancel button is clicked
  330. $('#cboxLoadedContent a.cancel').live('click', function(e) {
  331. e.preventDefault();
  332. $.colorbox.close();
  333. });
  334. // Title toggle
  335. $('a.toggle').click(function() {
  336. $(this).parent().next('.item').slideToggle(500);
  337. });
  338. // Draggable / Droppable
  339. $("#sortable").sortable({
  340. placeholder : 'dropzone',
  341. handle : '.draggable',
  342. update : function () {
  343. var order = $('#sortable').sortable('serialize');
  344. }
  345. });
  346. // Pretty Photo
  347. $('#main a:has(img)').addClass('prettyPhoto');
  348. $("a[class^='prettyPhoto']").prettyPhoto();
  349. // Tipsy
  350. $('.tooltip').tipsy({
  351. gravity: $.fn.tipsy.autoNS,
  352. fade: true,
  353. html: true
  354. });
  355. $('.tooltip-s').tipsy({
  356. gravity: 's',
  357. fade: true,
  358. html: true
  359. });
  360. $('.tooltip-e').tipsy({
  361. gravity: 'e',
  362. fade: true,
  363. html: true
  364. });
  365. $('.tooltip-w').tipsy({
  366. gravity: 'w',
  367. fade: true,
  368. html: true
  369. });
  370. //functions for codemirror
  371. $('.html_editor').each(function() {
  372. CodeMirror.fromTextArea(this, {
  373. mode: 'text/html',
  374. tabMode: 'indent',
  375. height : '500px',
  376. width : '500px',
  377. });
  378. });
  379. $('.css_editor').each(function() {
  380. CodeMirror.fromTextArea(this, {
  381. mode: 'css',
  382. tabMode: 'indent',
  383. height : '500px',
  384. width : '500px',
  385. });
  386. });
  387. $('.js_editor').each(function() {
  388. CodeMirror.fromTextArea(this, {
  389. mode: 'javascript',
  390. tabMode: 'indent',
  391. height : '500px',
  392. width : '500px',
  393. });
  394. });
  395. });