Discussion:
[Wt-interest] [Wt Interest] Using CodeMirror with Wt
Neil D'Souza
2012-08-31 14:35:02 UTC
Permalink
Dear All,

    I am trying to use CodeMirror [http://codemirror.net] with Wt. Specifically I am trying to modify the :
examples/feature/widgetset/hello.C to do this.

While I am successful in seeing the editor on screen and binding to a Wt Widget I get the following error on the screen, after which the hello application continues to run, if I press the button. However, the "Loading" notification does not go away.


Wt internal error: TypeError: j10 is undefined, code: undefined, description: undefined

Pasted below this is the code, the html file and the output.

In the output sections which I feel are relevant,

I have enclosed in "************".

The version of codemirror I am using is 2.13 and unmodified.

I am able to successfully load the javascript files as it does

syntax highlighting for the javascript entered in the text box.


You will notice that in the DOM, I have done this : 
==========================

      editor.id = "code_mirror_text_editor";
==========================

   immediately after creating the editor and in the c++ code I have

   bound the editor to a div element. This is because when inspecting

   through firefox, the editor seems to be rendered

   as a "div" with class = "CodeMirror",
   the original textarea is given a css class of "display: none;"
 

   Of course I could be wrong about the "div" and any advice you have

   on a better approach is highly appreciated.


   Many thanks for your help in advance.


Kind Regards,
Neil

=========================c++ code =================================



/*
 * Copyright (C) 2008 Emweb bvba, Kessel-Lo, Belgium.
 *
 * See the LICENSE file for terms of use.
 */

#include <Wt/WApplication>
#include <Wt/WBreak>
#include <Wt/WContainerWidget>
#include <Wt/WEnvironment>
#include <Wt/WLineEdit>
#include <Wt/WPushButton>
#include <Wt/WServer>
#include <Wt/WText>

class HelloApplication : public Wt::WApplication
{
public:
  HelloApplication(const Wt::WEnvironment& env, bool embedded);

private:
  Wt::WLineEdit *nameEdit_;
  Wt::WText *greeting_;

  void greet();
};

HelloApplication::HelloApplication(const Wt::WEnvironment& env, bool embedded)
  : WApplication(env)
{
      using namespace std;
  Wt::WContainerWidget *top;
  Wt::WContainerWidget * code_mirror_text_editor;
      

  setTitle("Hello world");

  if (!embedded) {
    /*
     * In Application mode, we have the root() is a container
     * corresponding to the entire browser window
     */
    top = root();
      cout << " I am not embedded" << endl;

  } else {
    /*
     * In WidgetSet mode, we create and bind containers to existing
     * divs in the web page. In this example, we create a single div
     * whose DOM id was passed as a request argument.
     */
      cout << " I am embedded" << endl;
    top = new Wt::WContainerWidget();
    const std::string *div = env.getParameter("div");
    if (div) {
      setJavaScriptClass(*div);
      bindWidget(top, *div);
      code_mirror_text_editor = new Wt::WContainerWidget(top);
      code_mirror_text_editor->setId("code_mirror_text_editor");
      bindWidget(code_mirror_text_editor, "code_mirror_text_editor");
      cout << "code_mirror_text_editor .id:"

           <<  code_mirror_text_editor->id() << endl;
    } else {
      std::cerr << "Missing: parameter: 'div'" << std::endl;
      return;
    }
  }

  if (!embedded)
    new Wt::WText
      ("<p><emph>Note: you can also run this application "
       "from within <a href=\"qscript-console.html\">a web page</a>.</emph></p>",
       root());

  /*
   * Everything else is business as usual.
   */

  top->addWidget(new Wt::WText("Your name, please ? "));
  nameEdit_ = new Wt::WLineEdit(top);
  nameEdit_->setFocus();

  Wt::WPushButton *b = new Wt::WPushButton("Greet me.", top);
  b->setMargin(5, Wt::Left);

  top->addWidget(new Wt::WBreak());

  greeting_ = new Wt::WText(top);

  /*
   * Connect signals with slots
   */
  b->clicked().connect(this, &HelloApplication::greet);
  nameEdit_->enterPressed().connect(this, &HelloApplication::greet);
}

void HelloApplication::greet()
{
  /*
   * Update the text, using text input into the nameEdit_ field.
   */
  greeting_->setText("Hello there, " + nameEdit_->text());
}

Wt::WApplication *createApplication(const Wt::WEnvironment& env)
{
  return new HelloApplication(env, false);
}

Wt::WApplication *createWidgetSet(const Wt::WEnvironment& env)
{
  return new HelloApplication(env, true);
}

int main(int argc, char **argv)
{
  Wt::WServer server(argv[0]);

  server.setServerConfiguration(argc, argv, WTHTTP_CONFIGURATION);

 
  server.addEntryPoint(Wt::Application, createApplication);

  // The following adds an entry point for a widget set. A widget set
  // must be loaded as a JavaScript from an HTML page.
  server.addEntryPoint(Wt::WidgetSet, createWidgetSet, "/qscript-console.js");

 
  if (server.start()) {
    Wt::WServer::waitForShutdown();

    // Cleanly terminate all sessions
    server.stop();
  }
}

==============  HTML file qscript-console.html ===========
<html>
<head>
<title>Embedded Wt/CodeMirror 2: JavaScript mode</title>
  <style type="text/css">
    .widget {
      width: 400px;
      height: 200px;
      margin: 10px auto;
      padding: 4px;
      border: 4px solid gray;
    }

    .IE-hidden-iframe {
      position: absolute;
      top: 0; left: 0;
      width: 1px; height: 1px;
      visibility: hidden;
    }
  </style>
    <link rel="stylesheet" href="code-mirror/codemirror.css">
    <script src="code-mirror/codemirror.js"></script>
    <script src="code-mirror/mode/javascript/javascript.js"></script>
    <link rel="stylesheet" href="code-mirror/theme/default.css">
    <link rel="stylesheet" href="code-mirror/css/docs.css">
    <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
</head>
<body>

<input id="Wt-history-field" type="hidden"/>
<div><textarea id="code" name="code">
    </textarea>
</div>
 <script>
      var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
        lineNumbers: true,
        matchBrackets: true
      });
      editor.id = "code_mirror_text_editor";
    </script>



<!-- End hidden fields for Wt's internal path API -->

<!--
   We need a place holder for every widget to which we want to bind
   a WContainerWidget in Wt
  -->
<div id="hello" class="widget">
</div>

<!--
   As the last step, we load our application.
  -->
<script src="http://127.0.0.1:8080/qscript-console.js?div=hello&amp;Wt-history=Wt-history"></script>

</body>
</html>

=================== output ===============
/home/nxd/Progs/xtcc/xtcc/qscript/stubs/simple_compiler/stubs/widgetset>./qscript-console.exe   --http-address=127.0.0.1 --http-port=8080 --docroot=.
[2012-Aug-31 19:50:23.271032] 1869 - [info] "config: reading Wt config file: /etc/wt/wt_config.xml (location = './qscript-console.exe')"
[2012-Aug-31 19:50:23.272056] 1869 - [info] "WServer/wthttp: initializing built-in wthttpd"
[2012-Aug-31 19:50:23.272376] 1869 - [info] "wthttp: started server: http://127.0.0.1:8080"
[2012-Aug-31 19:50:32.695055] 1869 - [info] "Wt: session created (#sessions = 1)"
[2012-Aug-31 19:50:32.695332] 1869 [/ 6c24O0WArxvBFgbd] [info] "WEnvironment: UserAgent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:13.0) Gecko/20100101 Firefox/13.0.1"
127.0.0.1 - - [2012-Aug-31 19:50:32.696206] "GET / HTTP/1.1" 200 1845
[2012-Aug-31 19:50:32.696276] 1869 - [info] "WebRequest: took 1.354ms"
 I am not embedded
127.0.0.1 - - [2012-Aug-31 19:50:33.203252] "GET /?wtd=6c24O0WArxvBFgbd&request=style HTTP/1.1" 200 89
[2012-Aug-31 19:50:33.203343] 1869 - [info] "WebRequest: took 29.771ms"
127.0.0.1 - - [2012-Aug-31 19:50:33.211998] "GET /?wtd=6c24O0WArxvBFgbd&sid=1858417332&htmlHistory=true&deployPath=%2F&request=script&rand=1953192535 HTTP/1.1" 200 48958
[2012-Aug-31 19:50:33.212138] 1869 - [info] "WebRequest: took 10.138ms"
127.0.0.1 - - [2012-Aug-31 19:50:33.493852] "POST /?wtd=6c24O0WArxvBFgbd HTTP/1.1" 200 50
[2012-Aug-31 19:50:33.493913] 1869 - [info] "WebRequest: took 0.494ms"
[2012-Aug-31 19:50:39.975074] 1869 - [info] "Wt: session created (#sessions = 2)"
******************************************************
[2012-Aug-31 19:50:39.975214] 1869 [/qscript-console.js f8GP6gXSMX66R9Q6] [info] "WEnvironment: UserAgent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:13.0) Gecko/20100101 Firefox/13.0.1"
 I am embedded
[2012-Aug-31 19:50:39.975602] 1869 [/qscript-console.js f8GP6gXSMX66R9Q6] [warning] "WContainerWidget: addWidget(): reparenting widget"
******************************************************

code_mirror_text_editor .id:code_mirror_text_editor
******************************************************
127.0.0.1 - - [2012-Aug-31 19:50:39.983278] "GET /qscript-console.js?div=hello&Wt-history=Wt-history HTTP/1.1" 200 47839
[2012-Aug-31 19:50:39.983405] 1869 - [info] "WebRequest: took 8.422ms"
127.0.0.1 - - [2012-Aug-31 19:50:40.238160] "POST /qscript-console.js?wtd=f8GP6gXSMX66R9Q6&wtd=f8GP6gXSMX66R9Q6 HTTP/1.1" 200 1550
[2012-Aug-31 19:50:40.238267] 1869 - [info] "WebRequest: took 1.653ms"
Neil D'Souza
2012-08-31 20:03:56 UTC
Permalink
Hi All,

    I tried solving this and I think I got a solution working. So thanks to anyone who tried looking into this. I am pasting the working code below. My failed and successful attempts are marked with NxD in the comments.

    If anyone wants to see the app working, please just ask and I will put it on my server.


Kind Regards,
Neil


================= qscript-console.html ==============

<html>
<head>
<title>Embedded Wt/CodeMirror 2: JavaScript mode</title>
  <style type="text/css">
    .widget {
      width: 400px;
      height: 200px;
      margin: 10px auto;
      padding: 4px;
      border: 4px solid gray;
    }

    .IE-hidden-iframe {
      position: absolute;
      top: 0; left: 0;
      width: 1px; height: 1px;
      visibility: hidden;
    }
  </style>
    <link rel="stylesheet" href="code-mirror/codemirror.css">
    <script src="code-mirror/codemirror.js"></script>
    <script src="code-mirror/mode/javascript/javascript.js"></script>
    <link rel="stylesheet" href="code-mirror/theme/default.css">
    <link rel="stylesheet" href="code-mirror/css/docs.css">
    <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
</head>
<body>

<input id="Wt-history-field" type="hidden"/>
<div>
    <input id="get_the_code" type="button" value="Transfer Code">
</div>
<div id="put_code_here">
</div>


    <script type="text/javascript">
    var myCodeMirror = CodeMirror(document.body, {
      value: "function myScript(){return 100;}\n",
      mode:  "javascript"
    });
    myCodeMirror.id = "code_mirror_text_editor";
    </script>




<!-- End hidden fields for Wt's internal path API -->

<!--
   We need a place holder for every widget to which we want to bind
   a WContainerWidget in Wt
  -->
<div id="hello" class="widget">
</div>

<!--
   As the last step, we load our application.
  -->
<script src="http://127.0.0.1:8080/qscript-console.js?div=hello&amp;Wt-history=Wt-history"></script>

    <script type="text/javascript">
    var get_the_code = document.getElementById("get_the_code");
    get_the_code.onclick = function () {
        var put_code_here = document.getElementById("put_code_here");
        var the_code =  myCodeMirror.getValue();
        put_code_here.innerHTML = the_code;
        // This doesnt work although I thought it should
        if (this.Wt) {
            alert("this.Wt: " + this.Wt);
        }
        if (this.Wt3_2_1) {
            alert("this.Wt: " + this.Wt);
        }
        // NxD: I thought this would work but it doesnt
        Wt.emit(Wt, 'getTheCode', the_code);
    }
    </script>

</body>
</html>


================= qscript-console.C


#include <Wt/WApplication>
#include <Wt/WBreak>
#include <Wt/WContainerWidget>
#include <Wt/WEnvironment>
#include <Wt/WPushButton>
#include <Wt/WServer>
#include <Wt/WText>
#include <Wt/WJavaScript>

class HelloApplication : public Wt::WApplication
{
public:
  HelloApplication(const Wt::WEnvironment& env, bool embedded);

private:

  void transferCode();
  Wt::JSignal<std::string> getTheCodeSignal_;
  void getTheCode(std::string p_the_code);
  Wt::JSlot my_js_slot;

};

HelloApplication::HelloApplication(const Wt::WEnvironment& env, bool embedded)
  : WApplication(env), getTheCodeSignal_(this, "getTheCode"), my_js_slot()
{
  using namespace std;
  Wt::WContainerWidget *top;
  //Wt::WContainerWidget * code_mirror_text_editor;
      
  getTheCodeSignal_.connect(this, &HelloApplication::getTheCode);
  setTitle("Hello world");


  if (!embedded) {
    /*
     * In Application mode, we have the root() is a container
     * corresponding to the entire browser window
     */
    top = root();
      cout << " I am not embedded" << endl;

  } else {
    /*
     * In WidgetSet mode, we create and bind containers to existing
     * divs in the web page. In this example, we create a single div
     * whose DOM id was passed as a request argument.
     */
      cout << " I am embedded" << endl;
    top = new Wt::WContainerWidget();
    const std::string *div = env.getParameter("div");
    if (div) {
      setJavaScriptClass(*div);
      bindWidget(top, *div);
      // NxD: another red herring - didnt need this at all
      //code_mirror_text_editor = new Wt::WContainerWidget(top);
      ////code_mirror_text_editor->setId("code_mirror_text_editor");
      //bindWidget(code_mirror_text_editor, "code_mirror_text_editor");
      //cout << "code_mirror_text_editor .id:" <<  code_mirror_text_editor->id() << endl;
    } else {
      std::cerr << "Missing: parameter: 'div'" << std::endl;
      return;
    }
  }
 
  Wt::WPushButton *b = new Wt::WPushButton("Transfer Code To Server.", top);
  b->setMargin(5, Wt::Left);
  // NxD: My initial attempts that failed
  //my_js_slot.setJavaScript("alert('my_js_slot');Wt.emit(Wt, 'getTheCode', myCodeMirror.getValue());");
  //my_js_slot.setJavaScript ("alert('my_js_slot');" + getTheCodeSignal_.createCall ("myCodeMirror.getValue()") );
  //  my_js_slot.setJavaScript (string("function() { alert('my_js_slot');")
  //    + string("Wt.emit('") + b->id() + string("','getTheCode',myCodeMirror.getValue()); }"));
  // NxD: this one works
  my_js_slot.setJavaScript (string("function () { alert('my_js_slot');")
              + getTheCodeSignal_.createCall ("myCodeMirror.getValue()")
            + string ("}")
            );

  if (!embedded)
    new Wt::WText
      ("<p><emph>Please run this application from within a web page to see the code transfer demo"
       "from within <a href=\"qscript-console.html\">a web page</a>.</emph></p>",
       root());


  top->addWidget(new Wt::WBreak());


  /*
   * Connect signals with slots
   */
  b->clicked().connect(this, &HelloApplication::transferCode);
}


void HelloApplication::getTheCode (std::string p_the_code)
{
  using namespace std;
  cout << p_the_code << endl;
}

void HelloApplication::transferCode()
{
  my_js_slot.exec();
}

Wt::WApplication *createApplication(const Wt::WEnvironment& env)
{
  return new HelloApplication(env, false);
}

Wt::WApplication *createWidgetSet(const Wt::WEnvironment& env)
{
  return new HelloApplication(env, true);
}

int main(int argc, char **argv)
{
  Wt::WServer server(argv[0]);

  // Use default server configuration: command line arguments and the
  // wthttpd configuration file.
  server.setServerConfiguration(argc, argv, WTHTTP_CONFIGURATION);

  // Application entry points. Each entry point binds an URL with an
  // application (with a callback function used to bootstrap a new
  // application).

  // The following is the default entry point. It configures a
  // standalone Wt application at the deploy path configured in the
  // server configuration.
  server.addEntryPoint(Wt::Application, createApplication);

  // The following adds an entry point for a widget set. A widget set
  // must be loaded as a JavaScript from an HTML page.
  server.addEntryPoint(Wt::WidgetSet, createWidgetSet, "/qscript-console.js");

  // Start the server (in the background if there is threading support)
  // and wait for a shutdown signal (e.g. Ctrl C, SIGKILL)
  if (server.start()) {
    Wt::WServer::waitForShutdown();

    // Cleanly terminate all sessions
    server.stop();
  }
}
=======================
Wim Dumon
2012-09-03 18:31:34 UTC
Permalink
Hello Neil,

Is there a specific reason why you're using the widgetset mode, rather
than just writing a CodeMirror widget? We have recently used Code
Mirror in combination with Wt.

BR,
Wim.
Post by Neil D'Souza
Hi All,
I tried solving this and I think I got a solution working. So thanks to
anyone who tried looking into this. I am pasting the working code below. My
failed and successful attempts are marked with NxD in the comments.
If anyone wants to see the app working, please just ask and I will put
it on my server.
Kind Regards,
Neil
================= qscript-console.html ==============
<html>
<head>
<title>Embedded Wt/CodeMirror 2: JavaScript mode</title>
<style type="text/css">
.widget {
width: 400px;
height: 200px;
margin: 10px auto;
padding: 4px;
border: 4px solid gray;
}
.IE-hidden-iframe {
position: absolute;
top: 0; left: 0;
width: 1px; height: 1px;
visibility: hidden;
}
</style>
<link rel="stylesheet" href="code-mirror/codemirror.css">
<script src="code-mirror/codemirror.js"></script>
<script src="code-mirror/mode/javascript/javascript.js"></script>
<link rel="stylesheet" href="code-mirror/theme/default.css">
<link rel="stylesheet" href="code-mirror/css/docs.css">
<style type="text/css">.CodeMirror {border-top: 1px solid black;
border-bottom: 1px solid black;}</style>
</head>
<body>
<input id="Wt-history-field" type="hidden"/>
<div>
<input id="get_the_code" type="button" value="Transfer Code">
</div>
<div id="put_code_here">
</div>
<script type="text/javascript">
var myCodeMirror = CodeMirror(document.body, {
value: "function myScript(){return 100;}\n",
mode: "javascript"
});
myCodeMirror.id = "code_mirror_text_editor";
</script>
<!-- End hidden fields for Wt's internal path API -->
<!--
We need a place holder for every widget to which we want to bind
a WContainerWidget in Wt
-->
<div id="hello" class="widget">
</div>
<!--
As the last step, we load our application.
-->
<script
src="http://127.0.0.1:8080/qscript-console.js?div=hello&amp;Wt-history=Wt-history"></script>
<script type="text/javascript">
var get_the_code = document.getElementById("get_the_code");
get_the_code.onclick = function () {
var put_code_here = document.getElementById("put_code_here");
var the_code = myCodeMirror.getValue();
put_code_here.innerHTML = the_code;
// This doesnt work although I thought it should
if (this.Wt) {
alert("this.Wt: " + this.Wt);
}
if (this.Wt3_2_1) {
alert("this.Wt: " + this.Wt);
}
// NxD: I thought this would work but it doesnt
Wt.emit(Wt, 'getTheCode', the_code);
}
</script>
</body>
</html>
================= qscript-console.C
#include <Wt/WApplication>
#include <Wt/WBreak>
#include <Wt/WContainerWidget>
#include <Wt/WEnvironment>
#include <Wt/WPushButton>
#include <Wt/WServer>
#include <Wt/WText>
#include <Wt/WJavaScript>
class HelloApplication : public Wt::WApplication
{
HelloApplication(const Wt::WEnvironment& env, bool embedded);
void transferCode();
Wt::JSignal<std::string> getTheCodeSignal_;
void getTheCode(std::string p_the_code);
Wt::JSlot my_js_slot;
};
HelloApplication::HelloApplication(const Wt::WEnvironment& env, bool embedded)
: WApplication(env), getTheCodeSignal_(this, "getTheCode"), my_js_slot()
{
using namespace std;
Wt::WContainerWidget *top;
//Wt::WContainerWidget * code_mirror_text_editor;
getTheCodeSignal_.connect(this, &HelloApplication::getTheCode);
setTitle("Hello world");
if (!embedded) {
/*
* In Application mode, we have the root() is a container
* corresponding to the entire browser window
*/
top = root();
cout << " I am not embedded" << endl;
} else {
/*
* In WidgetSet mode, we create and bind containers to existing
* divs in the web page. In this example, we create a single div
* whose DOM id was passed as a request argument.
*/
cout << " I am embedded" << endl;
top = new Wt::WContainerWidget();
const std::string *div = env.getParameter("div");
if (div) {
setJavaScriptClass(*div);
bindWidget(top, *div);
// NxD: another red herring - didnt need this at all
//code_mirror_text_editor = new Wt::WContainerWidget(top);
////code_mirror_text_editor->setId("code_mirror_text_editor");
//bindWidget(code_mirror_text_editor, "code_mirror_text_editor");
//cout << "code_mirror_text_editor .id:" <<
code_mirror_text_editor->id() << endl;
} else {
std::cerr << "Missing: parameter: 'div'" << std::endl;
return;
}
}
Wt::WPushButton *b = new Wt::WPushButton("Transfer Code To Server.", top);
b->setMargin(5, Wt::Left);
// NxD: My initial attempts that failed
//my_js_slot.setJavaScript("alert('my_js_slot');Wt.emit(Wt, 'getTheCode',
myCodeMirror.getValue());");
//my_js_slot.setJavaScript ("alert('my_js_slot');" +
getTheCodeSignal_.createCall ("myCodeMirror.getValue()") );
// my_js_slot.setJavaScript (string("function() { alert('my_js_slot');")
// + string("Wt.emit('") + b->id() +
string("','getTheCode',myCodeMirror.getValue()); }"));
// NxD: this one works
my_js_slot.setJavaScript (string("function () { alert('my_js_slot');")
+ getTheCodeSignal_.createCall ("myCodeMirror.getValue()")
+ string ("}")
);
if (!embedded)
new Wt::WText
("<p><emph>Please run this application from within a web page to see
the code transfer demo"
"from within <a href=\"qscript-console.html\">a web
page</a>.</emph></p>",
root());
top->addWidget(new Wt::WBreak());
/*
* Connect signals with slots
*/
b->clicked().connect(this, &HelloApplication::transferCode);
}
void HelloApplication::getTheCode (std::string p_the_code)
{
using namespace std;
cout << p_the_code << endl;
}
void HelloApplication::transferCode()
{
my_js_slot.exec();
}
Wt::WApplication *createApplication(const Wt::WEnvironment& env)
{
return new HelloApplication(env, false);
}
Wt::WApplication *createWidgetSet(const Wt::WEnvironment& env)
{
return new HelloApplication(env, true);
}
int main(int argc, char **argv)
{
Wt::WServer server(argv[0]);
// Use default server configuration: command line arguments and the
// wthttpd configuration file.
server.setServerConfiguration(argc, argv, WTHTTP_CONFIGURATION);
// Application entry points. Each entry point binds an URL with an
// application (with a callback function used to bootstrap a new
// application).
// The following is the default entry point. It configures a
// standalone Wt application at the deploy path configured in the
// server configuration.
server.addEntryPoint(Wt::Application, createApplication);
// The following adds an entry point for a widget set. A widget set
// must be loaded as a JavaScript from an HTML page.
server.addEntryPoint(Wt::WidgetSet, createWidgetSet,
"/qscript-console.js");
// Start the server (in the background if there is threading support)
// and wait for a shutdown signal (e.g. Ctrl C, SIGKILL)
if (server.start()) {
Wt::WServer::waitForShutdown();
// Cleanly terminate all sessions
server.stop();
}
}
=======================
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
witty-interest mailing list
https://lists.sourceforge.net/lists/listinfo/witty-interest
Neil D'Souza
2012-09-03 18:53:09 UTC
Permalink
Hi Wim,

   I initially started with the example below, but could not get it to work. Looking at it now I can see that the code passed to doJavaScript should most probably be a function, and there are other problems as well that I should fix. It was the first time I needed custom JavaScript in Wt so I am sure my approach was the initial falterin steps of a beginner.


   I would be happier if I didnt have to go the widgetset route, but it was a great learning experience for me, and now I am comfortable with it.


   Of course, I see it irritating for the end user that they have to click load, to actually load the gui. If you can point me to the codemirror example I will be happy to morph it into what I need for my app.

   Thanks for your help.


Kind Regards,
Neil


  

================================================


#include <iostream>
#include <string>

#include <Wt/WApplication>
#include <Wt/WBreak>
#include <Wt/WContainerWidget>
#include <Wt/WEnvironment>
#include <Wt/WLineEdit>
#include <Wt/WPushButton>
#include <Wt/WServer>
#include <Wt/WText>
#include <Wt/WTemplate>
#include <Wt/WTextArea>

class MyWtCodeMirror : public Wt::WApplication
{
    public:
        MyWtCodeMirror (const Wt::WEnvironment& env);
    Wt::WContainerWidget *top;
    Wt::WTextArea * textCodeEditor_;
};

MyWtCodeMirror::MyWtCodeMirror (const Wt::WEnvironment& env)
    : Wt::WApplication (env), top (0), textCodeEditor_ (0)
{
    using std::cout;
    using std::cerr;
    using std::endl;
    using std::string;
    top = root();
    bool success = require ("code-mirror/codemirror.js");
    if (success) {
        cout << "loaded codemirror.js" << endl;
    }
    success = require ("code-mirror/mode/javascript/javascript.js");
    if (success) {
        cout << "loaded javascript.js" << endl;
    }

    Wt::WTemplate * t = new Wt::WTemplate(root());
    //t->setTemplateText ("<div><textarea id=\"code\" name=\"code\"> Some text in the text area</textarea> </div>");
    t->setTemplateText ("<div> I contain a WTextArea called code: ${code} </div>");
    t->bindWidget ("code", textCodeEditor_ = new Wt::WTextArea (top));
    textCodeEditor_->setId("code");
    std::string text_area_id = textCodeEditor_->id();
    cout << "textCodeEditor_ id(): " << text_area_id << endl;
    //Wt::WWidget  * found =  findWidget     ("code");
    //if (found) {
    //    cout << "found the code widget" << endl;
    //} else {
    //    cout << "DID NOT FIND the \"code\" widget" << endl;
    //}
    //string text_area_id = "code";
        doJavaScript(string("var editor = CodeMirror.fromTextArea(document.getElementById('")
            + text_area_id
            + string("'), { lineNumbers: true, matchBrackets: true }); alert('success');"));
    //doJavaScript(string("var myCodeMirror = CodeMirror(document.body);"));


}


Wt::WApplication *createApplication(const Wt::WEnvironment& env)
{
  /*
   * You could read information from the environment to decide whether
   * the user has permission to start a new application
   */
  return new MyWtCodeMirror(env);
}


int main(int argc, char **argv)
{
  return Wt::WRun(argc, argv, &createApplication);
}
Post by Neil D'Souza
________________________________
Sent: Tuesday, September 4, 2012 12:01 AM
Subject: Re: [Wt-interest] [Wt Interest] Using CodeMirror with Wt
Hello Neil,
Is there a specific reason why you're using the widgetset mode, rather
than just writing a CodeMirror widget? We have recently used Code
Mirror in combination with Wt.
BR,
Wim.
Post by Neil D'Souza
Hi All,
    I tried solving this and I think I got a solution working. So thanks to
anyone who tried looking into this. I am pasting the working code below. My
failed and successful attempts are marked with NxD in the comments.
    If anyone wants to see the app working, please just ask and I will put
it on my server.
Kind Regards,
Neil
================= qscript-console.html ==============
<html>
<head>
<title>Embedded Wt/CodeMirror 2: JavaScript mode</title>
  <style type="text/css">
    .widget {
      width: 400px;
      height: 200px;
      margin: 10px auto;
      padding: 4px;
      border: 4px solid gray;
    }
    .IE-hidden-iframe {
      position: absolute;
      top: 0; left: 0;
      width: 1px; height: 1px;
      visibility: hidden;
    }
  </style>
    <link rel="stylesheet" href="code-mirror/codemirror.css">
    <script src="code-mirror/codemirror.js"></script>
    <script src="code-mirror/mode/javascript/javascript.js"></script>
    <link rel="stylesheet" href="code-mirror/theme/default.css">
    <link rel="stylesheet" href="code-mirror/css/docs.css">
    <style type="text/css">.CodeMirror {border-top: 1px solid black;
border-bottom: 1px solid black;}</style>
</head>
<body>
<input id="Wt-history-field" type="hidden"/>
<div>
    <input id="get_the_code" type="button" value="Transfer Code">
</div>
<div id="put_code_here">
</div>
    <script type="text/javascript">
    var myCodeMirror = CodeMirror(document.body, {
      value: "function myScript(){return 100;}\n",
      mode:  "javascript"
    });
    myCodeMirror.id = "code_mirror_text_editor";
    </script>
<!-- End hidden fields for Wt's internal path API -->
<!--
    We need a place holder for every widget to which we want to bind
    a WContainerWidget in Wt
  -->
<div id="hello" class="widget">
</div>
<!--
    As the last step, we load our application.
  -->
<script
src="http://127.0.0.1:8080/qscript-console.js?div=hello&Wt-history=Wt-history"></script>
    <script type="text/javascript">
    var get_the_code = document.getElementById("get_the_code");
    get_the_code.onclick = function () {
        var put_code_here = document.getElementById("put_code_here");
        var the_code =  myCodeMirror.getValue();
        put_code_here.innerHTML = the_code;
        // This doesnt work although I thought it should
        if (this.Wt) {
            alert("this.Wt: " + this.Wt);
        }
        if (this.Wt3_2_1) {
            alert("this.Wt: " + this.Wt);
        }
        // NxD: I thought this would work but it doesnt
        Wt.emit(Wt, 'getTheCode', the_code);
    }
    </script>
</body>
</html>
================= qscript-console.C
#include <Wt/WApplication>
#include <Wt/WBreak>
#include <Wt/WContainerWidget>
#include <Wt/WEnvironment>
#include <Wt/WPushButton>
#include <Wt/WServer>
#include <Wt/WText>
#include <Wt/WJavaScript>
class HelloApplication : public Wt::WApplication
{
  HelloApplication(const Wt::WEnvironment& env, bool embedded);
  void transferCode();
  Wt::JSignal<std::string> getTheCodeSignal_;
  void getTheCode(std::string p_the_code);
  Wt::JSlot my_js_slot;
};
HelloApplication::HelloApplication(const Wt::WEnvironment& env, bool embedded)
  : WApplication(env), getTheCodeSignal_(this, "getTheCode"), my_js_slot()
{
  using namespace std;
  Wt::WContainerWidget *top;
  //Wt::WContainerWidget * code_mirror_text_editor;
  getTheCodeSignal_.connect(this, &HelloApplication::getTheCode);
  setTitle("Hello world");
  if (!embedded) {
    /*
      * In Application mode, we have the root() is a container
      * corresponding to the entire browser window
      */
    top = root();
      cout << " I am not embedded" << endl;
  } else {
    /*
      * In WidgetSet mode, we create and bind containers to existing
      * divs in the web page. In this example, we create a single div
      * whose DOM id was passed as a request argument.
      */
      cout << " I am embedded" << endl;
    top = new Wt::WContainerWidget();
    const std::string *div = env.getParameter("div");
    if (div) {
      setJavaScriptClass(*div);
      bindWidget(top, *div);
      // NxD: another red herring - didnt need this at all
      //code_mirror_text_editor = new Wt::WContainerWidget(top);
      ////code_mirror_text_editor->setId("code_mirror_text_editor");
      //bindWidget(code_mirror_text_editor, "code_mirror_text_editor");
      //cout << "code_mirror_text_editor .id:" <<
code_mirror_text_editor->id() << endl;
    } else {
      std::cerr << "Missing: parameter: 'div'" << std::endl;
      return;
    }
  }
  Wt::WPushButton *b = new Wt::WPushButton("Transfer Code To Server.", top);
  b->setMargin(5, Wt::Left);
  // NxD: My initial attempts that failed
  //my_js_slot.setJavaScript("alert('my_js_slot');Wt.emit(Wt, 'getTheCode',
myCodeMirror.getValue());");
  //my_js_slot.setJavaScript ("alert('my_js_slot');" +
getTheCodeSignal_.createCall ("myCodeMirror.getValue()") );
  //  my_js_slot.setJavaScript (string("function() { alert('my_js_slot');")
  //    + string("Wt.emit('") + b->id() +
string("','getTheCode',myCodeMirror.getValue()); }"));
  // NxD: this one works
  my_js_slot.setJavaScript (string("function () { alert('my_js_slot');")
              + getTheCodeSignal_.createCall ("myCodeMirror.getValue()")
            + string ("}")
            );
  if (!embedded)
    new Wt::WText
      ("<p><emph>Please run this application from within a web page to see
the code transfer demo"
        "from within <a href=\"qscript-console.html\">a web
page</a>.</emph></p>",
        root());
  top->addWidget(new Wt::WBreak());
  /*
    * Connect signals with slots
    */
  b->clicked().connect(this, &HelloApplication::transferCode);
}
void HelloApplication::getTheCode (std::string p_the_code)
{
  using namespace std;
  cout << p_the_code << endl;
}
void HelloApplication::transferCode()
{
  my_js_slot.exec();
}
Wt::WApplication *createApplication(const Wt::WEnvironment& env)
{
  return new HelloApplication(env, false);
}
Wt::WApplication *createWidgetSet(const Wt::WEnvironment& env)
{
  return new HelloApplication(env, true);
}
int main(int argc, char **argv)
{
  Wt::WServer server(argv[0]);
  // Use default server configuration: command line arguments and the
  // wthttpd configuration file.
  server.setServerConfiguration(argc, argv, WTHTTP_CONFIGURATION);
  // Application entry points. Each entry point binds an URL with an
  // application (with a callback function used to bootstrap a new
  // application).
  // The following is the default entry point. It configures a
  // standalone Wt application at the deploy path configured in the
  // server configuration.
  server.addEntryPoint(Wt::Application, createApplication);
  // The following adds an entry point for a widget set. A widget set
  // must be loaded as a JavaScript from an HTML page.
  server.addEntryPoint(Wt::WidgetSet, createWidgetSet,
"/qscript-console.js");
  // Start the server (in the background if there is threading support)
  // and wait for a shutdown signal (e.g. Ctrl C, SIGKILL)
  if (server.start()) {
    Wt::WServer::waitForShutdown();
    // Cleanly terminate all sessions
    server.stop();
  }
}
=======================
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
witty-interest mailing list
https://lists.sourceforge.net/lists/listinfo/witty-interest
Rob Van Dyck
2012-09-04 07:15:14 UTC
Permalink
Wim,,

I would also be interested in seeing a small example on how this is
supposed to be done.

Thanx and regards,
Rob.
Post by Neil D'Souza
Hi Wim,
If you can point me to the codemirror
example I will be happy to morph it into what I need for my app.
Thanks for your help.
Kind Regards,
Neil
________________________________
Post by Neil D'Souza
Sent: Tuesday, September 4, 2012 12:01 AM
Subject: Re: [Wt-interest] [Wt Interest] Using CodeMirror with Wt
Hello Neil,
Is there a specific reason why you're using the widgetset mode, rather
than just writing a CodeMirror widget? We have recently used Code
Mirror in combination with Wt.
BR,
Wim.
Wim Dumon
2012-09-04 15:04:31 UTC
Permalink
This is for JWt. The translation to C++ is left as an exercise to the
reader. And maybe if someone contributes a nice C++ widget we may add
it to Wt (and JWt)?

Anyway, it's a nice example of how you can pimp a Wt application with
JS libraries.

BR,
Wim.

import eu.webtoolkit.jwt.WApplication;
import eu.webtoolkit.jwt.WContainerWidget;
import eu.webtoolkit.jwt.WTextArea;

public class CodeMirrorTextArea extends WContainerWidget {
private WTextArea textArea;
public CodeMirrorTextArea(WContainerWidget parent) {
super(parent);

textArea = new WTextArea(this);

WApplication app = WApplication.getInstance();

app.require(app.resolveRelativeUrl("codemirror-2.32/lib/codemirror.js"));
app.require(app.resolveRelativeUrl("codemirror-2.32/mode/groovy/groovy.js"));

//TODO:
//We save the editor state to the text area on each key stroke,
//it appears to be not a performance issue,
//however it might very well become one when editing larger fragments of code.
//A better solution would be to save this state to the text area only when
//the form is submitted, currently this is not yet possible in Wt???.

String js =
"var e = " + textArea.getJsRef() + ";" +
"var cm = CodeMirror.fromTextArea(e, {" +
" onKeyEvent : function (editor, event) {" +
" editor.save();" +
" }," +
" lineNumbers: true" +
" });" +
"var self = " + getJsRef() + ";" +
"self.cm = cm;";

this.doJavaScript(js);
}

public CodeMirrorTextArea() {
this(null);
}

public void setText(String text) {
textArea.setText(text);
}

public String getText() {
return textArea.getText();
}

public void setMarker(int line, String htmlMarker) {
String js =
"var self = " + getJsRef() + ";" +
"self.cm.setMarker(" + line + ", " + jsStringLiteral(htmlMarker +
"%N%") + ");";

this.doJavaScript(js);
}

public void clearMarker(int line) {
String js =
"var self = " + getJsRef() + ";" +
"self.cm.clearMarker(" + line + ");";

this.doJavaScript(js);
}
}
Post by Rob Van Dyck
Wim,,
I would also be interested in seeing a small example on how this is
supposed to be done.
Thanx and regards,
Rob.
Post by Neil D'Souza
Hi Wim,
If you can point me to the codemirror
example I will be happy to morph it into what I need for my app.
Thanks for your help.
Kind Regards,
Neil
________________________________
Post by Neil D'Souza
Sent: Tuesday, September 4, 2012 12:01 AM
Subject: Re: [Wt-interest] [Wt Interest] Using CodeMirror with Wt
Hello Neil,
Is there a specific reason why you're using the widgetset mode, rather
than just writing a CodeMirror widget? We have recently used Code
Mirror in combination with Wt.
BR,
Wim.
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
witty-interest mailing list
https://lists.sourceforge.net/lists/listinfo/witty-interest
Neil D'Souza
2012-09-06 10:03:26 UTC
Permalink
________________________________
Sent: Tuesday, September 4, 2012 8:34 PM
Subject: Re: [Wt-interest] [Wt Interest] Using CodeMirror with Wt
This is for JWt. The translation to C++ is left as an exercise to the
reader. And maybe if someone contributes a nice C++ widget we may add
it to Wt (and JWt)?
Hi Rob, Wim,


    Pasted below is the beginnings of the code sent by Wim that I translated into C++.


    I was having trouble with it, just as I was having trouble with my own initial attempt, until I realised I had not loaded the CodeMirror CSS.


    Once that was done, it is working fine.  No additional functionality has been added, but I intend to do that, now that the core functionality seems fine. I have pasted the code below along with the test class.


Regards,
Neil


/*
 * =====================================================================================
 *
 *       Filename:  WCodeMirror.h
 *
 *    Description: 
 *
 *        Version:  1.0
 *        Created:  Thursday 06 September 2012 01:05:33  IST
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  YOUR NAME (),
 *        Company: 
 *
 * =====================================================================================
 */

/*
import eu.webtoolkit.jwt.WApplication;
import eu.webtoolkit.jwt.WContainerWidget;
import eu.webtoolkit.jwt.WTextArea;

public class CodeMirrorTextArea extends WContainerWidget {
    private WTextArea textArea;
    public CodeMirrorTextArea(WContainerWidget parent) {
        super(parent);
      
        textArea = new WTextArea(this);
      
        WApplication app = WApplication.getInstance();
      
        app.require(app.resolveRelativeUrl("codemirror-2.32/lib/codemirror.js"));
        app.require(app.resolveRelativeUrl("codemirror-2.32/mode/groovy/groovy.js"));
      
        //TODO:
        //We save the editor state to the text area on each key stroke,
        //it appears to be not a performance issue,
        //however it might very well become one when editing larger fragments of code.
        //A better solution would be to save this state to the text area only when
        //the form is submitted, currently this is not yet possible in Wt???.
      
        String js =
            "var e = " + textArea.getJsRef() + ";" +
            "var cm = CodeMirror.fromTextArea(e, {" +
            "    onKeyEvent : function (editor, event) {" +
            "        editor.save();" +
            "    }," +
            "    lineNumbers: true" +
            "    });" +
            "var self = " + getJsRef() + ";" +
            "self.cm = cm;";
      
        this.doJavaScript(js);
    }
  
    public CodeMirrorTextArea() {
        this(null);
    }
  
    public void setText(String text) {
        textArea.setText(text);
    }
  
    public String getText() {
        return textArea.getText();
    }
  
    public void setMarker(int line, String htmlMarker) {
        String js =
            "var self = " + getJsRef() + ";" +
            "self.cm.setMarker(" + line + ", " + jsStringLiteral(htmlMarker +
"%N%") + ");";
      
        this.doJavaScript(js);
    }
  
    public void clearMarker(int line) {
        String js =
            "var self = " + getJsRef() + ";" +
            "self.cm.clearMarker(" + line + ");";
      
        this.doJavaScript(js);
    }
}
  */
#ifndef WT_WCodeMirrorTextArea
#define WT_WCodeMirrorTextArea

#include <Wt/WApplication>
#include <Wt/WTextArea>
#include <Wt/WContainerWidget>
#include <string>
#include <sstream>

namespace Wt {

class WCodeMirrorTextArea : public WContainerWidget
{
public:
    WTextArea * textArea_;
    WCodeMirrorTextArea (WContainerWidget * parent)
        : WContainerWidget (parent)
    {

    textArea_ = new WTextArea(this);
    textArea_->setText("var v1;\nfunction f (p1, p2, p3) {\n // does nothing \n};\n");

    WApplication * app = WApplication:: instance();

    //app.require(app.resolveRelativeUrl("codemirror-2.32/lib/codemirror.js"));
    //app.require(app.resolveRelativeUrl("codemirror-2.32/mode/groovy/groovy.js"));
    //true
    //
    app->useStyleSheet(app->resolveRelativeUrl("CodeMirror-2.33/lib/codemirror.css"));
    app->require(app->resolveRelativeUrl("CodeMirror-2.33/lib/codemirror.js"));
    app->require(app->resolveRelativeUrl("CodeMirror-2.33/mode/javascript/javascript.js"));
    app->useStyleSheet(app->resolveRelativeUrl("CodeMirror-2.33/doc/docs.css"));

    //TODO:
    //We save the editor state to the text area on each key stroke,
    //it appears to be not a performance issue,
    //however it might very well become one when editing larger fragments of code.
    //A better solution would be to save this state to the text area only when
    //the form is submitted, currently this is not yet possible in Wt???.

    using std::string;
    string js =
        "var e = " + textArea_->jsRef() + ";" +
        "var cm = CodeMirror.fromTextArea(e, {" +
        "    onKeyEvent : function (editor, event) {" +
        "        editor.save();" +
        "    }," +
        "    lineNumbers: true, " +
        "    value: \"var v1; function f2 (p1, p2, p3) { var v2; }\" " +
        "    });" +
        "var self = " + this->jsRef() + ";" +
        "self.cm = cm;";

    this->doJavaScript(js);
    }

    /*
    public CodeMirrorTextArea() {
    this(null);
    }
    */

    void setText(std::string text)
    {
        textArea_->setText(text);
    }

    std::string getText()
    {
        return textArea_-> text().toUTF8();
    }

    void setMarker(int line, std::string htmlMarker)
    {
        std::stringstream js ;
        js     << "var self = " << jsRef() <<  ";"
            <<  "self.cm.setMarker("
            <<  line <<  ", " << jsStringLiteral(htmlMarker + "%N%")
            << ");";
        this->doJavaScript(js.str());
    }

    void clearMarker(int line)
    {
        std::stringstream js ;
        js     << "var self = " <<  jsRef() << ";"
            << "self.cm.clearMarker(" << line << ");";

        this->doJavaScript(js.str());
    }
};

}
#endif /*  WT_WCodeMirrorTextArea */

// ============== test main function: testCM.C =============


#include "WCodeMirror.h"

#include <iostream>
#include <string>

#include <Wt/WApplication>

class MyWtCodeMirror : public Wt::WApplication
{
    public:
    MyWtCodeMirror (const Wt::WEnvironment& env);
    Wt::WCodeMirrorTextArea * cmta_;

};

MyWtCodeMirror::MyWtCodeMirror (const Wt::WEnvironment& env)
    : Wt::WApplication (env), cmta_(new Wt::WCodeMirrorTextArea(this->root()))
{
    std::cout << cmta_->getText() << std::endl;
}


Wt::WApplication *createApplication(const Wt::WEnvironment& env)
{
  /*
   * You could read information from the environment to decide whether
   * the user has permission to start a new application
   */
  return new MyWtCodeMirror(env);
}


int main(int argc, char **argv)
{
  return Wt::WRun(argc, argv, &createApplication);
}


=======================================
And for completeness sake - compile instructions

simple_compiler/stubs/widgetset>g++ testCM.C -lwt -lwthttp  

simple_compiler/stubs/widgetset>./a.out --http-address=127.0.0.1 --http-port=8081 --docroot .
Loading...