Added selection and popup for <pre> tags within wikitext. Also fixed more bugs found in the HTML paragraph parser (mostly self-closing tags e.g. <hr />).
authorDan
Tue, 30 Mar 2010 11:37:00 -0400
changeset 1231 4797a4a88533
parent 1230 31d226269d2f
child 1232 83fd4ed90cc6
Added selection and popup for <pre> tags within wikitext. Also fixed more bugs found in the HTML paragraph parser (mostly self-closing tags e.g. <hr />).
includes/clientside/css/enano-shared.css
includes/clientside/static/enano-lib-basic.js
includes/clientside/static/login.js
includes/clientside/static/preformat.js
includes/sessions.php
includes/wikiengine/parse_mediawiki.php
language/english/core.json
themes/enanium/css/babygrand.css
--- a/includes/clientside/css/enano-shared.css	Tue Mar 30 11:34:56 2010 -0400
+++ b/includes/clientside/css/enano-shared.css	Tue Mar 30 11:37:00 2010 -0400
@@ -1039,3 +1039,20 @@
 .log_addfilter {
 	display: none;
 }
+
+/*
+ * The header over <pre> in the content area
+ */
+
+div.preformat-panel {
+	text-transform: uppercase;
+	font-size: 9px;
+	font-family: tahoma, arial, sans-serif;
+	font-weight: bold;
+	margin-left: 1em;
+	border-width: 1px 1px 0 1px;
+	border-style: dashed;
+	border-color: black;
+	background-color: #ddd;
+	padding: 3px;
+}
--- a/includes/clientside/static/enano-lib-basic.js	Tue Mar 30 11:34:56 2010 -0400
+++ b/includes/clientside/static/enano-lib-basic.js	Tue Mar 30 11:37:00 2010 -0400
@@ -58,6 +58,8 @@
 var is_Opera = checkIt('opera');
 var is_iPhone = checkIt('iphone') || checkIt('ipod');
 var is_iPhone_3 = checkIt('iphone os 3_');
+var is_Webkit = checkIt('applewebkit');
+var is_Gecko = checkIt('gecko');
 var is_firefox2 = checkIt('firefox/2.');
 
 var KILL_SWITCH = false;
@@ -474,6 +476,7 @@
 	'json.js',
 	'sliders.js',
 	'tinymce-init.js',
+	'preformat.js',
 	'loader.js'
 ];
 
--- a/includes/clientside/static/login.js	Tue Mar 30 11:34:56 2010 -0400
+++ b/includes/clientside/static/login.js	Tue Mar 30 11:37:00 2010 -0400
@@ -973,6 +973,7 @@
 
 window.ajaxLoginShowFriendlyError = function(response)
 {
+	eval(setHook('ajax_login_process_error'));
 	var text = ajaxLoginGetErrorText(response);
 	if ( text == false )
 		return true;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/static/preformat.js	Tue Mar 30 11:37:00 2010 -0400
@@ -0,0 +1,94 @@
+//
+// Add the wrappers for preformatted tags within content.
+//
+
+addOnloadHook(function()
+	{
+		preformat_process_all();
+	});
+
+function preformat_process_all()
+{
+	var aec = document.getElementById('ajaxEditContainer');
+	if ( !aec )
+		return false;
+	var pres = aec.getElementsByTagName('pre');
+	for ( var i = 0; i < pres.length; i++ )
+	{
+		if ( pres[i].hasButtonPanel )
+			continue;
+		pres[i].hasButtonPanel = true;
+		
+		var btnp = document.createElement('div');
+		btnp.mypre = pres[i];
+		btnp.className = 'preformat-panel';
+		btnp.appendChild(document.createTextNode($lang.get('onpage_pre_lbl_code')));
+		btnp.appendChild(document.createTextNode(' <'));
+		var a_sel = document.createElement('a');
+		a_sel.href = '#';
+		a_sel.onclick = function()
+			{
+				preformat_handle_select_click(this.parentNode);
+				return false;
+			};
+		a_sel.appendChild(document.createTextNode($lang.get('onpage_pre_btn_select')));
+		btnp.appendChild(a_sel);
+		btnp.appendChild(document.createTextNode('> <'));
+		var a_pop = document.createElement('a');
+		a_pop.href = '#';
+		a_pop.onclick = function()
+			{
+				preformat_handle_popup_click(this.parentNode);
+				return false;
+			};
+		a_pop.appendChild(document.createTextNode($lang.get('onpage_pre_btn_popup')));
+		btnp.appendChild(a_pop);
+		btnp.appendChild(document.createTextNode('>'));
+		pres[i].parentNode.insertBefore(btnp, pres[i]);
+	}
+}
+
+function preformat_handle_select_click(btnp)
+{
+	var pre = btnp.mypre;
+	select_element(pre);
+}
+
+function preformat_handle_popup_click(btnp)
+{
+	var pre = btnp.mypre;
+	var text = pre.innerHTML;
+	var newwin = window.open('about:blank', 'codepopwin', 'width=800,height=600,status=no,toolbars=no,toolbar=no,address=no,scroll=yes');
+	newwin.document.open();
+	newwin.document.write('<html><head><title>' + $lang.get('onpage_pre_popup_title') + '</title></head><body>');
+	newwin.document.write('<pre>' + text + '</pre>');
+	newwin.document.write('</body></html>');
+	newwin.document.close();
+}
+
+function select_element(element)
+{
+	if (IE)
+	{
+		// IE
+		var range = document.body.createTextRange();
+		range.moveToElementText(element);
+		range.select();
+	}
+	else if (is_Gecko || is_Opera)
+	{
+		// Mozilla/Opera
+		var selection = window.getSelection();
+		var range = document.createRange();
+		range.selectNodeContents(element);
+		selection.removeAllRanges();
+		selection.addRange(range);
+	}
+	else if (is_Webkit)
+	{
+		// Safari (Chrome?)
+		var selection = window.getSelection();
+		selection.setBaseAndExtent(element, 0, element, 1);
+	}
+}
+
--- a/includes/sessions.php	Tue Mar 30 11:34:56 2010 -0400
+++ b/includes/sessions.php	Tue Mar 30 11:37:00 2010 -0400
@@ -3822,7 +3822,7 @@
  	* @return array LoginAPI response
  	*/
 	
-	function process_login_request($req, $_dbgtmp = false)
+	function process_login_request($req)
 	{
 		global $db, $session, $paths, $template, $plugins; // Common objects
 		
--- a/includes/wikiengine/parse_mediawiki.php	Tue Mar 30 11:34:56 2010 -0400
+++ b/includes/wikiengine/parse_mediawiki.php	Tue Mar 30 11:37:00 2010 -0400
@@ -188,7 +188,20 @@
 		
 		// Find all opening and closing tags
 		
-		$regex = ";(<(?:/(?:$blocklevel)|(?:$blocklevel)(?: [^>]*?)?)>);s";
+		$regex = ";(
+						<
+							(?:
+								# closing tag
+								/(?:$blocklevel)
+							|
+								# opening or self-closing tag
+								(?:$blocklevel)
+								(?:[ ][^>]*?)?
+								/?
+							)
+						>
+					)
+					;xs";
 								
 		// oh. and we're using this tokens thing because for identical matches, the first match will
 		// get wrapped X number of times instead of all matches getting wrapped once; replacing each
@@ -204,11 +217,11 @@
 			// go through the text, extract tag names, and push them to a stack.
 			foreach ( $text_split as $splitpart )
 			{
-				if ( preg_match(";^<(/)?($blocklevel)( |>);i", $splitpart, $match) )
+				if ( preg_match(";^<(/)?($blocklevel)( ([^>]*?(/)?>)|(/)?>);i", $splitpart, $match) )
 				{
 					$tagname = $match[2];
 					if ( $match[1] == '/' )
-					{
+					{                    
 						// closing tag
 						if ( $tagname != ($top = array_pop($tag_stack)) )
 						{
@@ -224,21 +237,32 @@
 					}
 					else
 					{
-						// push
-						array_push($tag_stack, $tagname);
-						if ( count($tag_stack) == 1 )
-							$splitpart = '<_paragraph_bypass>' . $splitpart;
+						// is it a self-closed tag?
+						// FIXME: This parser is VERY STRICT right now as far as XHTML compliance. <hr> will
+						// pretty much totally break it, because it will be treated as an opening tag.
+						// Yes, self closing tags work.
+						if ( (isset($match[5]) && $match[5] === '/') || (isset($match[6]) && $match[6] === '/') )
+						{
+							// yes
+							if ( count($tag_stack) == 0 )
+								$splitpart = "<_paragraph_bypass>$splitpart</_paragraph_bypass>";
+						}
+						else
+						{
+							// opening tag - push
+							array_push($tag_stack, $tagname);
+							if ( count($tag_stack) == 1 )
+								$splitpart = '<_paragraph_bypass>' . $splitpart;
+						}
 					}
 				}
 				$text .= $splitpart;
 			}
-			//echo '<pre>' . htmlspecialchars(print_r($text, true)) . '</pre>';
+			// echo '<pre>' . htmlspecialchars(print_r($text, true)) . '</pre>';
 		}
 		
 		// All things that should be para-bypassed now are surrounded by _paragraph_bypass tags.
 		
-		// die('<pre>' . htmlspecialchars($text) . '</pre>');
-	
 		RenderMan::tag_unstrip('_paragraph_bypass', $text, $_nw, true);
 		
 		// This is potentially a hack. It allows the parser to stick in <_paragraph_bypass> tags
--- a/language/english/core.json	Tue Mar 30 11:34:56 2010 -0400
+++ b/language/english/core.json	Tue Mar 30 11:37:00 2010 -0400
@@ -315,6 +315,11 @@
 			cat_heading_pages: 'Pages',
 			cat_msg_no_pages: 'No pages in this category.',
 			
+			pre_lbl_code: 'Code:',
+			pre_btn_select: 'Select',
+			pre_btn_popup: 'Popup',
+			pre_popup_title: 'Code window',
+			
 			filebox_heading: 'Uploaded file',
 			filebox_msg_not_found: 'There are no files uploaded with this name yet. <a href="%upload_link%">Upload a file...</a>',
 			filebox_lbl_type: 'Type:',
--- a/themes/enanium/css/babygrand.css	Tue Mar 30 11:34:56 2010 -0400
+++ b/themes/enanium/css/babygrand.css	Tue Mar 30 11:37:00 2010 -0400
@@ -306,6 +306,16 @@
 	margin-left: 0.8em;
 }
 
+div.content pre {
+	margin-left: 1em;
+	margin-top: 0;
+	background-color: #F8F8F8;
+	border: 1px dashed #90B0D0;
+	padding: 10px;
+	overflow: auto;
+	clip: rect(0px, auto, auto, 0px);
+}
+
 /* Wikilinks to pages that don't exist */
 div.content a.wikilink-nonexistent {
 	color: #B05020;