forked from Botanical/BotanJS
		
	Choice Tabbing
This commit is contained in:
		@@ -246,7 +246,10 @@
 | 
			
		||||
		{
 | 
			
		||||
			if ( !stay )
 | 
			
		||||
			{
 | 
			
		||||
				window.open( base_path + "article/view/" + ArticleModel.slug + "/") && window.close();
 | 
			
		||||
				var op = window.open( base_path + "article/view/" + ArticleModel.slug + "/" );
 | 
			
		||||
				Cycle.next( function() {
 | 
			
		||||
					if( op ) window.close();
 | 
			
		||||
				});
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -10,3 +10,7 @@
 | 
			
		||||
.smartbar-candidates .cn:hover {
 | 
			
		||||
	background-color: rgba( 0, 0, 0, 0.2 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.smartbar-candidates .cn[data-selected="1"] {
 | 
			
		||||
	background-color: orangered;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -26,22 +26,89 @@
 | 
			
		||||
	/** @type {Astro.Blog.Config} */
 | 
			
		||||
	var Config                                  = __import( "Astro.Blog.Config" );
 | 
			
		||||
 | 
			
		||||
	var __cands = [];
 | 
			
		||||
	var GetCandidates = function()
 | 
			
		||||
	{
 | 
			
		||||
		var c = [];
 | 
			
		||||
		if( __cands.length ) return __cands;
 | 
			
		||||
 | 
			
		||||
		var Cands = {
 | 
			
		||||
			"facts": "T"
 | 
			
		||||
			"Article Reference": "Ref"
 | 
			
		||||
			, "facts": "T"
 | 
			
		||||
			, "text": "T"
 | 
			
		||||
			, "h1": "h1"
 | 
			
		||||
			, "h2": "h2"
 | 
			
		||||
			, "h3": "h3"
 | 
			
		||||
			, "h4": "h4"
 | 
			
		||||
			, "h5": "h5"
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		for( var i in Cands )
 | 
			
		||||
		{
 | 
			
		||||
			c.push( Dand.wrapc( "cn", i ) );
 | 
			
		||||
			__cands.push( Dand.wrapc( "cn", i, new DataKey( "key", Cands[i] ) ) );
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return c;
 | 
			
		||||
		return __cands;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	var ResetCandidates = function()
 | 
			
		||||
	{
 | 
			
		||||
		var Cands = GetCandidates();
 | 
			
		||||
		for( var i in Cands )
 | 
			
		||||
		{
 | 
			
		||||
			var c = IDOMElement( Cands[i] );
 | 
			
		||||
			c.setAttribute( new DataKey( "selected", 0 ) );
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	var FilteredCandidates = function()
 | 
			
		||||
	{
 | 
			
		||||
		var Cands = GetCandidates();
 | 
			
		||||
		var selected = [];
 | 
			
		||||
		for( var i in Cands )
 | 
			
		||||
		{
 | 
			
		||||
			var c = IDOMElement( Cands[i] );
 | 
			
		||||
			c.setAttribute( new DataKey( "selected", 0 ) );
 | 
			
		||||
 | 
			
		||||
			if( c.style.display != "none" )
 | 
			
		||||
			{
 | 
			
		||||
				selected.push( c );
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return selected;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	var SelectedCandidate = function()
 | 
			
		||||
	{
 | 
			
		||||
		var Cands = GetCandidates();
 | 
			
		||||
		for( var i in Cands )
 | 
			
		||||
		{
 | 
			
		||||
			var c = IDOMElement( Cands[i] );
 | 
			
		||||
			if( c.getDAttribute( "selected" ) == "1" )
 | 
			
		||||
			{
 | 
			
		||||
				return c;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return null;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	var KeyHandler = function( sender, handler )
 | 
			
		||||
	{
 | 
			
		||||
		return function( e )
 | 
			
		||||
		{
 | 
			
		||||
			e = e || window.event;
 | 
			
		||||
			if ( e.keyCode ) code = e.keyCode;
 | 
			
		||||
			else if ( e.which ) code = e.which;
 | 
			
		||||
 | 
			
		||||
			handler( sender, e );
 | 
			
		||||
		};
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	var CandidateCycle = -1;
 | 
			
		||||
	var KeywordTyped = 0;
 | 
			
		||||
	var shiftTabbed = false;
 | 
			
		||||
 | 
			
		||||
	/** @param {Astro.Blog.AstroEdit.Visualizer} */
 | 
			
		||||
	var SmartInput = function ( visualizer )
 | 
			
		||||
	{
 | 
			
		||||
@@ -50,12 +117,14 @@
 | 
			
		||||
 | 
			
		||||
		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;
 | 
			
		||||
			if( e.shiftKey || e.ctrlKey )
 | 
			
		||||
			{
 | 
			
		||||
				// Except the Shift + Tab, we need to cycle this
 | 
			
		||||
				shiftTabbed = e.shiftKey && e.keyCode == 9;
 | 
			
		||||
 | 
			
		||||
				if( !shiftTabbed ) return;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			switch( e.keyCode )
 | 
			
		||||
			{
 | 
			
		||||
@@ -67,18 +136,21 @@
 | 
			
		||||
					var v = sender.value.substr( 1 );
 | 
			
		||||
					if( v == "" ) insert = function() { return Dand.textNode( "`" ); };
 | 
			
		||||
 | 
			
		||||
					insert = undefined;
 | 
			
		||||
					sender.BindingBox.close( true );
 | 
			
		||||
 | 
			
		||||
					// 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();
 | 
			
		||||
 | 
			
		||||
					var selected = SelectedCandidate();
 | 
			
		||||
					// Check if matched an action first
 | 
			
		||||
					if( false )
 | 
			
		||||
					if( selected )
 | 
			
		||||
					{
 | 
			
		||||
 | 
			
		||||
					}
 | 
			
		||||
					else
 | 
			
		||||
					{
 | 
			
		||||
@@ -91,6 +163,36 @@
 | 
			
		||||
				case 27: // Esc
 | 
			
		||||
					sender.BindingBox.close();
 | 
			
		||||
					break;
 | 
			
		||||
				case 9: // Tab
 | 
			
		||||
					// Hitting tab will cycle around the candidates
 | 
			
		||||
					e.preventDefault();
 | 
			
		||||
 | 
			
		||||
					var c = FilteredCandidates();
 | 
			
		||||
					var l = c.length;
 | 
			
		||||
					if( !l ) break;
 | 
			
		||||
 | 
			
		||||
					CandidateCycle += e.shiftKey ? -1 : 1;
 | 
			
		||||
 | 
			
		||||
					if( CandidateCycle == l )
 | 
			
		||||
					{
 | 
			
		||||
						CandidateCycle = 0;
 | 
			
		||||
					}
 | 
			
		||||
					else if( CandidateCycle == -1 )
 | 
			
		||||
					{
 | 
			
		||||
						CandidateCycle = c.length - 1;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					var ThisCandidate = c[ CandidateCycle ];
 | 
			
		||||
					ThisCandidate.setAttribute( new DataKey( "selected", 1 ) );
 | 
			
		||||
 | 
			
		||||
					var CyclingKeyword = ThisCandidate.element.textContent;
 | 
			
		||||
 | 
			
		||||
					sender.value = "`" + CyclingKeyword;
 | 
			
		||||
					sender.setSelectionRange( KeywordTyped, sender.value.length );
 | 
			
		||||
					break;
 | 
			
		||||
				default:
 | 
			
		||||
					FilteredCandidates();
 | 
			
		||||
					CandidateCycle = -1;
 | 
			
		||||
			}
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
@@ -100,10 +202,39 @@
 | 
			
		||||
			{
 | 
			
		||||
				sender.BindingBox.close();
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Search exact matched Candidates
 | 
			
		||||
			switch( e.keyCode )
 | 
			
		||||
			{
 | 
			
		||||
				case 9: // Tab, do nothing
 | 
			
		||||
					break;
 | 
			
		||||
				case 16: // Shift, check if shiftTabbed
 | 
			
		||||
					if( shiftTabbed )
 | 
			
		||||
					{
 | 
			
		||||
						shiftTabbed = false;
 | 
			
		||||
						break;
 | 
			
		||||
					}
 | 
			
		||||
				default:
 | 
			
		||||
					if( CandidateCycle == -1 )
 | 
			
		||||
					{
 | 
			
		||||
						KeywordTyped = sender.value.length;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					var c = GetCandidates();
 | 
			
		||||
					var keyword = sender.value.substr( 1 );
 | 
			
		||||
					for( var i in c )
 | 
			
		||||
					{
 | 
			
		||||
						var Cand = c[i];
 | 
			
		||||
						var t = Cand.textContent;
 | 
			
		||||
						Cand.style.display = t.match( new RegExp( "^" + keyword, "i" ) ) ? "" : "none";
 | 
			
		||||
					}
 | 
			
		||||
			}
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		var ClosePanel = function( confirmed )
 | 
			
		||||
		{
 | 
			
		||||
			ResetCandidates();
 | 
			
		||||
 | 
			
		||||
			Cycle.next( function() { SBarPresent = false; } );
 | 
			
		||||
			visualizer.restoreSelection();
 | 
			
		||||
 | 
			
		||||
@@ -120,13 +251,13 @@
 | 
			
		||||
 | 
			
		||||
			SBarPresent = true;
 | 
			
		||||
 | 
			
		||||
			var title = "Quick Access";
 | 
			
		||||
			var title = "Quick Access ( Prototype )";
 | 
			
		||||
 | 
			
		||||
			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() );
 | 
			
		||||
			var Candidates = Dand.wrap( "div", null, "compx smartbar-candidates", GetCandidates() );
 | 
			
		||||
 | 
			
		||||
			Command.selectionStart = Command.selectionEnd = 1;
 | 
			
		||||
 | 
			
		||||
@@ -141,16 +272,12 @@
 | 
			
		||||
			Command.focus();
 | 
			
		||||
 | 
			
		||||
			var DCommand = IDOMElement( Command );
 | 
			
		||||
			DCommand.addEventListener( "KeyDown", function( e ) { HandleInput( Command, e ); } );
 | 
			
		||||
			DCommand.addEventListener( "KeyUp", function( e ) { TestEmpty( Command, e ); } );
 | 
			
		||||
			DCommand.addEventListener( "KeyDown", KeyHandler( Command, HandleInput ) );
 | 
			
		||||
			DCommand.addEventListener( "KeyUp", KeyHandler( Command, TestEmpty ) );
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		var BackQuoteBinding = function ( e )
 | 
			
		||||
		var BackQuoteBinding = function ( sender, e )
 | 
			
		||||
		{
 | 
			
		||||
			e = e || window.event;
 | 
			
		||||
			if ( e.keyCode ) code = e.keyCode;
 | 
			
		||||
			else if ( e.which ) code = e.which;
 | 
			
		||||
 | 
			
		||||
			if( !SBarPresent && code == 192 )
 | 
			
		||||
			{
 | 
			
		||||
				e.preventDefault();
 | 
			
		||||
@@ -158,7 +285,7 @@
 | 
			
		||||
			}
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		IDOMObject( document ).addEventListener( "KeyDown", BackQuoteBinding, false );
 | 
			
		||||
		IDOMObject( document ).addEventListener( "KeyDown", KeyHandler( document, BackQuoteBinding ), false );
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	ns[ NS_EXPORT ]( EX_CLASS, "SmartInput", SmartInput );
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,8 @@
 | 
			
		||||
 | 
			
		||||
.inline-code {
 | 
			
		||||
	font-family: monospace;
 | 
			
		||||
	font-size: 1.12em;
 | 
			
		||||
 | 
			
		||||
	background-color: #EEE;
 | 
			
		||||
	padding: 0.2em 0.5em;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user