From 1d812de551ae9652c967a857c54c79d3cb41db36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=9F=E9=85=8C=20=E9=B5=AC=E5=85=84?= Date: Tue, 22 Sep 2015 19:31:53 +0800 Subject: [PATCH] Generalize tags to flags --- botanjs/src/Astro/Blog/AstroEdit/Article.js | 98 +++++++-- .../Blog/AstroEdit/{Tag.css => Flag.css} | 12 +- botanjs/src/Astro/Blog/AstroEdit/Flag.js | 187 +++++++++++++++++ botanjs/src/Astro/Blog/AstroEdit/Tag.js | 197 ------------------ botanjs/src/Astro/Blog/AstroEdit/_this.css | 6 + botanjs/src/Astro/Blog/AstroEdit/_this.js | 13 +- .../externs/Astro.Blog.AstroEdit.IPlugin.js | 8 + .../src/externs/Astro.Blog.AstroEdit.Tag.js | 6 - botanjs/src/externs/_AstConf_.AstroEdit.js | 16 +- .../src/externs/_AstJson_.AJaxGetArticle.js | 2 + 10 files changed, 315 insertions(+), 230 deletions(-) rename botanjs/src/Astro/Blog/AstroEdit/{Tag.css => Flag.css} (63%) create mode 100644 botanjs/src/Astro/Blog/AstroEdit/Flag.js delete mode 100644 botanjs/src/Astro/Blog/AstroEdit/Tag.js create mode 100644 botanjs/src/externs/Astro.Blog.AstroEdit.IPlugin.js delete mode 100644 botanjs/src/externs/Astro.Blog.AstroEdit.Tag.js diff --git a/botanjs/src/Astro/Blog/AstroEdit/Article.js b/botanjs/src/Astro/Blog/AstroEdit/Article.js index cfe7210..5cfde04 100644 --- a/botanjs/src/Astro/Blog/AstroEdit/Article.js +++ b/botanjs/src/Astro/Blog/AstroEdit/Article.js @@ -20,11 +20,11 @@ /** @type {Astro.Blog.Components.Bubble} */ var Bubble = __import( "Astro.Blog.Components.Bubble" ); - var opostData = __import( "System.Net.postData" ); + var opostData = __import( "System.Net.postData" ); var prettyDate = __import( "Astro.utils.Date.pretty" ); var Visualizer = ns[ NS_INVOKE ]( "Visualizer" ); - var Tag = ns[ NS_INVOKE ]( "Tag" ); + var Flag = ns[ NS_INVOKE ]( "Flag" ); // Editor Override @@ -34,7 +34,43 @@ opostData( processor, data, success, failed ); }; - var Article = function( processorSet ) + // Wrappers for every plugins + var PluginBundles = function( article, plugins ) + { + this.plugins = plugins; + for( var i in this.plugins ) + { + /* @type {Astro.Blog.AstroEdit.IPlugins} */ + var g = this.plugins[i]; + g.bindArticle = article; + } + }; + + PluginBundles.prototype.setForView = function( pluginId, data ) + { + for( var i in this.plugins ) + { + var p = this.plugins[i]; + if( p.id == pluginId ) + { + p.setForView( data ); + } + } + }; + + PluginBundles.prototype.getSetData = function( pluginId, data ) + { + for( var i in this.plugins ) + { + var p = this.plugins[i]; + if( p.id == pluginId ) + { + p.getSetData( data ); + } + } + }; + + var Article = function( processorSet, plugins ) { var pBubble = new Bubble(); @@ -44,7 +80,6 @@ var _content = ""; //// Classes & obj - var _ae_tag = null; var _visualizer = null; var timestamp = new Date(); @@ -58,6 +93,7 @@ , date_created: timestamp , archived: false , tags: null + , section: null , draft: true , article_id: false }; @@ -78,7 +114,7 @@ var a_conf = Config.get( "AstroEdit" ); var base_path = Config.get( "BasePath" ); - ///// preview fields + /*{{{ preview fields */ var ae_p_fields = { mtime: set_field_name( Dand.wrap( "input" ), "date_modified" ) , ptime: set_field_name( Dand.wrap( "input" ), "date_published" ) @@ -94,8 +130,42 @@ var temp; for ( var i in ae_p_fields ) ae_preview.appendChild( ae_p_fields[i] ); - //// End preview fields + /* End preview fields }}}*/ + /*{{{ Button sections */ + var ae_stitles = Dand.glass( "ae_stitle", true ); + var ae_panel_section = Dand.glass( "ae_panel_section", true ); + + var l = ae_stitles.length; + for( var i = 0; i < l; i ++ ) + { + var t = ae_stitles[i]; + var p = ae_panel_section[i]; + t.addEventListener( "Click", function( e ) + { + var p = this.p; + if( this.t.expanded = !this.t.expanded ) + { + p.style.height = "auto"; + Cycle.next( + function(){ + p.style.height = this.h + "px"; + }.bind({ h: p.element.clientHeight }) + ); + p.style.height = 0; + } + else + { + p.style.height = 0; + } + }.bind({ t: t, p: p }) ); + } + + ae_stitles[0].element.click(); + /* End Button sections }}}*/ + + // Install plugins + plugins = new PluginBundles( this, plugins ); var enableSaveFunction = function () { @@ -253,8 +323,8 @@ ae_publish.innerHTML = ArticleModel.draft ? "Publish" : "Done edit"; ae_backup.innerHTML = ( ArticleModel.draft ? "Save" : "Backup" ) + "(Ctrl + s)"; - - _ae_tag && _ae_tag.setTags( ArticleModel.tags ); + plugins.setForView( "tags", ArticleModel.tags ); + plugins.setForView( "section", ArticleModel.section ); } , deleteDraft = function ( confirmed ) @@ -311,10 +381,12 @@ article_id: __article_id ? __article_id : "" , title: _title , content: _content - , tags: _ae_tag.getTags() , draft: 1 }; + plugins.getSetData( "tags", _data ); + plugins.getSetData( "section", _data ); + postData( processorSet, _data, saveSuccess, serverFailed ); } }; @@ -345,7 +417,7 @@ ? ArticleModel.date_published : Math.floor( 0.001*( new Date().getTime() ) ) ; - ae_p_fields.tags.value = _ae_tag.getTags(); + ae_p_fields.tags.value = _ae_tag.getFlags(); ae_preview.submit(); }; @@ -358,10 +430,10 @@ _visualizer = _class; _visualizer.setContentDiv( ae_content ); } - if ( _class instanceof Tag ) + if ( _class instanceof Flag ) { _ae_tag = _class; - ArticleModel && ArticleModel.tags && ( _ae_tag ).setTags( ArticleModel.tags ); + ArticleModel && ArticleModel.tags && ( _ae_tag ).setFlags( ArticleModel.tags ); } }; @@ -389,7 +461,7 @@ _data.title = _title; _data.content = _content; - _data.tags = _ae_tag.getTags(); + _data.tags = _ae_tag.getFlags(); postData( processorSet, _data, publishSuccess.bind({ contentUpdate: true }), serverFailed ); } diff --git a/botanjs/src/Astro/Blog/AstroEdit/Tag.css b/botanjs/src/Astro/Blog/AstroEdit/Flag.css similarity index 63% rename from botanjs/src/Astro/Blog/AstroEdit/Tag.css rename to botanjs/src/Astro/Blog/AstroEdit/Flag.css index 10b6b7b..5968bfd 100644 --- a/botanjs/src/Astro/Blog/AstroEdit/Tag.css +++ b/botanjs/src/Astro/Blog/AstroEdit/Flag.css @@ -1,27 +1,27 @@ -.tag_active { +.flag_active { color: white; opacity: 1 !important; } -.ae_tag_delete { +.ae_flag_delete { color: white; padding: 0 0.5em 0 0; } -.ae_tag_delete:hover { +.ae_flag_delete:hover { color: red; } -.ae_tag_add { +.ae_flag_add { color: white; cursor: default; font-weight: 200; } -.ae_tag_add:hover { +.ae_flag_add:hover { color: dodgerblue; } -#ae_tags > span { +.ae_flags > span { float: left; } diff --git a/botanjs/src/Astro/Blog/AstroEdit/Flag.js b/botanjs/src/Astro/Blog/AstroEdit/Flag.js new file mode 100644 index 0000000..63081ee --- /dev/null +++ b/botanjs/src/Astro/Blog/AstroEdit/Flag.js @@ -0,0 +1,187 @@ +(function(){ + var ns = __namespace( "Astro.Blog.AstroEdit" ); + + /** @type {System.Debug} */ + var debug = __import( "System.Debug" ); + /** @type {Components.MessageBox} */ + var MessageBox = __import( "Components.MessageBox" ); + /** @type {Dandelion} */ + var Dand = __import( "Dandelion" ); + /** @type {Dandelion.IDOMElement} */ + var IDOMElement = __import( "Dandelion.IDOMElement" ); + /** @type {Astro.Blog.Config} */ + var Config = __import( "Astro.Blog.Config" ); + + var postData = __import( "System.Net.postData" ); + + /* @type {AstroEdit.IPlugins} */ + var Flag = function ( id, target, flagConf ) + { + this.id = id; + var stage = Dand.id( target ); + var ae_addFlag = Dand.glass( "ae_flag_add" , true, stage )[0]; + var ae_flags = Dand.glass( "ae_flags" , false, stage )[0]; + + // Store flags for future use + var flags = {}; + + ////// Handlers + ae_addFlag.addEventListener( + "Click", function ( e ) + { + e.stopPropagation(); + // Input fields + var ae_flagInput; + + // Popup MessageBox + new MessageBox( + "Add new flag(s)" + , Dand.wrape([ + Dand.wrapc( + "v_instruction flsf" + , "Flags are separated by \\n. (existing flags will be ignored.)" + ) + , ae_flagInput = Dand.wrap( "textarea", null, "v_snippet_input" ) + ]) + , "OK", "Cancel" + , parseFlags.bind( ae_flagInput ) + ).show(); + } + ); + + var deleteFlag = function (e) + { + var p = { flag: this.nodeValue, sflage: this.parentNode }; + postData( flagConf.URICount, p, confirmDelete.bind( p ), serverFailed ); + e.stopPropagation(); + }; + + var confirmDelete = function (obj) + { + new MessageBox( + "Delete Flag" + , [ + Dand.wrapc("ae_blockswitch", + [ + Dand.textNode( "Are you sure you want to delete " ) + , Dand.wrap( "span", null, "flag_active", Dand.textNode( this.flag ) ) + , Dand.textNode( " ?." ) + ] + ) + , obj.count > 0 + ? Dand.wrape([ + Dand.textNode( "This will affect " ) + , Dand.wrap( + "span", null, "ae_affected_count", Dand.textNode( obj.count ) + ) + , Dand.textNode(" article(s).") + ]) + : null + ] + , "Delete", "No" + , doDelete.bind(this) + ).show(); + }; + + var doDelete = function( confirmed ) + { + if ( confirmed ) + { + postData( + flagConf.URISet + , { flag: this.flag, del: 1 } + , deleteSuccess.bind( this ) + , serverFailed + ); + } + }; + + var deleteSuccess = function(obj) + { + // Remove element + this.sflage.parentNode.removeChild(this.sflage); + // Delete reference + delete flags[this.flag]; + }; + + var parseFlags = function () + { + // Filter invalid flags + var nflags = this.value.trim().match(/[^\n]+/g), d, e; + for (var i in nflags) + { + if(!flags[(i = nflags[i]).toLowerCase()]) + { + flags[i] = Dand.wrap("span", null, "flag_active", + [d = Dand.wrap("span", null, "ae_flag_delete", "\u00D7"), e = Dand.textNode(i)] + ); + // Seperator + ae_flags.appendChild(Dand.textNode(" ")); + ae_flags.appendChild(flags[i]); + + flags[i].onclick = function() { toggleFlag(this) }.bind(flags[i]); + d.onclick = deleteFlag.bind(e); + + } + else + { + debug.Info("Flag exist: " + i); + // Hightlight these flags + flags[i.toLowerCase()].className = "flag_active"; + } + } + + }; + + var toggleFlag = function (flag) + { + var isEnabled = flag.className == "flag_active" ? true : false; + flag.className = isEnabled ? "ae_disabled" : "flag_active"; + }; + + var serverFailed = function (obj) { }; + + var cflag, ae_children = ae_flags.childNodes; + for (var i in ae_children) + { + if((cflag = ae_children[i]).nodeType == 1) + { + flags[cflag.lastChild.nodeValue.toLowerCase()] = cflag; + IDOMElement( cflag ).addEventListener( "Click", function() { toggleFlag( this ); }.bind( cflag ) ); + // Bind the last child (x button) to firstChild (textNode: flagname) + IDOMElement( cflag.firstChild ).addEventListener( "Click", deleteFlag.bind( cflag.lastChild ) ); + } + } + + this.getSetData = function ( data ) + { + // Compile flag list + var tlist = []; + + // Return names + for (var i in flags) + { + if(flags[i].className == "flag_active") + tlist[tlist.length] = flags[i].lastChild.nodeValue; + } + + data[ this.id ] = tlist.join("\n"); + } + + this.setForView = function ( flagList ) + { + // Disable all flags first + for ( var i in flags ) flags[i].className = "ae_disabled"; + + // Set flags from flagList + for ( i in flagList ) + if ( flagList[i] ) flags[flagList[i].toLowerCase()].className = "flag_active"; + } + } + + Flag.prototype.getSetData = function () { }; + Flag.prototype.setForView = function ( flagList ) { }; + + ns[ NS_EXPORT ]( EX_CLASS, "Flag", Flag ); + +})(); diff --git a/botanjs/src/Astro/Blog/AstroEdit/Tag.js b/botanjs/src/Astro/Blog/AstroEdit/Tag.js deleted file mode 100644 index 028da5b..0000000 --- a/botanjs/src/Astro/Blog/AstroEdit/Tag.js +++ /dev/null @@ -1,197 +0,0 @@ -(function(){ - var ns = __namespace( "Astro.Blog.AstroEdit" ); - - /** @type {System.Debug} */ - var debug = __import( "System.Debug" ); - /** @type {Components.MessageBox} */ - var MessageBox = __import( "Components.MessageBox" ); - /** @type {Dandelion} */ - var Dand = __import( "Dandelion" ); - /** @type {Dandelion.IDOMElement} */ - var IDOMElement = __import( "Dandelion.IDOMElement" ); - /** @type {Astro.Blog.Config} */ - var Config = __import( "Astro.Blog.Config" ); - - var postData = __import( "System.Net.postData" ); - - /** @param {Astro.Blog.AstroEdit.Article} */ - var Tag = function ( ae_article, tagCountUri ) - { - var Article = ns[ NS_INVOKE ]( "Article" ); - - if ( !( ae_article instanceof Article ) ) - return false; - - /** @type {_AstConf_.AstroEdit} */ - var a_conf = Config.get( "AstroEdit" ); - - var ae_document = ae_article; - - var ae_addTag = Dand.id( "ae_addTags" ); - var ae_tags = Dand.id( "ae_tags" ); - - // Store tags for future use - var tags = {}; - - ////// Handlers - ae_addTag.onclick = function () - { - - // Input fields - var ae_tagInput; - - // Popup MessageBox - new MessageBox( - "Add new tag(s)" - , Dand.wrape([ - Dand.wrapc( - "v_instruction flsf" - , "Tags are separated by \\n. (existing tags will be ignored.)" - ) - , ae_tagInput = Dand.wrap( "textarea", null, "v_snippet_input" ) - ]) - , "OK", "Cancel" - , parseTags.bind( ae_tagInput ) - ).show(); - }; - - var deleteTag = function (e) - { - var p = { tag: this.nodeValue, stage: this.parentNode }; - postData( tagCountUri, p, confirmDelete.bind( p ), serverFailed ); - e.stopPropagation(); - }; - - var confirmDelete = function (obj) - { - new MessageBox( - "Delete Tag" - , [ - Dand.wrapc("ae_blockswitch", - [ - Dand.textNode( "Are you sure you want to delete " ) - , Dand.wrap( "span", null, "tag_active", Dand.textNode( this.tag ) ) - , Dand.textNode( " ?." ) - ] - ) - , obj.count > 0 - ? Dand.wrape([ - Dand.textNode( "This will affect " ) - , Dand.wrap( - "span", null, "ae_affected_count", Dand.textNode( obj.count ) - ) - , Dand.textNode(" article(s).") - ]) - : null - ] - , "Delete", "No" - , doDelete.bind(this) - ).show(); - }; - - var doDelete = function( confirmed ) - { - if ( confirmed ) - { - postData( - a_conf.paths.set_tag - , { tag: this.tag, del: 1 } - , deleteSuccess.bind( this ) - , serverFailed - ); - } - }; - - var deleteSuccess = function(obj) - { - // Remove element - this.stage.parentNode.removeChild(this.stage); - // Delete reference - delete tags[this.tag]; - }; - - var parseTags = function () - { - // Filter invalid tags - var ntags = this.value.trim().match(/[^\n]+/g), d, e; - for (var i in ntags) - { - if(!tags[(i = ntags[i]).toLowerCase()]) - { - tags[i] = Dand.wrap("span", null, "tag_active", - [d = Dand.wrap("span", null, "ae_tag_delete", "\u00D7"), e = Dand.textNode(i)] - ); - // Seperator - ae_tags.appendChild(Dand.textNode(" ")); - ae_tags.appendChild(tags[i]); - - tags[i].onclick = function() { toggleTag(this) }.bind(tags[i]); - d.onclick = deleteTag.bind(e); - - } - else - { - debug.Info("Tag exist: " + i); - // Hightlight these tags - tags[i.toLowerCase()].className = "tag_active"; - } - } - - }; - - var toggleTag = function (tag) - { - var isEnabled = tag.className == "tag_active" ? true : false; - tag.className = isEnabled ? "ae_disabled" : "tag_active"; - }; - - var serverFailed = function (obj) { }; - - - - var ctag, ae_children = ae_tags.childNodes; - for (var i in ae_children) - { - if((ctag = ae_children[i]).nodeType == 1) - { - tags[ctag.lastChild.nodeValue.toLowerCase()] = ctag; - IDOMElement( ctag ).addEventListener( "Click", function() { toggleTag( this ); }.bind( ctag ) ); - // Bind the last child (x button) to firstChild (textNode: tagname) - IDOMElement( ctag.firstChild ).addEventListener( "Click", deleteTag.bind( ctag.lastChild ) ); - } - } - - this.getTags = function () - { - // Compile tag list - var tlist = []; - - // Return names - for (var i in tags) - { - if(tags[i].className == "tag_active") - tlist[tlist.length] = tags[i].lastChild.nodeValue; - } - - return tlist.join("\n"); - } - - this.setTags = function (tagList) - { - // Disable all tags first - for (var i in tags) tags[i].className = "ae_disabled"; - - // Set tags from tagList - for (i in tagList) - if (tagList[i]) tags[tagList[i].toLowerCase()].className = "tag_active"; - } - - ae_document.invoke(this); - } - - Tag.prototype.getTags = function () { }; - Tag.prototype.setTags = function (tagList) { }; - - ns[ NS_EXPORT ]( EX_CLASS, "Tag", Tag ); - -})(); diff --git a/botanjs/src/Astro/Blog/AstroEdit/_this.css b/botanjs/src/Astro/Blog/AstroEdit/_this.css index e312862..a948732 100644 --- a/botanjs/src/Astro/Blog/AstroEdit/_this.css +++ b/botanjs/src/Astro/Blog/AstroEdit/_this.css @@ -1,6 +1,8 @@ .ae_panel_section { padding: 0 1em; color: white; + height: 0; + overflow: hidden;; } .ae_section_prop { @@ -116,6 +118,10 @@ font-size: 2em; } +.ae_stitle:hover { + background-color: rgba( 0, 0, 0, 0.2 ); +} + .ae_stitle { font-size: 1.5em; } diff --git a/botanjs/src/Astro/Blog/AstroEdit/_this.js b/botanjs/src/Astro/Blog/AstroEdit/_this.js index 9e173e9..e013993 100644 --- a/botanjs/src/Astro/Blog/AstroEdit/_this.js +++ b/botanjs/src/Astro/Blog/AstroEdit/_this.js @@ -13,8 +13,8 @@ var Article = __import( "Astro.Blog.AstroEdit.Article" ); /** @type {Astro.Blog.AstroEdit.Draft} */ var Draft = __import( "Astro.Blog.AstroEdit.Draft" ); - /** @type {Astro.Blog.AstroEdit.Tag} */ - var Tag = __import( "Astro.Blog.AstroEdit.Tag" ); + /** @type {Astro.Blog.AstroEdit.Flag} */ + var Flag = __import( "Astro.Blog.AstroEdit.Flag" ); /** @type {Astro.Blog.AstroEdit.Visualizer} */ var Visualizer = __import( "Astro.Blog.AstroEdit.Visualizer" ); /** @type {Astro.Blog.AstroEdit.Uploader} */ @@ -44,11 +44,16 @@ } ); - article = new Article( a_conf.paths.set_article ); + article = new Article( + a_conf.paths.set_article + , [ + new Flag( "tags", "ae_tags", a_conf.paths.tags ) + , new Flag( "section", "ae_secs", a_conf.paths.sections ) + ] + ); // Article modules new Draft( article, a_conf.paths.get_drafts ); - new Tag( article, a_conf.paths.tag_count ); new Visualizer( article , Dand.id( "ae_visual_snippets" ) diff --git a/botanjs/src/externs/Astro.Blog.AstroEdit.IPlugin.js b/botanjs/src/externs/Astro.Blog.AstroEdit.IPlugin.js new file mode 100644 index 0000000..78a1000 --- /dev/null +++ b/botanjs/src/externs/Astro.Blog.AstroEdit.IPlugin.js @@ -0,0 +1,8 @@ +/** @constructor Plugin Interface */ +Astro.Blog.AstroEdit.IPlugin = function(){}; +/** @type {String} */ +Astro.Blog.AstroEdit.IPlugin.id; +/** @type {Function} */ +Astro.Blog.AstroEdit.IPlugin.setFromData; +/** @type {Function} */ +Astro.Blog.AstroEdit.IPlugin.getSetData; diff --git a/botanjs/src/externs/Astro.Blog.AstroEdit.Tag.js b/botanjs/src/externs/Astro.Blog.AstroEdit.Tag.js deleted file mode 100644 index a3c6b92..0000000 --- a/botanjs/src/externs/Astro.Blog.AstroEdit.Tag.js +++ /dev/null @@ -1,6 +0,0 @@ -/** @constructor */ -Astro.Blog.AstroEdit.Tag = function(){}; -/** @type {Function} */ -Astro.Blog.AstroEdit.Tag.getTags; -/** @type {Function} */ -Astro.Blog.AstroEdit.Tag.setTags; diff --git a/botanjs/src/externs/_AstConf_.AstroEdit.js b/botanjs/src/externs/_AstConf_.AstroEdit.js index 0ef0cc9..ac4fddb 100644 --- a/botanjs/src/externs/_AstConf_.AstroEdit.js +++ b/botanjs/src/externs/_AstConf_.AstroEdit.js @@ -14,7 +14,15 @@ _AstConf_.AstroEdit.paths = {}; _AstConf_.AstroEdit.paths.get_files; /** @type {string} */ _AstConf_.AstroEdit.paths.set_file; - /** @type {string} */ - _AstConf_.AstroEdit.paths.tag_count; - /** @type {string} */ - _AstConf_.AstroEdit.paths.set_tag; + + /** @type {object} */ + _AstConf_.AstroEdit.tags; + /** @type {object} */ + _AstConf_.AstroEdit.sections; + +/** @type {object} */ +_AstConf_.AstroEdit.flags = {}; +/** @type {string} */ +_AstConf_.AstroEdit.flags.URICount; +/** @type {string} */ +_AstConf_.AstroEdit.flags.URISet; diff --git a/botanjs/src/externs/_AstJson_.AJaxGetArticle.js b/botanjs/src/externs/_AstJson_.AJaxGetArticle.js index 71eebd7..9a528da 100644 --- a/botanjs/src/externs/_AstJson_.AJaxGetArticle.js +++ b/botanjs/src/externs/_AstJson_.AJaxGetArticle.js @@ -27,6 +27,8 @@ _AstJson_.AJaxGetArticle.entry; _AstJson_.AJaxGetArticle.entry.date_published; /** @type {Array} */ _AstJson_.AJaxGetArticle.entry.tags; + /** @type {Array} */ + _AstJson_.AJaxGetArticle.entry.section; /** @type {String} */ _AstJson_.AJaxGetArticle.entry.text; /** @type {String} */