1 // ==========================================================================
  2 // Project:   SproutCore - JavaScript Application Framework
  3 // Copyright: ©2006-2011 Strobe Inc. and contributors.
  4 //            ©2008-2011 Apple Inc. All rights reserved.
  5 // License:   Licensed under MIT license (see license.js)
  6 // ==========================================================================
  7 
  8 SC.mixin( /** @scope SC */ {
  9   _downloadFrames: 0, // count of download frames inserted into document
 10 
 11   /**
 12     Starts a download of the file at the named path.
 13 
 14     Use this method when you want to cause a file to be downloaded to a users
 15     desktop instead of having it display in the web browser.  Note that your
 16     server must return a header indicating that the file  is intended for
 17     download also.
 18   */
 19   download: function(path) {
 20     var tempDLIFrame=document.createElement('iframe'),
 21         frameId = 'DownloadFrame_' + this._downloadFrames;
 22     SC.$(tempDLIFrame).attr('id',frameId);
 23     tempDLIFrame.style.border='10px';
 24     tempDLIFrame.style.width='0px';
 25     tempDLIFrame.style.height='0px';
 26     tempDLIFrame.style.position='absolute';
 27     tempDLIFrame.style.top='-10000px';
 28     tempDLIFrame.style.left='-10000px';
 29     // Don't set the iFrame content yet if this is Safari
 30     if (!SC.browser.isSafari) {
 31       SC.$(tempDLIFrame).attr('src',path);
 32     }
 33     document.getElementsByTagName('body')[0].appendChild(tempDLIFrame);
 34     if (SC.browser.isSafari) {
 35       SC.$(tempDLIFrame).attr('src',path);
 36     }
 37     this._downloadFrames = this._downloadFrames + 1;
 38     if (!SC.browser.isSafari) {
 39       var r = function() {
 40         document.body.removeChild(document.getElementById(frameId));
 41         frameId = null;
 42       } ;
 43       r.invokeLater(null, 2000);
 44     }
 45     //remove possible IE7 leak
 46     tempDLIFrame = null;
 47   },
 48 
 49   // Get the computed style from specific element. Useful for cloning styles
 50   getStyle: function(oElm, strCssRule){
 51     var strValue = "";
 52     if(document.defaultView && document.defaultView.getComputedStyle){
 53       strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule);
 54     }
 55     else if(oElm.currentStyle){
 56      strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1){
 57       return p1.toUpperCase();
 58      });
 59      strValue = oElm.currentStyle[strCssRule];
 60     }
 61     return strValue;
 62   },
 63 
 64   // Convert double byte characters to standard Unicode. Considers only
 65   // conversions from zenkaku to hankaky roomaji
 66   uniJapaneseConvert: function (str){
 67     var nChar, cString= '', j, jLen;
 68     //here we cycle through the characters in the current value
 69     for (j=0, jLen = str.length; j<jLen; j++){
 70       nChar = str.charCodeAt(j);
 71 
 72       //here we do the unicode conversion from zenkaku to hankaku roomaji
 73       nChar = ((nChar>=65281 && nChar<=65392)?nChar-65248:nChar);
 74 
 75       //MS IME seems to put this character in as the hyphen from keyboard but not numeric pad...
 76       nChar = ( nChar===12540?45:nChar) ;
 77       cString = cString + String.fromCharCode(nChar);
 78     }
 79     return cString;
 80   },
 81 
 82   /**
 83     Determines if the given point is within the given element.
 84 
 85     The test rect will include the element's padding and can be configured to
 86     optionally include the border or border and margin.
 87 
 88     @param {Object} point the point as an Object (ie. Hash) in the form { x: value, y: value }.
 89     @param {DOMElement|jQuery|String} elem the element to test inclusion within.
 90       This is passed to `jQuery()`, so any value supported by `jQuery()` will work.
 91     @param {String} includeFlag flag to determine the dimensions of the element to test within.
 92       One of either: 'padding', 'border' or 'margin' (default: 'border').
 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 {Boolean} YES if the point is within the element; NO otherwise
 96   */
 97 
 98   // Note: This method is the most correct way to test the inclusion of a point within a DOM element.
 99   // First, it uses SC.offset which is a slightly improved version of jQuery's offset and much more reliable
100   // than writing your own offset determination code.
101   // Second, the offset must be adjusted to account for the element's left and top border
102   // if not including the border or to account for the left and top margins when including the margins.
103   pointInElement: function(point, elem, includeFlag, relativeToFlag) {
104     var offset,
105         width,
106         height,
107         rect;
108 
109     elem = jQuery(elem);
110     includeFlag = includeFlag || 'border';
111 
112     // Find the offset
113     offset = SC.offset(elem, relativeToFlag);
114 
115     // Find the dimensions
116     if (includeFlag === 'padding') {
117       width = elem.innerWidth();
118       height = elem.innerHeight();
119 
120       // Adjust offset to account for top & left borders
121       offset.x += window.parseInt(elem.css('border-left-width').replace('px', ''));
122       offset.y += window.parseInt(elem.css('border-top-width').replace('px', ''));
123     } else {
124       width = elem.outerWidth(includeFlag === 'margin');
125       height = elem.outerHeight(includeFlag === 'margin');
126 
127       if (includeFlag === 'margin') {
128         // Adjust offset to account for top & left margins
129         offset.x -= window.parseInt(elem.css('margin-left').replace('px', ''));
130         offset.y -= window.parseInt(elem.css('margin-top').replace('px', ''));
131       }
132     }
133 
134     rect = {
135       x: offset.x,
136       y: offset.y,
137       width: width,
138       height: height
139     };
140 
141     return SC.pointInRect(point, rect);
142   },
143 
144 
145   /**
146     Switch the scale of your app. Useful when visualizing apps not designed
147     for iphone.
148   */
149   switchScale: function() {
150     $('head meta[name=viewport]').remove();
151     if(window.innerWidth === window.screen.width){
152       $('head').prepend('<meta name="viewport" content="width=device-width, initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=0" />');
153     }else{
154       $('head').prepend('<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=0" />');
155     }
156   }
157 });
158