After some time I'm posting here my code, that's only stripped from
our application. I don't have time to make it functional without our
components.
Currently we are not using this RichText and we will probably never use.
Cheers
- Petr
/**
* Html area widget width toolbar.
*/
qx.Class.define("bfly.ui.RichText",
{
extend: qx.ui.container.Composite,
construct: function()
{
// [Super Class]
this.base(arguments);
// [UI]
this.setLayout(new qx.ui.layout.VBox());
this._tools = {};
this._syncing = false;
this._toolBar = new qx.ui.toolbar.ToolBar().set({show: "icon"});
this._htmlArea = new htmlarea.HtmlArea();
this._htmlArea.setPostprocess(this.self(arguments)._postprocess);
this._htmlArea.addListener("cursorContext", this._oncursorcontext, this);
this.add(this._toolBar);
this.add(this._htmlArea, {flex:1});
this.addTools(this.getTools());
},
members:
{
getToolBar: function()
{
return this._toolBar;
},
getHtmlArea: function()
{
return this._htmlArea;
},
getTools: function()
{
var area = this._htmlArea;
var tools =
[
{ name: "bold" , type: "checkbox" , res:
"editor/format-text-bold" , action: this._onbold
, context: this },
{ name: "italic" , type: "checkbox" , res:
"editor/format-text-italic" , action: this._onitalic
, context: this },
{ name: "underline" , type: "checkbox" , res:
"editor/format-text-underline" , action: this._onunderline
, context: this },
{ name: "strikethrough" , type: "checkbox" , res:
"editor/format-text-strikethrough" , action: this._onstrikethrough
, context: this },
{ name: "alignLeft" , type: "radiobutton", res:
"editor/format-justify-left" , action: area.setJustifyLeft
, context: area },
{ name: "alignCenter" , type: "radiobutton", res:
"editor/format-justify-center" , action: area.setJustifyCenter
, context: area },
{ name: "alignRight" , type: "radiobutton", res:
"editor/format-justify-right" , action: area.setJustifyRight
, context: area },
{ name: "alignJustify" , type: "radiobutton", res:
"editor/format-justify-fill" , action: area.setJustifyFull
, context: area },
//{ name: "fontsize", res:
"editor/format-font-size" , action: this._onFontSize
, context: this },
//{ name: "fontcolor", res:
"editor/format-text-color" , action: this._onFontColor
, context: this },
//{ name: "textBackgroundColor", res:
"editor/format-text-bg" , action:
this._onTextBackgroundColor , context: this },
{ name: "insertImage" , type: "button" , res:
"editor/insert-image" , action: this._onInsertImage
, context: this },
//{ name: "insertTable", res: "editor/insert-table"
, action: this._onInsertTable , context: this },
//{ name: "ol", res: "editor/list-ordered"
, action: area.insertOrderedList , context: area },
//{ name: "ul", res:
"editor/list-unordered" , action: area.insertUnorderedList
, context: area },
//{ name: "undo", res: "actions/go-previous"
, action: area.undo , context: area },
//{ name: "redo", res: "actions/go-next"
, action: area.redo , context: area },
//{ name: "removeFormat", res: "editor/format-clear"
, action: area.removeFormat , context: area }
{ name: "test" , type: "button" , res:
"actions/wheel" , action: this._onTest
, context: area },
{ name: "spacer" , type: "spacer"
},
{ name: "html" , type: "checkbox" , res:
"actions/wheel" , action: this._onhtml
, context: area }
];
return tools;
},
// [Put together toolbar entries]
addTools: function(tools)
{
for (var i = 0, len = tools.length; i < len; i++) this.addTool(tools[i]);
},
addTool: function(tool)
{
var widget;
var layout = {};
switch (tool.type)
{
case "button":
widget = new qx.ui.toolbar.Button(null,
bfly.ui.Resources.getIcon(tool.res, "toolbar"));
widget.set({ focusable : false, keepFocus : true });
widget.addListener("execute", tool.action, tool.context || this);
break;
case "checkbox":
widget = new qx.ui.toolbar.CheckBox(null,
bfly.ui.Resources.getIcon(tool.res, "toolbar"));
widget.set({ focusable : false, keepFocus : true });
widget.addListener("changeChecked", tool.action,
tool.context || this);
break;
case "radiobutton":
widget = new qx.ui.toolbar.CheckBox(null,
bfly.ui.Resources.getIcon(tool.res, "toolbar"));
widget.set({ focusable : false, keepFocus : true });
widget.addListener("changeChecked", tool.action,
tool.context || this);
break;
case "spacer":
widget = new qx.ui.core.Spacer();
layout.flex = 1;
break;
default:
throw new Error("Unknown tool type: " + tool.type);
}
this._tools[tool.name] = widget;
this._toolBar.add(widget, layout);
},
// ------------------------------------------------------------------------
// [Event Handlers]
// ------------------------------------------------------------------------
_oncursorcontext: function(e)
{
var val = e.getData();
var old = e.getOldData();
var tools = this._tools;
this._syncing = true;
if (tools.bold) tools.bold.setChecked(!!val.bold);
if (tools.italic) tools.italic.setChecked(!!val.italic);
if (tools.underline) tools.underline.setChecked(!!val.underline);
if (tools.strikethrough)
tools.strikethrough.setChecked(!!val.strikethrough);
this._syncing = false;
},
_onbold: function(e)
{
if (!this._syncing) this._htmlArea.setBold();
},
_onitalic: function(e)
{
if (!this._syncing) this._htmlArea.setItalic();
},
_onunderline: function(e)
{
if (!this._syncing) this._htmlArea.setUnderline();
},
_onstrikethrough: function(e)
{
if (!this._syncing) this._htmlArea.setStrikeThrough();
},
_onhtml: function(e)
{
},
// [Special handler for Toolbar entries]
_onFontSize: function(e)
{
var result = window.prompt("FontSize: ", "");
this.getHtmlArea().setFontSize(parseInt(result));
},
_onFontColor: function(e)
{
var result = window.prompt("Color (Hex): ", "#");
this.getHtmlArea().setTextColor(result);
},
_onTextBackgroundColor: function(e)
{
var result = window.prompt("BgColor (Hex): ", "#");
this.getHtmlArea().setTextBackgroundColor(result);
},
_onInsertImage: function(e)
{
var win = new bfly.admin.tools.FileBrowserWindow().set({
width: 800,
modal: true
});
win.getFileBrowser().setAddress("/res/");
win.getFileBrowser().addListener("confirm", function(e)
{
var attributes = {
src : e.getData(),
border : 0,
title : "image",
alt : "image"
};
this.getHtmlArea().insertImage(attributes);
win.close();
}, this);
win.addListener("close", function()
{
win.close();
win.destroy();
}, this);
app.getRoot().add(win);
win.center();
win.show();
},
_onInsertTable: function(e)
{
var table =
"<table border='1'>" +
"<tbody>" +
"<tr>" +
"<td>First Row, First cell</td>" +
"<td>First Row, Second cell</td>" +
"</tr>" +
"<tr>" +
"<td>Second Row, First cell</td>" +
"<td>Second Row, Second cell</td>" +
"</tr>" +
"</tbody>" +
"</table>";
this.getHtmlArea().insertHtml(table);
},
_onTest: function(e)
{
alert(this.getHtml());
}
},
statics:
{
_postprocess: function(i)
{
if (i.tag === "span")
{
// Create <b> from <span style="font-weight: bold;">
if (i.styles["font-weight"] === "bold")
{
i.tag = "b"; delete i.styles["font-weight"];
}
// Create <i> from <span style="font-style: italic;">
else if (i.styles["font-style"] === "italic")
{
i.tag = "i"; delete i.styles["font-style"];
}
// Create <u> from <span style="font-style: italic;">
else if (i.styles["text-decoration"] === "underline")
{
i.tag = "u"; delete i.styles["text-decoration"];
}
// Create <s> from <span style="text-decoration: line-through;">
else if (i.styles["text-decoration"] === "line-through")
{
i.tag = "strike"; delete i.styles["text-decoration"];
}
}
// Remove empty tag <span></span>, but this also removes
generated <b></b>, ...
//
// NOTE: There are checks if element contains attributes and
styles, so it will
// be removed ONLY if it's really empty "<span></span>" if span
has for example
// id or class, it will be not removed.
//
// This can be called as "non-destructive" removing
if (qx.lang.Object.isEmpty(i.attributes) &&
qx.lang.Object.isEmpty(i.styles) && !i.domElement.hasChildNodes())
{
i.tag = "";
}
}
}
});
2008/10/11 Petr Kobalíček <[EMAIL PROTECTED]>:
> Hi John,
>
> Thanks for you sample, I'm trying to split my implementation but some
> things are very dependent to our file browser. I hope that tonight it
> will be ready, but without file browser.
>
> You implementation is good:)
>
> Cheers
> - Petr
>
> 2008/10/10 John Spackman <[EMAIL PROTECTED]>:
>> Hi guys,
>>
>> I've uploaded my sample and the code to
>> http://www.zenesis.com/qx/dev/myapp/source/ - there's a readme at
>> http://www.zenesis.com/qx/dev/README.txt and if you want to take a look at
>> the code it's http://www.zenesis.com/qx/dev.zip.
>>
>> John
>>
>> -----Original Message-----
>> From: John Spackman [mailto:[EMAIL PROTECTED]
>> Sent: 09 October 2008 12:32
>> To: 'qooxdoo Development'
>> Subject: Re: [qooxdoo-devel] HtmlArea for 0.8 still not usable
>>
>> Hi Petr,
>>
>> I'm very happy to collaborate on this - although I suspect I'll be more a
>> user of HtmlArea itself than a major contributor to it. I think that there
>> is a reasonable amount of work to add rich controls to the editor and make
>> it a very accessible and easy to use component, especially for the smarter
>> features like image pickers and other dialogs etc so it would be great to
>> work together on this. Is it possible for you to put your RichEditor on the
>> web somewhere? I need to finish some things off today but upload it later
>> on for you to look at.
>>
>> Regards,
>> John
>>
>> -----Original Message-----
>> From: Petr Kobalíček [mailto:[EMAIL PROTECTED]
>> Sent: 09 October 2008 11:57
>> To: qooxdoo Development
>> Subject: Re: [qooxdoo-devel] HtmlArea for 0.8 still not usable
>>
>> Hi Guys,
>>
>> I'm happy for too much comments here :-)
>>
>> First
>>
>> a) about [HTMLSpanElement] bug:
>>
>> I'm corrected it, but unfortunally there is something wrong with my
>> code (see latest commit), because it not behaves good (I don't know
>> how to document it, there are growing number if <p> tags and I don't
>> know).
>>
>> b) about anything else :)
>>
>> I have sometimes time to contribute to HtmlArea, I have read early all
>> code, but I have sometimes problems to understand it at all (it's not
>> badly written, but there seems be too much bugs in browsers and Html
>> editing is COMPLEX to implement).
>>
>> Problem for me is that the "firefox focus bug" is still there, try this
>> code:
>>
>> qx.Class.define("bfly.admin.Application",
>> {
>> extend : qx.application.Standalone,
>>
>> members :
>> {
>> // [Entry point]
>> main: function()
>> {
>> // [SuperClass]
>> this.base(arguments);
>>
>> // [Main Container]
>> this._container = new qx.ui.container.Composite(
>> new qx.ui.layout.VBox().set({
>> spacing: 1
>> })
>> );
>> this.getRoot().add(this._container, {edge:0});
>>
>> // [MenuBar]
>> this._tabView = new qx.ui.tabview.TabView();
>> this._container.add(this._tabView, {flex: 1});
>>
>> for (var i = 0; i < 3; i++)
>> {
>> var page = new qx.ui.tabview.Page("Page " + i);
>> var area = new htmlarea.HtmlArea();
>>
>> page.setLayout(new qx.ui.layout.Canvas);
>> page.add(area, {edge: 0});
>>
>> this._tabView.add(page);
>> }
>> }
>> }
>> });
>>
>> When you use TABs, you can't focus to previously hidden HtmlAreas in
>> Firefox.
>>
>> c) And for John,
>>
>> John, I'm doing something very similar to your work. I called it
>> RichEditor and it's HtmlArea with toolbars with some customizing way.
>> My code depends to our system, but I try to make it generic. We can
>> colaborate on this if you want.
>>
>> Cheers
>> - Petr
>>
>> 2008/10/9 Fabian Jakobs <[EMAIL PROTECTED]>:
>>> Andreas Ecker schrieb:
>>>> Hi John!
>>>>
>>>>
>>>>> I realise Alexander is on holiday right now so I'm leaving this as a
>> note
>>>>> for when he returns as much as anything.
>>>>>
>>>>> I'd like to add my vote to this - a rich text editor is important and
>> we've
>>>>> abandoned the FCKeditor integration because it's too slow.
>>>>>
>>>>
>>>> Would be great we could collaborate on improving HtmlArea. Such a widget
>>>> requires quite some community effort to iron out immanent cross-browser
>>>> issues.
>>>>
>>>>
>>>>> I've nearly finished a wrapper around HtmlArea which adds toolbars for
>>>>> styling, formatting, images, links, etc in one Widget; I'd like to
>>>>> contribute it as part of the HtmlArea package but obviously don't want
>> to go
>>>>> steaming in until Alexander is back. I'll post it here if anyone wants
>> to
>>>>> take a look in the mean time.
>>>>>
>>>>
>>>> Yes, that could become a fine contribution to qooxdoo-contrib for people
>>>> interested in an out-of-the-box solution for an HTML editor. Actually,
>>>> we never wanted to package up such a combined solution (other than the
>>>> sample included with HtmlArea), as one would need to support so many
>>>> variants that it easily becomes (again) a heavy-weight configuration
>>>> thingy. Attaching toolbars and other elements to HtmlArea should be
>>>> fairly easy in qooxdoo to satisfy individual requirements. But if you
>>>> think you've come up with a solution that could be widely used, that's
>>>> great.
>>>>
>>>> Anyway, as I suggested it should rather be a separate contribution
>>>> (maybe called "HtmlEditor") next to the existing HtmlArea. The area
>>>> itself should stay a plain html editing widget without custom chrome
>>>> (toolbars, etc.). Well, we'll figure out the details, also when Alex is
>>>> back.
>>>>
>>> I absolutely agree that the core HtmlArea widget should only focus on
>>> plain Html editing but why not include it into the current HtmlArea as
>>> an example application. It is not required to have just one example
>>> application in a contrib project. This way example editor is always in
>>> sync with the editing component and serves as a good example.
>>>> What do you think? In the meantime you could have a look at
>>>> http://contrib.qooxdoo.org for the contribution details and then email
>>>> me directly to answer all your questions and getting you started,
>>>>
>>>>
>>> Best Fabian
>>>
>>>
>>> --
>>> Fabian Jakobs
>>> JavaScript Framework Developer
>>>
>>> 1&1 Internet AG
>>> Brauerstraße 48
>>> 76135 Karlsruhe
>>>
>>> Amtsgericht Montabaur HRB 6484
>>>
>>> Vorstand: Henning Ahlert, Ralph Dommermuth, Matthias Ehrlich, Thomas
>> Gottschlich, Matthias Greve, Robert Hoffmann, Markus Huhn, Oliver Mauss,
>> Achim Weiss
>>> Aufsichtsratsvorsitzender: Michael Scheeren
>>>
>>>
>>> -------------------------------------------------------------------------
>>> This SF.Net email is sponsored by the Moblin Your Move Developer's
>> challenge
>>> Build the coolest Linux based applications with Moblin SDK & win great
>> prizes
>>> Grand prize is a trip for two to an Open Source event anywhere in the
>> world
>>> http://moblin-contest.org/redirect.php?banner_id=100&url=/
>>> _______________________________________________
>>> qooxdoo-devel mailing list
>>> [email protected]
>>> https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel
>>>
>>
>> -------------------------------------------------------------------------
>> This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
>> Build the coolest Linux based applications with Moblin SDK & win great
>> prizes
>> Grand prize is a trip for two to an Open Source event anywhere in the world
>> http://moblin-contest.org/redirect.php?banner_id=100&url=/
>> _______________________________________________
>> qooxdoo-devel mailing list
>> [email protected]
>> https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel
>>
>>
>>
>>
>> -------------------------------------------------------------------------
>> This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
>> Build the coolest Linux based applications with Moblin SDK & win great
>> prizes
>> Grand prize is a trip for two to an Open Source event anywhere in the world
>> http://moblin-contest.org/redirect.php?banner_id=100&url=/
>> _______________________________________________
>> qooxdoo-devel mailing list
>> [email protected]
>> https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel
>>
>>
>>
>>
>> -------------------------------------------------------------------------
>> This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
>> Build the coolest Linux based applications with Moblin SDK & win great prizes
>> Grand prize is a trip for two to an Open Source event anywhere in the world
>> http://moblin-contest.org/redirect.php?banner_id=100&url=/
>> _______________________________________________
>> qooxdoo-devel mailing list
>> [email protected]
>> https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel
>>
>
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
qooxdoo-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel