Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

#5001: Fixes jqLite not correctly adding & removing classes in IE9 #5686

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions docs/src/example.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@ var makeUnique = {
'script.js': true,
'unit.js': true,
'spec.js': true,
'scenario.js': true
'scenario.js': true,
'protractorTest.js': true
}

function ids(list) {
return list.map(function(item) { return item.id; }).join(' ');
};


exports.Example = function(scenarios) {
exports.Example = function(scenarios, protractorTests) {
this.module = '';
this.deps = ['angular.js'];
this.html = [];
Expand All @@ -24,6 +25,8 @@ exports.Example = function(scenarios) {
this.unit = [];
this.scenario = [];
this.scenarios = scenarios;
this.protractorTest = [];
this.protractorTests = protractorTests;
}

exports.Example.prototype.setModule = function(module) {
Expand All @@ -44,6 +47,10 @@ exports.Example.prototype.addSource = function(name, content) {
var ext = name == 'scenario.js' ? 'scenario' : name.split('.')[1],
id = name;

if (name == 'protractorTest.js') {
ext = 'protractorTest';
}

if (makeUnique[name] && usedIds[id]) {
id = name + '-' + (seqCount++);
}
Expand All @@ -56,6 +63,9 @@ exports.Example.prototype.addSource = function(name, content) {
if (ext == 'scenario') {
this.scenarios.push(content);
}
if (ext == 'protractorTest') {
this.protractorTests.push(content);
}
};

exports.Example.prototype.enableAnimations = function() {
Expand Down Expand Up @@ -92,6 +102,7 @@ exports.Example.prototype.toHtmlEdit = function() {
out.push(' source-edit-json="' + ids(this.json) + '"');
out.push(' source-edit-unit="' + ids(this.unit) + '"');
out.push(' source-edit-scenario="' + ids(this.scenario) + '"');
out.push(' source-edit-protractor="' + ids(this.protractorTest) + '"');
out.push('></div>\n');
return out.join('');
};
Expand All @@ -107,6 +118,7 @@ exports.Example.prototype.toHtmlTabs = function() {
htmlTabs(this.json);
htmlTabs(this.unit);
htmlTabs(this.scenario);
htmlTabs(this.protractorTest);
out.push('</div>');
return out.join('');

Expand All @@ -119,7 +131,8 @@ exports.Example.prototype.toHtmlTabs = function() {
if (name === 'index.html') {
wrap = ' ng-html-wrap="' + self.module + ' ' + self.deps.join(' ') + '"';
}
if (name == 'scenario.js') name = 'End to end test';
if (name == 'scenario.js') name = 'ngScenario e2e test';
if (name == 'protractorTest.js') name = 'Protractor e2e test';

out.push(
'<div class="tab-pane" title="' + name + '">\n' +
Expand Down
6 changes: 6 additions & 0 deletions docs/src/gen-docs.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ writer.makeDir('build/docs/', true).then(function() {
return writer.makeDir('build/docs/components/bootstrap');
}).then(function() {
return writer.makeDir('build/docs/components/font-awesome');
}).then(function() {
return writer.makeDir('build/docs/e2etests');
}).then(function() {
console.log('Generating AngularJS Reference Documentation...');
return reader.collect();
Expand Down Expand Up @@ -53,6 +55,10 @@ writer.makeDir('build/docs/', true).then(function() {
var id = doc.id.replace('angular.Module', 'angular.IModule');

fileFutures.push(writer.output('partials/' + doc.section + '/' + id + '.html', doc.html()));
// If it has a sample Protractor test, output that as well.
if (doc.protractorTests.length) {
fileFutures.push(writer.output('ptore2e/' + doc.section + '/' + id + '_test.js', ngdoc.writeProtractorTest(doc)));
}
});

ngdoc.checkBrokenLinks(docs);
Expand Down
24 changes: 22 additions & 2 deletions docs/src/ngdoc.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ var lookupMinerrMsg = function (doc) {
exports.trim = trim;
exports.metadata = metadata;
exports.scenarios = scenarios;
exports.writeProtractorTest = writeProtractorTest;
exports.merge = merge;
exports.checkBrokenLinks = checkBrokenLinks;
exports.Doc = Doc;
Expand Down Expand Up @@ -155,6 +156,7 @@ function Doc(text, file, line) {
this.line = line;
}
this.scenarios = this.scenarios || [];
this.protractorTests = this.protractorTests || [];
this.requires = this.requires || [];
this.param = this.param || [];
this.properties = this.properties || [];
Expand Down Expand Up @@ -292,7 +294,7 @@ Doc.prototype = {
replace(/<example(?:\s+module="([^"]*)")?(?:\s+deps="([^"]*)")?(\s+animations="true")?>([\s\S]*?)<\/example>/gmi,
function(_, module, deps, animations, content) {

var example = new Example(self.scenarios);
var example = new Example(self.scenarios, self.protractorTests);
if(animations) {
example.enableAnimations();
example.addDeps('angular-animate.js');
Expand Down Expand Up @@ -329,7 +331,7 @@ Doc.prototype = {
}).
replace(/^<doc:example(\s+[^>]*)?>([\s\S]*)<\/doc:example>/mi, function(_, attrs, content) {
var html, script, scenario,
example = new Example(self.scenarios);
example = new Example(self.scenarios, self.protractorTests);

example.setModule((attrs||'module=""').match(/^\s*module=["'](.*)["']\s*$/)[1]);
content.
Expand All @@ -347,6 +349,8 @@ Doc.prototype = {
}).
replace(/(<doc:scenario>)([\s\S]*)(<\/doc:scenario>)/mi, function(_, before, content){
example.addSource('scenario.js', content);
}).replace(/(<doc:protractor>)([\s\S]*)(<\/doc:protractor>)/mi, function(_, before, content){
example.addSource('protractorTest.js', content);
});

return placeholder(example.toHtml());
Expand Down Expand Up @@ -1106,6 +1110,22 @@ function scenarios(docs){
}
}

function writeProtractorTest(doc){
var lines = [];
lines.push('describe("' + doc.section + '/' + doc.id + '", function() {');
lines.push(' beforeEach(function() {');
lines.push(' browser.get("index-nocache.html#!/' + doc.section + '/' + doc.id + '");');
lines.push(' });');
lines.push('');
doc.protractorTests.forEach(function(test){
lines.push(indentCode(trim(test), 2));
lines.push('');
});
lines.push('});');
lines.push('');
return lines.join('\n');
}


//////////////////////////////////////////////////////////
function metadata(docs){
Expand Down
10 changes: 6 additions & 4 deletions src/jqLite.js
Original file line number Diff line number Diff line change
Expand Up @@ -299,9 +299,10 @@ function jqLiteHasClass(element, selector) {
}

function jqLiteRemoveClass(element, cssClasses) {
if (cssClasses && element.setAttribute) {
var setter = element.setAttribute ? function(value) { element.setAttribute('class', value) } : function(value) { element.className = value};
if (cssClasses && (element.setAttribute || msie === 9)) {
forEach(cssClasses.split(' '), function(cssClass) {
element.setAttribute('class', trim(
setter(trim(
(" " + (element.getAttribute('class') || '') + " ")
.replace(/[\n\t]/g, " ")
.replace(" " + trim(cssClass) + " ", " "))
Expand All @@ -312,7 +313,7 @@ function jqLiteRemoveClass(element, cssClasses) {

function jqLiteAddClass(element, cssClasses) {
if (cssClasses && element.setAttribute) {
var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ')
var existingClasses = (' ' + (element.getAttribute('class') || element.className || '') + ' ')
.replace(/[\n\t]/g, " ");

forEach(cssClasses.split(' '), function(cssClass) {
Expand All @@ -322,7 +323,8 @@ function jqLiteAddClass(element, cssClasses) {
}
});

element.setAttribute('class', trim(existingClasses));
(msie === 9 && !(element instanceof SVGElement)) ? element.className = trim(existingClasses) :
element.setAttribute('class', trim(existingClasses));
}
}

Expand Down
10 changes: 5 additions & 5 deletions src/ng/directive/ngEventDirs.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@
</button>
count: {{count}}
</doc:source>
<doc:scenario>
<doc:protractor>
it('should check ng-click', function() {
expect(binding('count')).toBe('0');
element('.doc-example-live :button').click();
expect(binding('count')).toBe('1');
expect(element(by.binding('count')).getText()).toMatch('0');
element(by.css('.doc-example-live button')).click();
expect(element(by.binding('count')).getText()).toMatch('1');
});
</doc:scenario>
</doc:protractor>
</doc:example>
*/
/*
Expand Down
8 changes: 8 additions & 0 deletions test/jqLiteSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,14 @@ describe('jqLite', function() {
expect(jqLite(b).hasClass('abc')).toEqual(true);
});

it('should allow adding of class in IE9', function() {
if (msie !== 9) return; // IE9 doesn't support node.setAttribute
var selector = jqLite([a, b]);
expect(selector.addClass('abc')).toBe(selector);
expect(jqLite(a).hasClass('abc')).toBe(true);
expect(jqLite(b).hasClass('abc')).toBe(true);
});


it('should ignore falsy values', function() {
var jqA = jqLite(a);
Expand Down