1+ /****************************************************************************
2+ Copyright (c) 2013-2014 Chukong Technologies Inc.
3+
4+ http://www.cocos2d-x.org
5+
6+ Permission is hereby granted, free of charge, to any person obtaining a copy
7+ of this software and associated documentation files (the "Software"), to deal
8+ in the Software without restriction, including without limitation the rights
9+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+ copies of the Software, and to permit persons to whom the Software is
11+ furnished to do so, subject to the following conditions:
12+
13+ The above copyright notice and this permission notice shall be included in
14+ all copies or substantial portions of the Software.
15+
16+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+ THE SOFTWARE.
23+ ****************************************************************************/
24+
25+ ccui . WebView = ccui . Widget . extend ( {
26+
27+ ctor : function ( path ) {
28+ ccui . Widget . prototype . ctor . call ( this ) ;
29+ if ( path )
30+ this . loadURL ( path ) ;
31+ this . _EventList = { } ;
32+ } ,
33+
34+
35+ setJavascriptInterfaceScheme : function ( scheme ) { } ,
36+ loadData : function ( data , MIMEType , encoding , baseURL ) { } ,
37+ loadHTMLString : function ( string , baseURL ) { } ,
38+
39+
40+ /**
41+ * Load an URL
42+ * @param {String } url
43+ */
44+ loadURL : function ( url ) {
45+ this . _renderCmd . updateURL ( url ) ;
46+ cc . eventManager . dispatchCustomEvent ( ccui . WebView . EventType . LOADING ) ;
47+ } ,
48+
49+ /**
50+ * Stop loading
51+ */
52+ stopLoading : function ( ) {
53+ cc . log ( "Web does not support loading" ) ;
54+ } ,
55+ reload : function ( ) {
56+ var iframe = this . _renderCmd . _iframe ;
57+ if ( iframe ) {
58+ var win = iframe . contentWindow ;
59+ if ( win && win . location )
60+ win . location . reload ( ) ;
61+ }
62+ } ,
63+
64+ /**
65+ * Determine whether to go back
66+ */
67+ canGoBack : function ( ) {
68+ cc . log ( "Web does not support query history" ) ;
69+ } ,
70+
71+ /**
72+ * Determine whether to go forward
73+ */
74+ canGoForward : function ( ) {
75+ cc . log ( "Web does not support query history" ) ;
76+ } ,
77+
78+ /**
79+ * go back
80+ */
81+ goBack : function ( ) {
82+ var iframe = this . _renderCmd . _iframe ;
83+ if ( iframe ) {
84+ var win = iframe . contentWindow ;
85+ if ( win && win . location )
86+ win . history . back ( ) ;
87+ }
88+ } ,
89+
90+ /**
91+ * go forward
92+ */
93+ goForward : function ( ) {
94+ var iframe = this . _renderCmd . _iframe ;
95+ if ( iframe ) {
96+ var win = iframe . contentWindow ;
97+ if ( win && win . location )
98+ win . history . forward ( ) ;
99+ }
100+ } ,
101+
102+ /**
103+ * In the webview execution within a period of js string
104+ * @param str
105+ */
106+ evaluateJS : function ( str ) {
107+ var iframe = this . _renderCmd . _iframe ;
108+ if ( iframe ) {
109+ var win = iframe . contentWindow ;
110+ try {
111+ win . eval ( str ) ;
112+ } catch ( err ) {
113+ console . error ( err ) ;
114+ }
115+ }
116+ } ,
117+
118+ /**
119+ * Limited scale
120+ */
121+ setScalesPageToFit : function ( ) {
122+ cc . log ( "Web does not support zoom" ) ;
123+ } ,
124+
125+ /**
126+ * The binding event
127+ * @param event string: load | loading | error Or: ccui.WebView.EventType
128+ * @param callback
129+ */
130+ addEventListener : function ( event , callback ) {
131+ if ( ! / ^ u i _ w e b v i e w _ / . test ( event ) )
132+ event = "ui_webview_" + event ;
133+ return cc . eventManager . addCustomListener ( event , callback ) ;
134+ } ,
135+
136+ /**
137+ * Delete events
138+ * @param event
139+ * @param callbackOrListener
140+ */
141+ removeEventListener : function ( event , callbackOrListener ) {
142+ var map , list ;
143+ if ( ! / ^ u i _ w e b v i e w _ / . test ( event ) )
144+ event = "ui_webview_" + event ;
145+ if ( typeof callbackOrListener === "function" ) {
146+ map = cc . eventManager . _listenersMap [ event ] ;
147+ if ( map ) {
148+ list = map . getFixedPriorityListeners ( ) ;
149+ list && cc . eventManager . _removeListenerInCallback ( list , callbackOrListener ) ;
150+ }
151+ } else {
152+ map = cc . eventManager . _listenersMap [ event ] ;
153+ if ( map ) {
154+ list = map . getFixedPriorityListeners ( ) ;
155+ list && cc . eventManager . _removeListenerInVector ( list , callbackOrListener ) ;
156+ }
157+ }
158+ } ,
159+
160+ //setOnShouldStartLoading: function(callback){},
161+ //setOnDidFinishLoading: function(){},
162+ //setOnDidFailLoading: function(){},
163+ //setOnJSCallback: function(){},
164+
165+ //getOnShouldStartLoading: function(){},
166+ //getOnDidFinishLoading: function(){},
167+ //getOnDidFailLoading: function(){},
168+ //getOnJSCallback: function(){},
169+
170+ _createRenderCmd : function ( ) {
171+ return new ccui . WebView . RenderCmd ( this ) ;
172+ } ,
173+
174+ setContentSize : function ( w , h ) {
175+ ccui . Widget . prototype . setContentSize . call ( this , w , h ) ;
176+ if ( h === undefined ) {
177+ h = w . height ;
178+ w = w . width ;
179+ }
180+ this . _renderCmd . changeSize ( w , h ) ;
181+ } ,
182+
183+ cleanup : function ( ) {
184+ this . _renderCmd . removeDom ( ) ;
185+ this . stopAllActions ( ) ;
186+ this . unscheduleAllCallbacks ( ) ;
187+ }
188+ } ) ;
189+
190+ ccui . WebView . EventType = {
191+ LOADING : "ui_webview_loading" ,
192+ LOADED : "ui_webview_load" ,
193+ ERROR : "ui_webview_error"
194+ } ;
195+
196+ ( function ( ) {
197+
198+ ccui . WebView . polyfill = {
199+ devicePixelRatio : false ,
200+ enableDiv : false
201+ } ;
202+
203+ if ( cc . sys . os === cc . sys . OS_IOS )
204+ ccui . WebView . polyfill . enableDiv = true ;
205+
206+ } ) ( ) ;
207+
208+ ( function ( polyfill ) {
209+
210+ ccui . WebView . RenderCmd = function ( node ) {
211+ cc . Node . CanvasRenderCmd . call ( this , node ) ;
212+
213+ this . _div = null ;
214+ this . _iframe = null ;
215+
216+ if ( polyfill . enableDiv ) {
217+ this . _div = document . createElement ( "div" ) ;
218+ this . _div . style [ "-webkit-overflow" ] = "auto" ;
219+ this . _div . style [ "-webkit-overflow-scrolling" ] = "touch" ;
220+ this . _iframe = document . createElement ( "iframe" ) ;
221+ this . _div . appendChild ( this . _iframe ) ;
222+ } else {
223+ this . _div = this . _iframe = document . createElement ( "iframe" ) ;
224+ }
225+ this . _iframe . addEventListener ( "load" , function ( ) {
226+ cc . eventManager . dispatchCustomEvent ( ccui . WebView . EventType . LOADED ) ;
227+ } ) ;
228+ this . _iframe . addEventListener ( "error" , function ( ) {
229+ cc . eventManager . dispatchCustomEvent ( ccui . WebView . EventType . ERROR ) ;
230+ } ) ;
231+ this . _div . style [ "background-color" ] = "#FFF" ;
232+ this . _div . style . height = "200px" ;
233+ this . _div . style . width = "300px" ;
234+ this . _div . style . overflow = "scroll" ;
235+ this . _listener = null ;
236+ this . initStyle ( ) ;
237+ } ;
238+
239+ var proto = ccui . WebView . RenderCmd . prototype = Object . create ( cc . Node . CanvasRenderCmd . prototype ) ;
240+ proto . constructor = ccui . WebView . RenderCmd ;
241+
242+ proto . updateStatus = function ( ) {
243+ polyfill . devicePixelRatio = cc . view . isRetinaEnabled ( ) ;
244+ var flags = cc . Node . _dirtyFlags , locFlag = this . _dirtyFlag ;
245+ if ( locFlag & flags . transformDirty ) {
246+ //update the transform
247+ this . transform ( this . getParentRenderCmd ( ) , true ) ;
248+ this . updateMatrix ( this . _worldTransform , cc . view . _scaleX , cc . view . _scaleY ) ;
249+ this . _dirtyFlag = this . _dirtyFlag & cc . Node . _dirtyFlags . transformDirty ^ this . _dirtyFlag ;
250+ }
251+ } ;
252+
253+ proto . visit = function ( ) {
254+ var self = this ,
255+ container = cc . container ,
256+ eventManager = cc . eventManager ;
257+ if ( this . _node . _visible ) {
258+ container . appendChild ( this . _div ) ;
259+ if ( this . _listener === null )
260+ this . _listener = eventManager . addCustomListener ( cc . game . EVENT_RESIZE , function ( ) {
261+ self . resize ( ) ;
262+ } ) ;
263+ } else {
264+ var hasChild = false ;
265+ if ( 'contains' in container ) {
266+ hasChild = container . contains ( this . _div ) ;
267+ } else {
268+ hasChild = container . compareDocumentPosition ( this . _div ) % 16 ;
269+ }
270+ if ( hasChild )
271+ container . removeChild ( this . _div ) ;
272+ var list = eventManager . _listenersMap [ cc . game . EVENT_RESIZE ] . getFixedPriorityListeners ( ) ;
273+ eventManager . _removeListenerInVector ( list , this . _listener ) ;
274+ this . _listener = null ;
275+ }
276+ this . updateStatus ( ) ;
277+ this . resize ( cc . view ) ;
278+ } ;
279+
280+ proto . resize = function ( view ) {
281+ view = view || cc . view ;
282+ var node = this . _node ,
283+ eventManager = cc . eventManager ;
284+ if ( node . _parent && node . _visible )
285+ this . updateMatrix ( this . _worldTransform , view . _scaleX , view . _scaleY ) ;
286+ else {
287+ var list = eventManager . _listenersMap [ cc . game . EVENT_RESIZE ] . getFixedPriorityListeners ( ) ;
288+ eventManager . _removeListenerInVector ( list , this . _listener ) ;
289+ this . _listener = null ;
290+ }
291+ } ;
292+
293+ proto . updateMatrix = function ( t , scaleX , scaleY ) {
294+ var node = this . _node ;
295+ if ( polyfill . devicePixelRatio && scaleX !== 1 && scaleX !== 1 ) {
296+ var dpr = window . devicePixelRatio ;
297+ scaleX = scaleX / dpr ;
298+ scaleY = scaleY / dpr ;
299+ }
300+ if ( this . _loaded === false ) return ;
301+ var cw = node . _contentSize . width ,
302+ ch = node . _contentSize . height ;
303+ var a = t . a * scaleX ,
304+ b = t . b ,
305+ c = t . c ,
306+ d = t . d * scaleY ,
307+ tx = t . tx * scaleX - cw / 2 + cw * node . _scaleX / 2 * scaleX ,
308+ ty = t . ty * scaleY - ch / 2 + ch * node . _scaleY / 2 * scaleY ;
309+ var matrix = "matrix(" + a + "," + b + "," + c + "," + d + "," + tx + "," + - ty + ")" ;
310+ this . _div . style [ "transform" ] = matrix ;
311+ this . _div . style [ "-webkit-transform" ] = matrix ;
312+ } ;
313+
314+ proto . initStyle = function ( ) {
315+ if ( ! this . _div ) return ;
316+ var div = this . _div ;
317+ div . style . position = "absolute" ;
318+ div . style . bottom = "0px" ;
319+ div . style . left = "0px" ;
320+ } ;
321+
322+ proto . updateURL = function ( url ) {
323+ var iframe = this . _iframe ;
324+ iframe . src = url ;
325+ var self = this ;
326+ var cb = function ( ) {
327+ self . _loaded = true ;
328+ iframe . removeEventListener ( "load" , cb ) ;
329+ } ;
330+ iframe . addEventListener ( "load" , cb ) ;
331+ } ;
332+
333+ proto . changeSize = function ( w , h ) {
334+ var div = this . _div ;
335+ if ( div ) {
336+ div . style [ "width" ] = w + "px" ;
337+ div . style [ "height" ] = h + "px" ;
338+ }
339+ } ;
340+
341+ proto . removeDom = function ( ) {
342+ var div = this . _div ;
343+ if ( div ) {
344+ var hasChild = false ;
345+ if ( 'contains' in cc . container ) {
346+ hasChild = cc . container . contains ( div ) ;
347+ } else {
348+ hasChild = cc . container . compareDocumentPosition ( div ) % 16 ;
349+ }
350+ if ( hasChild )
351+ cc . container . removeChild ( div ) ;
352+ }
353+ } ;
354+
355+ } ) ( ccui . WebView . polyfill ) ;
0 commit comments