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

Reply via email to