Bringing VersionCompare into zamboni, as well as user agent detection.
This commit is contained in:
Родитель
dffb52cc03
Коммит
5825249d19
|
@ -1,122 +1,3 @@
|
|||
/* TODO(jbalogh): save from amo2009. */
|
||||
var UA_PATTERN_FIREFOX = /Mozilla.*(Firefox|Minefield|Namoroka|Shiretoko|GranParadiso|BonEcho|Iceweasel|Fennec|MozillaDeveloperPreview)\/([^\s]*).*$/;
|
||||
var UA_PATTERN_SEAMONKEY = /Mozilla.*(SeaMonkey|Iceape)\/([^\s]*).*$/;
|
||||
var UA_PATTERN_MOBILE = /Mozilla.*(Fennec)\/([^\s]*)$/;
|
||||
var UA_PATTERN_THUNDERBIRD = /Mozilla.*(Thunderbird|Shredder|Lanikai)\/([^\s*]*).*$/;
|
||||
|
||||
/* TODO(jbalogh): save from amo2009. */
|
||||
function VersionCompare() {
|
||||
/**
|
||||
* Mozilla-style version numbers comparison in Javascript
|
||||
* (JS-translated version of PHP versioncompare component)
|
||||
* @return -1: a<b, 0: a==b, 1: a>b
|
||||
*/
|
||||
this.compareVersions = function(a,b) {
|
||||
var al = a.split('.');
|
||||
var bl = b.split('.');
|
||||
|
||||
for (var i=0; i<al.length || i<bl.length; i++) {
|
||||
var ap = (i<al.length ? al[i] : null);
|
||||
var bp = (i<bl.length ? bl[i] : null);
|
||||
|
||||
var r = this.compareVersionParts(ap,bp);
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* helper function: compare a single version part
|
||||
*/
|
||||
this.compareVersionParts = function(ap,bp) {
|
||||
var avp = this.parseVersionPart(ap);
|
||||
var bvp = this.parseVersionPart(bp);
|
||||
|
||||
var r = this.cmp(avp['numA'],bvp['numA']);
|
||||
if (r) return r;
|
||||
|
||||
r = this.strcmp(avp['strB'],bvp['strB']);
|
||||
if (r) return r;
|
||||
|
||||
r = this.cmp(avp['numC'],bvp['numC']);
|
||||
if (r) return r;
|
||||
|
||||
return this.strcmp(avp['extraD'],bvp['extraD']);
|
||||
}
|
||||
|
||||
/**
|
||||
* helper function: parse a version part
|
||||
*/
|
||||
this.parseVersionPart = function(p) {
|
||||
if (p == '*') {
|
||||
return {
|
||||
'numA' : Number.MAX_VALUE,
|
||||
'strB' : '',
|
||||
'numC' : 0,
|
||||
'extraD' : ''
|
||||
};
|
||||
}
|
||||
|
||||
var pattern = /^([-\d]*)([^-\d]*)([-\d]*)(.*)$/;
|
||||
var m = pattern.exec(p);
|
||||
|
||||
var r = {
|
||||
'numA' : parseInt(m[1]),
|
||||
'strB' : m[2],
|
||||
'numC' : parseInt(m[3]),
|
||||
'extraD' : m[4]
|
||||
};
|
||||
|
||||
if (r['strB'] == '+') {
|
||||
r['numA']++;
|
||||
r['strB'] = 'pre';
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* helper function: compare numeric version parts
|
||||
*/
|
||||
this.cmp = function(an,bn) {
|
||||
if (isNaN(an)) an = 0;
|
||||
if (isNaN(bn)) bn = 0;
|
||||
|
||||
if (an < bn)
|
||||
return -1;
|
||||
|
||||
if (an > bn)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* helper function: compare string version parts
|
||||
*/
|
||||
this.strcmp = function(as,bs) {
|
||||
if (as == bs)
|
||||
return 0;
|
||||
|
||||
// any string comes *before* the empty string
|
||||
if (as == '')
|
||||
return 1;
|
||||
|
||||
if (bs == '')
|
||||
return -1;
|
||||
|
||||
// normal string comparison for non-empty strings (like strcmp)
|
||||
if (as < bs)
|
||||
return -1;
|
||||
else if(as > bs)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* TODO(jbalogh): save from amo2009. */
|
||||
/**
|
||||
|
|
|
@ -51,7 +51,7 @@ $(document).ready(function() {
|
|||
/* No restart required box. (Only shown in Fx4+). */
|
||||
var no_restart = $('#addon-summary #no-restart');
|
||||
if (no_restart.length && z.browser.firefox
|
||||
&& (new VersionCompare()).compareVersions(z.browserVersion, '4.0a1') > 0) {
|
||||
&& VersionCompare.compareVersions(z.browserVersion, '4.0a1') > 0) {
|
||||
no_restart.show();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
/* Browser Utilities
|
||||
* Based on amo2009/addons.js
|
||||
**/
|
||||
|
||||
var escape_ = function(s){
|
||||
return s.replace('&', '&').replace('>', '>').replace('<', '<')
|
||||
.replace("'", ''').replace('"', '"');
|
||||
};
|
||||
|
||||
function BrowserUtils() {
|
||||
"use strict";
|
||||
|
||||
var exports = {},
|
||||
userAgentStrings = {
|
||||
'firefox' : /Mozilla.*(Firefox|Minefield|Namoroka|Shiretoko|GranParadiso|BonEcho|Iceweasel|Fennec|MozillaDeveloperPreview)\/([^\s]*).*$/,
|
||||
'seamonkey': /Mozilla.*(SeaMonkey|Iceape)\/([^\s]*).*$/,
|
||||
'mobile': /Mozilla.*(Fennec)\/([^\s]*)$/,
|
||||
'thunderbird': /Mozilla.*(Thunderbird|Shredder|Lanikai)\/([^\s*]*).*$/
|
||||
},
|
||||
osStrings = {
|
||||
'windows': 'Win32',
|
||||
'mac': 'Mac',
|
||||
'linux': 'Linux'
|
||||
};
|
||||
|
||||
// browser detection
|
||||
var browser = exports.browser = {},
|
||||
browserVersion = 0,
|
||||
pattern, match, i;
|
||||
for (i in userAgentStrings) {
|
||||
if (userAgentStrings.hasOwnProperty(i)) {
|
||||
pattern = userAgentStrings[i];
|
||||
match = pattern.exec(navigator.userAgent);
|
||||
browser[i] = !!(match && match.length === 3);
|
||||
if (browser[i]) {
|
||||
browserVersion = escape_(match[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (browser.mobile) browser.firefox = false;
|
||||
exports.browserVersion = browserVersion;
|
||||
|
||||
var os = exports.os = {},
|
||||
platform = "";
|
||||
for (i in osStrings) {
|
||||
if (osStrings.hasOwnProperty(i)) {
|
||||
pattern = osStrings[i];
|
||||
if (navigator.platform.indexOf(pattern) != -1) {
|
||||
$(document.body).addClass(os);
|
||||
os[i] = true;
|
||||
platform = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
os['other'] = !platform;
|
||||
exports.platform = platform;
|
||||
|
||||
return exports;
|
||||
}
|
||||
|
||||
var VersionCompare = {
|
||||
/**
|
||||
* Mozilla-style version numbers comparison in Javascript
|
||||
* (JS-translated version of PHP versioncompare component)
|
||||
* @return -1: a<b, 0: a==b, 1: a>b
|
||||
*/
|
||||
compareVersions: function(a,b) {
|
||||
var al = a.split('.'),
|
||||
bl = b.split('.'),
|
||||
ap, bp, r, i;
|
||||
for (var i=0; i<al.length || i<bl.length; i++) {
|
||||
ap = (i<al.length ? al[i] : null);
|
||||
bp = (i<bl.length ? bl[i] : null);
|
||||
r = this.compareVersionParts(ap,bp);
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* helper function: compare a single version part
|
||||
*/
|
||||
compareVersionParts: function(ap,bp) {
|
||||
var avp = this.parseVersionPart(ap),
|
||||
bvp = this.parseVersionPart(bp),
|
||||
r = this.cmp(avp['numA'],bvp['numA']);
|
||||
if (r) return r;
|
||||
r = this.strcmp(avp['strB'],bvp['strB']);
|
||||
if (r) return r;
|
||||
r = this.cmp(avp['numC'],bvp['numC']);
|
||||
if (r) return r;
|
||||
return this.strcmp(avp['extraD'],bvp['extraD']);
|
||||
},
|
||||
|
||||
/**
|
||||
* helper function: parse a version part
|
||||
*/
|
||||
parseVersionPart: function(p) {
|
||||
if (p == '*') {
|
||||
return {
|
||||
'numA' : Number.MAX_VALUE,
|
||||
'strB' : '',
|
||||
'numC' : 0,
|
||||
'extraD' : ''
|
||||
};
|
||||
}
|
||||
var pattern = /^([-\d]*)([^-\d]*)([-\d]*)(.*)$/,
|
||||
m = pattern.exec(p),
|
||||
r = {
|
||||
'numA' : parseInt(m[1]),
|
||||
'strB' : m[2],
|
||||
'numC' : parseInt(m[3]),
|
||||
'extraD' : m[4]
|
||||
};
|
||||
if (r['strB'] == '+') {
|
||||
r['numA']++;
|
||||
r['strB'] = 'pre';
|
||||
}
|
||||
return r;
|
||||
},
|
||||
|
||||
/**
|
||||
* helper function: compare numeric version parts
|
||||
*/
|
||||
cmp: function(an,bn) {
|
||||
if (isNaN(an)) an = 0;
|
||||
if (isNaN(bn)) bn = 0;
|
||||
if (an < bn)
|
||||
return -1;
|
||||
if (an > bn)
|
||||
return 1;
|
||||
return 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* helper function: compare string version parts
|
||||
*/
|
||||
strcmp: function(as,bs) {
|
||||
if (as == bs)
|
||||
return 0;
|
||||
// any string comes *before* the empty string
|
||||
if (as == '')
|
||||
return 1;
|
||||
if (bs == '')
|
||||
return -1;
|
||||
// normal string comparison for non-empty strings (like strcmp)
|
||||
if (as < bs)
|
||||
return -1;
|
||||
else if(as > bs)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
};
|
|
@ -11,8 +11,7 @@ z.button.after = {'contrib': function(xpi_url, status) {
|
|||
}
|
||||
}};
|
||||
|
||||
var vc = new VersionCompare(),
|
||||
notavail = '<div class="extra"><span class="notavail">{0}</span></div>',
|
||||
var notavail = '<div class="extra"><span class="notavail">{0}</span></div>',
|
||||
download_re = new RegExp('(/downloads/(?:latest|file)/\\d+)');
|
||||
|
||||
/* Called by the jQuery plugin to set up a single button. */
|
||||
|
@ -67,8 +66,8 @@ var installButton = function() {
|
|||
// min and max only exist if the add-on is compatible with request[APP].
|
||||
if (appSupported) {
|
||||
// The user *has* an older/newer browser.
|
||||
olderBrowser = vc.compareVersions(z.browserVersion, min) < 0;
|
||||
newerBrowser = vc.compareVersions(z.browserVersion, max) > 0;
|
||||
olderBrowser = VersionCompare.compareVersions(z.browserVersion, min) < 0;
|
||||
newerBrowser = VersionCompare.compareVersions(z.browserVersion, max) > 0;
|
||||
}
|
||||
|
||||
// Helper for dealing with lazy-loaded z.button.messages.
|
||||
|
|
|
@ -98,41 +98,7 @@ _.haskey = function(obj, key) {
|
|||
|
||||
|
||||
/* Detect browser, version, and OS. */
|
||||
z.browser = {firefox: false, seamonkey: false, mobile: false,
|
||||
thunderbird: false};
|
||||
z.browserVersion = 0;
|
||||
z.os = {windows: false, mac: false, linux: false, other: false};
|
||||
|
||||
(function(){
|
||||
// Globals are coming from amo2009/addons.js.
|
||||
var ua = function(browser, pattern) {
|
||||
match = pattern.exec(navigator.userAgent);
|
||||
if (match && match.length == 3) {
|
||||
z.browser[browser] = true;
|
||||
z.browserVersion = escape_(match[2]);
|
||||
}
|
||||
}
|
||||
// Mobile comes after Firefox to overwrite the browser version.
|
||||
ua('firefox', UA_PATTERN_FIREFOX);
|
||||
ua('mobile', UA_PATTERN_MOBILE);
|
||||
ua('seamonkey', UA_PATTERN_SEAMONKEY);
|
||||
ua('thunderbird', UA_PATTERN_THUNDERBIRD);
|
||||
|
||||
var platform = function(os, needle) {
|
||||
if (navigator.platform.indexOf(needle) != -1) {
|
||||
$(document.body).addClass(os);
|
||||
z.os[os] = true;
|
||||
z.platform = os;
|
||||
}
|
||||
}
|
||||
platform('windows', 'Win32');
|
||||
platform('mac', 'Mac');
|
||||
platform('linux', 'Linux');
|
||||
|
||||
if (!_.any(_.values(z.os))) {
|
||||
platform('other', '');
|
||||
}
|
||||
})();
|
||||
$.extend(z, BrowserUtils());
|
||||
|
||||
/* Details for the current application. */
|
||||
z.app = document.body.getAttribute('data-app');
|
||||
|
@ -146,9 +112,8 @@ z.media_url = document.body.getAttribute('data-media-url');
|
|||
z.readonly = JSON.parse(document.body.getAttribute('data-readonly'));
|
||||
|
||||
if (z.browser.firefox) {
|
||||
var vc = new VersionCompare(),
|
||||
betaVer = document.body.getAttribute('data-min-beta-version');
|
||||
z.fxBeta = vc.compareVersions(z.browserVersion, betaVer);
|
||||
var betaVer = document.body.getAttribute('data-min-beta-version');
|
||||
z.fxBeta = VersionCompare.compareVersions(z.browserVersion, betaVer);
|
||||
if (z.fxBeta) {
|
||||
$(document.body).addClass('fxbeta');
|
||||
}
|
||||
|
|
|
@ -81,8 +81,7 @@ $.hasPersonas = function() {
|
|||
if (!jQuery.browser.mozilla) return false;
|
||||
|
||||
// Fx 3.6 has lightweight themes (aka personas)
|
||||
var versionCompare = new VersionCompare();
|
||||
if (versionCompare.compareVersions(
|
||||
if (VersionCompare.compareVersions(
|
||||
$.browser.version, '1.9.2') > -1) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -395,6 +395,7 @@ MINIFY_BUNDLES = {
|
|||
'js/zamboni/jquery-1.4.2.min.js',
|
||||
'js/zamboni/jquery-ui/custom-1.8.5.min.js',
|
||||
'js/zamboni/underscore-min.js',
|
||||
'js/zamboni/browser.js',
|
||||
'js/amo2009/addons.js',
|
||||
'js/zamboni/init.js',
|
||||
'js/zamboni/format.js',
|
||||
|
|
Загрузка…
Ссылка в новой задаче