Skip to content
This repository has been archived by the owner on Sep 24, 2019. It is now read-only.

Commit

Permalink
Merge branch 'wcag2' into feature/aInPhasADistinctStyle
Browse files Browse the repository at this point in the history
  • Loading branch information
Wilco Fiers committed Dec 15, 2014
2 parents c8951fb + fc81527 commit e5adc0f
Show file tree
Hide file tree
Showing 29 changed files with 1,432 additions and 588 deletions.
4 changes: 2 additions & 2 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ module.exports = function(grunt) {
stripBanners: true
},
dist: {
src: ['src/js/core.js', 'src/js/components/*.js', 'src/js/strings/*.js', 'src/js/custom/*.js', 'src/js/lib/*.js', 'src/js/lib/wcag/*.js'],
src: ['src/js/core.js', 'src/js/components/*.js', 'src/js/strings/*.js', 'src/js/custom/*.js', 'src/js/lib/*.js', 'src/js/lib/wcag/*.js', 'src/js/lib/wcag2/*.js'],
dest: 'dist/quail.jquery.js'
},
test: {
src: ['src/js/core.js', 'src/js/components/*.js', 'src/js/strings/*.js', 'src/js/custom/*.js', 'src/js/lib/*.js', 'src/js/lib/wcag/*.js'],
src: ['src/js/core.js', 'src/js/components/*.js', 'src/js/strings/*.js', 'src/js/custom/*.js', 'src/js/lib/*.js', 'src/js/lib/wcag/*.js', 'src/js/lib/wcag2/*.js'],
dest: 'test/quail-testing.jquery.js',
options: {
banner: '<%= pkg.options.banner %>' + "\n" + 'var __testQuail = {};(function($) {' + "\n",
Expand Down
15 changes: 11 additions & 4 deletions src/js/components/color.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ quail.components.color = function(quail, test, Case, options) {
level = 3;
}
else {
level = 5;
level = 4.5;
}
}
}
Expand Down Expand Up @@ -142,7 +142,6 @@ quail.components.color = function(quail, test, Case, options) {
if (!element.attr('data-cacheId')) {
element.attr('data-cacheId', 'id_' + Math.random());
}

var cacheKey = 'getColor_' + type + '_' + element.attr('data-cacheId');
if (this.cache[cacheKey] !== undefined) {
return this.cache[cacheKey];
Expand Down Expand Up @@ -458,6 +457,11 @@ quail.components.color = function(quail, test, Case, options) {
var $this = $(element);
var algorithm = options.algorithm;
var id, failureFound, failedWCAGColorTest, failedWAIColorTest;
// Ignore elements who's content isn't displayed to the page
if (['script', 'style', 'title', 'object', 'applet', 'embed', 'template']
.indexOf(element.nodeName.toLowerCase()) !== -1) {
return;
}

// Bail out is the text is not readable.
if (quail.isUnreadable($this.text())) {
Expand All @@ -470,7 +474,8 @@ quail.components.color = function(quail, test, Case, options) {
// Check text and background color using DOM.
id = 'colorFontContrast';
// Build a case.
if ((algorithm === 'wcag' && !colors.passesWCAG($this)) || (algorithm === 'wai' && !colors.passesWAI($this))) {
if ((algorithm === 'wcag' && !colors.passesWCAG($this)) ||
(algorithm === 'wai' && !colors.passesWAI($this))) {
buildCase(element, 'failed', id, 'The font contrast of the text impairs readability');
}
else {
Expand Down Expand Up @@ -641,7 +646,9 @@ quail.components.color = function(quail, test, Case, options) {
nodes.push(text);
text = textnodes.iterateNext();
}
nodes.forEach(testCandidates);
nodes.forEach(function (textNode) {
testCandidates(textNode);
});
}
});
};
Expand Down
12 changes: 6 additions & 6 deletions src/js/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,18 +209,18 @@ var quail = {
});
_run.call(quail);
}
// If a list of specific tests is provided, use them.
else if (options.accessibilityTests) {
buildTests(quail, options.accessibilityTests, options);
_run.call(quail);
}

// Let wcag2 run itself, will call quail again when it knows what
// to
else if (options.guideline === 'wcag2') {
quail.lib.wcag2.run(options);
}

// If a list of specific tests is provided, use them.
else if (options.accessibilityTests) {
buildTests(quail, options.accessibilityTests, options);
_run.call(quail);
}

// Otherwise get the tests from the json data list.
else {
var url = options.jsonPath;
Expand Down
92 changes: 92 additions & 0 deletions src/js/custom/animatedGifMayBePresent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
quail.animatedGifMayBePresent=function(quail, test, Case){

/**
* Test if gif is animated
* Implemented from: https://gist.github.com/3012623.git
* @param src
* @param ext
* @param cb
*/
function isAnimatedGif(src, ext, cb){

if(ext !== 'gif'){
cb(false);
return;
}

var request=new XMLHttpRequest();
request.open('GET', src, true);
request.responseType='arraybuffer';
request.addEventListener('load', function () {
var arr = new Uint8Array(request.response);
var frames = 0;

// make sure it's a gif (GIF8)
if (arr[0] !== 0x47 || arr[1] !== 0x49 ||
arr[2] !== 0x46 || arr[3] !== 0x38)
{
cb(false);
return;
}

//ported from php http://www.php.net/manual/en/function.imagecreatefromgif.php#104473
//an animated gif contains multiple "frames", with each frame having a
//header made up of:
// * a static 4-byte sequence (\x00\x21\xF9\x04)
// * 4 variable bytes
// * a static 2-byte sequence (\x00\x2C) (some variants may use \x00\x21 ?)
// We read through the file til we reach the end of the file, or we've found
// at least 2 frame headers
for (var i=0; i < arr.length -9; i++) {
if (arr[i] === 0x00 && arr[i+1] === 0x21 &&
arr[i+2] === 0xF9 && arr[i+3] === 0x04 &&
arr[i+8] === 0x00 &&
(arr[i+9] === 0x2C || arr[i+9] === 0x21))
{
frames++;
}
if(frames > 1){
cb(true);
return;
}
}

cb(false);
window.console.log("AFTER PARSING: ", frames);
});
request.send();
}

test.get('$scope').find('img').each(function(){

var _case=Case({
element: this,
expected: $(this).closest('.quail-test').data('expected')
});
test.add(_case);

var imgSrc=$(this).attr('src');
var ext=$(this).attr('src').split('.').pop().toLowerCase();

if (ext !== 'gif') {
_case.set({
'status': 'inapplicable'
});
return;
}

isAnimatedGif(imgSrc, ext, function(animated){
if (animated) {
_case.set({
'status': 'cantTell'
});
return;
} else{
_case.set({
'status': 'inapplicable'
});
return;
}
});
});
};
42 changes: 42 additions & 0 deletions src/js/custom/audioMayBePresent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
quail.audioMayBePresent=function(quail, test, Case){
var audioExtensions = ['mp3', 'm4p', 'ogg', 'oga', 'opus', 'wav', 'wma', 'wv'];

test.get('$scope').each(function() {
var $this = $(this);
var hasCase = false; // Test if a case has been created

// Audio is definately an audio, and objects could be too.
$this.find('object, audio').each(function () {
hasCase = true;
test.add(Case({
element: this,
expected: $(this).closest('.quail-test').data('expected'),
status: 'cantTell'
}));
});

// Links refering to files with an audio extensions are good indicators too
$this.find('a[href]').each(function () {
var $this = $(this);
var extension = $this.attr('href').split('.').pop();
if ($.inArray(extension, audioExtensions) !== -1) {
hasCase = true;
test.add(Case({
element: this,
expected: $this.closest('.quail-test').data('expected'),
status: 'cantTell'
}));
}
});

// if no case was added, return inapplicable
if (!hasCase) {
test.add(Case({
element: this,
status: 'inapplicable',
expected: $(this).closest('.quail-test').data('expected')
}));
}
});

};
65 changes: 39 additions & 26 deletions src/js/custom/documentIDsMustBeUnique.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,46 @@
quail.documentIDsMustBeUnique = function(quail, test, Case) {
var ids = {};
test.get('$scope').each(function(){
if($(this).children().length === 0) {
test.add(Case({
element: this,
'status': 'inapplicable',
expected: $(this).closest('.quail-test').data('expected')
}));
}
});
test.get('$scope').find(':not([id])').each(function() {
var _case = Case({
element: this
});
test.add(_case);
_case.set({
test.add(Case({
element: this,
'status': 'inapplicable',
expected: $(this).closest('.quail-test').data('expected')
});
}));
});
test.get('$scope').find('[id]').each(function() {
var _case = Case({
element: this,
expected: (function (element) {
return quail.components.resolveExpectation(element);
}(this))
});
test.add(_case);
if (typeof ids[$(this).attr('id')] === 'undefined') {
_case.set({
'status': 'passed'
});
ids[$(this).attr('id')] = $(this).attr('id');
}
else {
_case.set({
'status': 'failed'
test.get('$scope').each(function(){
var ids = {};
$(this).find('[id]').each(function() {
var _case = Case({
element: this,
expected: (function (element) {
return quail.components.resolveExpectation(element);
}(this))
});
}
test.add(_case);
if(typeof ids[$(this).attr('id')] === 'undefined' && Object.keys(ids).length === 0){
_case.set({
'status': 'inapplicable'
});
ids[$(this).attr('id')] = $(this).attr('id');
}else if (typeof ids[$(this).attr('id')] === 'undefined') {
_case.set({
'status': 'passed'
});
ids[$(this).attr('id')] = $(this).attr('id');
}
else {
_case.set({
'status': 'failed'
});
}
});
});
};
};
38 changes: 38 additions & 0 deletions src/js/custom/headersAttrRefersToATableCell.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
quail.headersAttrRefersToATableCell = function(quail, test, Case) {

// Table cell headers without referred ids
test.get('$scope').find('table').each(function() {

var element = this;
var _case = Case({
element: element,
expected: $(this).closest('.quail-test').data('expected')
});
test.add(_case);
var elmHeaders = $(element).find('th[headers], td[headers]');

if (elmHeaders.length === 0) {
_case.set({
'status': 'inapplicable'
});
return;
} else {
elmHeaders.each(function() {
var headers = $(this).attr('headers').split(/\s+/);
$.each(headers, function(index, item) {
if (item === "" || $(element).find('th#' + item + ',td#' + item).length > 0) {
_case.set({
'status': 'passed'
});
return;
} else {
_case.set({
'status': 'failed'
});
return;
}
});
});
}
});
};
9 changes: 6 additions & 3 deletions src/js/custom/idRefHasCorrespondingId.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
quail.idRefHasCorrespondingId = function(quail, test, Case) {
test.get('$scope').find('[idref]').each(function() {
test.get('$scope').find('label[for], *[aria-activedescendant]').each(function() {
var $this = $(this);
var _case = Case({
element: this,
expected: $(this).closest('.quail-test').data('expected')
expected: $this.closest('.quail-test').data('expected')
});
test.add(_case);
if (test.get('$scope').find('#' + $(this).attr('idref')).length === 0) {

var find = $this.attr('for') || $this.attr('aria-activedescendant');
if (test.get('$scope').find('#' + find).length === 0) {
_case.set({
'status': 'failed'
});
Expand Down
Loading

0 comments on commit e5adc0f

Please sign in to comment.