      1 /**
      2  * Validator for Internet Explorer 6 and 7
      3  */
      4 xq.ValidatorTrident = Class.create(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 = rdom.findByAttribute("className", "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 = rdom.findByAttribute("className", "underline");
     39 		for(var i = 0; i < underlines.length; i++) {
     40 			if(["EM", "I"].include(underlines[i].nodeName)) 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 = $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 = $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 = $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 = $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