ChiliProject is not maintained anymore. Please be advised that there will be no more updates.

We do not recommend that you setup new ChiliProject instances and we urge all existing users to migrate their data to a maintained system, e.g. Redmine. We will provide a migration script later. In the meantime, you can use the instructions by Christian Daehn.

mobile.js

The current JS for mobile agent adjustments (WIP) - Tim Felgentreff, 2011-02-01 06:51 am

Download (8.9 kB)

 
1
window.MobileJS = {}
2
3
MobileJS.cssua = function(html, userAgent) {
4
  /** This block is taken from cssua.js
5
      User-agent specific CSS support
6
7
      Created: 2006-06-10-1635
8
      Modified: 2011-01-10-1101
9
10
      Copyright (c)2006-2011 Stephen M. McKamey
11
      Distributed under The MIT License */
12
13
  /*const string*/ var PREFIX = " ua-";
14
15
  var R_All = /[\w\-\.]+[\/][v]?\d+(\.\d+)*/g,
16
      R_AOL = /\b(aol|america online browser)[\s\/]*(\d+(\.\d+)*)/,
17
      R_MSIE = /\b(msie|microsoft internet explorer)[\s\/]*(\d+(\.\d+)*)/,
18
      R_Gecko = /rv[:](\d+(\.\d+)*).*?\bgecko[\/]\d+/,
19
      R_Opera = /\bopera[\s\/]*(\d+(\.\d+)*)/,
20
      R_Android = /\bandroid[\s]+(\d+(\.\d+)*)/,
21
      R_iOS = /\bos[\s]+(\d+(\_\d+)*) like mac os x/,
22
      R_WinPhone = /\bwindows phone os (\d+(\_\d+)*)/,
23
      R_MSPIE = /\b(mspie|microsoft pocket internet explorer)[\s\/]*(\d+(\.\d+)*)/,
24
      R_iCab = /\bicab[\s\/]*(\d+(\.\d+)*)/,
25
      R_BlackBerry = /\bblackberry\w*[\s\/]+(\d+(\.\d+)*)/,
26
      R_mobile = /(\bandroid\b|\bipad\b|\bipod\b|\bblackberry|\bwebos\b|\bwindows ce\b|\bwindows phone os\b|\bwindows ce\b|\bpalm|\bsymbian|\bj2me\b|\bdocomo\b|\bpda\b|\bchtml\b|\bmidp\b|\bcldc\b|\w*?mobile\w*?|\w*?phone\w*?)/;
27
28
  var cssua = {
29
    /*Map<string,string>*/
30
    parse : function(/*string*/ uaStr) {
31
      /*Map<string,string>*/
32
      var ua = {};
33
34
      uaStr = (""+uaStr).toLowerCase();
35
      if (!uaStr) {
36
        return ua;
37
      }
38
39
      // do this first for all (covers generic user-agents)
40
      var raw = uaStr.match(R_All);
41
      if (raw) {
42
        for (var i=0; i<raw.length; i++) {
43
          var s = raw[i].indexOf('/'),
44
          b = raw[i].substring(0, s);
45
          if (b && b !== "mozilla") {
46
            // shorten this common engine
47
            if (b === "applewebkit") {
48
              b = "webkit";
49
            }
50
            ua[b] = raw[i].substr(s+1);
51
          }
52
        }
53
      }
54
55
       // aol uses multiple engines so continue checking
56
      if (R_AOL.exec(uaStr)) {
57
         ua.aol = RegExp.$2;
58
      }
59
60
       // order is important as user-agents spoof each other
61
      if (R_Opera.exec(uaStr)) {
62
         ua.opera = RegExp.$1;
63
      } else if (R_iCab.exec(uaStr)) {
64
         ua.icab = RegExp.$1;
65
      } else if (R_MSIE.exec(uaStr)) {
66
         ua.ie = RegExp.$2;
67
      } else if (R_MSPIE.exec(uaStr)) {
68
         ua.mspie = RegExp.$2;
69
      } else if (R_Gecko.exec(uaStr)) {
70
         ua.gecko = RegExp.$1;
71
      } else if (R_Android.exec(uaStr)) {
72
         ua.android = RegExp.$1;
73
      } else if (R_iOS.exec(uaStr)) {
74
         ua.ios = RegExp.$1.split('_').join('.');
75
      } else if (R_WinPhone.exec(uaStr)) {
76
         ua.winphone = RegExp.$1;
77
      }
78
79
       // ensure that mobile devices have indication
80
      if (!ua.blackberry && R_BlackBerry.exec(uaStr)) {
81
         ua.blackberry = RegExp.$1;
82
      }
83
      if (R_mobile.exec(uaStr)) {
84
         ua.mobile = RegExp.$1;
85
      }
86
87
      // version standardization
88
      if (ua.safari) {
89
        if (ua.chrome || (ua.mobile && !ua.ios)) {
90
          delete ua.safari;
91
        } else if (ua.version) {
92
          ua.safari = ua.version;
93
        } else {
94
          ua.safari = ({
95
            "419": "2.0.4",
96
            "417": "2.0.3",
97
            "416": "2.0.2",
98
            "412": "2.0",
99
            "312": "1.3",
100
            "125": "1.2",
101
            "85": "1.0"
102
          })[parseInt(ua.safari, 10)] || ua.safari;
103
        }
104
      } else if (ua.opera && ua.version) {
105
         ua.opera = ua.version;
106
      }
107
108
      if (ua.version) {
109
        delete ua.version;
110
      }
111
112
      return ua;
113
    },
114
115
    /*string*/
116
    format : function (/*Map<string,string>*/ ua) {
117
      /*string*/
118
      function format(/*string*/ b, /*string*/ v) {
119
        b = b.split(' ').join('_').split('.').join('-');
120
        /*string*/ var css = PREFIX+b;
121
        if (v) {
122
          v = v.split(' ').join('_').split('.').join('-');
123
          var i = v.indexOf('-');
124
          while (i > 0) {
125
            // loop through chopping last '-' to end off
126
            // concat result onto return string
127
            css += PREFIX+b+'-'+v.substring(0, i);
128
            i = v.indexOf('-', i+1);
129
          }
130
          css += PREFIX+b+'-'+v;
131
        }
132
        return css;
133
      }
134
135
      var  uaCss = "";
136
      for (var b in ua) {
137
        if (b && ua.hasOwnProperty(b)) {
138
          uaCss += format(b, ua[b]);
139
        }
140
      }
141
142
      // user-agent classNames
143
      return uaCss;
144
    },
145
146
    /* Encodes parsed userAgent object as a compact URI-Encoded key-value collection */
147
    /*string*/
148
    encode : function(/*Map<string,string>*/ ua) {
149
      var query = "";
150
      for (var b in ua) {
151
        if (b && ua.hasOwnProperty(b)) {
152
          if (query) {
153
            query += "&";
154
          }
155
          query += encodeURIComponent(b)+"="+encodeURIComponent(ua[b]);
156
        }
157
      }
158
      return query;
159
    }
160
  };
161
162
  // calculate userAgent
163
  cssua.userAgent = cssua.ua = cssua.parse(userAgent);
164
165
  // append CSS classes to HTML node
166
  var ua = cssua.format(cssua.ua);
167
  if (html.className) {
168
    html.className += ua;
169
  } else {
170
    html.className = ua.substr(1);
171
  }
172
173
  return cssua;
174
}
175
176
MobileJS.top_menu = function() {
177
  $("top-menu").hide();
178
  $$('div.quick-search/h1').first().observe("click", function(event) {
179
    $("top-menu").toggle();
180
  });
181
}
182
183
MobileJS.main_menu = function() {
184
  // Get visible menu links
185
  menu_links = $('main-menu').select("a").collect(function(a) {
186
    a.hide();
187
    return { name: a.innerHTML, target: a.getAttribute("href") };
188
  });
189
  // Build selectbox
190
  var selectbox = "<select id='main-menu-selectbox'>";
191
  menu_links.each(function(ary) {
192
    selectbox = selectbox + "<option value='" + ary.target + "'>" + ary.name + "</option>";
193
  });
194
  selectbox = selectbox + "<option value='quick-search'>" + $('quick-search').select("a").first().innerHTML + " ... </option>"
195
  selectbox = selectbox + "</select>";
196
  // insert selectbox, set current page value and install onchange handler
197
  $('main-menu').innerHTML = selectbox;
198
  var current_select_value = menu_links.select(function(ary) {
199
    return ary.target.search(document.location.pathname) > -1;
200
  }).first();
201
  if (current_select_value != undefined) {
202
    $('main-menu-selectbox').value = current_select_value.target;
203
  }
204
  $('main-menu-selectbox').observe("change", function(event) {
205
    if (this.value == "quick-search") {
206
      $('quick-search').show();
207
    } else {
208
      $('quick-search').hide();
209
      document.location.pathname = this.value;
210
    }
211
  });
212
}
213
214
MobileJS.issues_filter = function() {
215
  var qf = $("query_form");
216
  if (qf == undefined) {
217
    return false;
218
  }
219
  qf.hide();
220
  var headline = qf.up().select("h2").first();
221
  headline.observe("click", function(event) {
222
    $("query_form").toggle();
223
  });
224
}
225
226
MobileJS.quick_search = function() {
227
  $('quick-search').hide();
228
}
229
230
MobileJS.headline = function() {
231
  var magic_header_width_factor = 1.5;
232
  var current_width = $$("#header/h1").first().getWidth() * magic_header_width_factor;
233
  var screen_width = document.width;
234
  if (current_width > screen_width) {
235
    // Try decreasing kerning, first
236
    $$("#header/h1").first().style.letterSpacing="-0.2ex"
237
    current_width = $$("#header/h1").first().getWidth() * magic_header_width_factor;
238
  }
239
  if (current_width > screen_width) {
240
    // Try decreasing font size, but not too far
241
    for (i = 2.0; i > 1.0; i = i - 0.1) {
242
      $$("#header/h1").first().style.fontSize = i + "em";
243
      current_width = $$("#header/h1").first().getWidth() * magic_header_width_factor;
244
      if (current_width < screen_width) break;
245
    }
246
  }
247
}
248
249
MobileJS.contextual_actions = function() {
250
  var contextual = $$("#content").first().select(".contextual").first();
251
  if (contextual == undefined) {
252
    return false;
253
  }
254
  var context_links = contextual.select("a");
255
  if (context_links.size() == 0) {
256
    return false;
257
  }
258
  context_links.each(function(a) {
259
    a.observe("click", function() {
260
      contextual.hide();
261
      return true;
262
    });
263
  });
264
  contextual.hide();
265
  var headline = contextual.up().select("h2").first();
266
  headline.observe("click", function(event) {
267
    contextual.toggle();
268
  });
269
}
270
271
MobileJS.hidden_sidebar = function() {
272
  $("sidebar").hide();
273
  var sidebar_button = "<span id='sidebar-toggle-button'>&nbsp;&nbsp;</span>";
274
  $("main-menu").insert({before: sidebar_button});
275
  $("sidebar-toggle-button").observe("click", function() {
276
    $("sidebar").toggle();
277
  });
278
}
279
280
MobileJS.screen_adjustment = function() {
281
  var mobile_viewport_tag = '<meta name = "viewport" ' +
282
      'content = "width=device-width; initial-scale=1.0;' +
283
      'maximum-scale=1.0; user-scalable=0;" />';
284
  $$('head').first().insert({bottom: mobile_viewport_tag});
285
}
286
287
document.observe("dom:loaded", function() {
288
  if (cssua.userAgent.mobile) {
289
    MobileJS.headline();
290
    MobileJS.top_menu();
291
    MobileJS.quick_search();
292
    MobileJS.main_menu();
293
    MobileJS.issues_filter();
294
    MobileJS.contextual_actions();
295
    MobileJS.hidden_sidebar();
296
    MobileJS.screen_adjustment();
297
  }
298
});
299
300
window.cssua = MobileJS.cssua(document.documentElement, navigator.userAgent);