Issues (1839)

boinc/themes/boinc/js/jquery.detectwidths.js (3 issues)

1
/**
2
 * JQuery functions used to determine whether the theme layout should
3
 * use a fixed-width navigation bar or a mobile hamburger style menu.
4
 *
5
 * The functions determine the width of the navigation bar text. This
6
 * text is translated into many languages, and is not static. If the
7
 * text width is too wide for the screen, inject CSS to toggle between
8
 * using a hamburger menu (usehamburger) or a navigation bar
9
 * (usenavbar).
10
 *
11
 * If the menubar text is so wide it will not fit on the desktop width
12
 * site (980 px), then the CSS class (oversizemenubar) will be
13
 * used. In addition, the oversize flag will be set. This flag informs
14
 * the resize function not to swap out the hamburger menu
15
 * (userhamburger) for the navigation bar, as the latter will be too
16
 * wide for the layout.
17
 */
18
19
/*
20
 * The mobile and desktop minimum breakpoints set here must match the
21
 * breakpoints set in the CSS @media query. See file
22
 * css/responsive-media.css.
23
 *
24
 * N.B. These breakpoints may be different if you are using a sub-theme.
25
 */
26
var padding = 30;
27
var mobile_bp = 750;
28
var desktop_min = 980;
29
var oversize = 0;
30
31
/*
32
 * jQuery plugin from http://www.foliotek.com/devblog/getting-the-width-of-a-hidden-element-with-jquery-using-width/
33
 * Obtains the width of the hidden item.
34
 * Returns a dim object containing the items heights and widths.
35
 */
36
(function ($) {
37
$.fn.getHiddenDimensions = function (includeMargin) {
38
    var $item = this,
39
    props = { display: 'block' },
40
    dim = { width: 0, height: 0, innerWidth: 0, innerHeight: 0, outerWidth: 0, outerHeight: 0 },
41
    $hiddenParents = $item.parents().andSelf().not(':visible'),
42
    includeMargin = (includeMargin == null) ? false : includeMargin;
0 ignored issues
show
Comparing includeMargin to null using the == operator is not safe. Consider using === instead.
Loading history...
43
44
    var oldProps = [];
45
    $hiddenParents.each(function () {
46
        var old = {};
47
48
        for (var name in props) {
0 ignored issues
show
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
49
            old[name] = this.style[name];
50
            this.style[name] = props[name];
51
        }
52
53
        oldProps.push(old);
54
    });
55
56
    dim.width = $item.width();
57
    dim.outerWidth = $item.outerWidth(includeMargin);
58
    dim.innerWidth = $item.innerWidth();
59
    dim.height = $item.height();
60
    dim.innerHeight = $item.innerHeight();
61
    dim.outerHeight = $item.outerHeight(includeMargin);
62
63
    $hiddenParents.each(function (i) {
64
        var old = oldProps[i];
65
        for (var name in props) {
0 ignored issues
show
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
66
            this.style[name] = old[name];
67
        }
68
    });
69
70
    return dim;
71
}
72
}(jQuery));
73
74
75
/**
76
 * Helper function to obtain the width of the navigation bar elements,
77
 * regardless of its visibility.
78
 *
79
 * Returns the total width of the two menu items plus padding.
80
 */
81
function getNavWidth() {
82
  var maindims   = $('#main-menu ul').getHiddenDimensions();
83
  var actiondims = $('#action-links ul').getHiddenDimensions();
84
  var total_width = maindims.outerWidth + actiondims.outerWidth + padding;
85
  return total_width;
86
}
87
88
$(document).ready(function() {
89
  var window_width = $(window).width();
90
  var total_width = getNavWidth();
91
  if ( ((total_width) > Math.min(window_width, desktop_min)) || window_width <= mobile_bp ) {
92
    $('#header-wrapper div').addClass('usehamburger');
93
  } else {
94
    $('#header-wrapper div').addClass('usenavbar');
95
  }
96
  if (total_width > desktop_min) {
97
    oversize = 1;
98
    if (window_width > desktop_min) {
99
      $('#header-wrapper div').addClass('oversizemenubar');
100
    }
101
  }
102
});
103
104
105
$(window).resize(function() {
106
  var window_width = $(window).width();
107
  var total_width = getNavWidth();
108
109
  if (total_width > desktop_min) {
110
    oversize = 1;
111
    if (window_width > desktop_min) {
112
      $('#header-wrapper div').addClass('oversizemenubar');
113
    } else {
114
      $('#header-wrapper div').removeClass('oversizemenubar');
115
    }
116
  }
117
118
  if ($('#header-wrapper div').hasClass('usenavbar')) {
119
    if ( total_width > Math.min(window_width, desktop_min) || window_width <= mobile_bp ) {
120
      $('#header-wrapper div').removeClass('usenavbar');
121
      $('#header-wrapper div').addClass('usehamburger');
122
    }
123
  }
124
  if ($('#header-wrapper div').hasClass('usehamburger')) {
125
    if ( (window_width >= desktop_min) && !oversize ) {
126
      $('#header-wrapper div').removeClass('usehamburger');
127
      $('#header-wrapper div').addClass('usenavbar');
128
    }
129
    // Set CSS of mobile menu to display: none when window is resized.
130
    document.getElementById("navigation-mmt").style.display = "none";
131
  }
132
});
133