penguin/AstroJS

Javascript framework for my blog

botanjs/src/Astro/Blog/AstroEdit/SmartInput.js

raw ยท 4631 bytes

(function(){
	var ns = __namespace( "Astro.Blog.AstroEdit" );

	/** @type {Dandelion} */
	var Dand                                    = __import( "Dandelion" );
	/** @type {Dandelion.IDOMElement} */
	var IDOMElement                             = __import( "Dandelion.IDOMElement" );
	/** @type {Dandelion.IDOMObject} */
	var IDOMObject                              = __import( "Dandelion.IDOMObject" );
	/** @type {System.Cycle} */
	var Cycle                                   = __import( "System.Cycle" );
	/** @type {System.Debug} */
	var debug                                   = __import( "System.Debug" );
	/** @type {System.utils} */
	var utils                                   = __import( "System.utils" );
	/** @type {System.utils.Perf} */
	var Perf                                    = __import( "System.utils.Perf" );
	/** @type {System.utils.DataKey} */
	var DataKey                                 = __import( "System.utils.DataKey" );
	/** @type {System.utils.EventKey} */
	var EventKey                                = __import( "System.utils.EventKey" );
	/** @type {System.utils.IKey} */
	var IKey                                    = __import( "System.utils.IKey" );
	/** @type {Components.MessageBox} */
	var MessageBox                              = __import( "Components.MessageBox" );
	/** @type {Astro.Blog.Config} */
	var Config                                  = __import( "Astro.Blog.Config" );

	var GetCandidates = function()
	{
		var c = [];
		var Cands = {
			"facts": "T"
			, "text": "T"
		};

		for( var i in Cands )
		{
			c.push( Dand.wrapc( "cn", i ) );
		}

		return c;
	};

	/** @param {Astro.Blog.AstroEdit.Visualizer} */
	var SmartInput = function ( visualizer )
	{
		var SBarPresent = false;
		var insert = function() { return Dand.textNode( "" ); };

		var HandleInput = function( sender, e )
		{
			e = e || window.event;
			if ( e.keyCode ) code = e.keyCode;
			else if ( e.which ) code = e.which;

			// Don't handle if holding shift or ctrl key
			if( e.shiftKey || e.ctrlKey ) return;

			switch( e.keyCode )
			{
				case 192: // `
					// Closing the quote, that means this is a block-quoted text
					e.preventDefault();

					// Hitting ` twice escapes the ` character itself
					var v = sender.value.substr( 1 );
					if( v == "" ) insert = function() { return Dand.textNode( "`" ); };

					// Insert the code snippet with inline flag
					visualizer.insertSnippet( "code", { "inline": "on", "lang": "plain", "value": v } );

					sender.BindingBox.close( true );
					break;
				case 13: // Enter
					// Not closing the quote, either a direct text or the first matched action
					e.preventDefault();

					// Check if matched an action first
					if( false )
					{
					}
					else
					{
						// Insert this text directly
						var v = Dand.textNode( sender.value.substr( 1 ) );
						insert = function() { return v; };
						sender.BindingBox.close( true );
					}
					break;
				case 27: // Esc
					sender.BindingBox.close();
					break;
			}
		};

		var TestEmpty = function( sender, e )
		{
			if( sender.value == "" )
			{
				sender.BindingBox.close();
			}
		};

		var ClosePanel = function( confirmed )
		{
			Cycle.next( function() { SBarPresent = false; } );
			visualizer.restoreSelection();

			if( !confirmed ) return;

			if( insert != undefined )
				visualizer.insertAtCaret( insert() );
		};

		var ShowSmartBar = function()
		{
			if( SBarPresent ) return;
			visualizer.saveSelection();

			SBarPresent = true;

			var title = "Quick Access";

			var Command = Dand.wrap(
				"input", null, "v_snippet_input_single"
				, null, IKey.quickDef( "type", "text", "placeholder", "Command", "value", "`" )
			);
			var Candidates = Dand.wrap( "div", null, "smartbar-candidates", GetCandidates() );

			Command.selectionStart = Command.selectionEnd = 1;

			Command.BindingBox = new MessageBox(
				title
				, Dand.wrape([ Command, Candidates ])
				, "Back", false
				, ClosePanel
			);

			Command.BindingBox.show();
			Command.focus();

			var DCommand = IDOMElement( Command );
			DCommand.addEventListener( "KeyDown", function( e ) { HandleInput( Command, e ); } );
			DCommand.addEventListener( "KeyUp", function( e ) { TestEmpty( Command, e ); } );
		};

		var BackQuoteBinding = function ( e )
		{
			e = e || window.event;
			if ( e.keyCode ) code = e.keyCode;
			else if ( e.which ) code = e.which;

			if( !SBarPresent && code == 192 )
			{
				e.preventDefault();
				ShowSmartBar();
			}
		};

		IDOMObject( document ).addEventListener( "KeyDown", BackQuoteBinding, false );
	};

	ns[ NS_EXPORT ]( EX_CLASS, "SmartInput", SmartInput );
})();