SmartInput for back quoted text

This commit is contained in:
斟酌 鵬兄 2016-02-22 03:08:07 +08:00
parent 82451a41b9
commit 82ef981d0a
14 changed files with 297 additions and 50 deletions

View File

@ -223,10 +223,11 @@
// General file, list view // General file, list view
/** @param {_AstJson_.AJaxGetFiles} */ /** @param {_AstJson_.AJaxGetFiles} */
, buildGeneralCanvas = function (e) , buildGeneralCanvas = function ( e )
{ {
if( !e ) return;
var f = e.files, dateStamp; var f = e.files, dateStamp;
resetCanvas("canvasGeneral"); resetCanvas( "canvasGeneral" );
for(var i in f) for(var i in f)
{ {
@ -527,9 +528,13 @@
, requestInsert = function(confirmed) , requestInsert = function(confirmed)
{ {
if(confirmed) if( confirmed )
{ {
var selectedAlbum = IDOMElement(IDOMElement(this.albumList).first(1, function(elem) { return elem.hasAttribute("selected"); })).getDAttribute("id"); var selectedAlbum = IDOMElement(
IDOMElement( this.albumList ).first( 1, function(elem) {
return elem.hasAttribute("selected");
} ) ).getDAttribute( "id" );
postData( postData(
processorSet processorSet
, { "group": "insert", "id": selectedAlbum , "files": this.collection.join(",") } , { "group": "insert", "id": selectedAlbum , "files": this.collection.join(",") }
@ -541,17 +546,17 @@
, delCollection = function (confirmed) , delCollection = function (confirmed)
{ {
var album_id = IDOMElement(this).getDAttribute("id"); var album_id = IDOMElement(this).getDAttribute("id");
if(confirmed) if( confirmed )
{ {
postData(processorGet, { group: "get", aid: album_id }, getFilestoDelete.bind(this), loadFailed); postData( processorGet, { group: "get", aid: album_id }, getFilestoDelete.bind( this ), loadFailed );
} }
else else
{ {
postData(processorSet, { group: "remove", id: album_id }, refreshCanvas, loadFailed); postData( processorSet, { group: "remove", id: album_id }, refreshCanvas, loadFailed );
} }
} }
, getFilestoDelete = function (e) , getFilestoDelete = function ( e )
{ {
var l = Object.keys(e.files).length var l = Object.keys(e.files).length
, fc = 0 , fc = 0
@ -646,20 +651,29 @@
, f = e.files, first; , f = e.files, first;
// button mime/type ( counts ) // button mime/type ( counts )
for(var i in f) for( var i in f )
{ {
var elem = Dand.wrap("span", null, "asl_menuItem", (i + "(" + f[i] + ")"), new DataKey("name", i)); var elem = Dand.wrap(
"span", null, "asl_menuItem"
, i + "(" + f[i] + ")"
, new DataKey( "name", i ) );
view_index[view_index.length] = [i, elem]; view_index[view_index.length] = [i, elem];
menuBar.appendChild(elem); menuBar.appendChild(elem);
IDOMElement(elem).addEventListener(new EventKey("Click", switchView.bind(IDOMElement(elem)))); IDOMElement(elem).addEventListener(new EventKey("Click", switchView.bind(IDOMElement(elem))));
if(!first) first = [i, elem]; if( !first ) first = [ i, elem ];
}
if( !first )
{
debug.Info( "No files" );
return;
} }
// begin load index // begin load index
refreshCanvas(first[0]); refreshCanvas( first[0] );
// Set style // Set style
first[1].setAttribute("current", 1); first[1].setAttribute("current", 1);
} }

View File

@ -0,0 +1,12 @@
.smartbar-candidates {
padding: 0.5em;
background-color: rgba( 0, 0, 0, 0.2 );
}
.smartbar-candidates .cn {
padding: 0.2em 0.5em;
}
.smartbar-candidates .cn:hover {
background-color: rgba( 0, 0, 0, 0.2 );
}

View File

@ -0,0 +1,165 @@
(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 );
})();

View File

@ -0,0 +1,12 @@
.v_boundary[data-inline="on"][data-type="Code"] {
display: inline-block;
background-color: #EEE;
}
.v_box[data-inline="on"] .v_description {
display: none;
}
.v_box[data-inline="on"] {
min-height: 0;
}

View File

@ -14,6 +14,7 @@
var MessageBox = __import( "Components.MessageBox" ); var MessageBox = __import( "Components.MessageBox" );
var escapeStr = ns[ NS_INVOKE ]( "escapeStr" ); var escapeStr = ns[ NS_INVOKE ]( "escapeStr" );
var compileProp = ns[ NS_INVOKE ]( "compileProp" );
var code = function ( insertSnippet, snippetWrap, createContext, override ) var code = function ( insertSnippet, snippetWrap, createContext, override )
{ {
@ -55,7 +56,8 @@
{ {
// Input fields // Input fields
var v_snippetInput = Dand.wrap( "textarea", null, "v_snippet_input" ) var v_snippetInput = Dand.wrap( "textarea", null, "v_snippet_input" )
, v_codelang = Dand.wrap( "select", null, "v_select flsf", compileListItems() ); , v_codelang = Dand.wrap( "select", null, "v_select flsf", compileListItems() )
, input_inline = Dand.wrapna('input', new IKey("type", "checkbox") );
if ( this._stage ) if ( this._stage )
{ {
@ -71,6 +73,7 @@
} }
v_snippetInput.value = this._content || ""; v_snippetInput.value = this._content || "";
input_inline.checked = ( this._inline == "on" );
} }
else else
{ {
@ -87,29 +90,31 @@
, [ , [
Dand.wrapc( "v_instruction", v_codelang ) Dand.wrapc( "v_instruction", v_codelang )
, v_snippetInput , v_snippetInput
, Dand.wrape([ input_inline, Dand.textNode( "Inline" ) ])
] ]
) )
, "OK", "Cancel" , "OK", "Cancel"
// Switcher // Switcher
, visualizer.bind({ code:v_snippetInput, lang: v_codelang, stage: this._stage }) , visualizer.bind({ code:v_snippetInput, inline: input_inline, lang: v_codelang, stage: this._stage })
).show(); ).show();
} }
, visualizer = function ( submitted, override ) , visualizer = function ( submitted, override )
{ {
var lang, code var lang, code, inline
, stage = this.stage; , stage = this.stage;
if ( override ) if ( override )
{ {
lang = override.lang; lang = override.lang;
code = override.value; code = override.value;
inline = override.inline;
} }
else else
{ {
lang = this.lang[this.pSnippeCodeChoice = this.lang.selectedIndex].value; lang = this.lang[this.pSnippeCodeChoice = this.lang.selectedIndex].value;
code = this.code.value; code = this.code.value;
inline = this.inline.checked ? "on" : "";
} }
var langName; var langName;
@ -124,7 +129,7 @@
if ( submitted && code ) if ( submitted && code )
{ {
if (!stage) if ( !stage )
{ {
// Visualize component // Visualize component
temp = Dand.wrapc( temp = Dand.wrapc(
@ -136,8 +141,10 @@
, [ , [
new DataKey( "value", code ) new DataKey( "value", code )
, new DataKey( "lang", lang ) , new DataKey( "lang", lang )
, new DataKey( "inline", inline )
] ]
); );
insertSnippet( j = snippetWrap( "Code", temp ), Boolean( override ) ); insertSnippet( j = snippetWrap( "Code", temp ), Boolean( override ) );
} }
else else
@ -146,6 +153,7 @@
[ [
new DataKey( "value", code ) new DataKey( "value", code )
, new DataKey( "lang", lang ) , new DataKey( "lang", lang )
, new DataKey( "inline", inline )
] ]
); );
@ -161,7 +169,10 @@
} }
i = { _lang: lang, _content: code, _stage: temp }; i = { _inline: inline, _lang: lang, _content: code, _stage: temp };
// Set the inline style
IDOMElement( j ).setAttribute( new DataKey( "inline", inline ) );
// Set context menu // Set context menu
createContext( i, j, handler ); createContext( i, j, handler );
@ -185,10 +196,11 @@
{ {
// [code lang=\"" + lang + "\"]" + code + "[/code]" // [code lang=\"" + lang + "\"]" + code + "[/code]"
var element = IDOMElement( stage ) var element = IDOMElement( stage )
, lang = element.getDAttribute( "lang" ); , props= [ "lang", "inline" ];
return "[code" return "[code"
+ (lang ? (" lang=\"" + lang + "\"") : "") + "]" + compileProp( element, props )
+ "]"
+ escapeStr( element.getDAttribute( "value" ) ) + escapeStr( element.getDAttribute( "value" ) )
+ "[/code]" + "[/code]"
; ;

View File

@ -31,11 +31,11 @@
, input_preferred = Dand.wrapna('input', new IKey("type", "checkbox")) , input_preferred = Dand.wrapna('input', new IKey("type", "checkbox"))
; ;
if (this._stage) if ( this._stage )
{ {
input_url.value = this._url; input_url.value = this._url;
input_a.value = this._href; input_a.value = this._href;
input_preferred.checked = (this._preferred == "on"); input_preferred.checked = ( this._preferred == "on" );
} }
// Popup MessageBox // Popup MessageBox

View File

@ -37,8 +37,7 @@
, input_text , input_text
, Dand.wrapc("v_instruction flsf", "Link to:") , Dand.wrapc("v_instruction flsf", "Link to:")
, input_a , input_a
] ])
)
, "OK", "Cancel", visualizer.bind({text:input_text, href:input_a, stage: this._stage})).show(); , "OK", "Cancel", visualizer.bind({text:input_text, href:input_a, stage: this._stage})).show();
} }
@ -100,8 +99,7 @@
// Set context menu // Set context menu
createContext(i, j, handler); createContext(i, j, handler);
} }
} };
;
if (override) if (override)
{ {

View File

@ -165,6 +165,7 @@
var _resSelection = function () var _resSelection = function ()
{ {
contentDiv.focus();
if ( selRange ) if ( selRange )
{ {
if ( window.getSelection ) if ( window.getSelection )
@ -186,17 +187,18 @@
{ {
if( !Dand.id( "v_linebreak" ) ) if( !Dand.id( "v_linebreak" ) )
{ {
insertSnippet( lastLine, true ); insertElement( lastLine, true );
} }
else else
{ {
insertSnippet( contentDiv.removeChild( lastLine ), true ); insertElement( contentDiv.removeChild( lastLine ), true );
} }
}; };
var insertAtCaret = function( element ) var insertAtCaret = function( element, newLine )
{ {
var sel, range; var sel, range;
if( newLine == undefined ) newLine = true;
sel = window.getSelection(); sel = window.getSelection();
if ( sel.getRangeAt && sel.rangeCount ) if ( sel.getRangeAt && sel.rangeCount )
@ -212,10 +214,11 @@
} }
e_document.updateContent(); e_document.updateContent();
ensureLastLinebreak();
if( newLine ) ensureLastLinebreak();
}; };
var insertSnippet = function( element, override ) var insertElement = function( element, override )
{ {
if ( override ) if ( override )
{ {
@ -223,7 +226,6 @@
return; return;
} }
contentDiv.focus();
_resSelection(); _resSelection();
insertAtCaret( element ); insertAtCaret( element );
}; };
@ -283,7 +285,7 @@
if ( _module ) if ( _module )
{ {
// Visualize snippet // Visualize snippet
new ( _module )( insertSnippet, snippetWrap, createSnippetMenu, temp ); new ( _module )( insertElement, snippetWrap, createSnippetMenu, temp );
} }
else else
{ {
@ -293,7 +295,7 @@
token.setAttribute( "class", token.getAttribute( "class" ) + " flsf" ); token.setAttribute( "class", token.getAttribute( "class" ) + " flsf" );
snippetQueue( type ).push([ token, temp ]); snippetQueue( type ).push([ token, temp ]);
insertSnippet( token, true ); insertElement( token, true );
} }
}; };
@ -397,7 +399,7 @@
snippetControls.appendChild( temp ); snippetControls.appendChild( temp );
snippetControls.appendChild( Dand.textNode( "\t" ) ); snippetControls.appendChild( Dand.textNode( "\t" ) );
temp.onclick = new ( _module )( insertSnippet, snippetWrap, createSnippetMenu ); temp.onclick = new ( _module )( insertElement, snippetWrap, createSnippetMenu );
var queue = snippetQueue( mod_name, _module.alias ); var queue = snippetQueue( mod_name, _module.alias );
for( var i in queue ) for( var i in queue )
@ -479,6 +481,18 @@
this.saveSelection = _savSelection; this.saveSelection = _savSelection;
this.restoreSelection = _resSelection; this.restoreSelection = _resSelection;
this.insertAtCaret = insertAtCaret;
this.insertSnippet = function( type, options )
{
var _module = loadedModule[ type ];
new ( _module )(
// Disables the override
function( e ) { insertElement( e ); }
, snippetWrap, createSnippetMenu, options
);
};
article.invoke(this); article.invoke(this);

View File

@ -24,6 +24,9 @@
/** @type {Astro.Blog.AstroEdit.SiteLibrary} */ /** @type {Astro.Blog.AstroEdit.SiteLibrary} */
var SiteLibrary = __import( "Astro.Blog.AstroEdit.SiteLibrary" ); var SiteLibrary = __import( "Astro.Blog.AstroEdit.SiteLibrary" );
// calls the smart bar
var SmartInput = __import( "Astro.Blog.AstroEdit.SmartInput" );
var wh, ww, cw, html, article; var wh, ww, cw, html, article;
var init = function () var init = function ()
@ -56,12 +59,15 @@
// Article modules // Article modules
new Draft( article, a_conf.paths.get_drafts ); new Draft( article, a_conf.paths.get_drafts );
new Visualizer(
var Vis = new Visualizer(
article article
, Dand.id( "ae_visual_snippets" ) , Dand.id( "ae_visual_snippets" )
, Config.get( "ServiceUri" ) , Config.get( "ServiceUri" )
); );
new SmartInput( Vis );
// Independent modules // Independent modules
new Uploader( a_conf.paths.set_file ); new Uploader( a_conf.paths.set_file );
new SiteLibrary( new SiteLibrary(

View File

@ -2,6 +2,12 @@
max-width: 100%; max-width: 100%;
} }
.inline-code {
font-family: monospace;
background-color: #EEE;
padding: 0.2em 0.5em;
}
.b_entry { .b_entry {
background-color: #FAFAFA; background-color: #FAFAFA;
/* box-shadow: 0 0 8px -2px black; */ /* box-shadow: 0 0 8px -2px black; */

View File

@ -11,7 +11,7 @@
opacity: 0.5; opacity: 0.5;
} }
.section-buttons > a:hover, .section-buttons > a[active]:hover { .section-buttons > a:hover, .section-buttons > a[data-active="1"]:hover {
opacity: 0.8; opacity: 0.8;
text-decoration: none; text-decoration: none;
} }
@ -50,7 +50,7 @@
.section-buttons > a > span { .section-buttons > a > span {
padding: 0.75em 0.5em; padding: 0.75em 0.5em;
} }
.section-buttons > a[active] { .section-buttons > a[data-active="1"] {
opacity: 1; opacity: 1;
} }
.section-buttons > a > .count { .section-buttons > a > .count {

View File

@ -26,11 +26,12 @@
var init = function () var init = function ()
{ {
var username;
var form = Dand.wrapne('form' var form = Dand.wrapne('form'
, [ , [
// Basic login and password fields // Basic login and password fields
, Dand.wrapc("flsf", "Name:") , Dand.wrapc("flsf", "Name:")
, Dand.wrapna('input', [ field_username, new IKey("type", "text") ] ) , username = Dand.wrapna('input', [ field_username, new IKey("type", "text") ] )
, Dand.wrapc("flsf", "Password:") , Dand.wrapc("flsf", "Password:")
, Dand.wrapna('input', [ field_password, new IKey("type", "password") ] ) , Dand.wrapna('input', [ field_password, new IKey("type", "password") ] )
@ -42,13 +43,13 @@
new IKey('action', formAction) new IKey('action', formAction)
, new IKey('method', 'POST') , new IKey('method', 'POST')
] ]
) );
;
var mbox = new MessageBox( "Blog.Astro", form, "Login", false, submitForm.bind( form ) ).show(); var mbox = new MessageBox( "Blog.Astro", form, "Login", false, submitForm.bind( form ) ).show();
// Handle enter button username.focus();
// Handle enter button
mbox.onkeyup = function( _e ) mbox.onkeyup = function( _e )
{ {
if ( submitForm.bind( form )( _e.which == 13 ) ) if ( submitForm.bind( form )( _e.which == 13 ) )

View File

@ -1,7 +1,10 @@
.site-news { font-family: monospace; } .site-news { font-family: monospace; }
.site-news > span { display: block; } .site-news > span { display: block; }
.rbuilds > a { display: block; } .rbuilds > a {
display: block;
font-family: monospace;
}
.rbuilds > a > span { .rbuilds > a > span {
padding: 0 0.5em; padding: 0 0.5em;
} }

View File

@ -9,4 +9,8 @@ Astro.Blog.AstroEdit.Visualizer.visualizeData;
/** @type {Function} */ /** @type {Function} */
Astro.Blog.AstroEdit.Visualizer.saveSelection; Astro.Blog.AstroEdit.Visualizer.saveSelection;
/** @type {Function} */ /** @type {Function} */
Astro.Blog.AstroEdit.Visualizer.insertAtCaret;
/** @type {Function} */
Astro.Blog.AstroEdit.Visualizer.insertSnippet;
/** @type {Function} */
Astro.Blog.AstroEdit.Visualizer.restoreSelection; Astro.Blog.AstroEdit.Visualizer.restoreSelection;