1 /**************************************************************************** 2 Copyright (c) 2010-2012 cocos2d-x.org 3 Copyright (c) 2008-2010 Ricardo Quesada 4 Copyright (c) 2011 Zynga Inc. 5 6 http://www.cocos2d-x.org 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy 9 of this software and associated documentation files (the "Software"), to deal 10 in the Software without restriction, including without limitation the rights 11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 copies of the Software, and to permit persons to whom the Software is 13 furnished to do so, subject to the following conditions: 14 15 The above copyright notice and this permission notice shall be included in 16 all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 THE SOFTWARE. 25 ****************************************************************************/ 26 27 /** 28 * create a webgl context 29 * @param {HTMLCanvasElement} canvas 30 * @param {Object} opt_attribs 31 * @return {WebGLRenderingContext} 32 */ 33 cc.create3DContext = function (canvas, opt_attribs) { 34 var names = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"]; 35 var context = null; 36 for (var ii = 0; ii < names.length; ++ii) { 37 try { 38 context = canvas.getContext(names[ii], opt_attribs); 39 } catch (e) { 40 } 41 if (context) { 42 break; 43 } 44 } 45 return context; 46 }; 47 48 /** 49 * Browser detection, based on mootools<br/> 50 * platform will print out win32, mac, etc<br/> 51 * type is the browser type, chrome, firefox etc 52 * @type {Object} 53 */ 54 cc.Browser = {}; 55 56 /** 57 * Browsers that Cocos2d-HTML5 support well in WebGL render mode 58 * @type {Array} 59 */ 60 cc.Browser.webglWhiteList = ["baidubrowser", "opera", "firefox", "chrome", "safari"]; 61 62 (function () { 63 var ua = navigator.userAgent; 64 cc.Browser.ua = ua.toLowerCase(); 65 cc.Browser.platform = navigator.platform.toLowerCase(); 66 cc.Browser.isMobile = (cc.Browser.ua.indexOf('mobile') != -1 || cc.Browser.ua.indexOf('android') != -1); 67 cc.Browser.type = (function () { 68 var browserTypes = cc.Browser.ua.match(/micromessenger|qqbrowser|mqqbrowser|ucbrowser|360browser|baidubrowser|maxthon|ie|opera|firefox/) || cc.Browser.ua.match(/chrome|safari/); 69 if (browserTypes && browserTypes.length > 0) { 70 var el = browserTypes[0]; 71 if (el == 'micromessenger') { 72 return 'wechat'; 73 } 74 return el; 75 } 76 return "unknow"; 77 })(); 78 cc.Browser.mode = cc.Browser.type == 'ie' && document.documentMode; 79 80 if (!document["ccConfig"]) 81 document["ccConfig"] = {}; 82 83 var c = document["ccConfig"]; 84 // check supportWebGL item 85 cc._userRenderMode = parseInt(c["renderMode"]) || 0; 86 87 var notInWhiteList = cc.Browser.webglWhiteList.indexOf(cc.Browser.type) == -1; 88 if (cc._userRenderMode === 1 || (cc._userRenderMode === 0 && (cc.Browser.isMobile || notInWhiteList))) { 89 //canvas only 90 cc.Browser.supportWebGL = false; 91 } else { 92 // WebGL first 93 cc.Browser.supportWebGL = !(window.WebGLRenderingContext == null); 94 var tempCanvas = document.createElement("Canvas"); 95 var tempContext = cc.create3DContext(tempCanvas, {'stencil': true, 'preserveDrawingBuffer': true }); 96 cc.Browser.supportWebGL = !(tempContext == null) 97 } 98 if (cc._userRenderMode === 2 && !cc.Browser.supportWebGL) { 99 // WebGL render only, but browser doesn't support WebGL. 100 cc.__renderDoesnotSupport = true; 101 } 102 103 // check if browser supports Web Audio 104 cc.Browser.supportWebAudio = (function () { 105 // check Web Audio's context 106 try { 107 var ctx = new (window.AudioContext || window.webkitAudioContext || window.mozAudioContext)(); 108 return ctx ? true : false; 109 } catch (e) { 110 return false; 111 } 112 })(); 113 114 115 cc.Browser.openURL = function (url) { 116 if (this.isMobile) { 117 var size = cc.Director.getInstance().getWinSize(); 118 var w = size.width + "px"; 119 var h = size.height + "px"; 120 121 var div = cc.$new("div"); 122 div.style.backgroundColor = "#ffffff"; 123 div.style.width = w; 124 div.style.height = h; 125 div.style.zindex = 1000; 126 div.style.position = 'absolute'; 127 div.style.top = 0 + 'px'; 128 div.style.left = 0 + 'px'; 129 div.id = "cocos2d-browser"; 130 131 var iframe = cc.$new("iframe"); 132 iframe.src = url; 133 iframe.style.width = w; 134 iframe.style.height = h; 135 iframe.setAttribute("frameborder", "no"); 136 iframe.setAttribute("scrolling", "no"); 137 div.appendChild(iframe); 138 139 iframe.onload = function () { 140 var close = document.createElement('img'); 141 close.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAhCAYAAABX5MJvAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo5OERBMEM3OUQzRTMxMUUyODg2Q0RFNjU1QkU1RjlFQSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo5OERBMEM3QUQzRTMxMUUyODg2Q0RFNjU1QkU1RjlFQSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjk4REEwQzc3RDNFMzExRTI4ODZDREU2NTVCRTVGOUVBIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjk4REEwQzc4RDNFMzExRTI4ODZDREU2NTVCRTVGOUVBIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+NwBuoAAAA/tJREFUeNrEWF0sW3EUb6+28zFhbGadsBaNhazV+kpDYhFWKRGWbHvwFV5IvPiIFw9evElEPEiWSUgsIWoIglhmUomPxj6aKC0zKVJjtPU5o9j5J7dLdbf33jKc5Jfc3v+v5/+755x7/j1lMoiNBRDh4AO88HvO2m+ACbAC+AJQAyz2JCbBFyMBWQA/xv+3DUAXLuivudhcY4BMwCuAB+NqDPmNAnAAOsCZvQgk4BnjeiwEwAbM2YoQA14yrteQEANgDcML7gXjZgw9OAuJkADu3JAIb7Q/hr+GtCwuLs6LDq+iooLvhBAREhFEl11ZWRne0tIiIeNIpVKv4uJi4dTUVApNt0EY3ohILSIiwqO7u1sql8vD8vLyJJ2dnXH2HDabzczPz3/Y1taWzOfz78XExDxSq9Vyd3d3jMK9F2pWr6lEtLa2RmVnZ4tt7w0NDWlTU1OVtkK7urqSQ0NDzzW5hYWFjcTExAGDwXDkyD+VSkZ7e3tsWlpamP19mUwWplQqk9B1UlKST3NzczxE4K49D4mCiDwn24PyPMjIyHjs6urKIVpLSEgInp6eZsM6Kzw8nEvEMZvNBxC1BbI9KCMhkUgUy8vLRpL1QIFA4EcSyZmcnJzpS4mYnZ3dj46O7p2fn193xIGi/CeiFovlFIp5pqGhYZ5qD1qFiQxCjk1OTsqEQmEAFReloL+/X0sVAadFWE2n02VA+O+TcVZXV01QkO8ODw9P6fjEnO2zvb2936g4XC7XG4rWm65P2iL8/f05kN8nBQUFQkqnGMYcGBjIys3N5dLxjY7ydDrE6urqsNLSUqmbmxuH1tOBkMzMTIHRaNxSqVTmS4soKyvjFRUViTw9PV2dTR901WAOh7M/MjKyeeHCbGpqEhcWFkY5Wl9aWtpUKBRaONziSbsii/Xm5OTk7EIdU6/X7zpaW1xc/Al5HxkfH9/e2dk5rqmpeUrE6+vr06ADzpEIlI5kMjFwPhh5PB5DJBKdK7KDg4Oj2tpaVUdHxw/0eWxszIjyj8Jvy4N60FdVVX2Grnt4dkaowYJESAG3yaLR09Oz5uvrexwbGxuAR2erpKTkI6RqxW5DM6RnLT09PQQV5vDwsDYlJWUU+I4EIDMhEQLAA6q0DA4OrqMCg/c/qL6+XtXY2Kgn4sGJuavRaFbFYrFPeXn5FIj6ReFa64KnIpJOpaMK39vbM9XV1X13lF9kc3Nz+xMTEwZo89s03A4ycRE1N/RjF/WPKgyfDRU39Gu7w1qYyNYAtwDB1yhgGPDBfgzU4bMi7xoEjAI6iWZRdGMGH80Cr2goRlP5W8B7qwBHfw1YO6kEH4yC8EnJ5QKbnuDFh17nr4BPRP9P/BFgAHo7ZNgI9EbHAAAAAElFTkSuQmCC"; 142 div.appendChild(close); 143 close.style.zindex = 1000; 144 close.style.position = 'absolute'; 145 close.style.bottom = 10 + 'px'; 146 close.style.right = 10 + 'px'; 147 close.onclick = function () { 148 div.remove(); 149 } 150 }; 151 152 var tag = document['ccConfig'].tag; 153 var parent = document.getElementById(tag).parentNode; 154 if (parent) { 155 parent.appendChild(div); 156 } 157 } 158 else { 159 window.open(url); 160 } 161 } 162 })(); 163 164 cc.RenderDoesnotSupport = function () { 165 if (cc.__renderDoesnotSupport === "undefined") 166 return false; 167 return cc.__renderDoesnotSupport; 168 }; 169 170 171 /** 172 * the dollar sign, classic like jquery, this selector add extra methods to HTMLElement without touching its prototype</br> 173 * it is also chainable like jquery 174 * @param {HTMLElement|String} x pass in a css selector in string or the whole HTMLElement 175 * @class 176 * @return {cc.$} 177 */ 178 cc.$ = function (x) { 179 /** @lends cc.$# */ 180 var parent = (this == cc) ? document : this; 181 182 /** 183 * @type {HTMLElement} 184 */ 185 var el = (x instanceof HTMLElement) ? x : parent.querySelector(x); 186 187 if (el) { 188 /** 189 * find and return the child wth css selector (same as jquery.find) 190 * @param {HTMLElement|String} x pass in a css selector in string or the whole HTMLElement 191 * @return {cc.$} 192 */ 193 el.find = el.find || cc.$; 194 /** 195 * check if a DOMNode has a specific class 196 * @param {String} cls 197 * @return {Boolean} 198 */ 199 el.hasClass = el.hasClass || function (cls) { 200 return this.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')); 201 }; 202 /** 203 * add a class to a DOMNode, returns self to allow chaining 204 * @param {String} cls 205 * @return {cc.$} 206 */ 207 el.addClass = el.addClass || function (cls) { 208 if (!this.hasClass(cls)) { 209 if (this.className) { 210 this.className += " "; 211 } 212 this.className += cls; 213 } 214 return this; 215 }; 216 /** 217 * remove a specific class from a DOMNode, returns self to allow chaining 218 * @param {String} cls 219 * @return {cc.$} 220 */ 221 el.removeClass = el.removeClass || function (cls) { 222 if (this.hasClass(cls)) { 223 this.className = this.className.replace(cls, ''); 224 } 225 return this; 226 }; 227 /** 228 * detach it self from parent 229 * @function 230 */ 231 el.remove = el.remove || function () { 232 if (this.parentNode) 233 this.parentNode.removeChild(this); 234 return this; 235 }; 236 237 /** 238 * add to another element as a child 239 * @param {HTMLElement|cc.$} x 240 * @return {cc.$} 241 */ 242 el.appendTo = el.appendTo || function (x) { 243 x.appendChild(this); 244 return this; 245 }; 246 247 /** 248 * add to another element as a child and place on the top of the children list 249 * @param {HTMLElement|cc.$} x 250 * @return {cc.$} 251 */ 252 el.prependTo = el.prependTo || function (x) { 253 ( x.childNodes[0]) ? x.insertBefore(this, x.childNodes[0]) : x.appendChild(this); 254 return this; 255 }; 256 257 /** 258 * helper function for updating the css transform 259 * @return {cc.$} 260 */ 261 el.transforms = el.transforms || function () { 262 this.style[cc.$.trans] = cc.$.translate(this.position) + cc.$.rotate(this.rotation) + cc.$.scale(this.scale) + cc.$.skew(this.skew); 263 return this; 264 }; 265 266 el.position = el.position || {x: 0, y: 0}; 267 el.rotation = el.rotation || 0; 268 el.scale = el.scale || {x: 1, y: 1}; 269 el.skew = el.skew || {x: 0, y: 0}; 270 271 /** 272 * move the element 273 * @param {Number} x in pixel 274 * @param {Number} y in pixel 275 * @return {cc.$} 276 */ 277 el.translates = function (x, y) { 278 this.position.x = x; 279 this.position.y = y; 280 this.transforms(); 281 return this 282 }; 283 284 /** 285 * rotate the element 286 * @param {Number} x in degrees 287 * @return {cc.$} 288 */ 289 el.rotate = function (x) { 290 this.rotation = x; 291 this.transforms(); 292 return this 293 }; 294 295 /** 296 * resize the element 297 * @param {Number} x 298 * @param {Number} y 299 * @return {cc.$} 300 */ 301 el.resize = function (x, y) { 302 this.scale.x = x; 303 this.scale.y = y; 304 this.transforms(); 305 return this 306 }; 307 308 /** 309 * skews the element 310 * @param {Number} x in degrees 311 * @param {Number} y 312 * @return {cc.$} 313 */ 314 el.setSkew = function (x, y) { 315 this.skew.x = x; 316 this.skew.y = y; 317 this.transforms(); 318 return this 319 }; 320 } 321 return el; 322 }; 323 //getting the prefix and css3 3d support 324 switch (cc.Browser.type) { 325 case "firefox": 326 cc.$.pfx = "Moz"; 327 cc.$.hd = true; 328 break; 329 case "chrome": 330 case "safari": 331 cc.$.pfx = "webkit"; 332 cc.$.hd = true; 333 break; 334 case "opera": 335 cc.$.pfx = "O"; 336 cc.$.hd = false; 337 break; 338 case "ie": 339 cc.$.pfx = "ms"; 340 cc.$.hd = false; 341 break; 342 default: 343 cc.$.pfx = "webkit"; 344 cc.$.hd = true; 345 } 346 //cache for prefixed transform 347 cc.$.trans = cc.$.pfx + "Transform"; 348 //helper function for constructing transform strings 349 cc.$.translate = (cc.$.hd) ? function (a) { 350 return "translate3d(" + a.x + "px, " + a.y + "px, 0) " 351 } : function (a) { 352 return "translate(" + a.x + "px, " + a.y + "px) " 353 }; 354 cc.$.rotate = (cc.$.hd) ? function (a) { 355 return "rotateZ(" + a + "deg) "; 356 } : function (a) { 357 return "rotate(" + a + "deg) "; 358 }; 359 cc.$.scale = function (a) { 360 return "scale(" + a.x + ", " + a.y + ") " 361 }; 362 cc.$.skew = function (a) { 363 return "skewX(" + -a.x + "deg) skewY(" + a.y + "deg)"; 364 }; 365 366 367 /** 368 * Creates a new element, and adds cc.$ methods 369 * @param {String} x name of the element tag to create 370 * @return {cc.$} 371 */ 372 cc.$new = function (x) { 373 return cc.$(document.createElement(x)) 374 }; 375 cc.$.findpos = function (obj) { 376 var curleft = 0; 377 var curtop = 0; 378 do { 379 curleft += obj.offsetLeft; 380 curtop += obj.offsetTop; 381 } while (obj = obj.offsetParent); 382 return {x: curleft, y: curtop}; 383 }; 384