1 /**
  2  * Validator for Internet Explorer 6 and 7
  3  */
  4 xq.ValidatorTrident = xq.Class(xq.Validator, {
  5 	validate: function(element, fullValidation) {
  6 		element = element.cloneNode(true);
  7 		
  8 		this.removeDangerousElements(element);
  9 		this.validateFontColor(element);
 10 		this.validateBackgroundColor(element);
 11 		
 12 		var content = element.innerHTML;
 13 		
 14 		try {
 15 			content = this.validateStrike(content);
 16 			content = this.validateUnderline(content);
 17 			
 18 			if(fullValidation) content = this.performFullValidation(content);
 19 		} catch(ignored) {}
 20 		
 21 		return content;
 22 	},
 23 	
 24 	invalidate: function(element) {
 25 		var rdom = xq.RichDom.createInstance();
 26 		rdom.setRoot(element);
 27 		
 28 		this.invalidateFontColor(element);
 29 		this.invalidateBackgroundColor(element);
 30 		
 31 		// <span class="strike"> -> <strike>
 32 		var strikes = xq.getElementsByClassName(rdom.getRoot(), "strike");
 33 		for(var i = 0; i < strikes.length; i++) {
 34 			if("SPAN" == strikes[i].nodeName) rdom.replaceTag("strike", strikes[i]).removeAttribute("className");
 35 		}
 36 		
 37 		// <em|i class="underline"> -> <u>
 38 		var underlines = xq.getElementsByClassName(rdom.getRoot(), "underline");
 39 		for(var i = 0; i < underlines.length; i++) {
 40 			if(["EM", "I"].indexOf(underlines[i].nodeName) != -1) rdom.replaceTag("u", underlines[i]).removeAttribute("className");
 41 		}
 42 
 43 		var content = rdom.getRoot().innerHTML;
 44 
 45 		content = this.removeComments(content);
 46 		
 47 		return content;
 48 	},
 49 	
 50 	performFullValidation: function(content) {
 51 		content = this.lowerTagNamesAndUniformizeQuotation(content);
 52 		content = this.validateSelfClosingTags(content);
 53 		content = this.applyWhitelist(content);
 54 		
 55 		if(this.urlValidationMode == 'relative') {
 56 			content = this.makeUrlsRelative(content);
 57 		} else if(this.urlValidationMode == 'host_relative') {
 58 			content = this.makeUrlsHostRelative(content);
 59 		} else if(this.urlValidationMode == 'absolute') {
 60 			// Trident always use absolute URL so we don't need to do anything.
 61 			//
 62 			// content = this.makeUrlsAbsolute(content);
 63 		}
 64 		
 65 		return content;
 66 	},
 67 	
 68 	validateFontColor: function(element) {
 69 		var rdom = xq.RichDom.createInstance();
 70 		rdom.setRoot(element);
 71 		
 72 		// It should be reversed to deal with nested elements
 73 		var fonts = xq.$A(element.getElementsByTagName('FONT')).reverse();
 74 		for(var i = 0; i < fonts.length; i++) {
 75 			var font = fonts[i];
 76 			var color = font.getAttribute('color');
 77 			
 78 			if(color) {
 79 				var span = rdom.replaceTag("span", font);
 80 				span.removeAttribute('color');
 81 				span.style.color = color;
 82 			}
 83 		}
 84 	},
 85 
 86 	invalidateFontColor: function(element) {
 87 		var rdom = xq.RichDom.createInstance();
 88 		rdom.setRoot(element);
 89 
 90 		var spans = xq.$A(element.getElementsByTagName('SPAN')).reverse();
 91 		for(var i = 0; i < spans.length; i++) {
 92 			var span = spans[i];
 93 			var color = span.style.color;
 94 			
 95 			if(color) {
 96 				var font = rdom.replaceTag("font", span);
 97 				font.style.color = "";
 98 				font.setAttribute('color', color);
 99 			}
100 		}
101 	},
102 
103 	validateBackgroundColor: function(element) {
104 		var rdom = xq.RichDom.createInstance();
105 		rdom.setRoot(element);
106 
107 		// It should be reversed to deal with nested elements
108 		var fonts = xq.$A(element.getElementsByTagName('FONT')).reverse();
109 		for(var i = 0; i < fonts.length; i++) {
110 			if(fonts[i].style.color || fonts[i].style.backgroundColor) rdom.replaceTag("span", fonts[i]);
111 		}
112 	},
113 
114 	invalidateBackgroundColor: function(element) {
115 		var rdom = xq.RichDom.createInstance();
116 		rdom.setRoot(element);
117 
118 		// It should be reversed to deal with nested elements
119 		var spans = xq.$A(element.getElementsByTagName('SPAN')).reverse();
120 		for(var i = 0; i < spans.length; i++) {
121 			if(spans[i].style.color || spans[i].style.backgroundColor) rdom.replaceTag("font", spans[i]);
122 		}
123 	},
124 	
125 	lowerTagNamesAndUniformizeQuotation: function(content) {
126 		// Uniformize quotation, turn tag names and attribute names into lower case
127 		content = content.replace(/<(\/?)(\w+)([^>]*?)>/img, function(str, closingMark, tagName, attrs) {
128 			return "<" + closingMark + tagName.toLowerCase() + this.correctHtmlAttrQuotation(attrs) + ">";
129 		}.bind(this));
130 		
131 		return content;
132 	},
133 	
134 	correctHtmlAttrQuotation: function(html) {
135 		html = html.replace(/\s(\w+?)=\s+"([^"]+)"/mg,function (str, name, value) {return " " + name.toLowerCase() + '=' + '"' + value + '"'});
136 		html = html.replace(/\s(\w+?)=([^ "]+)/mg,function (str, name, value) {return " " + name.toLowerCase() + '=' + '"' + value + '"'});
137 		return html;
138 	}
139 });
140