includes/clientside/static/dynano.js
changeset 1227 bdac73ed481e
parent 1040 c631faf25a12
child 1311 a228f7e8fb15
equal deleted inserted replaced
1226:de56132c008d 1227:bdac73ed481e
     1 // The "Dynano" Javascript framework. Similar in syntax to JQuery but highly Enano-specific (TinyMCE, etc).
     1 // The "Dynano" Javascript framework. Similar in syntax to JQuery but highly Enano-specific (TinyMCE, etc).
     2 
     2 
     3 var $dynano = function(id)
     3 var $dynano = function(id)
     4 {
     4 {
     5   return new DNobj(id);
     5 	return new DNobj(id);
     6 }
     6 }
     7 function DNobj(id)
     7 function DNobj(id)
     8 {
     8 {
     9   if ( id == undefined )
     9 	if ( id == undefined )
    10   {
    10 	{
    11     return {};
    11 		return {};
    12   }
    12 	}
    13   this.object = ( typeof(id) == 'object' ) ? id : document.getElementById(id);
    13 	this.object = ( typeof(id) == 'object' ) ? id : document.getElementById(id);
    14   if ( !this.object )
    14 	if ( !this.object )
    15   {
    15 	{
    16     console.warn('Dynano: requested object is bad. id parameter follows.');
    16 		console.warn('Dynano: requested object is bad. id parameter follows.');
    17     console.debug(id);
    17 		console.debug(id);
    18     this.object = false;
    18 		this.object = false;
    19     return this;
    19 		return this;
    20   }
    20 	}
    21   if ( this.object.Dynano )
    21 	if ( this.object.Dynano )
    22   {
    22 	{
    23     return this.object.Dynano;
    23 		return this.object.Dynano;
    24   }
    24 	}
    25   this.object.Dynano = this;
    25 	this.object.Dynano = this;
    26   
    26 	
    27   this.height = __DNObjGetHeight(this.object);
    27 	this.height = __DNObjGetHeight(this.object);
    28   this.width = __DNObjGetWidth(this.object);
    28 	this.width = __DNObjGetWidth(this.object);
    29   
    29 	
    30   if ( this.object.tagName == 'TEXTAREA' && ( typeof(tinyMCE) == 'object' || typeof(tinyMCE_GZ) == 'object' ) )
    30 	if ( this.object.tagName == 'TEXTAREA' && ( typeof(tinyMCE) == 'object' || typeof(tinyMCE_GZ) == 'object' ) )
    31   {
    31 	{
    32     this.object.dnIsMCE = 'no';
    32 		this.object.dnIsMCE = 'no';
    33     this.switchToMCE = DN_switchToMCE;
    33 		this.switchToMCE = DN_switchToMCE;
    34     this.destroyMCE = DN_destroyMCE;
    34 		this.destroyMCE = DN_destroyMCE;
    35     this.getContent = DN_mceFetchContent;
    35 		this.getContent = DN_mceFetchContent;
    36     this.setContent = DN_mceSetContent;
    36 		this.setContent = DN_mceSetContent;
    37     this.makeSwitchable = DN_makeSwitchableTA;
    37 		this.makeSwitchable = DN_makeSwitchableTA;
    38     this.isMCE = DN_isMCE;
    38 		this.isMCE = DN_isMCE;
    39   }
    39 	}
    40 }
    40 }
    41 function __DNObjGetHeight(o) {
    41 function __DNObjGetHeight(o) {
    42   return o.offsetHeight;
    42 	return o.offsetHeight;
    43 }
    43 }
    44 
    44 
    45 function __DNObjGetWidth(o) {
    45 function __DNObjGetWidth(o) {
    46   return o.offsetWidth;
    46 	return o.offsetWidth;
    47 }
    47 }
    48 
    48 
    49 function addClass(obj, clsname)
    49 function addClass(obj, clsname)
    50 {
    50 {
    51   var cnt = obj.className;
    51 	var cnt = obj.className;
    52   var space = ( (cnt + '').length > 0 ) ? ' ' : '';
    52 	var space = ( (cnt + '').length > 0 ) ? ' ' : '';
    53   var cls = cnt + space + clsname;
    53 	var cls = cnt + space + clsname;
    54   obj.className = cls;
    54 	obj.className = cls;
    55 }
    55 }
    56 
    56 
    57 function rmClass(obj, clsname)
    57 function rmClass(obj, clsname)
    58 {
    58 {
    59   var cnt = obj.className;
    59 	var cnt = obj.className;
    60   if ( cnt == clsname )
    60 	if ( cnt == clsname )
    61   {
    61 	{
    62     obj.className = '';
    62 		obj.className = '';
    63   }
    63 	}
    64   else
    64 	else
    65   {
    65 	{
    66     cnt = cnt.replace(clsname, '');
    66 		cnt = cnt.replace(clsname, '');
    67     cnt = trim(cnt);
    67 		cnt = trim(cnt);
    68     obj.className = cnt;
    68 		obj.className = cnt;
    69   }
    69 	}
    70 }
    70 }
    71 
    71 
    72 function hasClass(obj, clsname)
    72 function hasClass(obj, clsname)
    73 {
    73 {
    74   var cnt = obj.className;
    74 	var cnt = obj.className;
    75   if ( !cnt )
    75 	if ( !cnt )
    76     return false;
    76 		return false;
    77   if ( cnt == clsname )
    77 	if ( cnt == clsname )
    78     return true;
    78 		return true;
    79   cnt = cnt.split(' ');
    79 	cnt = cnt.split(' ');
    80   
    80 	
    81   for ( var i in cnt )
    81 	for ( var i in cnt )
    82     if ( cnt[i] == clsname )
    82 		if ( cnt[i] == clsname )
    83       return true;
    83 			return true;
    84     
    84 		
    85   return false;
    85 	return false;
    86 }
    86 }
    87 function __DNObjGetLeft(obj) {
    87 function __DNObjGetLeft(obj) {
    88   var left_offset = obj.offsetLeft;
    88 	var left_offset = obj.offsetLeft;
    89   while ((obj = obj.offsetParent) != null) {
    89 	while ((obj = obj.offsetParent) != null) {
    90     left_offset += obj.offsetLeft;
    90 		left_offset += obj.offsetLeft;
    91   }
    91 	}
    92   return left_offset;
    92 	return left_offset;
    93 }
    93 }
    94 
    94 
    95 function __DNObjGetTop(obj) {
    95 function __DNObjGetTop(obj) {
    96   var left_offset = obj.offsetTop;
    96 	var left_offset = obj.offsetTop;
    97   while ((obj = obj.offsetParent) != null) {
    97 	while ((obj = obj.offsetParent) != null) {
    98     left_offset += obj.offsetTop;
    98 		left_offset += obj.offsetTop;
    99   }
    99 	}
   100   return left_offset;
   100 	return left_offset;
   101 }
   101 }
   102 
   102 
   103 function DN_switchToMCE(performWikiTransform)
   103 function DN_switchToMCE(performWikiTransform)
   104 {
   104 {
   105   if ( !this.object.id )
   105 	if ( !this.object.id )
   106     this.object.id = 'textarea_' + Math.floor(Math.random() * 1000000);
   106 		this.object.id = 'textarea_' + Math.floor(Math.random() * 1000000);
   107   if ( !this.object.name )
   107 	if ( !this.object.name )
   108     this.object.name = 'textarea_' + Math.floor(Math.random() * 1000000);
   108 		this.object.name = 'textarea_' + Math.floor(Math.random() * 1000000);
   109   // Updated for TinyMCE 3.x
   109 	// Updated for TinyMCE 3.x
   110   if ( performWikiTransform )
   110 	if ( performWikiTransform )
   111   {
   111 	{
   112     this.object.value = DN_WikitextToXHTML(this.object.value);
   112 		this.object.value = DN_WikitextToXHTML(this.object.value);
   113   }
   113 	}
   114   // If tinyMCE init hasn't been called yet, do it now.
   114 	// If tinyMCE init hasn't been called yet, do it now.
   115   if ( !tinymce_initted )
   115 	if ( !tinymce_initted )
   116   {
   116 	{
   117     console.info('$dynano().switchToMCE(): doing "exact"-type MCE init');
   117 		console.info('$dynano().switchToMCE(): doing "exact"-type MCE init');
   118     enano_tinymce_options.mode = 'exact';
   118 		enano_tinymce_options.mode = 'exact';
   119     enano_tinymce_options.elements = this.object.id;
   119 		enano_tinymce_options.elements = this.object.id;
   120     initTinyMCE();
   120 		initTinyMCE();
   121     this.object.dnIsMCE = 'yes';
   121 		this.object.dnIsMCE = 'yes';
   122     return true;
   122 		return true;
   123   }
   123 	}
   124   else
   124 	else
   125   {
   125 	{
   126     console.info('$dynano().switchToMCE(): tinyMCE already loaded, calling mceAddControl');
   126 		console.info('$dynano().switchToMCE(): tinyMCE already loaded, calling mceAddControl');
   127     tinymce.EditorManager.execCommand("mceAddControl", true, this.object.id);
   127 		tinymce.EditorManager.execCommand("mceAddControl", true, this.object.id);
   128     this.object.dnIsMCE = 'yes';
   128 		this.object.dnIsMCE = 'yes';
   129   }
   129 	}
   130   return this;
   130 	return this;
   131 }
   131 }
   132 
   132 
   133 function DN_destroyMCE(performWikiTransform)
   133 function DN_destroyMCE(performWikiTransform)
   134 {
   134 {
   135   //if ( !this.object.dn_is_mce )
   135 	//if ( !this.object.dn_is_mce )
   136   //  return this;
   136 	//  return this;
   137   if ( this.object.id && window.tinymce )
   137 	if ( this.object.id && window.tinymce )
   138   {
   138 	{
   139     // TinyMCE 2.x
   139 		// TinyMCE 2.x
   140     // tinymce.EditorManager.removeMCEControl(this.object.name);
   140 		// tinymce.EditorManager.removeMCEControl(this.object.name);
   141     // TinyMCE 3.x
   141 		// TinyMCE 3.x
   142     var ed = tinymce.EditorManager.getInstanceById(this.object.id);
   142 		var ed = tinymce.EditorManager.getInstanceById(this.object.id);
   143     if ( ed )
   143 		if ( ed )
   144     {
   144 		{
   145       if ( !tinymce.EditorManager.execCommand("mceRemoveEditor", false, this.object.id) )
   145 			if ( !tinymce.EditorManager.execCommand("mceRemoveEditor", false, this.object.id) )
   146         alert('could not destroy editor');
   146 				alert('could not destroy editor');
   147       if ( performWikiTransform )
   147 			if ( performWikiTransform )
   148       {
   148 			{
   149         this.object.value = DN_XHTMLToWikitext(this.object.value);
   149 				this.object.value = DN_XHTMLToWikitext(this.object.value);
   150       }
   150 			}
   151     }
   151 		}
   152   }
   152 	}
   153   this.object.dnIsMCE = 'no';
   153 	this.object.dnIsMCE = 'no';
   154   return this;
   154 	return this;
   155 }
   155 }
   156 
   156 
   157 function DN_isMCE()
   157 function DN_isMCE()
   158 {
   158 {
   159   return ( this.object.dnIsMCE == 'yes' );
   159 	return ( this.object.dnIsMCE == 'yes' );
   160 }
   160 }
   161 
   161 
   162 function DN_mceFetchContent()
   162 function DN_mceFetchContent()
   163 {
   163 {
   164   if ( this.object.name )
   164 	if ( this.object.name )
   165   {
   165 	{
   166     var text = this.object.value;
   166 		var text = this.object.value;
   167     if ( tinymce.EditorManager.get(this.object.id) )
   167 		if ( tinymce.EditorManager.get(this.object.id) )
   168     {
   168 		{
   169       var editor = tinymce.EditorManager.get(this.object.id);
   169 			var editor = tinymce.EditorManager.get(this.object.id);
   170       text = editor.getContent();
   170 			text = editor.getContent();
   171     }
   171 		}
   172     return text;
   172 		return text;
   173   }
   173 	}
   174   else
   174 	else
   175   {
   175 	{
   176     return this.object.value;
   176 		return this.object.value;
   177   }
   177 	}
   178 }
   178 }
   179 
   179 
   180 function DN_mceSetContent(text)
   180 function DN_mceSetContent(text)
   181 {
   181 {
   182   if ( this.object.name )
   182 	if ( this.object.name )
   183   {
   183 	{
   184     this.object.value = text;
   184 		this.object.value = text;
   185     if ( tinymce.EditorManager.get(this.object.id) )
   185 		if ( tinymce.EditorManager.get(this.object.id) )
   186     {
   186 		{
   187       var editor = tinymce.EditorManager.get(this.object.id);
   187 			var editor = tinymce.EditorManager.get(this.object.id);
   188       editor.setContent(text);
   188 			editor.setContent(text);
   189     }
   189 		}
   190   }
   190 	}
   191   else
   191 	else
   192   {
   192 	{
   193     this.object.value = text;
   193 		this.object.value = text;
   194   }
   194 	}
   195 }
   195 }
   196 
   196 
   197 var P_BOTTOM = 1;
   197 var P_BOTTOM = 1;
   198 var P_TOP = 2;
   198 var P_TOP = 2;
   199 
   199 
   200 function DN_makeSwitchableTA(pos)
   200 function DN_makeSwitchableTA(pos)
   201 {
   201 {
   202   if ( this.toggler )
   202 	if ( this.toggler )
   203     return false;
   203 		return false;
   204   
   204 	
   205   if ( !pos )
   205 	if ( !pos )
   206     pos = P_BOTTOM;
   206 		pos = P_BOTTOM;
   207   
   207 	
   208   load_component('l10n');
   208 	load_component('l10n');
   209   var cookiename = 'enano_editor_mode';
   209 	var cookiename = 'enano_editor_mode';
   210   
   210 	
   211   var toggler = document.createElement('div');
   211 	var toggler = document.createElement('div');
   212   toggler.dynano = this;
   212 	toggler.dynano = this;
   213   this.toggler = toggler;
   213 	this.toggler = toggler;
   214   
   214 	
   215   if ( !this.object.id )
   215 	if ( !this.object.id )
   216     this.object.id = 'dynano_auto_' + Math.floor(Math.random() * 1000000);
   216 		this.object.id = 'dynano_auto_' + Math.floor(Math.random() * 1000000);
   217   
   217 	
   218   toggler.s_mode_text = $lang.get('editor_btn_wikitext');
   218 	toggler.s_mode_text = $lang.get('editor_btn_wikitext');
   219   toggler.s_mode_graphical = $lang.get('editor_btn_graphical');
   219 	toggler.s_mode_graphical = $lang.get('editor_btn_graphical');
   220   
   220 	
   221   toggler.set_text = function()
   221 	toggler.set_text = function()
   222   {
   222 	{
   223     if ( this.dynano.object.dnIsMCE == 'yes' )
   223 		if ( this.dynano.object.dnIsMCE == 'yes' )
   224       this.dynano.destroyMCE();
   224 			this.dynano.destroyMCE();
   225     
   225 		
   226     this.innerHTML = '';
   226 		this.innerHTML = '';
   227     this.appendChild(document.createTextNode(this.s_mode_text + ' | '));
   227 		this.appendChild(document.createTextNode(this.s_mode_text + ' | '));
   228     
   228 		
   229     var link = document.createElement('a');
   229 		var link = document.createElement('a');
   230     link.href = '#';
   230 		link.href = '#';
   231     link.onclick = function()
   231 		link.onclick = function()
   232     {
   232 		{
   233       this.parentNode.set_graphical();
   233 			this.parentNode.set_graphical();
   234       return false;
   234 			return false;
   235     }
   235 		}
   236     link.appendChild(document.createTextNode(this.s_mode_graphical));
   236 		link.appendChild(document.createTextNode(this.s_mode_graphical));
   237     this.appendChild(link);
   237 		this.appendChild(link);
   238     
   238 		
   239     createCookie('enano_editor_mode', 'text', 365);
   239 		createCookie('enano_editor_mode', 'text', 365);
   240   }
   240 	}
   241   
   241 	
   242   toggler.set_graphical = function()
   242 	toggler.set_graphical = function()
   243   {
   243 	{
   244     this.dynano.switchToMCE();
   244 		this.dynano.switchToMCE();
   245     this.innerHTML = '';
   245 		this.innerHTML = '';
   246     
   246 		
   247     var link = document.createElement('a');
   247 		var link = document.createElement('a');
   248     link.href = '#';
   248 		link.href = '#';
   249     link.onclick = function()
   249 		link.onclick = function()
   250     {
   250 		{
   251       this.parentNode.set_text();
   251 			this.parentNode.set_text();
   252       return false;
   252 			return false;
   253     }
   253 		}
   254     link.appendChild(document.createTextNode(this.s_mode_text));
   254 		link.appendChild(document.createTextNode(this.s_mode_text));
   255     this.appendChild(link);
   255 		this.appendChild(link);
   256     
   256 		
   257     this.appendChild(document.createTextNode(' | ' + this.s_mode_graphical));
   257 		this.appendChild(document.createTextNode(' | ' + this.s_mode_graphical));
   258     createCookie('enano_editor_mode', 'tinymce', 365);
   258 		createCookie('enano_editor_mode', 'tinymce', 365);
   259   }
   259 	}
   260   
   260 	
   261   toggler.style.styleFloat = 'right';
   261 	toggler.style.styleFloat = 'right';
   262   toggler.style.cssFloat = 'right';
   262 	toggler.style.cssFloat = 'right';
   263   if ( pos == P_BOTTOM )
   263 	if ( pos == P_BOTTOM )
   264   {
   264 	{
   265     insertAfter(this.object.parentNode, toggler, this.object);
   265 		insertAfter(this.object.parentNode, toggler, this.object);
   266   }
   266 	}
   267   else
   267 	else
   268   {
   268 	{
   269     this.object.parentNode.insertBefore(toggler, this.object);
   269 		this.object.parentNode.insertBefore(toggler, this.object);
   270   }
   270 	}
   271   
   271 	
   272   if ( readCookie(cookiename) == 'tinymce' )
   272 	if ( readCookie(cookiename) == 'tinymce' )
   273   {
   273 	{
   274     toggler.set_graphical();
   274 		toggler.set_graphical();
   275   }
   275 	}
   276   else
   276 	else
   277   {
   277 	{
   278     toggler.set_text();
   278 		toggler.set_text();
   279   }
   279 	}
   280 }
   280 }
   281 
   281 
   282 function DN_WikitextToXHTML(text)
   282 function DN_WikitextToXHTML(text)
   283 {
   283 {
   284   return DN_AjaxGetTransformedText(text, 'xhtml');
   284 	return DN_AjaxGetTransformedText(text, 'xhtml');
   285 }
   285 }
   286 
   286 
   287 function DN_XHTMLToWikitext(text)
   287 function DN_XHTMLToWikitext(text)
   288 {
   288 {
   289   return DN_AjaxGetTransformedText(text, 'wikitext');
   289 	return DN_AjaxGetTransformedText(text, 'wikitext');
   290 }
   290 }
   291 
   291 
   292 // AJAX to the server to transform text
   292 // AJAX to the server to transform text
   293 function DN_AjaxGetTransformedText(text, to)
   293 function DN_AjaxGetTransformedText(text, to)
   294 {
   294 {
   295   // get an XHR instance
   295 	// get an XHR instance
   296   var ajax = ajaxMakeXHR();
   296 	var ajax = ajaxMakeXHR();
   297   
   297 	
   298   var uri = stdAjaxPrefix + '&_mode=transform&to=' + to;
   298 	var uri = stdAjaxPrefix + '&_mode=transform&to=' + to;
   299   var parms = 'text=' + ajaxEscape(text);
   299 	var parms = 'text=' + ajaxEscape(text);
   300   try
   300 	try
   301   {
   301 	{
   302     ajax.open('POST', uri, false);
   302 		ajax.open('POST', uri, false);
   303     ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
   303 		ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
   304     // Setting Content-length in Safari triggers a warning
   304 		// Setting Content-length in Safari triggers a warning
   305     if ( !is_Safari )
   305 		if ( !is_Safari )
   306     {
   306 		{
   307       ajax.setRequestHeader("Content-length", parms.length);
   307 			ajax.setRequestHeader("Content-length", parms.length);
   308     }
   308 		}
   309     ajax.send(parms);
   309 		ajax.send(parms);
   310     // async request, so if status != 200 at this point then we're screwed
   310 		// async request, so if status != 200 at this point then we're screwed
   311     if ( ajax.readyState == 4 && ajax.status == 200 )
   311 		if ( ajax.readyState == 4 && ajax.status == 200 )
   312     {
   312 		{
   313       var response = String(ajax.responseText + '');
   313 			var response = String(ajax.responseText + '');
   314       if ( !check_json_response(response) )
   314 			if ( !check_json_response(response) )
   315       {
   315 			{
   316         handle_invalid_json(response);
   316 				handle_invalid_json(response);
   317         return text;
   317 				return text;
   318       }
   318 			}
   319       response = parseJSON(response);
   319 			response = parseJSON(response);
   320       if ( response.mode == 'error' )
   320 			if ( response.mode == 'error' )
   321       {
   321 			{
   322         alert(response.error);
   322 				alert(response.error);
   323         return text;
   323 				return text;
   324       }
   324 			}
   325       return response.text;
   325 			return response.text;
   326     }
   326 		}
   327   }
   327 	}
   328   catch(e)
   328 	catch(e)
   329   {
   329 	{
   330     console.warn('DN_AjaxGetTransformedText: XHR failed');
   330 		console.warn('DN_AjaxGetTransformedText: XHR failed');
   331   }
   331 	}
   332   return text;
   332 	return text;
   333 }
   333 }
   334 
   334 
   335 DNobj.prototype.addClass = function(clsname) { addClass(this.object, clsname); return this; };
   335 DNobj.prototype.addClass = function(clsname) { addClass(this.object, clsname); return this; };
   336 DNobj.prototype.rmClass  = function(clsname) { rmClass( this.object, clsname); return this; };
   336 DNobj.prototype.rmClass  = function(clsname) { rmClass( this.object, clsname); return this; };
   337 DNobj.prototype.hasClass = function(clsname) { return hasClass(this.object, clsname); };
   337 DNobj.prototype.hasClass = function(clsname) { return hasClass(this.object, clsname); };