001 
002 /*
003  *  JScripter Simulation 1.0 - For Java To Script
004  *  Copyright (C) 2008-2011  J.J.Liu<jianjunliu@126.com> <http://www.jscripter.org>
005  *  
006  *  This program is free software: you can redistribute it and/or modify
007  *  it under the terms of the GNU Affero General Public License as published by
008  *  the Free Software Foundation, either version 3 of the License, or
009  *  (at your option) any later version.
010  *  
011  *  This program is distributed in the hope that it will be useful,
012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014  *  GNU Affero General Public License for more details.
015  *  
016  *  You should have received a copy of the GNU Affero General Public License
017  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
018  */
019 
020 package org.jscripter.sim.client;
021 
022 import java.applet.Applet;
023 
024 import netscape.javascript.JSObject;
025 import js.*;
026 import js.core.*;
027 import js.user.*;
028 
029 /**
030  * <p>An <b>internal</b> class for JS Embeded Simulation on IE browser series.</p>
031  * <p>This <b>internal</b> class is only extended internally in JS Simulation Library.</p>
032  *
033  * @author <a href="mailto:jianjunliu@126.com">J.J.Liu (Jianjun Liu)</a> at <a href="http://www.jscripter.org" target="_blank">http://www.jscripter.org</a>
034  * 
035  * @javascript Re-compilers must report error on resolving an <tt>internal</tt> class. 
036  */
037 public final class EmbededIE extends Embeded
038 {
039     /**
040      * <p>Internally constructs a JS Embeded Simulation from an applet on an IE browser.</p>
041      * @param applet A Java applet.
042      * @since 1.0
043      * 
044      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> constructor. 
045      */
046     protected EmbededIE(Applet applet) {
047         super(applet);
048         getWindow().eval(
049                 "window.$$set=function(o,p,v){o[p]=v;};" +
050                 "alert0=window.alert;" +
051                 "window.alert=function(s){" +
052                     "return alert0(s);" +
053                 "};" +
054                 "setTimeout0=window.setTimeout;" +
055                 "window.setTimeout=function(f,d){" +
056                     "return setTimeout0(f,d);" +
057                 "};" +
058                 "clearTimeout0=window.clearTimeout;" +
059                 "window.clearTimeout=function(i){" +
060                     "return clearTimeout0(i);" +
061                 "};" +
062                 "setInterval0=window.setInterval;" +
063                 "window.setInterval=function(f,i){" +
064                     "return setInterval0(f,i);" +
065                 "};" +
066                 "clearInterval0=window.clearInterval;" +
067                 "window.clearInterval=function(i){" +
068                     "return clearInterval0(i);" +
069                 "};" +
070                 "window.$cpe=function(){" +
071                     "return $cp(event);" +
072                 "};"
073         );
074     }
075 
076     /**
077      * <p>Internally creates function object from a function definition.</p>
078      * @param f A {@link Function} definition.
079      * @return The function object.
080      * @since 1.0
081      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
082      */
083     @Override
084     protected <T> JsFunction<T> var(Function<T> f) {
085         return new JseFunction<T>(
086                 new JseObjectIE.JseoFunction<T>(
087                         f
088                 )
089         );
090     }
091 
092     private JsWin win;
093 
094     /**
095      * <p>Returns the opaque global object with the client-side support.</p>
096      * @return The opaque global object with the client-side support.
097      * @see Js#win()
098      * @see jsx.client.Client
099      * @since 1.0
100      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
101      */
102     @Override
103     protected JsWin win() {
104         if (win == null) {
105             win = new JsWin(new JseObjectIE(getWindow()));;
106         }
107         return win;
108     }
109 
110     /**
111      * <p>Internally creates a variable list from a value or object.</p>
112      * @param args A value or object.
113      * @return The variable list created.
114      * @since 1.0
115      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
116      */
117     @Override
118     protected Vars<?> vars(Object args) {
119         if (args instanceof Var<?>) {
120             args = ((Var<?>)args).var();
121         }
122         Vars<Object> vars = new Vars<Object>();
123         if (args instanceof JsObject) {
124             args = ((Live)((JsObject)args).var()).getJSObject();
125         }
126         if (args instanceof JSObject) {
127             if (((JSObject)args).getMember("length") != null) {
128                 args = new JseArray(new JseObjectIE(args));
129             }
130         }
131         if (args instanceof ArrayObject<?>) {
132             ArrayObject<?> a = (ArrayObject<?>)args;
133             for (int l = a.length(), i = 0; i < l; i++) {
134                 vars.add(JseObjectIE.wrap(a.get(i)));
135             }
136         } else if (args.getClass().isArray()) {
137             Object[] a = (Object[])args;
138             for (int l = a.length, i = 0; i < l; i++) {
139                 vars.add(JseObjectIE.wrap(a[i]));
140             }
141         } else if (args != null){
142             vars.add(JseObjectIE.wrap(args));
143         }
144         return vars;
145     }
146 
147     /**
148      * <p>Creates a JavaScript function.</p>
149      * <p>A function is a fundamental data-type in JavaScript. Note that although functions 
150      * may be created with this method, this is not efficient, and the preferred way to 
151      * define functions, in most cases, is to extend {@link Function}.</p>
152      * @param args A list of the argument values, each naming one or more arguments of the 
153      * function being created, ended with a string that specifies the body of the function.
154      * @return A newly created function. Invoking it executes the JavaScript code specified 
155      * by last string value of the variable argument <tt>args</tt>.
156      * @throws RuntimeException JavaScript throws a <tt>SyntaxError</tt> if there was a 
157      * JavaScript syntax error in one of the value of the variable arguments. See {@link Js#err(Object)} 
158      * and {@link js.core.JsSyntaxError} for JS Simulation.
159      * @see Function
160      * @since 1.0
161      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
162      */
163     @Override
164     protected <T> JsFunction<T> function(Vars<String> args) {
165         ArrayLike<String> a = args.var();
166         int alen = a.length();
167         StringBuilder sb = new StringBuilder("Object(function(");
168         if (alen < 1) {
169             sb.append("){})");
170         } else {
171             for (int i = 0; i < alen - 1; i++) {
172                 if (i > 0) {
173                     sb.append(',');
174                 }
175                 sb.append(a.get(i));
176             }
177             sb.append("){").append(a.get(alen - 1)).append("})");
178         }
179         return new JseFunction<T>(
180                 new JseObjectIE(
181                         getWindow().eval(sb.toString())
182                 )
183         );
184     }
185 
186     /**
187      * <p>Gets the list of the property names of an object.</p>
188      * @param o The object.
189      * @return The list of the property names of the object.
190      * @since 1.0
191      * @javascript Re-compilers must report error on the invocation to an <b>internal</b> method. 
192      */
193     @SuppressWarnings("unchecked")
194     @Override
195     protected final ArrayLike<String> keys(JsObject o) {
196         return (ArrayLike<String>)(ArrayLike<?>)new JseArray(new JseObjectIE(
197                 getWindow().call(
198                         "$keys",
199                         new Object[]{JseObject.unwrap(o)}
200                 )
201         ));
202     }
203 }