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 (function () { 56 var ua = navigator.userAgent; 57 cc.Browser.ua = ua.toLowerCase(); 58 cc.Browser.platform = navigator.platform.toLowerCase(); 59 cc.Browser.isMobile = (cc.Browser.ua.indexOf('mobile') != -1 || cc.Browser.ua.indexOf('android') != -1); 60 cc.Browser.type = (function () { 61 var browserTypes = cc.Browser.ua.match(/micromessenger|qqbrowser|mqqbrowser|ucbrowser|360browser|baidubrowser|maxthon|ie|opera|firefox/) || cc.Browser.ua.match(/chrome|safari/); 62 if (browserTypes && browserTypes.length > 0) { 63 var el = browserTypes[0]; 64 if (el == 'micromessenger') { 65 return 'wechat'; 66 } 67 return el; 68 } 69 return "unknow"; 70 })(); 71 cc.Browser.mode = cc.Browser.type == 'ie' && document.documentMode; 72 73 if (!document["ccConfig"]) 74 document["ccConfig"] = {}; 75 76 var c = document["ccConfig"]; 77 // check supportWebGL item 78 cc._userRenderMode = parseInt(c["renderMode"]) || 0; 79 80 if (cc._userRenderMode === 1 || (cc._userRenderMode === 0 && cc.Browser.isMobile)) { 81 //canvas only 82 cc.Browser.supportWebGL = false; 83 } else { 84 // WebGL first 85 cc.Browser.supportWebGL = !(window.WebGLRenderingContext == null); 86 var tempCanvas = document.createElement("Canvas"); 87 var tempContext = cc.create3DContext(tempCanvas, {'stencil': true, 'preserveDrawingBuffer': true }); 88 cc.Browser.supportWebGL = !(tempContext == null) 89 } 90 if (cc._userRenderMode === 2 && !cc.Browser.supportWebGL) { 91 // WebGL render only, but browser doesn't support WebGL. 92 cc.__renderDoesnotSupport = true; 93 } 94 95 // check if browser supports Web Audio 96 cc.Browser.supportWebAudio = (function () { 97 // check Web Audio's context 98 try { 99 var ctx = new (window.AudioContext || window.webkitAudioContext || window.mozAudioContext)(); 100 return ctx ? true : false; 101 } catch (e) { 102 return false; 103 } 104 })(); 105 106 107 cc.Browser.openURL = function (url) { 108 if (this.isMobile) { 109 var size = cc.Director.getInstance().getWinSize(); 110 var w = size.width + "px"; 111 var h = size.height + "px"; 112 113 var div = cc.$new("div"); 114 div.style.backgroundColor = "#ffffff"; 115 div.style.width = w; 116 div.style.height = h; 117 div.style.zindex = 1000; 118 div.style.position = 'absolute'; 119 div.style.top = 0 + 'px'; 120 div.style.left = 0 + 'px'; 121 div.id = "cocos2d-browser"; 122 123 var iframe = cc.$new("iframe"); 124 iframe.src = url; 125 iframe.style.width = w; 126 iframe.style.height = h; 127 iframe.setAttribute("frameborder", "no"); 128 iframe.setAttribute("scrolling", "no"); 129 div.appendChild(iframe); 130 131 iframe.onload = function () { 132 var close = new Image(); 133 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"; 134 div.appendChild(close); 135 close.style.zindex = 1000; 136 close.style.position = 'absolute'; 137 close.style.bottom = 10 + 'px'; 138 close.style.right = 10 + 'px'; 139 close.onclick = function () { 140 div.remove(); 141 } 142 }; 143 144 var tag = document['ccConfig'].tag; 145 var parent = document.getElementById(tag).parentNode; 146 if (parent) { 147 parent.appendChild(div); 148 } 149 } 150 else { 151 window.open(url); 152 } 153 } 154 })(); 155 156 cc.RenderDoesnotSupport = function () { 157 if (cc.__renderDoesnotSupport === "undefined") 158 return false; 159 return cc.__renderDoesnotSupport; 160 }; 161 162 163 /** 164 * the dollar sign, classic like jquery, this selector add extra methods to HTMLElement without touching its prototype</br> 165 * it is also chainable like jquery 166 * @param {HTMLElement|String} x pass in a css selector in string or the whole HTMLElement 167 * @class 168 * @return {cc.$} 169 */ 170 cc.$ = function (x) { 171 /** @lends cc.$# */ 172 var parent = (this == cc) ? document : this; 173 174 /** 175 * @type {HTMLElement} 176 */ 177 var el = (x instanceof HTMLElement) ? x : parent.querySelector(x); 178 179 if (el) { 180 /** 181 * find and return the child wth css selector (same as jquery.find) 182 * @param {HTMLElement|String} x pass in a css selector in string or the whole HTMLElement 183 * @return {cc.$} 184 */ 185 el.find = el.find || cc.$; 186 /** 187 * check if a DOMNode has a specific class 188 * @param {String} cls 189 * @return {Boolean} 190 */ 191 el.hasClass = el.hasClass || function (cls) { 192 return this.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')); 193 }; 194 /** 195 * add a class to a DOMNode, returns self to allow chaining 196 * @param {String} cls 197 * @return {cc.$} 198 */ 199 el.addClass = el.addClass || function (cls) { 200 if (!this.hasClass(cls)) { 201 if (this.className) { 202 this.className += " "; 203 } 204 this.className += cls; 205 } 206 return this; 207 }; 208 /** 209 * remove a specific class from a DOMNode, returns self to allow chaining 210 * @param {String} cls 211 * @return {cc.$} 212 */ 213 el.removeClass = el.removeClass || function (cls) { 214 if (this.hasClass(cls)) { 215 this.className = this.className.replace(cls, ''); 216 } 217 return this; 218 }; 219 /** 220 * detach it self from parent 221 * @function 222 */ 223 el.remove = el.remove || function () { 224 if (this.parentNode) 225 this.parentNode.removeChild(this); 226 return this; 227 }; 228 229 /** 230 * add to another element as a child 231 * @param {HTMLElement|cc.$} x 232 * @return {cc.$} 233 */ 234 el.appendTo = el.appendTo || function (x) { 235 x.appendChild(this); 236 return this; 237 }; 238 239 /** 240 * add to another element as a child and place on the top of the children list 241 * @param {HTMLElement|cc.$} x 242 * @return {cc.$} 243 */ 244 el.prependTo = el.prependTo || function (x) { 245 ( x.childNodes[0]) ? x.insertBefore(this, x.childNodes[0]) : x.appendChild(this); 246 return this; 247 }; 248 249 /** 250 * helper function for updating the css transform 251 * @return {cc.$} 252 */ 253 el.transforms = el.transforms || function () { 254 this.style[cc.$.trans] = cc.$.translate(this.position) + cc.$.rotate(this.rotation) + cc.$.scale(this.scale) + cc.$.skew(this.skew); 255 return this; 256 }; 257 258 el.position = el.position || {x: 0, y: 0}; 259 el.rotation = el.rotation || 0; 260 el.scale = el.scale || {x: 1, y: 1}; 261 el.skew = el.skew || {x: 0, y: 0}; 262 263 /** 264 * move the element 265 * @param {Number} x in pixel 266 * @param {Number} y in pixel 267 * @return {cc.$} 268 */ 269 el.translates = function (x, y) { 270 this.position.x = x; 271 this.position.y = y; 272 this.transforms(); 273 return this 274 }; 275 276 /** 277 * rotate the element 278 * @param {Number} x in degrees 279 * @return {cc.$} 280 */ 281 el.rotate = function (x) { 282 this.rotation = x; 283 this.transforms(); 284 return this 285 }; 286 287 /** 288 * resize the element 289 * @param {Number} x 290 * @param {Number} y 291 * @return {cc.$} 292 */ 293 el.resize = function (x, y) { 294 this.scale.x = x; 295 this.scale.y = y; 296 this.transforms(); 297 return this 298 }; 299 300 /** 301 * skews the element 302 * @param {Number} x in degrees 303 * @param {Number} y 304 * @return {cc.$} 305 */ 306 el.setSkew = function (x, y) { 307 this.skew.x = x; 308 this.skew.y = y; 309 this.transforms(); 310 return this 311 }; 312 } 313 return el; 314 }; 315 //getting the prefix and css3 3d support 316 switch (cc.Browser.type) { 317 case "firefox": 318 cc.$.pfx = "Moz"; 319 cc.$.hd = true; 320 break; 321 case "chrome": 322 case "safari": 323 cc.$.pfx = "webkit"; 324 cc.$.hd = true; 325 break; 326 case "opera": 327 cc.$.pfx = "O"; 328 cc.$.hd = false; 329 break; 330 case "ie": 331 cc.$.pfx = "ms"; 332 cc.$.hd = false; 333 break; 334 default: 335 cc.$.pfx = "webkit"; 336 cc.$.hd = true; 337 } 338 //cache for prefixed transform 339 cc.$.trans = cc.$.pfx + "Transform"; 340 //helper function for constructing transform strings 341 cc.$.translate = (cc.$.hd) ? function (a) { 342 return "translate3d(" + a.x + "px, " + a.y + "px, 0) " 343 } : function (a) { 344 return "translate(" + a.x + "px, " + a.y + "px) " 345 }; 346 cc.$.rotate = (cc.$.hd) ? function (a) { 347 return "rotateZ(" + a + "deg) "; 348 } : function (a) { 349 return "rotate(" + a + "deg) "; 350 }; 351 cc.$.scale = function (a) { 352 return "scale(" + a.x + ", " + a.y + ") " 353 }; 354 cc.$.skew = function (a) { 355 return "skewX(" + -a.x + "deg) skewY(" + a.y + "deg)"; 356 }; 357 358 359 /** 360 * Creates a new element, and adds cc.$ methods 361 * @param {String} x name of the element tag to create 362 * @return {cc.$} 363 */ 364 cc.$new = function (x) { 365 return cc.$(document.createElement(x)) 366 }; 367 cc.$.findpos = function (obj) { 368 var curleft = 0; 369 var curtop = 0; 370 do { 371 curleft += obj.offsetLeft; 372 curtop += obj.offsetTop; 373 } while (obj = obj.offsetParent); 374 return {x: curleft, y: curtop}; 375 }; 376