Dotclear

source: admin/js/common.js @ 3839:783854ebd4ce

Revision 3839:783854ebd4ce, 18.1 KB checked in by franck <carnet.franck.paul@…>, 7 years ago (diff)

Some refinements for sortable area on dashboard, and some code refactoring

Line 
1/*global $, jQuery, dotclear_htmlFontSize */
2/*exported chainHandler */
3'use strict';
4
5/* Set some CSS variables here
6-------------------------------------------------------- */
7// set base font-size of body (62.5% default, usually : 50% to 75%)
8if (typeof dotclear_htmlFontSize !== 'undefined') {
9  document.documentElement.style.setProperty('--html-font-size', dotclear_htmlFontSize);
10}
11/* ChainHandler, py Peter van der Beken
12-------------------------------------------------------- */
13function chainHandler(obj, handlerName, handler) {
14  obj[handlerName] = (function(existingFunction) {
15    return function() {
16      handler.apply(this, arguments);
17      if (existingFunction) existingFunction.apply(this, arguments);
18    };
19  })(handlerName in obj ? obj[handlerName] : null);
20}
21/* jQuery extensions
22-------------------------------------------------------- */
23jQuery.fn.check = function() {
24  return this.each(function() {
25    if (this.checked != undefined) {
26      this.checked = true;
27    }
28  });
29};
30jQuery.fn.unCheck = function() {
31  return this.each(function() {
32    if (this.checked != undefined) {
33      this.checked = false;
34    }
35  });
36};
37jQuery.fn.setChecked = function(status) {
38  return this.each(function() {
39    if (this.checked != undefined) {
40      this.checked = status;
41    }
42  });
43};
44jQuery.fn.toggleCheck = function() {
45  return this.each(function() {
46    if (this.checked != undefined) {
47      this.checked = !this.checked;
48    }
49  });
50};
51jQuery.fn.enableShiftClick = function() {
52  this.click(function(event) {
53    if (event.shiftKey) {
54      if (dotclear.lastclicked != '') {
55        var range;
56        var trparent = $(this).parents('tr');
57        if (trparent.nextAll('#' + dotclear.lastclicked).length != 0) range = trparent.nextUntil('#' + dotclear.lastclicked);
58        else range = trparent.prevUntil('#' + dotclear.lastclicked);
59        range.find('input[type=checkbox]').setChecked(dotclear.lastclickedstatus);
60        this.checked = dotclear.lastclickedstatus;
61      }
62    } else {
63      dotclear.lastclicked = $(this).parents('tr')[0].id;
64      dotclear.lastclickedstatus = this.checked;
65    }
66    return true;
67  });
68};
69jQuery.fn.toggleWithLegend = function(target, s) {
70  var defaults = {
71    img_on_txt: dotclear.img_plus_txt,
72    img_on_alt: dotclear.img_plus_alt,
73    img_off_txt: dotclear.img_minus_txt,
74    img_off_alt: dotclear.img_minus_alt,
75    unfolded_sections: dotclear.unfolded_sections,
76    hide: true,
77    speed: 0,
78    legend_click: false,
79    fn: false, // A function called on first display,
80    user_pref: false,
81    reverse_user_pref: false // Reverse cookie behavior
82  };
83  var p = jQuery.extend(defaults, s);
84  if (!target) {
85    return this;
86  }
87  var set_cookie = p.hide ^ p.reverse_cookie;
88  if (p.cookie && jQuery.cookie(p.cookie)) {
89    p.hide = p.reverse_cookie;
90  }
91  var set_user_pref = p.hide ^ p.reverse_user_pref;
92  if (p.user_pref && p.unfolded_sections !== undefined && (p.user_pref in p.unfolded_sections)) {
93    p.hide = p.reverse_user_pref;
94  }
95  var toggle = function(i, speed) {
96    speed = speed || 0;
97    if (p.hide) {
98      $(i).get(0).value = p.img_on_txt;
99      $(i).get(0).setAttribute('aria-label', p.img_on_alt);
100      target.addClass('hide');
101    } else {
102      $(i).get(0).value = p.img_off_txt;
103      $(i).get(0).setAttribute('aria-label', p.img_off_alt);
104      target.removeClass('hide');
105      if (p.fn) {
106        p.fn.apply(target);
107        p.fn = false;
108      }
109    }
110    if (p.cookie && set_cookie) {
111      if (p.hide ^ p.reverse_cookie) {
112        jQuery.cookie(p.cookie, '', {
113          expires: -1
114        });
115      } else {
116        jQuery.cookie(p.cookie, 1, {
117          expires: 30
118        });
119      }
120    }
121    p.hide = !p.hide;
122  };
123  return this.each(function() {
124    var b = document.createElement('input');
125    b.setAttribute('type', 'submit');
126    b.className = 'details-cmd';
127    b.value = p.img_on_txt;
128    b.setAttribute('aria-label', p.img_off_alt);
129
130    var ctarget = p.legend_click ? this : b;
131    $(ctarget).css('cursor', 'pointer');
132    if (p.legend_click) {
133      $(ctarget).find('label').css('cursor', 'pointer');
134    }
135    $(ctarget).click(function(e) {
136      if (p.user_pref && set_user_pref) {
137        jQuery.post('services.php', {
138          'f': 'setSectionFold',
139          'section': p.user_pref,
140          'value': (p.hide ^ p.reverse_user_pref ? 1 : 0),
141          xd_check: dotclear.nonce
142        }, function() {});
143        jQuery.cookie(p.user_pref, '', {
144          expires: -1
145        });
146      }
147      toggle(b, p.speed);
148      e.preventDefault();
149      return false;
150    });
151    toggle($(b).get(0));
152    $(this).prepend(b);
153  });
154};
155(function($) {
156  $.expandContent = function(opts) {
157    if (opts == undefined || opts.callback == undefined || !$.isFunction(opts.callback)) {
158      return;
159    }
160    if (opts.line != undefined) {
161      multipleExpander(opts.line, opts.lines, opts.callback);
162    }
163    opts.lines.each(function() {
164      singleExpander(this, opts.callback);
165    });
166  };
167  var singleExpander = function singleExpander(line, callback) {
168    $('<input class="details-cmd" type="submit" value="' + dotclear.img_plus_txt + '" aria-label="' + dotclear.img_plus_alt + '"/>').click(function(e) {
169      toggleArrow(this);
170      callback(line);
171      e.preventDefault();
172    }).prependTo($(line).children().get(0)); // first td
173  };
174  var multipleExpander = function multipleExpander(line, lines, callback) {
175    $('<input class="details-cmd" type="submit" value="' + dotclear.img_plus_txt + '" aria-label="' + dotclear.img_plus_alt + '"/>').click(function(e) {
176      var action = toggleArrow(this);
177      lines.each(function() {
178        toggleArrow(this.firstChild.firstChild, action);
179        callback(this, action);
180      });
181      e.preventDefault();
182    }).prependTo($(line).children().get(0)); // first td
183  };
184  var toggleArrow = function toggleArrow(button, action) {
185    action = action || '';
186    if (action == '') {
187      if (button.getAttribute('aria-label') == dotclear.img_plus_alt) {
188        action = 'open';
189      } else {
190        action = 'close';
191      }
192    }
193    if (action == 'open') {
194      button.value = dotclear.img_minus_txt;
195      button.setAttribute('aria-label', dotclear.img_minus_alt);
196    } else {
197      button.value = dotclear.img_plus_txt;
198      button.setAttribute('aria-label', dotclear.img_plus_alt);
199    }
200    return action;
201  };
202})(jQuery);
203jQuery.fn.helpViewer = function() {
204  if (this.length < 1) {
205    return this;
206  }
207  var p = {
208    img_on_txt: dotclear.img_plus_txt,
209    img_on_alt: dotclear.img_plus_alt,
210    img_off_txt: dotclear.img_minus_txt,
211    img_off_alt: dotclear.img_minus_alt
212  };
213  var This = this;
214  var toggle = function() {
215    $('#content').toggleClass('with-help');
216    if (document.all) {
217      if ($('#content').hasClass('with-help')) {
218        select = $('#content select:visible').hide();
219      } else {
220        select.show();
221      }
222    }
223    $('p#help-button span a').text($('#content').hasClass('with-help') ? dotclear.msg.help_hide : dotclear.msg.help);
224    sizeBox();
225    return false;
226  };
227  var sizeBox = function() {
228    This.css('height', 'auto');
229    if ($('#wrapper').height() > This.height()) {
230      This.css('height', $('#wrapper').height() + 'px');
231    }
232  };
233  var textToggler = function(o) {
234    var b = $('<input class="details-cmd" type="submit" value="' + p.img_on_txt + '" aria-label="' + p.img_on_alt + '"/>');
235    o.css('cursor', 'pointer');
236    var hide = true;
237    o.prepend(' ').prepend(b);
238    o.click(function() {
239      $(this).nextAll().each(function() {
240        if ($(this).is('h4')) {
241          return false;
242        }
243        $(this).toggle();
244        sizeBox();
245        return true;
246      });
247      hide = !hide;
248      var img = $(this).find('input.details-cmd');
249      if (!hide) {
250        img.attr('value', p.img_off_txt);
251        img.attr('aria-label', p.img_off_alt);
252      } else {
253        img.attr('value', p.img_on_txt);
254        img.attr('aria-label', p.img_on_alt);
255      }
256    });
257  };
258  this.addClass('help-box');
259  this.find('>hr').remove();
260  this.find('h4').each(function() {
261    textToggler($(this));
262  });
263  this.find('h4:first').nextAll('*:not(h4)').hide();
264  sizeBox();
265  var img = $('<p id="help-button"><span><a href="">' + dotclear.msg.help + '</a></span></p>');
266  var select = $();
267  img.click(function(e) {
268    return toggle();
269    e.preventDefault();
270  });
271  $('#content').append(img);
272  // listen for scroll
273  var peInPage = $('#help-button').offset().top;
274  $('#help-button').addClass('floatable');
275  var peInFloat = $('#help-button').offset().top - $(window).scrollTop();
276  $('#help-button').removeClass('floatable');
277  $(window).scroll(function() {
278    if ($(window).scrollTop() >= peInPage - peInFloat) {
279      $('#help-button').addClass('floatable');
280    } else {
281      $('#help-button').removeClass('floatable');
282    }
283  });
284  return this;
285};
286/* Dotclear common object
287-------------------------------------------------------- */
288var dotclear = {
289  msg: {},
290  enterKeyInForm: function(frm_id, ok_id, cancel_id) {
291    $(frm_id + ':not(' + cancel_id + ')').keyup(function(e) {
292      if (e.key == 'Enter') {
293        e.preventDefault();
294        e.stopPropagation();
295        $(ok_id).trigger('click');
296      }
297    });
298  },
299  condSubmit: function(chkboxes, target) {
300    var checkboxes = $(chkboxes),
301      submitButt = $(target);
302    if (checkboxes === undefined || submitButt === undefined) {
303      return;
304    }
305    // Set initial state
306    submitButt.attr('disabled', !checkboxes.is(':checked'));
307    if (!checkboxes.is(':checked')) {
308      submitButt.addClass('disabled');
309    } else {
310      submitButt.removeClass('disabled');
311    }
312    checkboxes.click(function() {
313      // Update target state
314      submitButt.attr('disabled', !checkboxes.is(':checked'));
315      if (!checkboxes.is(':checked')) {
316        submitButt.addClass('disabled');
317      } else {
318        submitButt.removeClass('disabled');
319      }
320    });
321  },
322  hideLockable: function() {
323    $('div.lockable').each(function() {
324      var current_lockable_div = this;
325      $(this).find('p.form-note').hide();
326      $(this).find('input').each(function() {
327        this.disabled = true;
328        $(this).width(($(this).width() - 14) + 'px');
329        var imgE = document.createElement('img');
330        imgE.src = 'images/locker.png';
331        imgE.style.position = 'absolute';
332        imgE.style.top = '1.8em';
333        imgE.style.left = ($(this).width() + 14) + 'px';
334        imgE.alt = dotclear.msg.click_to_unlock;
335        $(imgE).css('cursor', 'pointer');
336        $(imgE).click(function() {
337          $(this).hide();
338          $(this).prev('input').each(function() {
339            this.disabled = false;
340            $(this).width(($(this).width() + 14) + 'px');
341          });
342          $(current_lockable_div).find('p.form-note').show();
343        });
344        $(this).parent().css('position', 'relative');
345        $(this).after(imgE);
346      });
347    });
348  },
349  checkboxesHelpers: function(e, target, c, s) {
350    $(e).append(document.createTextNode(dotclear.msg.to_select));
351    $(e).append(document.createTextNode(' '));
352    $('<button type="button" class="checkbox-helper select-all">' + dotclear.msg.select_all + '</button>').click(function() {
353      if (target !== undefined) {
354        target.check();
355      } else {
356        $(e).parents('form').find('input[type="checkbox"]').check();
357      }
358      if (c !== undefined && s !== undefined) {
359        dotclear.condSubmit(c, s);
360      }
361      return false;
362    }).appendTo($(e));
363    $(e).append(document.createTextNode(' '));
364    $('<button type="button" class="checkbox-helper select-none">' + dotclear.msg.no_selection + '</button>').click(function() {
365      if (target !== undefined) {
366        target.unCheck();
367      } else {
368        $(e).parents('form').find('input[type="checkbox"]').unCheck();
369      }
370      if (c !== undefined && s !== undefined) {
371        dotclear.condSubmit(c, s);
372      }
373      return false;
374    }).appendTo($(e));
375    $(e).append(document.createTextNode(' '));
376    $('<button type="button" class="checkbox-helper select-reverse">' + dotclear.msg.invert_sel + '</button>').click(function() {
377      if (target !== undefined) {
378        target.toggleCheck();
379      } else {
380        $(e).parents('form').find('input[type="checkbox"]').toggleCheck();
381      }
382      if (c !== undefined && s !== undefined) {
383        dotclear.condSubmit(c, s);
384      }
385      return false;
386    }).appendTo($(e));
387  },
388  postsActionsHelper: function() {
389    $('#form-entries').submit(function() {
390      var action = $(this).find('select[name="action"]').val();
391      if (action === undefined) {
392        return;
393      }
394      var checked = false;
395      $(this).find('input[name="entries[]"]').each(function() {
396        if (this.checked) {
397          checked = true;
398        }
399      });
400      if (!checked) {
401        return false;
402      }
403      if (action == 'delete') {
404        return window.confirm(dotclear.msg.confirm_delete_posts.replace('%s', $('input[name="entries[]"]:checked').size()));
405      }
406      return true;
407    });
408  },
409  commentsActionsHelper: function() {
410    $('#form-comments').submit(function() {
411      var action = $(this).find('select[name="action"]').val();
412      var checked = false;
413      $(this).find('input[name="comments[]"]').each(function() {
414        if (this.checked) {
415          checked = true;
416        }
417      });
418      if (!checked) {
419        return false;
420      }
421      if (action == 'delete') {
422        return window.confirm(dotclear.msg.confirm_delete_comments.replace('%s', $('input[name="comments[]"]:checked').size()));
423      }
424      return true;
425    });
426  },
427  outgoingLinks: function(target) {
428    $(target).filter(function() {
429      return ((this.hostname && this.hostname != location.hostname && !$(this).hasClass('modal') && !$(this).hasClass('modal-image')) || $(this).hasClass('outgoing'));
430    }).each(function() {
431      $(this).prop('title', $(this).prop('title') + ' (' + dotclear.msg.new_window + ')');
432      if (!$(this).hasClass('outgoing')) {
433        $(this).append('&nbsp;<img class="outgoing-js" src="images/outgoing-link.svg" alt=""/>');
434      }
435    }).click(function(e) {
436      e.preventDefault();
437      window.open($(this).attr('href'));
438    });
439  }
440};
441/* On document ready
442-------------------------------------------------------- */
443$(function() {
444  // remove class no-js from html tag; cf style/default.css for examples
445  $('body').removeClass('no-js').addClass('with-js');
446  $('body').contents().each(function() {
447    if (this.nodeType == 8) {
448      var data = this.data;
449      data = data.replace(/ /g, '&nbsp;').replace(/\n/g, '<br/>');
450      $('<span class="tooltip" aria-hidden="true">' + $('#footer a').prop('title') + data + '</span>').appendTo('#footer a');
451    }
452  });
453  // manage outgoing links
454  dotclear.outgoingLinks('a');
455  // Popups: dealing with Escape key fired
456  $('#dotclear-admin.popup').keyup(function(e) {
457    if (e.key == 'Escape') {
458      e.preventDefault();
459      window.close();
460      return false;
461    }
462  });
463  // Blog switcher
464  $('#switchblog').change(function() {
465    this.form.submit();
466  });
467  var menu_settings = {
468    img_on_src: dotclear.img_menu_off,
469    img_off_src: dotclear.img_menu_on,
470    legend_click: true,
471    speed: 100
472  };
473  $('#blog-menu h3:first').toggleWithLegend($('#blog-menu ul:first'), $.extend({
474    user_pref: 'dc_blog_menu'
475  }, menu_settings));
476  $('#system-menu h3:first').toggleWithLegend($('#system-menu ul:first'), $.extend({
477    user_pref: 'dc_system_menu'
478  }, menu_settings));
479  $('#plugins-menu h3:first').toggleWithLegend($('#plugins-menu ul:first'), $.extend({
480    user_pref: 'dc_plugins_menu'
481  }, menu_settings));
482  $('#favorites-menu h3:first').toggleWithLegend($('#favorites-menu ul:first'), $.extend({
483    user_pref: 'dc_favorites_menu',
484    hide: false,
485    reverse_user_pref: true
486  }, menu_settings));
487  $('#help').helpViewer();
488  // Notices
489  $('p.success,p.warning,p.error,div.error').each(function() {
490    $(this).addClass('close-notice-parent');
491    $(this).append('<button class="close-notice" type="button"><img src="images/close.png" alt="' + dotclear.msg.close_notice + '" /></button>');
492  });
493  $('button.close-notice').click(function(e) {
494    e.preventDefault();
495    $(this).parent().hide();
496  });
497  // Password
498  $('form:has(input[type=password][name=your_pwd])').submit(function() {
499    var e = this.elements.your_pwd;
500    if (e.value == '') {
501      $(e).addClass('missing').focusout(function() {
502        $(this).removeClass('missing');
503      });
504      e.focus();
505      return false;
506    }
507    return true;
508  });
509  // Cope with ellipsis'ed cells
510  $('table .maximal').each(function() {
511    if (this.offsetWidth < this.scrollWidth) {
512      if (this.title == '') {
513        this.title = this.innerText;
514        $(this).addClass('ellipsis');
515      }
516    }
517  });
518  $('table .maximal.ellipsis a').each(function() {
519    if (this.title == '') {
520      this.title = this.innerText;
521    }
522  });
523  // Advanced users
524  if (dotclear.hideMoreInfo) {
525    $('.more-info,.form-note:not(.warn,.warning,.info)').addClass('no-more-info');
526  }
527  // Ajax loader activity indicator
528  if (dotclear.showAjaxLoader) {
529    $(document).ajaxStart(function() {
530      $('body').addClass('ajax-loader');
531      $('div.ajax-loader').show();
532    });
533    $(document).ajaxStop(function() {
534      $('body').removeClass('ajax-loader');
535      $('div.ajax-loader').hide();
536    });
537  }
538  // Main menu collapser
539  var objMain = $('#wrapper');
540
541  function showSidebar() {
542    // Show sidebar
543    objMain.removeClass('hide-mm');
544    $.cookie('sidebar-pref', null, {
545      expires: 30
546    });
547  }
548
549  function hideSidebar() {
550    // Hide sidebar
551    objMain.addClass('hide-mm');
552    $.cookie('sidebar-pref', 'hide-mm', {
553      expires: 30
554    });
555  }
556  // Sidebar separator
557  var objSeparator = $('#collapser');
558  objSeparator.click(function(e) {
559    e.preventDefault();
560    if (objMain.hasClass('hide-mm')) {
561      showSidebar();
562      $('#main-menu input#qx').focus();
563    } else {
564      hideSidebar();
565      $('#content a.go_home').focus();
566    }
567  });
568  if ($.cookie('sidebar-pref') == 'hide-mm') {
569    objMain.addClass('hide-mm');
570  } else {
571    objMain.removeClass('hide-mm');
572  }
573  // totop scroll
574  $(window).scroll(function() {
575    if ($(this).scrollTop() != 0) {
576      $('#gototop').fadeIn();
577    } else {
578      $('#gototop').fadeOut();
579    }
580  });
581  $('#gototop').click(function(e) {
582    $('body,html').animate({
583      scrollTop: 0
584    }, 800);
585    e.preventDefault();
586  });
587});
Note: See TracBrowser for help on using the repository browser.

Sites map