#1410: Category Management within FCKeditor
-------------------------------------------+--------------------------------
Reporter: davidwilliambarker | Owner: Deimon
Type: New Feature | Status: assigned
Priority: Normal | Milestone:
Component: Project : MediaWiki+FCKeditor | Version:
Keywords: Confirmed |
-------------------------------------------+--------------------------------
Changes (by Deimon):
* owner: => Deimon
* status: new => assigned
Comment:
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.
--
Ticket URL: <http://dev.fckeditor.net/ticket/1410#comment:5>
FCKeditor <http://www.fckeditor.net/>
The text editor for Internet
------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
FCKeditor-Trac mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/fckeditor-trac