Opened 17 years ago
Closed 16 years ago
#1410 closed New Feature (fixed)
Category Management within FCKeditor
Reported by: | David Barker | Owned by: | Deimon |
---|---|---|---|
Priority: | Normal | Milestone: | |
Component: | Project : MediaWiki+FCKeditor | Version: | |
Keywords: | Confirmed HasPatch | Cc: |
Description
I like fckeditor for Mediawiki a lot. What I would find useful (and so might others) is some sort of Category Manager. By this I simply mean the ability to assign/create a category for the current document from the menu. It would access the database and create a dropdown (or pop-up, doesn't matter which) which would allow the user to select (or create new) a category for the current document.
Thanks for the amazing hard work that went into the creation of fckeditor. I was afraid I was going to have to create something like it myself, and that would be way beyond me.
David Barker
Attachments (1)
Change History (13)
comment:1 Changed 17 years ago by
comment:2 Changed 17 years ago by
I admit that having a checkbox like "search in categories" would be more user friendly.
comment:3 Changed 17 years ago by
Keywords: | Confirmed added |
---|
comment:4 Changed 16 years ago by
The linking functionality works, but I find it confusing, even as someone who develops MediaWiki extensions.
I think the main problem is that there is no way to distinguish a 'normal' link from a categorization link.
A secondary problem is that there is simply a 'floating' category link at the bottom of the page. Most new users would probably assume the link was not supposed to be there, and simply delete it.
I propose the following solution:
- Add a 'category' placeholder icon, like the placeholders used for templates and special tags. Use this to represent categories in the editor, rather than simply showing a link. Category links have very different behavior from standard links, and their representation should convey this.
- The link tool will ALWAYS insert the leading ':' for categories and images. This ensures that a link always creates a link, and eliminates the need to educate users to use a colon.
- Add a 'Add to category' button, which inserts the [[Category:Foo]] Wiki text. This will be represented in the editor by the category placeholder.
I might be willing to take a stab at implementing this... but does it seem like a valuable feature to have?
comment:5 Changed 16 years ago by
Owner: | set to Deimon |
---|---|
Status: | new → assigned |
I have created such functionality.
Add this functions in extensions\FCKeditor\FCKeditorSajax.body.php
function wfSajaxSearchCategoryFCKeditor() { global $wgContLang, $wgOut; $ns = NS_CATEGORY; $m_sql="SELECT tmpSelectCat1.cl_to AS title FROM wiki_categorylinks AS tmpSelectCat1 LEFT JOIN wiki_page AS tmpSelectCatPage ON ( tmpSelectCat1.cl_to = tmpSelectCatPage.page_title AND tmpSelectCatPage.page_namespace =14 ) LEFT JOIN wiki_categorylinks AS tmpSelectCat2 ON tmpSelectCatPage.page_id = tmpSelectCat2.cl_from WHERE tmpSelectCat2.cl_from IS NULL GROUP BY tmpSelectCat1.cl_to"; $db =& wfGetDB( DB_SLAVE ); $res = $db->query($m_sql,__METHOD__ ); $ret = ""; $i=0; while ( ( $row = $db->fetchObject( $res ) ) ) { $ret .= $row->title ."\n"; //$ret.=wfSajaxSearchCategoryChildrenFCKeditor($row->title); $sub = explode("\n",wfSajaxSearchCategoryChildrenFCKeditor($row->title)); foreach($sub as $subrow)if(strlen($subrow)>0)$ret.=" ".$subrow."\n"; } return $ret; } function wfSajaxSearchCategoryChildrenFCKeditor($m_root) { global $wgContLang, $wgOut; $limit = 50; $ns = NS_CATEGORY; $m_root = str_replace("'","\'",$m_root); $m_sql = " SELECT tmpSelectCatPage.page_title AS title FROM wiki_categorylinks AS tmpSelectCat LEFT JOIN wiki_page AS tmpSelectCatPage ON tmpSelectCat.cl_from = tmpSelectCatPage.page_id WHERE tmpSelectCat.cl_to LIKE '$m_root' AND tmpSelectCatPage.page_namespace = 14"; $db =& wfGetDB( DB_SLAVE ); $res = $db->query($m_sql,__METHOD__ ); $ret = ""; $i=0; while ( ( $row = $db->fetchObject( $res ) ) ) { $ret .= $row->title ."\n"; //$ret.=wfSajaxSearchCategoryChildrenFCKeditor($row->title); $sub = explode("\n",wfSajaxSearchCategoryChildrenFCKeditor($row->title)); foreach($sub as $subrow)if(strlen($subrow)>0)$ret.=" ".$subrow."\n"; } return $ret; }
Add this in file extensions\FCKeditor\FCKeditor.php
$wgAjaxExportList[] = 'wfSajaxSearchCategoryFCKeditor';
Create file extensions\FCKeditor\plugins\mediawiki\dialogs\category.html as this
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <!-- * Link dialog window. --> <html> <head> <title>Link Properties</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="robots" content="noindex, nofollow" /> <script type="text/javascript"> var oEditor = window.parent.InnerDialogLoaded() ; var FCK = oEditor.FCK ; var FCKLang = oEditor.FCKLang ; var FCKConfig = oEditor.FCKConfig ; var FCKRegexLib = oEditor.FCKRegexLib ; var FCKTools = oEditor.FCKTools ; var FCKBrowserInfo = oEditor.FCKBrowserInfo ; var EditorDocument = oEditor.FCK.EditorDocument ; document.write( '<script src="' + FCKConfig.BasePath + 'dialog/common/fck_dialog_common.js" type="text/javascript"><\/script>' ) ; </script> <script type="text/javascript"> // oLink: The actual selected link in the editor. window.onload = function() { // Translate the dialog box texts. oEditor.FCKLanguageManager.TranslatePage(document) ; // Load the selected link information (if any). InitSelected() ; SetSearchMessage( 'loading categories...' ) ; oEditor.window.parent.sajax_request_type = 'GET' ; oEditor.window.parent.sajax_do_call( 'wfSajaxSearchCategoryFCKeditor', [], InitCategoryTree ) ; // Activate the "OK" button. window.parent.SetOkButton( true ) ; window.parent.SetAutoSize( true ) ; } var selectedCats; function InitSelected() { selectedCats=new Array(); var node=EditorDocument; while(node){ if(node.nodeType==1 && node.tagName.toLowerCase() == 'a'){ // Get the actual Link href. var sHRef = node.getAttribute( '_fcksavedurl' ) ; if ( sHRef == null )sHRef = node.getAttribute( 'href' , 2 ) || '' ; if(sHRef.StartsWith('Category:')){ var select = GetE('xCategories' ) ; var cat=sHRef.slice(9); SelectCategory(cat,-1); } } node=FCKTools.GetNextNode(node,EditorDocument); } // Make an Ajax search for the pages. } function SelectCategory(cat,catTreeRow) { var row=parseInt(catTreeRow); if(row>=0){ var select = GetE('xWikiResults' ); cat=select.options[row].text; var lvl=0; while(cat.charAt(lvl)==placeholder)lvl++; cat=cat.slice(lvl); if(cat.charAt(0)=='[' && cat.charAt(cat.length-1)==']')cat=cat.substring(1,cat.length-1); } if(selectedCats[cat])delete selectedCats[cat]; else selectedCats[cat]=cat; var select = GetE( 'xCategories' ) ; while (select.options.length > 0 )select.remove( 0 ); for(var cat in selectedCats) FCKTools.AddSelectOption( select, cat, cat) ; } var catTree; function InitCategoryTree( result ) { SetSearchMessage( '' ) ; catTree=new Object(); var levelsHead=new Array('root'); var levelsBody=new Array(''); var results = result.responseText.Trim().split( '\n' ) ; var previousLvl=-1; for ( var i = 0 ; i < results.length ; i++ ){ var lvl=0; while(results[i].charAt(lvl)==' ')lvl++; var t=results[i].slice(lvl); for(var j=previousLvl;j>lvl-1;j--){ if(levelsBody[j+1]!='')catTree[levelsHead[j+1]]=levelsBody[j+1]; delete levelsHead[j+1]; delete levelsBody[j+1]; } if(lvl>previousLvl)levelsBody[lvl]=t; else levelsBody[lvl]=levelsBody[lvl]+' '+t; levelsHead[lvl+1]=t; levelsBody[lvl+1]=''; previousLvl=lvl; } for(var j=previousLvl;j>=-1;j--){ if(levelsBody[j+1]!='')catTree[levelsHead[j+1]]=levelsBody[j+1]; delete levelsHead[j+1]; delete levelsBody[j+1]; } ShowCategoriesSubTree(-1); } var placeholder='.'; //draw category subtree function ShowCategoriesSubTree(rowInTree){ var row=parseInt(rowInTree); var select = GetE('xWikiResults' ) ; var root='root'; var lvl=-1; var prefix=''; if(row>=0){ root=select.options[row].text; lvl=0; while(root.charAt(lvl)==placeholder)lvl++; root=root.slice(lvl); if(root.charAt(0)=='[' && root.charAt(root.length-1)==']') root=root.substring(1,root.length-1); prefix=new Array(lvl+1+3).join(placeholder); } if(!catTree[root])return; var itCount=select.options.length; var itSkip=row+1; var opts=new Array(); for(var i=row+1;i<itCount;i++){ var t=select.options[i].text; var sublvl=0; while(t.charAt(sublvl)==placeholder)sublvl++; if(sublvl>lvl)itSkip=i+1; else break; } for(var i=itCount-1;i>row;i--){ var t=select.options[i].text; //if(t==fullroot)break; if(i>=itSkip)opts.push(t); select.remove(i); } //while ( select.options.length > 0 ) // select.remove( 0 ) if(itSkip==row+1){ var cats = catTree[root].split(' ') ; for(var k in cats){ var p=cats[k]; if(catTree[cats[k]])p='['+p+']'; var e=FCKTools.AddSelectOption( select, prefix+p, ++row) ; if(catTree[cats[k]])e.style.color='#00f'; } } for(var i=opts.length-1;i>=0;i--){ var e=FCKTools.AddSelectOption( select, opts[i], ++row) ; if(opts[i].indexOf('[')>=0)e.style.color='#00f'; } } //draw filtered function ShowFilteredCategories(filter){ var select = GetE('xWikiResults' ) ; while (select.options.length > 0 )select.remove( 0 ); //alert(filter); var found=new Object(); if(filter.length==0){ ShowCategoriesSubTree(-1); return; } filter=filter.toLowerCase(); var row=-1; for(var folder in catTree){ var cats = catTree[folder].split(' ') ; for(var k in cats){ var p=cats[k].toLowerCase(); if(p.indexOf(filter)>=0){ if(found[cats[k]]); else{ found[cats[k]]=cats[k]; FCKTools.AddSelectOption( select, cats[k], ++row ) ; } } } } } function AddNew(){ var select = GetE('txtUrl' ); SelectCategory(select.value,-1) } //#### The OK button was hit. function Ok() { var nodes=new Array(); var node=EditorDocument; var nodeNext; var s=''; var i=0; while(node){ nodeNext=FCKTools.GetNextNode(node,EditorDocument); if(node.nodeType==1 && node.tagName.toLowerCase() == 'a'){ // Get the actual Link href. var sHRef = node.getAttribute( '_fcksavedurl' ) ; if ( sHRef == null )sHRef = node.getAttribute( 'href' , 2 ) || '' ; if(sHRef.StartsWith('Category:'))nodes[i++]=node; } node=nodeNext; } for(var i=0;i<nodes.length;i++)nodes[i].parentNode.removeChild(nodes[i]); for(var cat in selectedCats)AddCategoryLink(cat); return true; } function AddCategoryLink(cat){ var sUri = 'Category:'+cat; var sInnerHtml ; // If no link is selected, create a new one (it may result in more than one link creation - #220). var aLinks = oEditor.FCK.CreateLink( sUri ) ; // If no selection, no links are created, so use the uri as the link text (by dom, 2006-05-26) var aHasSelection = ( aLinks.length > 0 ) ; if ( !aHasSelection ) { sInnerHtml = sUri; var oLinkPathRegEx = new RegExp("//?([^?\"']+)([?].*)?$") ; var asLinkPath = oLinkPathRegEx.exec( sUri ) ; if (asLinkPath != null) sInnerHtml = asLinkPath[1]; // use matched path // Create a new (empty) anchor. aLinks = [ oEditor.FCK.InsertElement( 'a' ) ] ; } oEditor.FCKUndo.SaveUndoStep() ; for ( var i = 0 ; i < aLinks.length ; i++ ) { oLink = aLinks[i] ; if ( aHasSelection ) sInnerHtml = oLink.innerHTML ; // Save the innerHTML (IE changes it if it is like an URL). oLink.href = sUri ; SetAttribute( oLink, '_fcksavedurl', sUri ) ; oLink.innerHTML = sInnerHtml ; // Set (or restore) the innerHTML } // Select the (first) link. //oEditor.FCKSelection.SelectNode( aLinks[0] ); return true ; } ////////////////////// var searchTimer ; //#### Called while the user types the URL. function OnUrlChange() { var link =GetE('txtUrl').value.Trim(); ShowFilteredCategories(link); return; if ( searchTimer ) window.clearTimeout( searchTimer ) ; if ( link.StartsWith( '#' ) ) { SetSearchMessage( 'anchor link... no search for it' ) ; return ; } if ( link.StartsWith( 'mailto:' ) ) { SetSearchMessage( 'e-mail link... no search for it' ) ; return ; } if( /^\w+:\/\//.test( link ) ) { SetSearchMessage( 'external link... no search for it' ) ; return ; } /*if ( link.length < 3 ) { ClearSearch() ; if ( link.length == 0 ) SetSearchMessage( 'start typing in the above field' ) ; else SetSearchMessage( 'too short... type more' ) ; return ; } */ SetSearchMessage( 'stop typing to search' ) ; //searchTimer = window.setTimeout( StartSearch, 500 ) ; } function SetSearchMessage( message ) { GetE('xWikiSearchStatus').innerHTML = message ; } </script> </head> <body scroll="no" style="overflow: hidden"> <div id="divInfo"> <div id="divLinkTypeUrl"> <span>Selected categories</span><br /> <select id="xCategories" size="10" style="width: 100%; height:70px" ondblclick="SelectCategory( this.value,-1);"> </select><br /> Search category<br /> <input id="txtUrl" style="width: 80%" type="text" onkeyup="OnUrlChange();" /> <input id="btnNew" style="width: 18%" type="button" onclick="AddNew();" value="Add new"/> <br /> Category tree (<span id="xWikiSearchStatus">start typing in the above field</span>)<br /> <select id="xWikiResults" size="10" style="width: 100%; height:300px" onclick="ShowCategoriesSubTree( this.value );" ondblclick="SelectCategory('', this.value );"> </select> </div> </div> </body> </html>
Also you need to enable this new command. One way to do it is to add
tbButton = new FCKToolbarButton( 'Category', 'Categories', 'Insert/Edit categories' ) ; tbButton.IconPath = FCKConfig.PluginsPath + 'mediawiki/images/tb_icon_category.gif' ; FCKToolbarItems.RegisterItem( 'Category', tbButton ) ;
after
tbButton = new FCKToolbarButton( 'MW_Special', 'Special Tag', 'Insert/Edit Special Tag' ) ; tbButton.IconPath = FCKConfig.PluginsPath + 'mediawiki/images/tb_icon_special.gif' ; FCKToolbarItems.RegisterItem( 'MW_Special', tbButton ) ;
and add
FCKCommands.RegisterCommand( 'Category', new FCKDialogCommand( 'Category', 'Категории', FCKConfig.PluginsPath + 'mediawiki/dialogs/category.html', 400, 500 ) ) ;
after
FCKCommands.RegisterCommand( 'Link', new FCKDialogCommand( 'Link', FCKLang.DlgLnkWindowTitle, FCKConfig.PluginsPath + 'mediawiki/dialogs/link.html', 400, 250 ) ) ;
in extensions\FCKeditor\plugins\mediawiki\fckplugin.js
Also you need to create tb_icon_special.gif.
I'm new here. It's my first patch. Please correct the code above if it is not fit to coding standarts.
comment:8 Changed 16 years ago by
Summary: | Category Management within FCKeditor → f not |
---|
If you have SVN installed - you can use http://mediawiki.fckeditor.net/index.php/SVN_Instructions
If not - just provide version of the original files, I will make the patch.
comment:9 Changed 16 years ago by
Summary: | f not → Category Management within FCKeditor |
---|
Sorry. I changed summary by accident.
Changed 16 years ago by
Attachment: | 1410.patch added |
---|
comment:10 Changed 16 years ago by
Ok, here is the patch. I've changed some code to be more standart (like tableName() etc).
comment:12 Changed 16 years ago by
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
Thanks! Fixed with [3191].
This is already partly available: create a link with the link button, and type "Category:" + a part of the category name, you will get a list of available ones.