1 
  2 /**
  3  * @namespace Hilo的基础核心方法集合。
  4  * @static
  5  * @module hilo/core/Hilo
  6  */
  7 var Hilo = (function(){
  8 
  9 var win = window, doc = document, docElem = doc.documentElement,
 10     uid = 0;
 11 
 12 return {
 13     /**
 14      * 获取一个全局唯一的id。如Stage1,Bitmap2等。
 15      * @param {String} prefix 生成id的前缀。
 16      */
 17     getUid: function(prefix){
 18         var id = ++uid;
 19         if(prefix){
 20             var charCode = prefix.charCodeAt(prefix.length - 1);
 21             if (charCode >= 48 && charCode <= 57) prefix += "_"; // 0至9之间添加下划线
 22             return prefix + id;
 23         }
 24         return id;
 25     },
 26 
 27     /**
 28      * 为指定的可视对象生成一个包含路径的字符串表示形式。如Stage1.Container2.Bitmap3。
 29      * @param {View} view 指定的可视对象。
 30      */
 31     viewToString: function(view){
 32         var result, obj = view;
 33         while(obj){
 34             result = result ? (obj.id + '.' + result) : obj.id;
 35             obj = obj.parent;
 36         }
 37         return result;
 38     },
 39 
 40     /**
 41      * 简单的浅复制对象。
 42      * @param {Object} target 要复制的目标对象。
 43      * @param {Object} source 要复制的源对象。
 44      * @param {Boolean} strict 指定是否覆盖已有属性,默认为false,即不覆盖。
 45      */
 46     copy: function(target, source, strict){ 
 47         for(var key in source){
 48             if(!strict || target.hasOwnProperty(key) || target[key] !== undefined){
 49                 target[key] = source[key];
 50             }
 51         }
 52         return target;
 53     },
 54 
 55     /**
 56      * 浏览器特性。
 57      */
 58     browser: (function(){
 59         var ua = navigator.userAgent;
 60         var data = {
 61             iphone: /iphone/i.test(ua),
 62             ipad: /ipad/i.test(ua),
 63             ipod: /ipod/i.test(ua),
 64             android: /android/i.test(ua),
 65             webkit: /webkit/i.test(ua),
 66             chrome: /chrome/i.test(ua),
 67             safari: /safari/i.test(ua),
 68             firefox: /firefox/i.test(ua),
 69             ie: /msie/i.test(ua),
 70             opera: /opera/i.test(ua),
 71             supportTouch: 'ontouchstart' in win,
 72             supportCanvas: doc.createElement('canvas').getContext != null,
 73             supportStorage: false,
 74             supportOrientation: 'orientation' in win,
 75             supportDeviceMotion: 'ondevicemotion' in win
 76         };
 77 
 78         //`localStorage` is null or `localStorage.setItem` throws error in some cases (e.g. localStorage is disabled)
 79         try{
 80             var value = 'hilo';
 81             localStorage.setItem(value, value);
 82             localStorage.removeItem(value);
 83             data.supportStorage = true;
 84         }catch(e){ };
 85 
 86         //vendro prefix
 87         var jsVendor = data.jsVendor = data.webkit ? 'webkit' : data.firefox ? 'Moz' : data.opera ? 'O' : data.ie ? 'ms' : '';
 88         var cssVendor = data.cssVendor = '-' + jsVendor + '-';
 89 
 90         //css transform/3d feature dectection
 91         var testElem = doc.createElement('div'), style = testElem.style;
 92         var supportTransform = style[jsVendor + 'Transform'] != undefined;
 93         var supportTransform3D = style[jsVendor + 'Perspective'] != undefined;
 94         if(supportTransform3D){
 95             testElem.id = 'test3d';
 96             style = doc.createElement('style');
 97             style.textContent = '@media ('+ cssVendor +'transform-3d){#test3d{height:3px}}';
 98             doc.head.appendChild(style);
 99 
100             docElem.appendChild(testElem);
101             supportTransform3D = testElem.offsetHeight == 3;
102             doc.head.removeChild(style);
103             docElem.removeChild(testElem);
104         };
105         data.supportTransform = supportTransform;
106         data.supportTransform3D = supportTransform3D;
107 
108         return data;
109     })(),
110 
111     /**
112      * 事件类型枚举对象。
113      */
114     event: (function(){
115         var supportTouch = 'ontouchstart' in win;
116         return {
117             POINTER_START: supportTouch ? 'touchstart' : 'mousedown',
118             POINTER_MOVE: supportTouch ? 'touchmove' : 'mousemove',
119             POINTER_END: supportTouch ? 'touchend' : 'mouseup'
120         };
121     })(),
122 
123     /**
124      * 获取DOM元素在页面中的内容显示区域。
125      * @param {HTMLElement} elem DOM元素。
126      * @returns {Object} DOM元素的现实区域。格式为:{left:0, top:0, width:100, height:100}。
127      */
128     getElementRect: function(elem){
129         try{
130             //this fails if it's a disconnected DOM node
131             var bounds = elem.getBoundingClientRect();
132         }catch(e){
133             bounds = {top: elem.offsetTop, left: elem.offsetLeft, width:elem.offsetWidth, height:elem.offsetHeight};
134         }
135 
136         var offsetX = (win.pageXOffset || docElem.scrollLeft) - (docElem.clientLeft || 0);
137         var offsetY = (win.pageYOffset || docElem.scrollTop) - (docElem.clientTop || 0);
138         var styles = win.getComputedStyle ? getComputedStyle(elem) : elem.currentStyle;
139         var parseIntFn = parseInt;
140         var padLeft = parseIntFn(styles.paddingLeft) + parseIntFn(styles.borderLeftWidth);
141         var padTop = parseIntFn(styles.paddingTop) + parseIntFn(styles.borderTopWidth);
142         var padRight = parseIntFn(styles.paddingRight) + parseIntFn(styles.borderRightWidth);
143         var padBottom = parseIntFn(styles.paddingBottom) + parseIntFn(styles.borderBottomWidth);
144 
145         return {
146             left: bounds.left + offsetX + padLeft,
147             top: bounds.top + offsetY + padTop,
148             width: bounds.right - padRight - bounds.left - padLeft,
149             height: bounds.bottom - padBottom - bounds.top - padTop
150         };
151     },
152 
153     /**
154      * 创建一个DOM元素。可指定属性和样式。
155      * @param {String} type 要创建的DOM元素的类型。比如:'div'。
156      * @param {Object} properties 指定DOM元素的属性和样式。
157      * @returns {HTMLElement} 一个DOM元素。
158      */
159     createElement: function(type, properties){
160         var elem = doc.createElement(type), p, val, s;
161         for(p in properties){
162             val = properties[p];
163             if(p === 'style'){
164                 for(s in val) elem.style[s] = val[s];
165             }else{
166                 elem[p] = val;
167             }
168         }
169         return elem;
170     },
171 
172     /**
173      * 根据参数id获取一个DOM元素。此方法等价于document.getElementById(id)。
174      * @param {String} 要获取的DOM元素的id。
175      * @returns {HTMLElement} 一个DOM元素。
176      */
177     getElement: function(id){
178         return doc.getElementById(id);
179     },
180 
181     /**
182      * 设置可视对象DOM元素的CSS样式。
183      * @param {View} obj 指定要设置CSS样式的可视对象。
184      */
185     setElementStyleByView: function(obj){
186         var drawable = obj.drawable,
187             image = drawable.image,
188             rect = drawable.rect,
189             style = drawable.domElement.style,
190             prefix = Hilo.browser.jsVendor, px = 'px';
191         
192         style.pointerEvents = 'none';
193         style.display = (!obj.visible || obj.alpha <= 0) ? 'none' : '';
194         style.width = obj.width + px;
195         style.height = obj.height + px;
196         style.opacity = obj.alpha;
197         style.zIndex = obj.depth;
198         style[prefix + 'TransformOrigin'] = obj.pivotX + px + ' ' + obj.pivotY + px;
199         style[prefix + 'Transform'] = this.getTransformCSS(obj);
200         if(obj.bgFill) style.backgroundColor = obj.bgFill.style;
201 
202         if(image){
203             if(style.backgroundImage.indexOf(image.src) != 4){
204                 style.backgroundImage = 'url(' + image.src + ')';
205             }
206             if(rect){
207                 style.backgroundPosition = -rect[0] + px + ' ' + -rect[1] + px;
208             }
209         }
210         
211         if(obj.mask){
212             style[prefix + 'MaskImage'] = obj.mask.drawable.domElement.style.backgroundImage;
213             style[prefix + 'MaskRepeat'] = 'no-repeat';
214             style[prefix + 'MaskPosition'] = obj.mask.x + px + ' ' + obj.mask.y + px;
215         }
216     },
217 
218     /**
219      * 生成可视对象的CSS变换样式。
220      * @param {View} obj 指定生成CSS变换样式的可视对象。
221      * @returns {String} 生成的CSS样式字符串。
222      */
223     getTransformCSS: function(obj){
224         var use3d = this.browser.supportTransform3D, 
225             str3d = use3d ? '3d' : '';
226 
227         return 'translate' + str3d + '(' + (obj.x - obj.pivotX) + 'px, ' + (obj.y - obj.pivotY) + (use3d ? 'px, 0px)' : 'px)')
228              + 'rotate' + str3d + (use3d ? '(0, 0, 1, ' : '(') + obj.rotation + 'deg)'
229              + 'scale' + str3d + '(' + obj.scaleX + ', ' + obj.scaleY + (use3d ? ', 1)' : ')');
230     }
231 };
232 
233 })();