1 // ==========================================================================
  2 // Project:   SproutCore - JavaScript Application Framework
  3 // Copyright: ©2006-2011 Strobe Inc. and contributors.
  4 //            Portions ©2008-2011 Apple Inc. All rights reserved.
  5 // License:   Licensed under MIT license (see license.js)
  6 // ==========================================================================
  7 
  8 // These are helpful utility functions for calculating range and rect values
  9 sc_require('system/browser');
 10 
 11 SC.mixin( /** @scope SC */ {
 12 
 13   /**
 14     Takes a URL of any type and normalizes it into a fully qualified URL with
 15     hostname.  For example:
 16 
 17         "some/path" => "http://localhost:4020/some/path"
 18         "/some/path" => "http://localhost:4020/some/path"
 19         "http://localhost:4020/some/path" => "http://localhost:4020/some/path"
 20 
 21     @param url {String} the URL
 22     @returns {String} the normalized URL
 23   */
 24   normalizeURL: function(url) {
 25     if (url.slice(0,1) == '/') {
 26       url = window.location.protocol + '//' + window.location.host + url ;
 27     } else if ((url.slice(0,5) == 'http:') || (url.slice(0,6) == 'https:')) {
 28       // no change
 29     } else {
 30       url = window.location.href + '/' + url ;
 31     }
 32     return url ;
 33   },
 34 
 35   /** Return true if the number is between 0 and 1 */
 36   isPercentage: function(val){
 37     return (val<1 && val>0);
 38   },
 39 
 40   /** Return the left edge of the frame */
 41   minX: function(frame) {
 42     return frame.x || 0;
 43   },
 44 
 45   /** Return the right edge of the frame. */
 46   maxX: function(frame) {
 47     return (frame.x || 0) + (frame.width || 0);
 48   },
 49 
 50   /** Return the midpoint of the frame. */
 51   midX: function(frame) {
 52     return (frame.x || 0) + ((frame.width || 0) / 2) ;
 53   },
 54 
 55   /** Return the top edge of the frame */
 56   minY: function(frame) {
 57     return frame.y || 0 ;
 58   },
 59 
 60   /** Return the bottom edge of the frame */
 61   maxY: function(frame) {
 62     return (frame.y || 0) + (frame.height || 0) ;
 63   },
 64 
 65   /** Return the midpoint of the frame */
 66   midY: function(frame) {
 67     return (frame.y || 0) + ((frame.height || 0) / 2) ;
 68   },
 69 
 70   /** Returns the point that will center the frame X within the passed frame. */
 71   centerX: function(innerFrame, outerFrame) {
 72     return (outerFrame.width - innerFrame.width) / 2 ;
 73   },
 74 
 75   /** Return the point that will center the frame Y within the passed frame. */
 76   centerY: function(innerFrame, outerFrame) {
 77     return (outerFrame.height - innerFrame.height) /2  ;
 78   },
 79 
 80   /**
 81     The offset of an element.
 82 
 83     This function returns the left and top offset of an element with respect to either the document, the
 84     viewport or the element's parent element.  In standard SproutCore applications, the coordinates of the
 85     viewport are equivalent to the document, but a HTML5 application that wishes to use this component
 86     of SproutCore might need to properly distinguish between the two.
 87 
 88     For a useful discussion on the concepts of offsets and coordinates, see:
 89     http://www.quirksmode.org/mobile/viewports.html.
 90 
 91     @param {DOMElement|jQuery|String} elem the element to find the offset of.
 92       This is passed to `jQuery()`, so any value supported by `jQuery()` will work.
 93     @param {String} relativeToFlag flag to determine which relative element to determine offset by.
 94       One of either: 'document', 'viewport' or 'parent' (default: 'document').
 95     @returns {Object} the offset of the element as an Object (ie. Hash) in the form { x: value, y: value }.
 96    */
 97   offset: function(elem, relativeToFlag) {
 98     var userAgent,
 99         index,
100         mobileBuildNumber,
101         result;
102 
103     relativeToFlag = relativeToFlag || 'document';
104 
105     if (relativeToFlag === 'parent') {
106       result = jQuery(elem).position();
107     } else {
108       result = jQuery(elem).offset();
109 
110       // jQuery does not workaround a problem with Mobile Safari versions prior to 4.1 that add the scroll
111       // offset to the results of getBoundingClientRect.
112       //
113       // See http://dev.jquery.it/ticket/6446
114       if (SC.browser.isMobileSafari) {
115         userAgent = navigator.userAgent;
116         index = userAgent.indexOf('Mobile/');
117         mobileBuildNumber = userAgent.substring(index + 7, index + 9);
118 
119         if (parseInt(SC.browser.mobileSafari, 0) <= 532 || (mobileBuildNumber <= "8A")) {
120           result.left -= window.pageXOffset;
121           result.top -= window.pageYOffset;
122         }
123       }
124 
125       // Subtract the scroll offset for viewport coordinates
126       if (relativeToFlag === 'viewport') {
127 
128         if(SC.browser.isIE8OrLower){
129           result.left -= $(window).scrollLeft();
130           result.top -= $(window).scrollTop();
131         }else{
132           result.left -= window.pageXOffset;
133           result.top -= window.pageYOffset;
134         }
135       }
136     }
137 
138     // Translate 'left', 'top' to 'x', 'y'
139 
140     try{
141       result.x = result.left;
142       result.y = result.top;
143     } catch (e) {
144       // We need this for IE, when the element is detached, for some strange
145       // reason the object returned by element.getBoundingClientRect()
146       // is read-only
147       result = {x:result.left, y:result.top};
148     }
149     delete result.left;
150     delete result.top;
151 
152     return result;
153   },
154 
155   /**
156     @deprecated Use SC.offset instead.
157 
158     SC.offset() is more accurate, more flexible in the value for the element parameter and
159     easier to understand.
160 
161     @param el The DOM element
162     @returns {Point} A hash with x, y offsets.
163   */
164   viewportOffset: function(el) {
165     //@if(debug)
166     SC.warn("Developer Warning: SC.viewportOffset() has been deprecated in favor of SC.offset().  Please use SC.offset() from here on.");
167     //@endif
168     var result = SC.offset(el, 'viewport');
169 
170     return {x: result.left, y: result.top};
171   }
172 
173 }) ;
174