aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Rogan Creswick <creswick@gmail.com>2013-12-19 13:31:29 -0800
committerGravatar Rogan Creswick <creswick@gmail.com>2013-12-19 13:31:29 -0800
commitaa2a7b34b64be8daf1a9d50f589563275284d50e (patch)
treeda898aabcbca0191a57140e635e167b88aaa84e0
parent3b53cef842cf0288ad55fe55ae2f578f75b40ae7 (diff)
parent15a644f91a8b6e80bbd24a824b91c24547b80035 (diff)
merge
-rw-r--r--guidelines/wikipedia/bullets.js8
-rw-r--r--guidelines/wikipedia/color.js27
-rw-r--r--guidelines/wikipedia/horizontalRule.js8
-rw-r--r--guidelines/wikipedia/imageSize.js22
-rw-r--r--guidelines/wikipedia/paragraphLength.js15
-rw-r--r--guidelines/wikipedia/pseudoHeadings.js14
-rw-r--r--guidelines/wikipedia/spaceBetweenParagraphs.js28
-rw-r--r--guidelines/wikipedia/wikipedia.json8
-rw-r--r--src/js/chrome/js/platform-ajax.js17
-rw-r--r--src/js/firefox/js/platform-ajax.js4
-rw-r--r--src/js/fiveui/injected/compute.js59
-rw-r--r--src/js/fiveui/injected/prelude.js49
-rw-r--r--src/js/fiveui/injected/ui.js47
-rw-r--r--src/js/fiveui/js/rules.js158
-rw-r--r--src/js/fiveui/js/settings.js20
-rw-r--r--src/js/tests/specs/settings.js2
16 files changed, 327 insertions, 159 deletions
diff --git a/guidelines/wikipedia/bullets.js b/guidelines/wikipedia/bullets.js
new file mode 100644
index 0000000..80c5c4b
--- /dev/null
+++ b/guidelines/wikipedia/bullets.js
@@ -0,0 +1,8 @@
+exports.name = "Minimize use of bullet points";
+exports.description = "Bullet points should be minimized in the body and lead of the article, if they are used at all.";
+
+exports.rule = function(report) {
+ $5('#mw-content-text > ul, #mw-content-text > ol').each(function() {
+ report.warning('Minimize use of bullet points.', this);
+ });
+};
diff --git a/guidelines/wikipedia/color.js b/guidelines/wikipedia/color.js
index 13c5422..045a8ac 100644
--- a/guidelines/wikipedia/color.js
+++ b/guidelines/wikipedia/color.js
@@ -52,9 +52,10 @@ exports.rule = function (report) {
var $this = $(this);
return $this.children().length == 0 && $.trim($this.text()).length > 0;
})
- .each(function (i,elt) {
- var fg = fc.colorToRGB($(elt).css('color'));
- var bg = fc.findBGColor($(elt));
+ .filter(exceptions)
+ .each(function (i) {
+ var fg = fc.colorToRGB($(this).css('color'));
+ var bg = fc.findBGColor($(this));
if (fg && bg) {
var ratio = fc.contrast(fc.luminance(fg), fc.luminance(bg));
console.log("comparing witch ratio" + ratio);
@@ -68,3 +69,23 @@ exports.rule = function (report) {
}
});
};
+
+function exceptions() {
+ var $elem = $(this);
+ return !isStandardLink($elem) &&
+ !isNavboxLink($elem);
+}
+
+function isStandardLink($elem) {
+ var standard = ['new', 'external', 'extiw'];
+ var $a = $elem.closest('a');
+ return $a.is('a') && standard.some(function(klass) {
+ return $a.hasClass(klass);
+ });
+}
+
+function isNavboxLink($elem) {
+ var $a = $elem.closest('a');
+ var $nav = $a.closest('th.navbox-group');
+ return $a.length > 0 && $nav.length > 0;
+}
diff --git a/guidelines/wikipedia/horizontalRule.js b/guidelines/wikipedia/horizontalRule.js
new file mode 100644
index 0000000..b16375d
--- /dev/null
+++ b/guidelines/wikipedia/horizontalRule.js
@@ -0,0 +1,8 @@
+exports.name = "Horizontal rules are deprecated";
+exports.description = "Horizontal rules (----) are deprecated.";
+
+exports.rule = function(report) {
+ $5('#mw-content-text hr').each(function(i, hr) {
+ report.warning('Remove horizontal rule.', hr);
+ });
+};
diff --git a/guidelines/wikipedia/imageSize.js b/guidelines/wikipedia/imageSize.js
new file mode 100644
index 0000000..7000b0b
--- /dev/null
+++ b/guidelines/wikipedia/imageSize.js
@@ -0,0 +1,22 @@
+exports.name = "Large image";
+exports.description = "Images should be sized for comfortable display on the smallest displays in common use.";
+
+exports.rule = function(report) {
+ $5('#mw-content-text img').each(function() {
+ var $img = $(this);
+ if ($img.width() > 400 && !centered($img) && !locationNone($img)) {
+ report.warning('Image is more than 400px wide. Consider using the "center" or "none" location options for wide images', this);
+ }
+ if ($img.height() > 500 && !centered($img) && !locationNone($img)) {
+ report.warning('Image is more than 500px tall.', this);
+ }
+ });
+};
+
+function centered($img) {
+ return $img.closest('.center').length > 0;
+}
+
+function locationNone($img) {
+ return !centered($img) && $img.closest('.tnone').length > 0;
+}
diff --git a/guidelines/wikipedia/paragraphLength.js b/guidelines/wikipedia/paragraphLength.js
new file mode 100644
index 0000000..ba20306
--- /dev/null
+++ b/guidelines/wikipedia/paragraphLength.js
@@ -0,0 +1,15 @@
+exports.name = "Avoid single-sentence paragraphs";
+exports.description = "The number of single-sentence paragraphs should be minimized.";
+
+exports.rule = function(report) {
+ var sentenceBoundary = /[.?!](?:(?:\[\d+\])|['"])*(?:\s|$)/gm;
+
+ $5('#mw-content-text p').each(function(i, p) {
+ var $p = $(p);
+ var text = $.trim($p.text());
+ var boundaries = text && text.match(sentenceBoundary);
+ if (boundaries && boundaries.length === 1) {
+ report.warning('Paragraph with only one sentence: "' + text +'"', p);
+ }
+ });
+};
diff --git a/guidelines/wikipedia/pseudoHeadings.js b/guidelines/wikipedia/pseudoHeadings.js
new file mode 100644
index 0000000..bbf7d8d
--- /dev/null
+++ b/guidelines/wikipedia/pseudoHeadings.js
@@ -0,0 +1,14 @@
+exports.name = "Do not make pseudo-headings";
+exports.description = "Do not make pseudo-headings using bold or semicolon markup.";
+
+exports.rule = function(report) {
+ $5('#mw-content-text p > b:only-child').each(function(i, b) {
+ var text = $.trim($(b).text());
+ report.error('Bold text used as pseudo-heading: '+ text, b);
+ });
+
+ $5('#mw-content-text dl:not(:has(dd)) dt').each(function(i, dt) {
+ var text = $.trim($(dt).text());
+ report.error('Semicolon markup used to create pseudo-heading: '+ text, dt);
+ });
+};
diff --git a/guidelines/wikipedia/spaceBetweenParagraphs.js b/guidelines/wikipedia/spaceBetweenParagraphs.js
new file mode 100644
index 0000000..ccab3a4
--- /dev/null
+++ b/guidelines/wikipedia/spaceBetweenParagraphs.js
@@ -0,0 +1,28 @@
+exports.name = "There should only be one blank line between paragraphs";
+exports.description = "Between sections - as between sections - there should be only a single blank line.";
+
+exports.rule = function(report) {
+ var problemPs = [];
+
+ $5('p:has(> br)').each(function(i, p) {
+ var $p = $(p), prevP;
+ if ($.trim($p.text()).length === 0) {
+ prevP = $p.prevAll('p').filter(function(i, pp) {
+ return $.trim($(pp).text()).length > 0;
+ }).first();
+
+ if (prevP.length) {
+ problemPs.push(prevP.get(0));
+ }
+ else {
+ report.error('Paragraph contains line breaks but does not contain text.', p);
+ }
+ }
+ });
+
+ _.uniq(problemPs, false).forEach(function(p) {
+ var text = $.trim($(p).text());
+ report.error('Paragraph is followed by more than one blank line: '+ text, p);
+ });
+};
+
diff --git a/guidelines/wikipedia/wikipedia.json b/guidelines/wikipedia/wikipedia.json
index 87b20b1..67adf30 100644
--- a/guidelines/wikipedia/wikipedia.json
+++ b/guidelines/wikipedia/wikipedia.json
@@ -3,7 +3,13 @@
, "license": "BSD3"
, "rules":
[ "headingOrder.js"
+ , "bullets.js"
, "strikeout.js"
, "color.js"
+ , "spaceBetweenParagraphs.js"
+ , "paragraphLength.js"
+ , "imageSize.js"
+ , "horizontalRule.js"
+ , "pseudoHeadings.js"
]
-} \ No newline at end of file
+}
diff --git a/src/js/chrome/js/platform-ajax.js b/src/js/chrome/js/platform-ajax.js
index 32aac99..e5b4d1c 100644
--- a/src/js/chrome/js/platform-ajax.js
+++ b/src/js/chrome/js/platform-ajax.js
@@ -13,27 +13,12 @@ fiveui.ajax = fiveui.ajax || {};
*/
fiveui.ajax.get = function(url, options) {
- _.defaults(options, {
- success:function() {},
- error: function() {}
- });
-
- jQuery.ajax(url, {
+ return jQuery.ajax(url, {
cache: false,
dataType: 'text',
- success:function(text) {
- // strip out everything else from the args
- options.success(text);
- },
-
- error:function() {
- // call with no context
- options.error();
- },
-
});
};
diff --git a/src/js/firefox/js/platform-ajax.js b/src/js/firefox/js/platform-ajax.js
index e32225a..9b80633 100644
--- a/src/js/firefox/js/platform-ajax.js
+++ b/src/js/firefox/js/platform-ajax.js
@@ -5,4 +5,6 @@
var fiveui = fiveui || {};
fiveui.ajax = fiveui.ajax || {};
-fiveui.ajax.get = function () {};
+fiveui.ajax.get = function () {
+ return $.Deferred().promise();
+};
diff --git a/src/js/fiveui/injected/compute.js b/src/js/fiveui/injected/compute.js
index d8ae9e8..8fada15 100644
--- a/src/js/fiveui/injected/compute.js
+++ b/src/js/fiveui/injected/compute.js
@@ -19,6 +19,8 @@
* limitations under the License.
*/
+/*jshint evil:true */
+
(function(){
var guidGenerator = function () {
@@ -331,38 +333,43 @@
/**
* @param {{rules: [string], dependencies: [string]}} ruleDescr
*/
- var assembleRules = function(ruleDescr) {
- var ruleList = [];
-
- _.each(ruleDescr.dependencies,
- function(dep){
- try {
- eval(dep.content);
- } catch (x) {
- console.error('Could not evaluate rule dependency: ' + dep.url);
- console.error(x);
- }
- });
-
- var ruleStrList = ruleDescr.rules;
- for(var i=0; i<ruleStrList.length; ++i) {
- var moduleStr =
- [ '(function(){'
- , 'var exports = {};'
- , ruleStrList[i]
- , 'return exports;'
- , '})()'
- ].join('\n');
+ var assembleRules = function(__assembleRules_ruleDescr) {
+ // Use long variable names: top-level variables in eval'ed
+ // dependencies will be created in the scope of this function and
+ // we want to avoid collisions.
+ var __assembleRules_ruleList = []
+ , __assembleRules_deps = __assembleRules_ruleDescr.dependencies
+ , __assembleRules_i;
+
+ // Use for loop instead of _.each so that top-level variables in
+ // eval'ed dependencies will be created in the scope of the
+ // `assembleRules` function. The goal is to run rules in the
+ // same scope so that rules have access to top-level variables
+ // from defined in dependency scripts.
+ for (__assembleRules_i = 0; __assembleRules_i < __assembleRules_deps.length; __assembleRules_i += 1) {
+ try {
+ eval(__assembleRules_deps[__assembleRules_i].content);
+ } catch (x) {
+ console.error('Could not evaluate rule dependency: ' +
+ __assembleRules_deps[__assembleRules_i].url);
+ console.error(x);
+ }
+ }
+
+ var ruleStrList = __assembleRules_ruleDescr.rules;
+ for(__assembleRules_i=0; __assembleRules_i<ruleStrList.length; ++__assembleRules_i) {
+ var __assembleRules_moduleFunc = new Function('exports', ruleStrList[__assembleRules_i]);
try {
- var evaled = eval(moduleStr);
- ruleList.push(evaled);
+ var __assembleRules_exported = {};
+ __assembleRules_moduleFunc(__assembleRules_exported);
+ __assembleRules_ruleList.push(__assembleRules_exported);
} catch (x) {
console.error('Could not evaluate rule module: ' + x);
- console.error(moduleStr);
+ console.error(__assembleRules_moduleFunc);
}
}
- return ruleList;
+ return __assembleRules_ruleList;
};
port.on('SetRules', function(payload) {
diff --git a/src/js/fiveui/injected/prelude.js b/src/js/fiveui/injected/prelude.js
index 250488f..5e7a47f 100644
--- a/src/js/fiveui/injected/prelude.js
+++ b/src/js/fiveui/injected/prelude.js
@@ -19,6 +19,8 @@
* limitations under the License.
*/
+/*global $5: true, JSON: true */
+
/**
* The FiveUI Prelude.
*
@@ -64,7 +66,9 @@ fiveui.query = function (sel, context) {
var ctx = context || document;
var $results = jQuery(sel, ctx);
- jQuery('iframe, frame', ctx).each(
+ jQuery('iframe, frame', ctx)
+ .filter(function(idx, frame) { return sameOrigin(frame); })
+ .each(
function(idx, elt) {
var $tempResults;
if (elt.contentDocument) {
@@ -89,6 +93,14 @@ fiveui.query = function (sel, context) {
fiveui.stats.numElts += $filteredResults.length;
return $filteredResults;
+
+ // Frames are considered to be from the same origin if their location
+ // hosts, ports, and schemes are the same.
+ function sameOrigin(frame) {
+ var src = frame.src;
+ var origin = window.location.origin;
+ return src.indexOf(origin) === 0 && src.charAt(origin.length) !== ':';
+ }
};
/**
@@ -244,22 +256,22 @@ fiveui.color.colorCheck = function (selector, colorSet) {
var allowable, i, fnStr, forEachFuncStr;
allowable = {};
for (i = 0; i < colorSet.length; i += 1) { allowable[colorSet[i]] = true; }
- forEachFuncStr = 'function (j, elt) {\n'
- + ' var allowable = ' + JSON.stringify(allowable) + ';\n'
- + ' var color = fiveui.color.colorToHex($(elt).css("color"));\n'
- + ' if (!(color in allowable)) {\n'
- + ' report("Disallowed color " + color + " in element matching " + ' + JSON.stringify(selector) + ', $(elt));\n'
- + ' }\n'
- + '}\n';
- fnStr = 'function () { fiveui.query("' + selector + '").each(' + forEachFuncStr + '); }';
- return eval('false||'+fnStr); // the `false||` trick is required for eval to parse a
- // function expression ?!?
+
+ return function colorCheck() {
+ fiveui.query(selector).each(function(j, elt) {
+ var $elt = $(elt);
+ var color = fiveui.color.colorToHex($elt.css("color"));
+ if (!(color in allowable)) {
+ report("Disallowed color " + color + " in element matching " + selector, $elt);
+ }
+ });
+ };
};
componentToHex = function (c) {
var hex = c.toString(16).toUpperCase();
return hex.length == 1 ? "0" + hex : hex;
-}
+};
shortHexToHex = function (color) {
var have = color.length - 1;
@@ -287,7 +299,7 @@ fiveui.color.rgbToHex = function (r, g, b) {
};
/**
- * Convert a 3-byte hex value to base-10 RGB
+ * Convert a 3-byte hex value to base-10 RGB
*/
fiveui.color.hexToRGB = function (hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
@@ -356,7 +368,7 @@ fiveui.color.colorToRGB = function(color) {
}
var alpha = 1;
- if (digits[5] != undefined) {
+ if (digits[5]) {
alpha = parseFloat(digits[5]);
}
@@ -421,7 +433,7 @@ fiveui.color.contrast = function(lum1, lum2) {
/**
* Computationally determine the actual displayed background color for
- * an object. This accounts for parent colors that may appear when
+ * an object. This accounts for parent colors that may appear when
* a bg color is unspecified, or fully transparent.
*
* It does not account for elements that are shifted out of their
@@ -435,6 +447,7 @@ fiveui.color.findBGColor = function(obj) {
var fc = fiveui.color;
var real = fc.colorToRGB(obj.css('background-color'));
var none = fc.colorToRGB('rgba(0, 0, 0, 0)');
+ var i;
if (real.a != 1) {
@@ -453,7 +466,7 @@ fiveui.color.findBGColor = function(obj) {
// takeWhile alpha != 1
var colors = [];
- for (var i=0; i < parents.length; i++) {
+ for (i=0; i < parents.length; i++) {
colors.push(parents[i]);
if (parents[i].a == 1) {
break;
@@ -464,7 +477,7 @@ fiveui.color.findBGColor = function(obj) {
// neither commutative, nor associative, so we need to be carefull
// of the order in which parent colors are combined.
var res = real;
- for (var i=0; i < colors.length; i++) {
+ for (i=0; i < colors.length; i++) {
res = fc.alphaCombine(res, colors[i]);
}
return res;
@@ -476,7 +489,7 @@ fiveui.color.findBGColor = function(obj) {
/**
* Combines two colors, accounting for alpha values less than 1.
- *
+ *
* @param {color} top The color "on top"
* @param {color} bot The color "on bottom"
* @return {color} the composite RGBA color.
diff --git a/src/js/fiveui/injected/ui.js b/src/js/fiveui/injected/ui.js
index eb22136..e23aa90 100644
--- a/src/js/fiveui/injected/ui.js
+++ b/src/js/fiveui/injected/ui.js
@@ -27,6 +27,17 @@
var core = {};
core.port = obtainPort();
+ core.getElementByXPath = function(path, context) {
+ var nsResolver = document.createNSResolver(
+ context.ownerDocument == null ? context.documentElement : context.ownerDocument.documentElement
+ );
+ var xpathResult = document.evaluate(path, document, nsResolver, XPathResult.ANY_TYPE, null);
+ var $result = $(), nextElem;
+ while (nextElem = xpathResult.iterateNext()) {
+ $result = $result.add(nextElem);
+ }
+ return $result;
+ };
/* User Interface **********************************************************/
@@ -320,6 +331,7 @@
, ' <div class="fiveui-problem-header">'
, ' <div class="fiveui-problem-toggle"><span></span></div>'
, ' <%= name %>'
+ , ' <a href="#" class="fiveui-problem-scrollTo">show</a>'
, ' </div>'
, ' <div class="fiveui-problem-body">'
, ' <p><%= msg %></p>'
@@ -340,6 +352,20 @@
this.$toggle = this.$el.find('.fiveui-problem-toggle');
this.$body = this.$el.find('.fiveui-problem-body');
this.$header = this.$el.find('.fiveui-problem-header');
+ this.isOpen = false;
+
+ var self = this;
+
+ this.$el.on('click', function(event) {
+ if (!$(event.target).is('a, a *')) {
+ self.toggle();
+ }
+ });
+
+ this.$el.on('click', '.fiveui-problem-scrollTo', function(event) {
+ event.preventDefault();
+ self.scrollTo();
+ });
this.$body.hide();
@@ -350,6 +376,16 @@
el.append(this.$el);
},
+ toggle:function() {
+ this.isOpen = !this.isOpen;
+ if (this.isOpen) {
+ this.open();
+ }
+ else {
+ this.close();
+ }
+ },
+
/**
* Close the context for a problem entry.
* @public
@@ -358,7 +394,6 @@
this.$toggle.find('span').removeClass('icon-caret-down')
.addClass('icon-caret-right');
- this.$el.one('click', _.bind(this.open, this));
this.$body.slideUp(100);
core.maskProblem(this.problem);
@@ -368,12 +403,20 @@
this.$toggle.find('span').addClass('icon-caret-down')
.removeClass('icon-caret-right');
- this.$el.one('click', _.bind(this.close, this));
this.$body.slideDown(100);
core.highlightProblem(this.problem);
},
+ scrollTo:function() {
+ var $elem = core.getElementByXPath(this.problem.xpath, document);
+ var top = $elem.offset().top;
+ var height = $elem.height();
+ var viewHeight = $(window).height();
+ var extra = viewHeight - height;
+ $(window).scrollTop(top - (extra * 0.33));
+ }
+
});
diff --git a/src/js/fiveui/js/rules.js b/src/js/fiveui/js/rules.js
index 94d714f..16fb635 100644
--- a/src/js/fiveui/js/rules.js
+++ b/src/js/fiveui/js/rules.js
@@ -69,108 +69,87 @@ fiveui.RuleSet.fromJSON = function(id, obj) {
/**
- * Options is an object that can contain a success and error continuation.
+ * Returns a promise.
*/
fiveui.RuleSet.load = function(manifest_url, options) {
- _.defaults(options, {
- success: function() {},
- error: function() { throw "failed when loading url"; }
- });
-
var match = manifest_url.match(/\/[^\/]*$/);
if(match) {
var base_url = manifest_url.substring(0,match.index);
- var loadDependencies = function(manifest, dependencies, rules) {
- if (_.isEmpty(dependencies)) {
- loadRules(manifest, rules);
- } else {
- // XXX there's likely problems here, how should we make sure that the
- // url is what we expect?
- var dep_file = dependencies.pop();
- var dep_url = base_url + '/' + dep_file;
-
- fiveui.ajax.get(dep_url, {
- success: function(text) {
- manifest.dependencies.push({'url': dep_url, 'content': text});
- loadDependencies(manifest, dependencies, rules);
- },
-
- error: options.error
- });
+ // fetch the manifest, and load its rules
+ return fiveui.ajax.get(manifest_url).then(function success(text) {
+ // cleanup the parsed JSON object
+ var sanitized = fiveui.utils.filterJSON(text,'json');
+ var obj = null;
+
+ try {
+ obj = JSON.parse(sanitized);
+ } catch(e) {
+ return failure('failed to parse manifest');
}
- };
-
- // iterate over rules, retrieving the
- var loadRules = function(manifest, rules) {
- if(rules.length == 0) {
- options.success(manifest);
- } else {
+ // set defaults in the parsed manifest
+ var manifest = fiveui.RuleSet.sanitize(obj);
- // XXX there's likely problems here, how should we make sure that the
- // url is what we expect?
- var rule_file = rules.pop();
- var rule_url = base_url + '/' + rule_file;
+ return $.when(
+ loadDependencies(manifest.dependencies),
+ loadRules(manifest.rules)
+ )
+ .then(function(dependencies, rules) {
- fiveui.ajax.get(rule_url, {
+ return _.extend(manifest, {
+ // explicitly zero out the patterns, they shouldn't be part of the
+ // manifest.
+ patterns: [],
- success: function(text) {
- manifest.rules.push(text);
- loadRules(manifest, rules);
- },
+ // overwrite any source present with the one given by the user.
+ source: manifest_url,
- error: options.error
+ dependencies: dependencies,
+ rules: rules
});
- }
- };
+ });
+ },
- // fetch the manifest, and load its rules
- fiveui.ajax.get(manifest_url, {
-
- success: function(text) {
- // cleanup the parsed JSON object
- var sanitized = fiveui.utils.filterJSON(text,'json');
- var obj = null;
-
- try {
- obj = JSON.parse(sanitized);
- } catch(e) {
- options.error('failed to parse manifest');
- return;
- }
+ function error() {
+ return failure('failed to retrieve manifest');
+ });
- // set defaults in the parsed manifest
- var manifest = fiveui.RuleSet.sanitize(obj);
- // explicitly zero out the patterns, they shouldn't be part of the
- // manifest.
- manifest.patterns = [];
+ } else {
+ return failure("unable to parse manifest url");
+ }
- var dependencies = manifest.dependencies;
- manifest.dependencies = [];
+ function loadDependencies(dependencyFiles) {
+ var deps = dependencyFiles.map(function(dep_file) {
+ // XXX there's likely problems here, how should we make sure that the
+ // url is what we expect?
+ var dep_url = base_url + '/' + dep_file;
- // remove the rules, as they'll be added back once processed.
- var rules = manifest.rules;
- manifest.rules = [];
+ return fiveui.ajax.get(dep_url).then(function success(text) {
+ return {'url': dep_url, 'content': text};
+ });
+ });
- // overwrite any source present with the one given by the user.
- manifest.source = manifest_url;
+ return whenAll(deps);
+ }
- loadDependencies(manifest, dependencies, rules);
- },
+ function loadRules(ruleFiles) {
+ var rules = ruleFiles.map(function(rule_file) {
+ // XXX there's likely problems here, how should we make sure that the
+ // url is what we expect?
+ var rule_url = base_url + '/' + rule_file;
- error: function() {
- options.error('failed to retrieve manifest');
- },
+ return fiveui.ajax.get(rule_url).then(function(text) {
+ // Ensure that resulting promise holds only a single value.
+ return text;
+ });
});
-
- } else {
- options.error("unable to parse manifest url");
+ return whenAll(rules);
}
};
@@ -294,5 +273,32 @@ fiveui.RuleSets = Backbone.Collection.extend({
});
+/**
+ * Creates a resolved promise.
+ */
+function success(val) {
+ var deferred = $.Deferred();
+ deferred.resolve(val);
+ return deferred.promise();
+}
+
+/**
+ * Creates a rejected promise.
+ */
+function failure(reason) {
+ var deferred = $.Deferred();
+ deferred.reject(reason);
+ return deferred.promise();
+}
+
+/**
+ * Given an array of promises, returns a promise that will resolve to
+ * the array of resolved values of the input promises.
+ */
+function whenAll(promises) {
+ return $.when.apply($, promises).then(function() {
+ return Array.prototype.slice.call(arguments);
+ });
+}
})();
diff --git a/src/js/fiveui/js/settings.js b/src/js/fiveui/js/settings.js
index 6c0958e..1b5d4f8 100644
--- a/src/js/fiveui/js/settings.js
+++ b/src/js/fiveui/js/settings.js
@@ -43,11 +43,7 @@ _.extend(fiveui.Settings.prototype, {
*/
get: function(key) {
var value = this.store.getItem(key);
- if (value == null) {
- return null;
- } else {
- return JSON.parse(value);
- }
+ return value ? JSON.parse(value) : null;
},
/**
@@ -203,13 +199,11 @@ _.extend(fiveui.Settings.prototype, {
return false;
}
- var pat = _.find(rs.patterns, function(pat) {
+ return _.some(rs.patterns, function(pat) {
var regex = fiveui.utils.compilePattern(pat);
return regex.test(url);
});
- return pat != null;
-
});
},
@@ -228,7 +222,7 @@ fiveui.Settings.manager = function(chan, settings) {
// create a new rule set, and call the response continuation with the created
// object.
msg.register('addRuleSet', function(ruleSet,respond){
- var id = settings.addRuleSet(ruleSet)
+ var id = settings.addRuleSet(ruleSet);
respond(settings.getRuleSet(id));
});
@@ -249,12 +243,8 @@ fiveui.Settings.manager = function(chan, settings) {
// Retrieve the manifest, and return the object to the caller. Invokes the
// response continuation with an error object when rule set fails to load.
msg.register('loadRuleSet', function(url, respond) {
- fiveui.RuleSet.load(url, {
- success:respond,
-
- error:function(msg) {
- respond({ error : msg });
- },
+ fiveui.RuleSet.load(url).then(respond, function error(msg) {
+ respond({ error : msg });
});
});
diff --git a/src/js/tests/specs/settings.js b/src/js/tests/specs/settings.js
index 088b94d..19eb556 100644
--- a/src/js/tests/specs/settings.js
+++ b/src/js/tests/specs/settings.js
@@ -27,7 +27,7 @@ describe('fiveui.Settings', function() {
expect(settings.get(key)).toEqual(value);
});
- it('matches urls when there\s a valid pattern registered', function() {
+ it('matches urls when there\'s a valid pattern registered', function() {
var rset = new fiveui.RuleSet({ patterns: ['http://.*'] });
settings.addRuleSet(rset);
expect(settings.checkUrl('http://foo').id).toBe(0);