public.js

Sections

about

Page1

/**
 * @filename
 *     public.js
 *
 * @author
 *    Julian Turner, Ripley, Derbyshire, England
 *    http://www.baconbutty.com
 *
 * @copyright 
 *    (c) Julian Turner 2007
 *
 * @version
 *    1 (developed 2007)
 *
 * @fileoverview
 *    public.js contains a number of functions used by
 *    all of the web pages on http://www.baconbutty.com,
 *    where additional JavaScript functionality is offered,
 *    such as the CodePlay, HTMLPlay and PagePlay features.
 *
 * @dependencies
 *    public.js is not dependent on any other js file.
 *    
 * @licence
 *    Your only permission is to download and run
 *    this code in your browser as part of the HTML 
 *    page you are viewing at http://www.baconbutty.com.
 *    All other rights are reserved.
 */

DOMAIN

Local

var DOMAIN = "http://127.0.0.1:8080/baconbutty/";

Remote

var DOMAIN = "http://www.baconbutty.com/";

CodePlay_Edit(elementId : String) : void

Code

function CodePlay_Edit(
	elementId /*: String*/
) /*: void*/
{
	var element /*: HTMLElement*/ = document.getElementById(elementId);

	if (!element)
	{
		return;
	}

	if (element.getAttribute("activated") == "true")
	{
		return;
	}
	else
	{
		element.setAttribute("activated", "true");
	}

	var code /*: String*/ = HTMLElement_InnerText(element);

	var height /*: int*/ = element.offsetHeight - 2;
	height = 200;
	
	var div1 /*: HTMLDivElement*/ = document.createElement("div");
	div1.className = "edit-div-1";

	var div2 /*: HTMLDivElement*/ = document.createElement("div");
	div2.className = "edit-div-2";

	var div3 /*: HTMLDivElement*/ = document.createElement("div");
	div3.className = "edit-div-3";

	var textarea /*: HTMLTextAreaElement*/ = document.createElement("textarea");
	textarea.className = "edit-area";
	textarea.id = element.id;
	textarea.value = code;
	textarea.style.height = height + "px";

	HTMLElement_AttachEvent(textarea, "onkeydown", HTMLTextAreaElement_InsertTab);

	div1.appendChild(div2);
	div2.appendChild(div3);
	div3.appendChild(textarea);

	element.parentNode.insertBefore(div1, element);

	element.parentNode.removeChild(element);
}

Notes

Purpose

Replaces an HTMLElement with an HTMLTextAreaElement, and puts the element's textContent into the HTMLTextAreaElement.

Arguments

elementId : String

The id of the target HTMLElement.

Return Value

void

Requires

HTMLElement_InnerText
HTMLElement_AttachEvent
HTMLTextAreaElement_InsertTab

Remarks

None.

Example

None.

CodePlay_Play(elementId : String) : void

Code

function CodePlay_Play(
	elementId /*: String*/
) /*: void*/
{
	var element /*: HTMLElement*/ = document.getElementById(elementId);

	if (!element)
	{
		return;
	}


	var code /*: String*/ = HTMLElement_InnerText(element);
	code = CodePlay_ConvertHeredoc(code);

	var data /*: Object*/ = CodePlay_GetDataRegions(code);
	
	eval(code);
}

Notes

Purpose

Runs the JavaScript code in a code play region.

Arguments

elementId : String

The id of the HTMLElement whose content will be run.

Returns

void

Requires

CodePlay_GetDataRegions
CodePlay_ConvertHeredoc
HTMLElement_InnerText

Remarks

The JavaScript code is pre-processed using CodePlay_GetDataRegions and CodePlay_ConvertHeredoc to convert embedded data into valid JavaScript string literals.

Example

None

CodePlay_GetDataRegions(code : String) : Object

Code

function CodePlay_GetDataRegions(
	code /*: String*/
) /*: Object*/
{
	var data /*: Object*/ = {};
	var dataRegionStartPattern /*: RegExp*/ = /\/\*(\w+)/gi;

	var dataRegionName /*: String*/ = "";
	var dataRegionEndMarker /*: String*/ = "";

	var dataRegionStart /*: int*/ = 0;
	var dataRegionInnerStart /*: int*/ = 0;
	var dataRegionContents /*: String*/ = "";
	var dataRegionInnerEnd /*: int*/ = 0;
	var dataRegionEnd /*: int*/ = 0;

	var execResult /*: Array*/ = [];
	var overflow /*: int*/ = 100;
	
	while(overflow--)
	{
		dataRegionStartPattern.lastIndex = dataRegionEnd;

		execResult = dataRegionStartPattern.exec(code);

		if (!execResult)
		{
			break;
		}

		dataRegionName = execResult[1];
		dataRegionEndMarker = dataRegionName + "*/";
		dataRegionStart = execResult.index;
		dataRegionInnerStart = dataRegionStartPattern.lastIndex;

		dataRegionInnerEnd = code.indexOf(dataRegionEndMarker, dataRegionInnerStart);

		if (dataRegionInnerEnd == -1)
		{
			dataRegionEnd = dataRegionInnerStart;
			continue;
		}

		dataRegionEnd = dataRegionInnerEnd + dataRegionEndMarker.length;

		dataRegionContents = code.substring(dataRegionInnerStart, dataRegionInnerEnd);
		dataRegionContents = dataRegionContents.replace(/^\s\s*/g,"").replace(/\s*\s$/g,"");

		data[dataRegionName] = dataRegionContents;
	}

	return data;
}

Notes

Purpose

The purpose is to enable you to use strings in your code without escaping \t,\r and \n.

The function extracts from the code any strings stored within a multi-line comment /* */ (data regions) within the code, and returns them in an Object.

The idea being that you then eval the code in a scope which contains that Object. In effect you run this like a macro before you eval the code.

Arguments

code : String

The code to be evaluated, which contains data regions.

Returns

Object

Dependencies

None

Remarks

The function is used as follows.

1. Data Regions

The data regions are in the format:-

/*yourIdentifer

Some Data
	Some Data
		Some Data

yourIdentifier*/

The string is extracted, trimmed, and then made a property of the returned Object using the yourIdentifier name.

2. Evaluation

To use the Object in your evaluated code, you would do the following:-

var data /*: Object*/ = CodePlay_GetDataRegions(code);
	
eval(code);

The data variable would be a variable local to the scope in which the code is eval'd and the inner scopes of any functions within your code.

3. Eval Code

Your eval code would then look like this:-

alert(data.stringValue);

/*stringValue
Some Data
	Some Data
		Some Data
stringValue*/

Example

Try it out:-

alert(data.stringValue);

/*stringValue
Some Data
	Some Data
		Some Data
stringValue*/

editplay

CodePlay_ConvertHeredoc(code : String) : String

Code

function CodePlay_ConvertHeredoc(
	code /*: String*/
) /*: String*/
{
	var convertedCode /*: Array*/ = [];

	var heredocStartPattern /*: RegExp*/ = /<<<(\w+)/gi;
	var heredocEndPattern /*: RegExp*/ = null;

	var heredocIdentifier /*: String*/ = "";

	var heredocStart /*: int*/ = 0;	
	var heredocInnerStart /*: int*/ = 0;
	var heredocContents /*: String*/ = "";
	var heredocInnerEnd /*: int*/ = 0;
	var heredocEnd /*: int*/ = 0;	

	var execResult /*: Array*/ = [];
	var overflow /*: int*/ = 100;
	
	while(overflow--)
	{
		heredocStartPattern.lastIndex = heredocEnd;

		execResult = heredocStartPattern.exec(code);

		if (!execResult)
		{
			convertedCode[convertedCode.length] = code.substring(heredocEnd, code.length);	
			break;
		}

		heredocIdentifier = execResult[1];
		heredocStart = execResult.index;
		heredocInnerStart = heredocStartPattern.lastIndex;

		convertedCode[convertedCode.length] = code.substring(heredocEnd, heredocStart);	
	
		heredocEndPattern = new RegExp("(\\r|\\n)" + heredocIdentifier + ";", "g");
		heredocEndPattern.lastIndex = heredocInnerStart;

		execResult = heredocEndPattern.exec(code);

		if (!execResult)
		{
			alert("Could not find end of identifier " + heredocIdentifier);
			return "";
			break;
		}

		heredocInnerEnd = execResult.index;
		heredocEnd = heredocEndPattern.lastIndex;

		heredocContents = code.substring(heredocInnerStart, heredocInnerEnd);
		heredocContents = heredocContents.replace(/^\s\s*/g,"").replace(/\s*\s$/g,"");
		heredocContents = String_ToStringLiteral(heredocContents);
		
		convertedCode[convertedCode.length] = "\"" + heredocContents + "\";\r\n";
	}

	return convertedCode.join("");
}

Notes

Purpose

The purpose is to enable you to use strings in your code without escaping \t,\r and \n.

The function replaces within the code any strings stored within a Heredoc format (as used in PHP) with a JavaScript string literal using the same identifier.

In effect you run this like a macro before you eval the code.

Arguments

code : String

The code which contains Heredoc regions to be converted to string literals.

Returns

String

The code after conversion of the Heredoc areas.

Dependencies

String_ToStringLiteral

Remarks

The function is used as follows.

var myString /*: String*/ = <<<RANDOM

Some Data
	Some Data
		Some Data

RANDOM;

alert(myString);

The RANDOM can be any characters you want, and must not appear within the data itself.

The closing RANDOM must appear on its own line, and not be indented.

The code is transformed to:-

var myString /*: String*/ = "Some Data\r\n\tSome Data\r\n\t\tSome Data"

alert(myString);

Example

Try it out:-

var myString /*: String*/ = <<<RANDOM

Some Data
	Some Data
		Some Data

RANDOM;

alert(myString);

editplay

HTMLPlay_Edit(elementId : String) : void

Code

function HTMLPlay_Edit(
	elementId /*: String*/
)
{
	var element /*: HTMLElement*/ = document.getElementById(elementId);

	if (!element)
	{
		return;
	}

	if (element.getAttribute("activated") == "true")
	{
		return;
	}
	else
	{
		element.setAttribute("activated", "true");
	}

	var html /*: String*/ = HTMLElement_InnerText(element);

	var height /*: String*/ = element.offsetHeight - 2;
	height = 200;
	
	var div1 /*: HTMLDivElement*/ = document.createElement("div");
	div1.className = "edit-div-1";

	var div2 /*: HTMLDivElement*/ = document.createElement("div");
	div2.className = "edit-div-2";

	var div3 /*: HTMLDivElement*/ = document.createElement("div");
	div3.className = "edit-div-3";

	var textarea /*: HTMLTextAreaElement*/ = document.createElement("textarea");
	textarea.className = "edit-area";
	textarea.id = element.id;
	textarea.value = html;
	textarea.style.height = height + "px";

	HTMLElement_AttachEvent(textarea, "onkeydown", HTMLTextAreaElement_InsertTab);


	div1.appendChild(div2);
	div2.appendChild(div3);
	div3.appendChild(textarea);

	element.parentNode.insertBefore(div1, element);

	element.parentNode.removeChild(element);
}

Notes

Purpose

Replaces an HTMLElement with an HTMLTextAreaElement, and puts the element's textContent into the HTMLTextAreaElement.

Arguments

elementId : String

The id of the target HTMLElement.

Return Value

void

Requires

HTMLElement_InnerText
HTMLElement_AttachEvent
HTMLTextAreaElement_InsertTab

Remarks

None.

Example

None.

HTMLPlay_Play(elementId : String) : void

Code

function HTMLPlay_Play(
	elementId /*: String*/
)
{
	var element /*: HTMLElement*/ = document.getElementById(elementId);

	if (!element)
	{
		return;
	}


	var html /*: String*/ = HTMLElement_InnerText(element);

	var display /*: HTMLElement*/ = document.getElementById(elementId + "DISPLAY");

	if (!display)
	{
		return;
	}

	display.style.display = "block";

	display.innerHTML = html;
}

Notes

Purpose

Inserts the HTML mark-up into a revealed div.

Arguments

elementId : String

The id of the HTMLElement whose content will be run.

Returns

void

Requires

HTMLElement_InnerText

Remarks

None

Example

None

PagePlay_Edit(elementId : String) : void

Code

function PagePlay_Edit(
	elementId /*: String*/
)
{
	var element /*: HTMLElement*/ = document.getElementById(elementId);

	if (!element)
	{
		return;
	}

	if (element.getAttribute("activated") == "true")
	{
		return;
	}
	else
	{
		element.setAttribute("activated", "true");
	}

	var code /*: String*/ = HTMLElement_InnerText(element);

	var height /*: String*/ = element.offsetHeight - 2;
	height = 200;
	
	var div1 /*: HTMLDivElement*/ = document.createElement("div");
	div1.className = "edit-div-1";

	var div2 /*: HTMLDivElement*/ = document.createElement("div");
	div2.className = "edit-div-2";

	var div3 /*: HTMLDivElement*/ = document.createElement("div");
	div3.className = "edit-div-3";

	var textarea /*: HTMLTextAreaElement*/ = document.createElement("textarea");
	textarea.className = "edit-area";
	textarea.id = element.id;
	textarea.value = code;
	textarea.style.height = height + "px";

	HTMLElement_AttachEvent(textarea, "onkeydown", HTMLTextAreaElement_InsertTab);


	div1.appendChild(div2);
	div2.appendChild(div3);
	div3.appendChild(textarea);

	element.parentNode.insertBefore(div1, element);

	element.parentNode.removeChild(element);
}

Notes

Purpose

Replaces an HTMLElement with an HTMLTextAreaElement, and puts the element's textContent into the HTMLTextAreaElement.

Arguments

elementId : String

The id of the target HTMLElement.

Return Value

void

Requires

HTMLElement_InnerText
HTMLElement_AttachEvent
HTMLTextAreaElement_InsertTab

Remarks

None.

Example

None.

PagePlay_Play_NewWindow(elementId : String) : void

Code

function PagePlay_Play_NewWindow(
	elementId /*: String*/
)
{
	var element /*: HTMLElement*/ = document.getElementById(elementId);

	if (!element)
	{
		return;
	}

	var code /*: String*/ = HTMLElement_InnerText(element);

	code = CodePlay_ConvertHeredoc(code);

	var screenWidth /*: int*/ = screen.availWidth;
	var screenHeight /*: int*/ = screen.availHeight;

	if (screenWidth)
	{
		var border /*: int*/ = 200;
		var height /*: int*/ = screenHeight - (border * 2);
		var width /*: int*/ = screenWidth - (border * 2);
		var left /*: int*/ = border;
		var top /*: int*/ = border;
	}
	else
	{
		var height /*: int*/ = 300;
		var width /*: int*/ = 500;
		var left /*: int*/ = 0;
		var top /*: int*/ = 0;
	}		

	var win /*: Window*/ = window.open("", "", "status=yes,height=" + height + ",width=" + width + ",left=" + left + ",top=" + top + ",resizable=yes,scrollbars=yes");

	if (win.document)
	{
		var doc /* HTMLDocument*/ = win.document;
		doc.open();
		doc.write(code);
		doc.close();
	}
	else
	{	
		var count /*: int*/ = 10;

		var interval /*: HostObject*/ = window.setInterval(function()
		{
			if (!count--)
			{
				window.clearInterval(interval); 
				return;
			}
	
			if (!win.document)
			{
				return;
			}

			var doc /* HTMLDocument*/ = win.document;
			doc.open();
			doc.write(code);
			doc.close();

			window.clearInterval(interval);
		},200);
	}
}

Notes

Purpose

Opens the html document in the PagePlay region in a new browser window.

Arguments

elementId : String

The id of the PagePlay region.

Returns

void

Requires

CodePlay_ConvertHeredoc
HTMLElement_InnerText

Remarks

The html mark-up is pre-processed using CodePlay_ConvertHeredoc.

The window is written to using the classic:-

var doc /* HTMLDocument*/ = win.document;
doc.open();
doc.write(code);
doc.close();

The window starts off centered.

Example

None

PagePlay_Play_Iframe(elementId : String) : void

Code

function PagePlay_Play_IFrame(
	elementId /*: String*/
)
{
	var element /*: HTMLElement*/ = document.getElementById(elementId);

	if (!element)
	{
		return;
	}


	var html /*: String*/ = HTMLElement_InnerText(element);

	html = CodePlay_ConvertHeredoc(html);

	var div /*: HTMLDivElement*/ = document.getElementById(elementId + "DISPLAY");
	div.style.display = "block";

	var iframe /*: HTMLIFrameElement*/ = document.getElementById(elementId + "IFRAME");

	if (!iframe)
	{
		return;
	}

	var win /*: Window*/ = iframe.contentWindow || document.frames[elementId + "IFRAME"];
	var doc /*: HTMLDocument*/ = win.document;

	doc.open();
	doc.write(html);
	doc.close();
}

Notes

Purpose

Opens the html document in the PagePlay region in a revealed iframe beneath.

Arguments

elementId : String

The id of the PagePlay region.

Returns

void

Requires

CodePlay_ConvertHeredoc
HTMLElement_InnerText

Remarks

The html mark-up is pre-processed using CodePlay_ConvertHeredoc.

The iframe is written to using the classic:-

var doc /* HTMLDocument*/ = win.document;
doc.open();
doc.write(code);
doc.close();

Example

None

HTMLElement_InnerText(element : HTMLElement) : String

Code

function HTMLElement_InnerText(
	element /*: HTMLElement*/
) /*: String*/
{
	if (!element)
	{
		return "";
	}

	if (element.nodeName.toLowerCase() == "textarea" || element.nodeName.toLowerCase() == "input")
	{
		return element.value;
	}

	var innerText /*: String*/ = "";
	var childNodes /*: NodeList*/ = element.childNodes;
	var node /*: Node*/ = null;

	for (var i /*: int*/ = 0; i < childNodes.length; i++)
	{
		node = childNodes[i];

		if (node.nodeType == 1)
		{
			if (node.nodeName.toLowerCase() == "textarea" || node.nodeName.toLowerCase() == "input")
			{
				innerText += node.value;
			}
			else
			{
				innerText += HTMLElement_InnerText(node);
			}
		}

		if (node.nodeType == 3)
		{
			innerText += node.nodeValue;
		}

		if (node.nodeType == 4)
		{
			innerText += node.nodeValue;
		}
	}

	return innerText;
}

Notes

Purpose

Gets the text content of an HTMLElement.

Arguments

element : HTMLElement

The HTMLElement whose text content you are getting.

Returns

String

The text content of the HTMLElement.

Requires

None

Remarks

The function works by recursion; it applies itself again to each Element it finds.

The text content is the unescaped content of any of the following which is found as a descendent Node:-

  • Text
  • HTMLInputElement
  • HTMLTextAreaElement

Example

None

HTMLElement_AttachEvent(element : HTMLElement, eventType : String, handler : Function, capturePhase : Boolean) : void

Code

function HTMLElement_AttachEvent(
	element /*: HTMLElement*/, 
	eventType /*: String*/, 
	handler /*: Function*/, 
	capturePhase /*: Boolean*/
) /*: void*/
{
	if (typeof handler != "function")
	{
		return;
	}

	capturePhase = capturePhase || false;

	if (typeof element.addEventListener !== "undefined")
	{
		eventType = eventType.replace(/^on/, "");
		element.addEventListener(eventType, handler, capturePhase);
	}
	else if (typeof element.attachEvent !== "undefined")
	{
		if (!/^on/.test(eventType))
		{
			eventType = "on" + eventType;
		}

		element.attachEvent(eventType, handler);
	}
}

Notes

Purpose

Attaches an event handler (or listener) to an HTMLElement.

Arguments

element : HTMLElement

The HTMLElement to attach the event handler to.

eventType : String

The event's name such as:-

  • onclick
  • onmouseover

The on part is optional.

handler : Function

A function to handle the event.

Remember in non-IE browsers the function is passed the Event object as its first argument.

[capturePhase : Boolean]

For non-IE browsers, the event is triggered in the capture phase (on the way down the tree to the target element) rather than the bubble phase (on the way back up the tree from the target element).

Returns

void

Requires

None

Remarks

If you are planning to detach the Function later, then you need to keep a reference to it, because you need to supply the exact same Function to the detach method. If you wrap the Function in another function, then you need to keep a reference to the wrapper function.

Example

None

HTMLTextAreaElement_InsertTab([event : Event]) : void

Code

function HTMLTextAreaElement_InsertTab(
	event /*: Event*/
) /*: void*/
{
	event = event || window.event;

	var textarea /*: HTMLTextAreaElement*/ = event.srcElement || event.target;

	if (event.keyCode == 9)
	{
		if (typeof textarea.selectionStart !== "undefined")
		{
			event.stopPropagation();
			event.preventDefault();

			/* Collapse Insertion Point */
			//textarea.setSelectionRange(textarea.selectionEnd, textarea.selectionEnd);
			//textarea.focus();

			/* Insert Tab */
			var selStart /*: int*/ = textarea.selectionStart;
			var selEnd /*: int*/ = textarea.selectionEnd;
			var currentScroll /*: int*/ = textarea.scrollTop;
			var contents /*: String*/ = textarea.value;
	
			textarea.value = contents.substring(0, selStart) + "\t" + contents.substring(selEnd, contents.length);

			textarea.scrollTop = currentScroll;
			textarea.setSelectionRange(selEnd + 1, selEnd + 1);

			textarea.focus();
	
			//window.setTimeout(function(){
			//	textarea.focus();
			//}, 0);

			return false;
		}
		else if (document.selection)
		{
			var range /*: HostObject(TextRange)*/ = document.selection.createRange();
			range.collapse();
			range.text = String.fromCharCode(9);
			range.collapse();
			range.select();

			event.returnValue = false;
		}
	}

}

Notes

Purpose

This is attached as an event handler to an HTMLTextAreaElement.

It tries to insert a TAB character, and overrides the default behaviour for the TAB key. This is not recommended without warning the user.

Arguments

[event : Event]

For non-IE browsers the Event object is received as the first argument.

Returns

void

Requires

Nothing.

Remarks

Internet Explorer uses its proprietary TextRange object.

Other browsers implement simple selection properties on the HTMLTextAreaElement. In this case it is important to remember the scroll position of the element and reset this after inserting the TAB.

Opera inserts the TAB but does not let you override the default behaviour of jumping to the next form element. If that next element is off the page, then Opera scrolls to that element as well, causing the page to jump.

Example

None

String_ToStringLiteral(s : String) : String

Code

function String_ToStringLiteral(
	s /*: String*/
) /*: String*/
{	
	var escapedCharacters /*: RegExp*/ = /(\f|\n|\r|\t|'|"|\\|[\x00-\x1F]|[\x7F-\x9F])/gi;

	var overflow /*: int*/ = 10000;
	var execResult /*: Array*/;
	var stringLiteralBuffer /*: Array.<String>*/ = [];
	var previousIndex /*: int*/ = 0;
	var escaped /*: String*/ = "";
	var charCode /*: int*/;

	escapedCharacters.lastIndex = 0;

	while(overflow-- )
	{
		execResult /*: Array*/ = escapedCharacters.exec(s);

		if (!execResult)
		{
			break;
		}

		stringLiteralBuffer[stringLiteralBuffer.length] = s.substring(previousIndex, escapedCharacters.lastIndex - 1);

		escaped = "";

		switch(execResult[0])
		{
			case "\f":  /*FORM FEED(12)*/
				escaped = "\\f";
				break;

			case "\n": /*LINE FEED(10)*/
				escaped = "\\n";
				break;

			case "\r": /*CR(13)*/
				escaped = "\\r";
				break;

			case "\t":
				escaped = "\\t";
				break;

			case "\'":
				escaped = "\\\'";
				break;

			case "\"":
				escaped = "\\\"";
				break;

			case "\\":
				escaped = "\\\\";
				break;

			default:
				charCode = execResult[0].charCodeAt(0);

				if (charCode < 256)
				{
					escaped = "\\x" + LZ(charCode.toString(16), 2);
				}
				else
				{					
					escaped = "\\u" + LZ(charCode.toString(16), 4);
				}
				break;
		}

		stringLiteralBuffer[stringLiteralBuffer.length] = escaped;

		previousIndex = escapedCharacters.lastIndex;
	}

	stringLiteralBuffer[stringLiteralBuffer.length] = s.substring(previousIndex, s.length);

	return stringLiteralBuffer.join("");

	function LZ(
		s /*: String*/, 
		overflow /*: int*/
	) /*: String*/
	{
		var zeros /*: String*/ = "00000000000000000000";
	
		if (s.length < overflow)
		{
			return zeros.substr(0, overflow - s.length) + s;
		}
		else
		{
			return s;
		}
	}
}

Notes

Purpose

Converts a String into a literal value, escaping TAB to \t etc.

Arguments

s : String

String to be converted.

Return Value

String

The literal version.

Remarks

Does not work for \b (BACKSPACE) or \v (VERTICAL_TAB).

Does not escape unicode ranges \u0100-\uFFFF, because Opera does not recognise these.

Example

Basic test:-

var s = "start \f\t\n\r\t\'\"\\\0\x81\u0101 end";

var es = String_ToStringLiteral(s);

alert(es);

editplay