penguin/AstroJS

Javascript framework for my blog

commit 041617f0b415a1f5f23872e24f6e326317102cb2

author斟酌 鵬兄 <tgckpg@gmail.com>
date2016-03-06T15:25:13Z
subjectAdded footnote support
commit 041617f0b415a1f5f23872e24f6e326317102cb2
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date:   2016-03-06T15:25:13Z

    Added footnote support
---
 .../SmartInput/CandidateAction/Footnote.js         | 37 +++++++++
 .../src/Astro/Blog/AstroEdit/SmartInput/_this.js   | 19 +++--
 .../Blog/AstroEdit/Visualizer/Snippet/Footnote.css |  3 +
 .../Blog/AstroEdit/Visualizer/Snippet/Footnote.js  | 97 ++++++++++++++++++++++
 .../src/Astro/Blog/AstroEdit/Visualizer/_this.js   |  1 +
 botanjs/src/Astro/Blog/Components/Entry/Blog.css   |  1 +
 botanjs/src/Astro/Blog/Components/Footnote.css     | 31 +++++++
 botanjs/src/Astro/Blog/Components/Footnote.js      | 46 ++++++++++
 botanjs/src/Astro/Build/Components/BuildReport.css |  1 +
 9 files changed, 228 insertions(+), 8 deletions(-)

diff --git a/botanjs/src/Astro/Blog/AstroEdit/SmartInput/CandidateAction/Footnote.js b/botanjs/src/Astro/Blog/AstroEdit/SmartInput/CandidateAction/Footnote.js
new file mode 100644
index 0000000..75ff143
--- /dev/null
+++ b/botanjs/src/Astro/Blog/AstroEdit/SmartInput/CandidateAction/Footnote.js
@@ -0,0 +1,37 @@
+(function ()
+{
+	var ns = __namespace( "Astro.Blog.AstroEdit.SmartInput.CandidateAction" );
+
+	/** @type {System.utils.IKey} */
+	var IKey                              = __import( "System.utils.IKey" );
+	/** @type {System.utils.DataKey} */
+	var DataKey                           = __import( "System.utils.DataKey" );
+	/** @type {Dandelion.IDOMElement} */
+	var IDOMElement                       = __import( "Dandelion.IDOMElement" );
+	/** @type {Dandelion} */
+	var Dand                              = __import( "Dandelion" );
+
+	/** @type {Astro.Blog.AstroEdit.SmartInput.ICandidateAction} */
+	var Footnote = function ( visualizer, key )
+	{
+		this.visualizer = visualizer;
+		this.key = key;
+	};
+
+	Footnote.prototype.GetCandidates = function( handler )
+	{
+		handler( false );
+	};
+
+	Footnote.prototype.Process = function( content )
+	{
+		this.visualizer.insertSnippet( "footnote", { "value": content } );
+	};
+
+	Footnote.prototype.Retreat = function( sender, e )
+	{
+		return sender.value == "" && e.keyCode == 8; // Backspace
+	};
+
+	ns[ NS_EXPORT ]( EX_CLASS, "Footnote", Footnote );
+})();
diff --git a/botanjs/src/Astro/Blog/AstroEdit/SmartInput/_this.js b/botanjs/src/Astro/Blog/AstroEdit/SmartInput/_this.js
index 35169ba..d253281 100644
--- a/botanjs/src/Astro/Blog/AstroEdit/SmartInput/_this.js
+++ b/botanjs/src/Astro/Blog/AstroEdit/SmartInput/_this.js
@@ -140,6 +140,7 @@
 		var insert = function() { return Dand.textNode( "" ); };
 
 		var ModLevels = [];
+		var BindingBox = null;
 
 		ModLevels.Cands = function() { return ModLevels[0][0]; };
 		ModLevels.Action = function() { return ModLevels[0][1]; };
@@ -232,11 +233,11 @@
 					if( v == "" )
 					{
 						insert = function() { return Dand.textNode( "`" ); };
-						sender.BindingBox.close( true );
+						BindingBox.close( true );
 						break;
 					}
 
-					sender.BindingBox.close();
+					BindingBox.close();
 					// Insert the code snippet with inline flag
 					visualizer.insertSnippet( "code", { "inline": "on", "lang": "plain", "value": v } );
 					break;
@@ -249,7 +250,7 @@
 					if( ModLevels.Cands().Empty && 1 < ModLevels.length )
 					{
 						ModLevels.Action()( sender.value.substr( 1 ) );
-						sender.BindingBox.close();
+						BindingBox.close();
 						break;
 					}
 
@@ -259,19 +260,19 @@
 					{
 						insert = undefined;
 						var close = ModLevels.Action()( selected.getDAttribute( "key" ) );
-						if( close ) sender.BindingBox.close();
+						if( close ) BindingBox.close();
 					}
 					else
 					{
 						// Insert this text directly
 						var v = Dand.textNode( sender.value.substr( 1 ) );
 						insert = function() { return v; };
-						sender.BindingBox.close( true );
+						BindingBox.close( true );
 					}
 					break;
 
 				case 27: // Esc
-					sender.BindingBox.close();
+					BindingBox.close();
 					break;
 
 				case 9: // Tab
@@ -389,6 +390,7 @@
 				title( true );
 				stage()[0].value = "`";
 				stage()[0].setAttribute( "placeholder", ModLevels.Cands().desc );
+				BindingBox.show();
 			}
 		};
 
@@ -396,7 +398,7 @@
 		{
 			if( ModLevels.length == 1 )
 			{
-				sender.BindingBox.close();
+				BindingBox.close();
 				destructor.Destruct();
 			}
 
@@ -414,6 +416,7 @@
 
 				input.selectionStart = 1;
 				input.selectionEnd = input.value.length;
+				BindingBox.show();
 			}
 		};
 
@@ -434,7 +437,7 @@
 			MsgBox.show();
 
 			var Command = stage()[0];
-			Command.BindingBox = MsgBox;
+			BindingBox = MsgBox;
 
 			Command.focus();
 
diff --git a/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/Footnote.css b/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/Footnote.css
new file mode 100644
index 0000000..8c0af8d
--- /dev/null
+++ b/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/Footnote.css
@@ -0,0 +1,3 @@
+.v_boundary[data-type="Footnote"] {
+	color: #f15a24;
+}
diff --git a/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/Footnote.js b/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/Footnote.js
new file mode 100644
index 0000000..bc9c075
--- /dev/null
+++ b/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/Footnote.js
@@ -0,0 +1,97 @@
+(function ()
+{
+	var ns = __namespace( "Astro.Blog.AstroEdit.Visualizer.Snippet" );
+
+	/** @type {System.utils.IKey} */
+	var IKey                              = __import( "System.utils.IKey" );
+	/** @type {System.utils.DataKey} */
+	var DataKey                           = __import( "System.utils.DataKey" );
+	/** @type {Dandelion.IDOMElement} */
+	var IDOMElement                       = __import( "Dandelion.IDOMElement" );
+	/** @type {Dandelion} */
+	var Dand                              = __import( "Dandelion" );
+	/** @type {Components.MessageBox} */
+	var MessageBox                        = __import( "Components.MessageBox" );
+
+	var escapeStr = ns[ NS_INVOKE ]( "escapeStr" );
+
+	var footnote = function (insertSnippet, snippetWrap, createContext, override)
+	{
+		var temp, i, j
+		
+		, handler = function ()
+		{
+			// Input fields
+			var v_snippetInput = Dand.wrap( "textarea", null, "v_snippet_input" );
+			
+			if ( this._stage )
+			{
+				v_snippetInput.value = this._mText;
+			}
+			
+			// Popup MessageBox
+			new MessageBox(
+				"Insert Footnote"
+				, v_snippetInput
+				, "OK", "Cancel"
+				, visualizer.bind({ mText: v_snippetInput, stage: this._stage })
+			).show();
+		}
+		
+		, visualizer = function (submitted, override)
+		{
+			
+			var mText, stage = this.stage;
+			
+			mText = override ? override.value : this.mText.value;
+			
+			if (submitted && mText)
+			{
+				if (!stage)
+				{
+					// Visualize component
+					temp = Dand.wrapne( "span", "^", [
+						new DataKey( "value", mText )
+					]);
+
+					insertSnippet(
+						j = snippetWrap( "Footnote", temp, false, "span" )
+						, Boolean( override )
+					);
+				}
+				else
+				{
+					IDOMElement( stage ).setAttribute(new DataKey( "value", mText ));
+					temp = stage;
+				}
+				
+				i = { _mText: mText, _stage: temp };
+				
+				// Set context menu
+				createContext( i, j, handler );
+			}
+		};
+		
+		if ( override )
+		{
+			visualizer( true, override );
+			override = false;
+		}
+		else
+		{
+			return handler;
+		}
+		return true;
+	
+	};
+	
+	var compile = function (stage)
+	{
+		// [footnote][/footnote]
+		return "[footnote]" + escapeStr( IDOMElement(stage).getDAttribute("value") ) + "[/footnote]";
+	};
+
+	__static_method( footnote, "compile", compile );
+
+	ns[ NS_EXPORT ]( EX_CLASS, "Footnote", footnote );
+})();
diff --git a/botanjs/src/Astro/Blog/AstroEdit/Visualizer/_this.js b/botanjs/src/Astro/Blog/AstroEdit/Visualizer/_this.js
index a771c02..4280507 100644
--- a/botanjs/src/Astro/Blog/AstroEdit/Visualizer/_this.js
+++ b/botanjs/src/Astro/Blog/AstroEdit/Visualizer/_this.js
@@ -38,6 +38,7 @@
 		 , "Html"        , "background: coral;"
 		 , "SiteFile"    , "background: royalblue;"
 		 , "Heading"     , ""
+		 , "Footnote"     , ""
 		 , "ArticleLink" , ""
 	);
 
diff --git a/botanjs/src/Astro/Blog/Components/Entry/Blog.css b/botanjs/src/Astro/Blog/Components/Entry/Blog.css
index 8e63474..22d8790 100644
--- a/botanjs/src/Astro/Blog/Components/Entry/Blog.css
+++ b/botanjs/src/Astro/Blog/Components/Entry/Blog.css
@@ -51,6 +51,7 @@
 	color: #555;
     text-align: justify;
 	min-height: 155px;
+	margin-bottom: 3em;
 }
 
 .b_bodyWrapper a { color: #f15a24; }
diff --git a/botanjs/src/Astro/Blog/Components/Footnote.css b/botanjs/src/Astro/Blog/Components/Footnote.css
new file mode 100644
index 0000000..fb0ed7d
--- /dev/null
+++ b/botanjs/src/Astro/Blog/Components/Footnote.css
@@ -0,0 +1,31 @@
+.footnote {
+	padding-top: 0.25em;
+	position: relative;
+	margin-bottom: 2em;
+}
+
+.footnote {
+	color: #555;
+	list-style-type: decimal;
+	list-style-position: inside;
+}
+
+.footnote > li {
+	padding-left: 0.5em;
+}
+
+.footnote > li[focused] {
+	background-color: #EE5;
+}
+
+.footnote:before {
+	content: "";
+
+	position: absolute;
+
+	top: 0;
+
+	width: 40%;
+
+	border-top: 1px black solid;
+}
diff --git a/botanjs/src/Astro/Blog/Components/Footnote.js b/botanjs/src/Astro/Blog/Components/Footnote.js
new file mode 100644
index 0000000..ab66f56
--- /dev/null
+++ b/botanjs/src/Astro/Blog/Components/Footnote.js
@@ -0,0 +1,46 @@
+(function(){
+	var ns = __namespace( "Astro.Blog.Components.Footnote" );
+	/** @type {Dandelion} */
+	var Dand                             = __import( "Dandelion" );
+	/** @type {Dandelion.IDOMElement} */
+	var IDOMElement                      = __import( "Dandelion.IDOMElement" );
+	/** @type {Astro.Bootstrap} */
+	var Bootstrap                        = __import( "Astro.Bootstrap" );
+	/** @type {Astro.Blog.Config} */
+	var Config                           = __import( "Astro.Blog.Config" );
+	/** @type {Astro.utils.Date} */
+	var XDate                            = __import( "Astro.utils.Date" );
+
+	/** @param {Dandelion.IDOMElement} elem */
+	var Footnote = function( elem )
+	{
+		var jumpers = Dand.glass( "ft", true );
+		if( !jumpers.length ) return;
+
+		var notes = Dand.glass( "footnote", true )[0];
+
+		jumpers.forEach( function( e ) {
+
+			var a = e.first( 1 );
+			IDOMElement( a ).addEventListener( "Click", function()
+			{
+				var clicked = a.hash.substr( 1 );
+				notes.foreach( 1, function( e ) {
+					if( e.id == clicked )
+					{
+						e.setAttribute( "focused", 1 );
+					}
+					else
+					{
+						e.removeAttribute( "focused" );
+					}
+				});
+			});
+		} );
+	};
+
+	Bootstrap.regInit(function() {
+		new Footnote();
+	});
+
+})();
diff --git a/botanjs/src/Astro/Build/Components/BuildReport.css b/botanjs/src/Astro/Build/Components/BuildReport.css
index c615839..97984df 100644
--- a/botanjs/src/Astro/Build/Components/BuildReport.css
+++ b/botanjs/src/Astro/Build/Components/BuildReport.css
@@ -36,6 +36,7 @@
 
 .section {
 	position: relative;
+	overflow: hidden;
 
 	margin: 1em -2em;
 	padding: 2em;