PageRenderTime 57ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/static/plugin_wiki/elrte-1.0rc4/src/elrte/js/elRTE.filter.js

https://github.com/goldenboy/Web2py-Resume
JavaScript | 375 lines | 311 code | 35 blank | 29 comment | 56 complexity | 13ab1e1b35cfdec901f0c38c7e8a0e3d MD5 | raw file
  1. (function($) {
  2. /**
  3. * @class Clean html and make replace/restore for some patterns
  4. *
  5. * @param elRTE
  6. * @author Dmitry (dio) Levashov dio@std42.ru
  7. * @todo - replace/restore scripts
  8. */
  9. elRTE.prototype.filter = function(rte) {
  10. var self = this, chain, n;
  11. this.rte = rte;
  12. /* make xhtml tags? */
  13. this._xhtml = rte.options.doctype.match(/xhtml/i) ? true : false;
  14. /* chains of rules */
  15. this._chains = {};
  16. /* allowed tags */
  17. this._allow = rte.options.allowTags||[];
  18. /* deny tags */
  19. this._deny = rte.options.denyTags||[];
  20. /* swf placeholder class */
  21. this.swfClass = 'elrte-swf-placeholder';
  22. n = $('<span />').addClass(this.swfClass).appendTo(rte.editor).text('swf')[0];
  23. if (typeof n.currentStyle != "undefined") {
  24. url = n.currentStyle['backgroundImage'];
  25. } else {
  26. url = document.defaultView.getComputedStyle(n, null).getPropertyValue('background-image');
  27. }
  28. $(n).remove();
  29. /* swf placeholder url */
  30. this.swfSrc = url ? url.replace(/^url\("?([^"]+)"?\)$/, "$1") : '';
  31. /* create chains */
  32. for (chain in this.chains) {
  33. if (this.chains.hasOwnProperty(chain)) {
  34. this._chains[chain] = [];
  35. $.each(this.chains[chain], function() {
  36. if (typeof(self.rules[this]) == 'function') {
  37. self._chains[chain].push(self.rules[this]);
  38. }
  39. });
  40. }
  41. }
  42. /* check default chains exists */
  43. if (!this._chains.toSource || !this._chains.toSource.length) {
  44. this._chains.toSource = [this.rules.toSource]
  45. }
  46. if (!this._chains.fromSource || !this._chains.fromSource.length) {
  47. this._chains.fromSource = [this.rules.fromSource]
  48. }
  49. /**
  50. * Procces html in required chains
  51. *
  52. * @param String
  53. * @param String chain name
  54. * @return String
  55. */
  56. this.proccess = function(html, chain) {
  57. if (this._chains[chain]) {
  58. $.each(this._chains[chain], function() {
  59. html = this(self, html);
  60. });
  61. }
  62. return html;
  63. }
  64. /**
  65. * Procces html in toSource chain
  66. *
  67. * @param String
  68. * @return String
  69. */
  70. this.toSource = function(html) {
  71. return this.proccess(html, 'toSource');
  72. }
  73. /**
  74. * Procces html in fromSource chain
  75. *
  76. * @param String
  77. * @return String
  78. */
  79. this.fromSource = function(html) {
  80. return this.proccess(html, 'fromSource');
  81. }
  82. /**
  83. * Add user methods for replace/restore any patterns in html
  84. *
  85. * @param Function replace method
  86. * @param Function restore method
  87. */
  88. this.addReplacement = function(rp, rs) {
  89. if (typeof(rp) == 'function') {
  90. this._chains.fromSource.unshift(rp);
  91. }
  92. if (typeof(rs) == 'function') {
  93. this._chains.toSource.unshift(rp);
  94. }
  95. }
  96. }
  97. /**
  98. * Default rules
  99. */
  100. elRTE.prototype.filter.prototype.rules = {
  101. /* common cleanup tags and attrs */
  102. cleanup : function(f, html) {
  103. var at = f._allow.length,
  104. dt = f._deny.length,
  105. fsize = ['', 'xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large'],
  106. map = {
  107. b : ['strong'],
  108. big : ['span', 'font-size:large'],
  109. center : ['div', 'text-align:center'],
  110. font : ['span'],
  111. i : ['em'],
  112. nobr : ['span', 'white-space:nowrap'],
  113. small : ['span', 'font-size:small'],
  114. u : ['span', 'text-decoration:underline']
  115. };
  116. if ($.browser.opera||$.browser.msie) {
  117. html = f.rules.tagsToLower(f, html);
  118. }
  119. /* Replace non-semantic tags */
  120. html = html.replace(/\<(\/?)(b|i|u|font|center|nobr|big|small)(\s+[^>]*)?\>/gi, function(t, s, n, a) {
  121. n = n.toLowerCase(n);
  122. a = (a||'').toLowerCase(a);
  123. if (map[n]) {
  124. if (!s && map[n][1]) {
  125. a = a.indexOf('style="') == -1 ? a+' style="'+map[n][1]+'"' : a.replace('style="', 'style="'+map[n][1]+';');
  126. }
  127. return '<'+s+map[n][0]+a+'>';
  128. }
  129. return t;
  130. });
  131. /* Replace non-semantic attributes with css */
  132. html = html.replace(/\<([a-z1-6]+)\s+([^>]*(border|bordercolor|color|background|bgcolor|align|valign|hspace|vspace|clear|size|face)=[^>]*)\>/gi, function(t, n, a) {
  133. var attrs = {},
  134. m = a.match(/([a-z]+)="([^"]*)"/gi), _t, i;
  135. function style(v) {
  136. if (!attrs.style) {
  137. attrs.style = '';
  138. }
  139. attrs.style = v+';'+attrs.style;
  140. }
  141. if (m) {
  142. for (i=0; i<m.length; i++) {
  143. _t = m[i].split('=');
  144. attrs[_t[0]] = _t[1].replace(/"/g, '');
  145. }
  146. }
  147. if (attrs.border) {
  148. style('border:'+attrs.border+'px solid '+(attrs.bordercolor||'#000'));
  149. delete attrs.border;
  150. delete attrs.bordercolor;
  151. }
  152. if (attrs.color) {
  153. style('color:'+attrs.color);
  154. delete attrs.color
  155. }
  156. if (attrs.background) {
  157. style('background-image:url('+attrs.background+')');
  158. delete attrs.background;
  159. }
  160. if (attrs.bgcolor) {
  161. style('background-color:'+attrs.bgcolor);
  162. delete attrs.bgcolor;
  163. }
  164. if (attrs.align) {
  165. if (n == 'img') {
  166. if (attrs.align.match(/(left|right)/)) {
  167. style('float:'+attrs.align);
  168. } else {
  169. style('vertical-align:'+attrs.align);
  170. }
  171. } else if (n == 'table') {
  172. if (attrs.align == 'center') {
  173. style('margin-left:auto;margin-right:auto');
  174. } else {
  175. style('float:'+attrs.align);
  176. }
  177. } else {
  178. style('text-align:'+attrs.align);
  179. }
  180. delete attrs.align;
  181. }
  182. if (attrs.valign) {
  183. style('vertical-align:'+attrs.valign);
  184. delete attrs.valign;
  185. }
  186. if (attrs.hspace) {
  187. style('margin-left:'+attrs.hspace+'px;margin-right:'+attrs.hspace+'px');
  188. delete attrs.hspace;
  189. }
  190. if (attrs.vspace) {
  191. style('margin-top:'+attrs.vspace+'px;margin-bottom:'+attrs.vspace+'px');
  192. delete attrs.vspace;
  193. }
  194. if (attrs.size && n != 'input') {
  195. if (n == 'hr') {
  196. style('height:'+attrs.size+'px')
  197. } else {
  198. style('font-size:'+(fsize[attrs.size]||'medium'));
  199. }
  200. delete attrs.size;
  201. }
  202. if (attrs.clear) {
  203. style('clear:'+(attrs.clear=='all' ? 'both' : attrs.clear));
  204. delete attrs.clear;
  205. }
  206. if (attrs.face) {
  207. delete attrs.face;
  208. }
  209. a = '';
  210. for (i in attrs) {
  211. if (attrs.hasOwnProperty(i) && attrs[i]) {
  212. a += ' '+i+'="'+attrs[i]+'"';
  213. }
  214. }
  215. return '<'+n+a+'>';
  216. })
  217. /* Remove not allowed tags */
  218. if ( at || dt) {
  219. html = html.replace(/\<(\/?)([a-z1-6]+)([^>]*)\>/gi, function(t, s, n, a) {
  220. n = n.toLowerCase(n);
  221. return (at && $.inArray(n, f._allow) == -1) || (dt && $.inArray(n, f._deny) != -1) ? '' : '<'+s+n+a+'>';
  222. });
  223. }
  224. return html;
  225. },
  226. /* move tags to lowercase in ie and opera */
  227. tagsToLower : function(f, html) {
  228. return html.replace(/\<(\/?)([a-z1-6]+)([^\>]*)\>/ig, function(s, sl, tag, arg) {
  229. arg = arg.replace(/([a-z\-]+)\:/ig, function(s, a) { return a.toLowerCase()+':' });
  230. arg = arg.replace(/([a-z\-]+)=/ig, function(s, a) { return a.toLowerCase()+'=' });
  231. arg = arg.replace(/([a-z\-]+)=([a-z1-9\-]+)/ig, function(s, a, v) { return a+'="'+v+'"' })
  232. return '<'+sl+tag.toLowerCase()+arg+'>';
  233. })//.replace(/\<\/([a-z1-6]+)\>/ig, function(s, tag) { return '</'+tag.toLowerCase()+'>';});
  234. },
  235. /* make xhtml tags */
  236. xhtmlTags : function(f, html) {
  237. return html.replace(/\<(img|hr|br)([^>\/]*)\>/gi, "<$1$2 />");
  238. },
  239. /* proccess html for textarea */
  240. toSource : function(f, html) {
  241. html = f.rules.restore(f, html);
  242. /* clean tags & attributes */
  243. html = f.rules.cleanup(f, html);
  244. /* make xhtml tags if required */
  245. if (f._xhtml) {
  246. html = f.rules.xhtmlTags(f, html);
  247. }
  248. return html;
  249. },
  250. /* proccess html for editor */
  251. fromSource : function(f, html) {
  252. html = f.rules.replace(f, html);
  253. /* clean tags & attributes */
  254. html = f.rules.cleanup(f, html);
  255. return html;
  256. },
  257. /* replace swf with placeholder */
  258. replace : function(f, html) {
  259. var n = $('<div/>').html(html);
  260. n.find('object[classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"]')
  261. .each(function() {
  262. var t = $(this),
  263. url = t.children('param[name="'+($.browser.msie ? 'Movie' : 'movie')+'"]').attr('value'),
  264. st = t.attr('style')||'',
  265. w = parseInt(t.css('width')||0) || parseInt(t.attr('width')||0) || '',
  266. h = parseInt(t.css('height')||0) || parseInt(t.attr('height')||0) || '',
  267. fl = t.css('float') || t.attr('align'),
  268. a = t.css('vertical-align'),
  269. img = $('<img src="'+f.swfSrc+'" class="'+f.swfClass+'" rel="'+url+'" />');
  270. img.attr('style', st).css({
  271. width : w?(w+'px'):'auto',
  272. height : h?h+'px':'auto',
  273. 'float' : fl,
  274. 'vertical-align' : a
  275. });
  276. $(this).replaceWith(img);
  277. }).end().find('embed[type="application/x-shockwave-flash"]').each(function() {
  278. var t = $(this),
  279. url = t.attr('src'),
  280. st = t.attr('style')||'',
  281. w = parseInt(t.css('width')||0) || parseInt(t.attr('width')||0) || '',
  282. h = parseInt(t.css('height')||0) || parseInt(t.attr('height')||0) || '',
  283. fl = t.css('float') || t.attr('align'),
  284. a = t.css('vertical-align'),
  285. img = $('<img src="'+f.swfSrc+'" class="'+f.swfClass+'" rel="'+url+'" />');
  286. img.attr('style', st).css({
  287. width : w?(w+'px'):'auto',
  288. height : h?h+'px':'auto',
  289. 'float' : fl,
  290. 'vertical-align' : a
  291. });
  292. $(this).replaceWith(img);
  293. })
  294. return n.html();
  295. },
  296. /* restore swf from placeholder */
  297. restore : function(f, html) {
  298. var n = $('<div/>').html(html);
  299. n.find('.'+f.swfClass).each(function() {
  300. var t = $(this),
  301. w = parseInt(t.css('width'))||'',
  302. h = parseInt(t.css('height'))||'',
  303. s = t.attr('style')
  304. obj = '<embed type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" src="'+t.attr('rel')+'" width="'+w+'" height="'+h+'" style="'+s+'" play="true" loop="true" menu="true"> </embed>';
  305. // obj = '<object style="'+(t.attr('style')||'')+'" width="'+parseInt(t.css('width'))+'" height="'+parseInt(t.css('height'))+'" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="quality" value="high" /><param name="movie" value="'+$(this).attr('rel')+'" /><embed pluginspage="http://www.macromedia.com/go/getflashplayer" quality="high" src="'+$(this).attr('rel')+'" type="application/x-shockwave-flash"></embed></object>';
  306. // f.rte.log(obj)
  307. t.replaceWith($(obj));
  308. })
  309. .end().find('.Apple-style-span').removeClass('Apple-style-span')
  310. .end().find('*').each(function() {
  311. var t = $(this);
  312. if (t.attr('class') == '') {
  313. t.removeAttr('class')
  314. }
  315. if (t.attr('style') == '') {
  316. t.removeAttr('style')
  317. }
  318. });
  319. return n.html();
  320. }
  321. }
  322. /**
  323. * Default chains configuration
  324. */
  325. elRTE.prototype.filter.prototype.chains = {
  326. toSource : [ 'toSource' ],
  327. fromSource : [ 'fromSource' ]
  328. }
  329. })(jQuery);