1 /*
2  * Copyright (C) 2008 Emweb bv, Herent, Belgium.
3  *
4  * See the LICENSE file for terms of use.
5  */
6 #include "Wt/WApplication.h"
7 #include "Wt/WException.h"
8 #include "Wt/WJavaScriptSlot.h"
9 #include "Wt/WStatelessSlot.h"
10 #include "Wt/WWidget.h"
11 
12 namespace Wt {
13 
14 #if defined(WT_THREADED) || defined(WT_TARGET_JAVA)
15   std::atomic<unsigned> JSlot::nextFid_(0);
16 #else
17   unsigned JSlot::nextFid_ = 0;
18 #endif
19 
20 class WStatelessSlotImpl : public WStatelessSlot {
21 public:
WStatelessSlotImpl(WObject * target,WObjectMethod method,const std::string & javaScript)22   WStatelessSlotImpl(WObject *target, WObjectMethod method,
23 		     const std::string& javaScript) :
24     WStatelessSlot(target, method, javaScript) { }
25 };
26 
JSlot(WWidget * parent)27 JSlot::JSlot(WWidget *parent)
28   : widget_(parent),
29     fid_(nextFid_++),
30     nbArgs_(0)
31 {
32   create();
33 }
34 
JSlot(const std::string & javaScript,WWidget * parent)35 JSlot::JSlot(const std::string& javaScript, WWidget *parent)
36   : widget_(parent),
37     fid_(nextFid_++),
38     nbArgs_(0)
39 {
40   create();
41   setJavaScript(javaScript);
42 }
43 
JSlot(int nbArgs,WWidget * parent)44 JSlot::JSlot(int nbArgs, WWidget *parent)
45   : widget_(parent),
46     fid_(nextFid_++),
47     nbArgs_(nbArgs)
48 {
49   if (nbArgs_ < 0 || nbArgs_ > 6) {
50     throw WException("The number of arguments given must be between 0 and 6.");
51   }
52   create();
53 }
54 
JSlot(const std::string & javaScript,int nbArgs,WWidget * parent)55 JSlot::JSlot(const std::string& javaScript, int nbArgs, WWidget *parent)
56   : widget_(parent),
57     fid_(nextFid_++),
58     nbArgs_(nbArgs)
59 {
60   if (nbArgs_ < 0 || nbArgs_ > 6) {
61     throw WException("The number of arguments given must be between 0 and 6.");
62   }
63   create();
64   setJavaScript(javaScript, nbArgs_);
65 }
66 
create()67 void JSlot::create()
68 {
69   std::stringstream ss;
70 
71   if (widget_) {
72     WApplication *app = WApplication::instance();
73     if (app) {
74       ss << WApplication::instance()->javaScriptClass() << "."
75 	 << jsFunctionName() << "(o,e";
76       for (int i = 1; i <= nbArgs_; ++i) {
77 	ss << ",a" << i;
78       }
79       ss << ");";
80     }
81   }
82 
83   imp_ = new WStatelessSlotImpl(widget_, nullptr, ss.str());
84 }
85 
~JSlot()86 JSlot::~JSlot()
87 {
88   delete imp_;
89 }
90 
jsFunctionName()91 std::string JSlot::jsFunctionName() const
92 {
93   return "sf" + std::to_string(fid_);
94 }
95 
setJavaScript(const std::string & js,int nbArgs)96 void JSlot::setJavaScript(const std::string& js, int nbArgs)
97 {
98   if (nbArgs < 0 || nbArgs > 6) {
99     throw WException("The number of arguments given must be between 0 and 6.");
100   }
101   nbArgs_ = nbArgs;
102   WApplication *app = WApplication::instance();
103   if (widget_ && app)
104     WApplication::instance()->declareJavaScriptFunction(jsFunctionName(), js);
105   else {
106     std::stringstream ss;
107     ss << "{var f=" << js << ";f(o,e";
108     for (int i = 1; i <= nbArgs; ++i) {
109       ss << ",a" << i;
110     }
111     ss << ");}";
112     imp_->setJavaScript(ss.str());
113   }
114 }
115 
slotimp()116 WStatelessSlot* JSlot::slotimp()
117 {
118   return imp_;
119 }
120 
execJs(const std::string & object,const std::string & event,const std::string & arg1,const std::string & arg2,const std::string & arg3,const std::string & arg4,const std::string & arg5,const std::string & arg6)121 std::string JSlot::execJs(const std::string& object,
122 			  const std::string& event,
123 			  const std::string& arg1,
124 			  const std::string& arg2,
125 			  const std::string& arg3,
126 			  const std::string& arg4,
127 			  const std::string& arg5,
128 			  const std::string& arg6)
129 {
130   std::stringstream result;
131   result << "{var o=" << object;
132   result << ",e=" << event;
133   for (int i = 0; i < nbArgs_; ++i) {
134     result << ",a" << (i+1) << "=";
135     switch (i) {
136       case 0:
137 	result << arg1;
138 	break;
139       case 1:
140 	result << arg2;
141 	break;
142       case 2:
143 	result << arg3;
144 	break;
145       case 3:
146 	result << arg4;
147 	break;
148       case 4:
149 	result << arg5;
150 	break;
151       case 5:
152 	result << arg6;
153 	break;
154     }
155   }
156   result << ";" << imp_->javaScript() + "}";
157   return result.str();
158 }
159 
exec(const std::string & object,const std::string & event,const std::string & arg1,const std::string & arg2,const std::string & arg3,const std::string & arg4,const std::string & arg5,const std::string & arg6)160 void JSlot::exec(const std::string& object,
161 		 const std::string& event,
162 		 const std::string& arg1,
163 		 const std::string& arg2,
164 		 const std::string& arg3,
165 		 const std::string& arg4,
166 		 const std::string& arg5,
167 		 const std::string& arg6)
168 {
169   WApplication::instance()->doJavaScript(execJs(object, event, arg1, arg2, arg3, arg4, arg5, arg6));
170 }
171 
172 #ifndef WT_TARGET_JAVA
disconnectFrom(EventSignalBase * signal)173 void JSlot::disconnectFrom(EventSignalBase *signal)
174 {
175   imp_->disconnectFrom(signal);
176 }
177 #endif
178 
179 }
180