PageRenderTime 67ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/js/skype-uri.js

https://gitlab.com/spd90/cbw
JavaScript | 978 lines | 673 code | 141 blank | 164 comment | 236 complexity | 38b0783c0420cb6ea4724194c26101bd MD5 | raw file
  1. // Copyright © 2013 Skype and Microsoft
  2. // Version: 1.1.6
  3. var Skype = new function () {
  4. this.name = null;
  5. this.element = null;
  6. this.participants = ["echo123"];
  7. this.listParticipants = "false";
  8. this.video = "false";
  9. this.topic = null;
  10. this.listTopic = "false";
  11. this.imageSize = null;
  12. this.imageColor = null;
  13. this.useDetection = "true";
  14. this.protocol = "skype:";
  15. this.version = "1.1.6";
  16. this.httpProtocol = window.location.protocol !== "https:" ? "http:" : "https:";
  17. this.ui = ui;
  18. this.setImageAttributes = setImageAttributes;
  19. this.trimString = trimString;
  20. this.escapeString = escapeString;
  21. this.createDetectionFrame = createDetectionFrame;
  22. this.trySkypeUri_IE9_IE8 = trySkypeUri_IE9_IE8;
  23. this.trySkypeUri_IOS_Safari = trySkypeUri_IOS_Safari;
  24. this.trySkypeUri_Android_Firefox = trySkypeUri_Android_Firefox;
  25. this.trySkypeUri_Generic = trySkypeUri_Generic;
  26. this.SkypeClientDownloadUrl = this.httpProtocol + "//www.skype.com/download";
  27. this.installSkypeMsg = "Please install Skype application in order to make this call or send a message.";
  28. this.displayNotSupportedMsg = displayNotSupportedMsg;
  29. this.SkypeUriAssetMap = SkypeUriAssetMap;
  30. this.SkypeUriAssetColorMap = SkypeUriAssetColorMap;
  31. this.SkypeUriNameLinks = SkypeUriNameLinks;
  32. this.assetPrefix = this.httpProtocol + "//cdn.dev.skype.com/uri/";
  33. this.assetSizeArray = [10, 12, 14, 16, 24, 32];
  34. this.assetSizeDefault = 16;
  35. this.assetMarginMinimum = 16;
  36. this.assetSize = this.assetSizeDefault;
  37. this.assetMargin = (this.assetSize >= this.assetMarginMinimum) ? this.assetSize : this.assetMarginMinimum;
  38. this.assetColorPathWhite = "_trans_"
  39. this.assetColorFontWhite = "white";
  40. this.assetColorPathSkype = "_";
  41. this.assetColorFontSkype = "#444444";
  42. this.assetColorPathDefault = this.assetColorPathSkype;
  43. this.assetColorFontDefault = this.assetColorFontSkype;
  44. this.assetColor = new this.SkypeUriAssetColorMap(this.assetColorPathDefault, this.assetColorFontDefault);
  45. this.assetSizeMap = new Object();
  46. this.assetSizeMap.size10 = new this.SkypeUriAssetMap(10, -18);
  47. this.assetSizeMap.size12 = new this.SkypeUriAssetMap(12, -19);
  48. this.assetSizeMap.size14 = new this.SkypeUriAssetMap(14, -19);
  49. this.assetSizeMap.size16 = new this.SkypeUriAssetMap(16, -20);
  50. this.assetSizeMap.size24 = new this.SkypeUriAssetMap(24, -30);
  51. this.assetSizeMap.size32 = new this.SkypeUriAssetMap(32, -41);
  52. this.focusLinks = new this.SkypeUriNameLinks("", "");
  53. this.callLinks = new this.SkypeUriNameLinks("call", "");
  54. this.videoLinks = new this.SkypeUriNameLinks("call", "");
  55. this.chatLinks = new this.SkypeUriNameLinks("chat", "");
  56. this.multiChatLinks = new this.SkypeUriNameLinks("chat", "");
  57. this.dropdownLinks = new this.SkypeUriNameLinks("dropdown", "");
  58. this.setImageAttributes(this.assetSizeDefault, "");
  59. this.analyzeSkypeUriInit = null;
  60. this.analyzeSkypeUriAction = null;
  61. this.analyzeSkypeUriRedirect = null;
  62. this.analyzeSkypeUr = null;
  63. this.analyzePreCrumbs = [];
  64. this.analyzeCrumbs = [];
  65. this.analyzeCrumbIndex = -1;
  66. this.tryAnalyzeSkypeUri = tryAnalyzeSkypeUri;
  67. this.detectSkypeClientFrameId = null;
  68. this.detectedPlatform = "unknown";
  69. this.detectedBrowser = "unknown";
  70. this.isWinXP = false;
  71. this.isWinVista = false;
  72. this.isWin7 = false;
  73. this.isWin8 = false;
  74. this.isOSX_SnowLeopard = false; // 10.6.8
  75. this.isOSX_MountainLion = false; // 10.8
  76. this.isWinPhone8 = false;
  77. this.isAndroid = false;
  78. this.isAndroid_Gingerbread = false; // 2.3
  79. this.isAndroid_IceCream = false; // 4.0
  80. this.isAndroid_JellyBean = false; // 4.1
  81. this.isIOS6 = false;
  82. this.isIOS5 = false;
  83. this.isIOS4 = false;
  84. this.isIPhone = false;
  85. this.isIPad = false;
  86. this.isIPod = false;
  87. this.isIE10 = false;
  88. this.isIE9 = false;
  89. this.isIE8 = false;
  90. this.isIE7 = false;
  91. this.isIE6 = false;
  92. this.isFF = false;
  93. this.isAndroidBrowser = false;
  94. this.isChrome = false;
  95. this.isSafari = false;
  96. this.showDropdown = showDropdown;
  97. this.hideDropdown = hideDropdown;
  98. this.analyzeScript = this.assetPrefix + "skype-analytics.js"
  99. this.includeJavascript = includeJavascript;
  100. this.includeJavascript(this.analyzeScript);
  101. if (navigator.userAgent.indexOf("Windows NT 5.1") != -1) { this.isWinXP = true; this.detectedPlatform = "Windows XP"; }
  102. else if (navigator.userAgent.indexOf("Windows NT 6.0") != -1) { this.isWinVista = true; this.detectedPlatform = "Windows Vista"; }
  103. else if (navigator.userAgent.indexOf("Windows NT 6.1") != -1) { this.isWin7 = true; this.detectedPlatform = "Windows 7"; }
  104. else if (navigator.userAgent.indexOf("Windows NT 6.2") != -1) { this.isWin8 = true; this.detectedPlatform = "Windows 8"; }
  105. else if (navigator.userAgent.indexOf("Mac OS X 10_7") != -1) { this.isOSX_SnowLeopard = true; this.detectedPlatform = "OSX 10.7"; }
  106. else if (navigator.userAgent.indexOf("Mac OS X 10.8") != -1) { this.isOSX_MountainLion = true; this.detectedPlatform = "OSX 10.8"; } // Safari UA
  107. else if (navigator.userAgent.indexOf("Mac OS X 10_8") != -1) { this.isOSX_MountainLion = true; this.detectedPlatform = "OSX 10.8"; } // FF UA
  108. else if (navigator.userAgent.indexOf("Windows Phone 8") != -1) { this.isWinPhone8 = true; this.detectedPlatform = "Windows Phone 8"; }
  109. else if (navigator.userAgent.indexOf("Android") != -1) { this.isAndroid = true; this.detectedPlatform = "Android"; }
  110. else if (navigator.userAgent.indexOf("Android 2.3") != -1) { this.isAndroid_Gingerbread = true; this.detectedPlatform = "Android 2.3"; }
  111. else if (navigator.userAgent.indexOf("Android 4.0") != -1) { this.isAndroid_IceCream = true; this.detectedPlatform = "Android 4.0"; }
  112. else if (navigator.userAgent.indexOf("Android 4.1") != -1) { this.isAndroid_JellyBean = true; this.detectedPlatform = "Android 4.1"; }
  113. else if (navigator.userAgent.match(/OS 6_[0-9_]+ like Mac OS X/i)) { this.isIOS6 = true; this.detectedPlatform = "iOS6"; }
  114. else if (navigator.userAgent.match(/OS 5_[0-9_]+ like Mac OS X/i)) { this.isIOS5 = true; this.detectedPlatform = "iOS5"; }
  115. else if (navigator.userAgent.match(/OS 4_[0-9_]+ like Mac OS X/i)) { this.isIOS4 = true; this.detectedPlatform = "iOS4"; }
  116. if (navigator.userAgent.indexOf("iPhone") != -1) { this.isIPhone = true; this.detectedPlatform = "iPhone " + this.detectedPlatform; }
  117. else if (navigator.userAgent.indexOf("iPad") != -1) { this.IsPad = true; this.detectedPlatform = "iPad " + this.detectedPlatform; }
  118. else if (navigator.userAgent.indexOf("iPod") != -1) { this.IsPod = true; this.detectedPlatform = "iPod " + this.detectedPlatform; }
  119. if (navigator.userAgent.indexOf("MSIE 10") != -1) { this.isIE10 = true; this.detectedBrowser = "Internet Explorer 10"; }
  120. else if (navigator.userAgent.indexOf("MSIE 9") != -1) { this.isIE9 = true; this.detectedBrowser = "Internet Explorer 9"; }
  121. else if (navigator.userAgent.indexOf("MSIE 8") != -1) { this.isIE8 = true; this.detectedBrowser = "Internet Explorer 8"; }
  122. else if (navigator.userAgent.indexOf("MSIE 7") != -1) { this.isIE7 = true; this.detectedBrowser = "Internet Explorer 7"; }
  123. else if (navigator.userAgent.indexOf("MSIE 6") != -1) { this.isIE6 = true; this.detectedBrowser = "Internet Explorer 6"; }
  124. else if (navigator.userAgent.indexOf("Firefox") != -1) { this.isFF = true; this.detectedBrowser = "Firefox"; }
  125. else if (navigator.userAgent.indexOf("Chrome") != -1) { this.isChrome = true; this.detectedBrowser = "Chrome"; } // precedes AndroidBrowser due to similar UA
  126. else if (navigator.userAgent.indexOf("Mobile Safari") != -1 && this.isAndroid) { this.isAndroidBrowser = true; this.detectedBrowser = "Mobile Safari"; }
  127. else if (navigator.userAgent.indexOf("Safari") != -1) { this.isSafari = true; this.detectedBrowser = "Safari"; }
  128. if (this.isAndroid) {
  129. this.SkypeClientDownloadUrl = "market://details?id=com.skype.raider";
  130. } else if (this.isIOS6 || this.isIOS5 || this.isIOS4) {
  131. this.SkypeClientDownloadUrl = "itms-apps://itunes.com/apps/skype";
  132. }
  133. function displayNotSupportedMsg() {
  134. alert("Sorry this device doesn't support Skype Buttons yet. Please add " + this.participants[0] + " as a contact in your Skype Client to MAKE this call.");
  135. }
  136. function showDropdown(id) {
  137. document.getElementById(id).style.display = 'block';
  138. if (typeof (window["timer_" + id]) !== "undefined") {
  139. window.clearTimeout(window["timer_" + id]);
  140. }
  141. window["timer_" + id] = null;
  142. delete window["timer_" + id];
  143. }
  144. function hideDropdown(id) {
  145. window["timer_" + id] = window.setTimeout(function () { document.getElementById(id).style.display = 'none'; }, 1000);
  146. }
  147. // Check if the analyze method is ready
  148. function tryAnalyzeSkypeUri(analyzeType, crumbIndex) {
  149. if (!this.analyzeSkypeUri && typeof analyzeSkypeUri == 'function') {
  150. this.analyzeSkypeUri = analyzeSkypeUri;
  151. }
  152. if (typeof this.analyzeSkypeUri == 'function') {
  153. this.analyzeSkypeUri(analyzeType, crumbIndex);
  154. } else {
  155. var _t = {};
  156. _t.prop3 = "image size / color: " + this.imageSize + " / " + this.imageColor;
  157. _t.prop4 = "video / list participants / list topic: " + this.video + " / " + this.listParticipants + " / " + this.listTopic;
  158. _t.prop5 = "target(s): " + this.participants;
  159. _t.prop6 = "user agent: " + navigator.userAgent;
  160. _t.prop7 = "detected protocol: " + window.location.protocol;
  161. _t.prop8 = "detected platform: " + this.detectedPlatform;
  162. _t.prop9 = "detected browser: " + this.detectedBrowser;
  163. _t.prop10 = this.version + " (pre script load)";
  164. if (analyzeType === "init") {
  165. if (this.name === this.chatLinks.name) {
  166. _t.prop11 = "Chat Init";
  167. }
  168. else if (this.name === this.callLinks.name) {
  169. _t.prop11 = "Call Init";
  170. }
  171. else if (this.name === this.dropdownLinks.name) {
  172. _t.prop11 = "Dropdown Init";
  173. }
  174. _t.prop12 = document.domain + " - Init";
  175. }
  176. else if (analyzeType === "chat") {
  177. _t.prop11 = "Chat Action";
  178. _t.prop13 = document.domain + " - Chat";
  179. }
  180. else if (analyzeType === "call") {
  181. _t.prop11 = "Call Action";
  182. _t.prop14 = document.domain + " - Call";
  183. }
  184. else if (analyzeType === "dropdownChat") {
  185. _t.prop11 = "Dropdown Chat Action";
  186. _t.prop13 = document.domain + " - Chat";
  187. }
  188. else if (analyzeType === "dropdownCall") {
  189. _t.prop11 = "Dropdown Call Action";
  190. _t.prop14 = document.domain + " - Call";
  191. }
  192. else if (analyzeType === "redirect") {
  193. _t.prop11 = "Redirect";
  194. }
  195. this.analyzePreCrumbs.push(_t);
  196. }
  197. }
  198. // Dynamically include javascript
  199. function includeJavascript(scriptSrc) {
  200. var headTag = document.getElementsByTagName('head')[0];
  201. var scriptTag = document.createElement('script');
  202. scriptTag.setAttribute('type', 'text/javascript');
  203. scriptTag.setAttribute('src', scriptSrc);
  204. headTag.appendChild(scriptTag);
  205. }
  206. // Map entry associating the "call"/"chat" asset size with the vertical offset necessary to align
  207. // the asset with any following list of participants and/or topic string text.
  208. //
  209. // Arguments
  210. // =========
  211. // fontSize - the asset size in pixels
  212. // verticalOffset -- the required vertical offset (unsigned) in pixels
  213. //
  214. function SkypeUriAssetMap(size, verticalOffset) {
  215. this.size = size;
  216. this.verticalOffset = verticalOffset;
  217. }
  218. // Map entry detailing the current color values for the "call"/"chat" assets.
  219. //
  220. // Arguments
  221. // =========
  222. // path - the path component depicting the currently specified color for the asset, which must be one of the
  223. // this.assetColorPathxxx values
  224. // font - the font color specification (as required by style="color:...") for any following list of
  225. // participants and/or topic string text, which must be one of the
  226. // this.assetColorFontxxx values
  227. //
  228. function SkypeUriAssetColorMap(path, font) {
  229. this.path = path;
  230. this.font = font;
  231. }
  232. // Map entry detailing the asset path for a particular Skype URI name.
  233. //
  234. // Arguments
  235. // =========
  236. // name - the Skype URI name, for example, "call"
  237. // linkImage - the associated asset path
  238. //
  239. function SkypeUriNameLinks(name, linkImage) {
  240. this.name = name;
  241. this.linkImage = linkImage;
  242. }
  243. // Based on the information in the specified Skype instance (typically JSON):
  244. // 1. Set the presentation attributes - size and color.
  245. // 2. Find the node that will contain our generated Skype URI link and
  246. // associated image and/or text (element).
  247. // 3. Parse out the participants (participants).
  248. // 4. Construct the Skype URI:
  249. // a. Set the scheme.
  250. // b. Concatenate any targets.
  251. // c. Concatenate any explicit Skype URI name (type designation), such as "call" or "chat".
  252. // d. Concatenate any name-specific arguments (video, topic).
  253. // 5. Create an anchor element.
  254. // 6. Set the anchor's href attribute value to:
  255. // o the generated Skype URI if "missing" Skype client detection is disabled.
  256. // o "javascript:" with the generated Skype URI as part of an onclick handler
  257. // if "missing" Skype client detection is disabled.
  258. // 7. Create the anchor's associated nodes:
  259. // a. create an image element with the appropriate src, alt, and style attributes.
  260. // b. Append the image element as a child of the anchor.
  261. // 8. Create a paragraph element to contain the link and associated image and/or text.
  262. // 9. Append the anchor and any image nodes to the paragraph.
  263. // 10. Create and append a TextNode consisting of the any participant names and/or
  264. // topic to the paragraph, as requested.
  265. // 11. Append the paragraph containing the anchor as a child of to the specified "containing" node.
  266. //
  267. // Arguments
  268. // =========
  269. // skypeUri:
  270. // a JSON representation of a Skype URI object, which defines the type of Skype URI, its targets,
  271. // name-specific arguments, and where/how to generate it on the webpage. Specifically:
  272. // o name - the name of the Skype URI ("call", or "chat"), or omitted/null/the "empty" string if
  273. // the Skype URI is implied (currently "focus" if no participants, and an implied
  274. // "call" if at least one participant).
  275. // o element - "id" attribute value of the element that will contain the generated Skype URI
  276. // link (typically a "div" tag), or omitted/null/the "empty" string to simply
  277. // generate the Skype URI with out embedding a link on the webpage, for example, to
  278. // use in a drag-and-drop context.
  279. // o participants - an array of Skype Names and/or phone numbers. Omitted/null/the "empty" string
  280. // implies "focus" (implied Skype URI); cannot be empty otherwise. However, embedded
  281. // null/"empty" array members are silently skipped.
  282. // o listParticipants - whether to list the participant Skype Names and/or phone numbers immediately following the
  283. // associated button. Only a value of "true" results in its being listed.
  284. // o video - "true" to enable the sender's video at the start of the call; "false" or omitted otherwise.
  285. // Ignored if name is not an explicit "call". Note that some Skype clients will fail the
  286. // Skype URI if the sole participant is not video-capable.
  287. // o topic - topic string for a conference call, GVC, or multichat. Ignored if there are fewer than
  288. // two participants, it's null/the "empty" string, or "name" is not an explict "call" or "chat".
  289. // o listTopic - whether to list the topic string immediately following the
  290. // associated button. Only a value of "true" results in its being listed.
  291. // o imageSize - the size (in pixels) of the assets:
  292. // * undefined, null, or the empty string -- use the default asset size.
  293. // * a supported size -- use it.
  294. // * an unsupported size -- use the default asset size, and post an alert for
  295. // the unsupported size.
  296. // o imageColor - the text color of the assets.
  297. // Recognized colors are:
  298. // * undefined, null, or the empty string -- use the default color assets.
  299. // * "skype" -- use the Skype color assets.
  300. // * "black" -- use the black assets.
  301. // * "white" -- use the white assets.
  302. // * an unrecognized value -- use the default color asset, and post an alert for
  303. // the unrecognized value.
  304. //
  305. // Returns
  306. // =======
  307. // true on success, or false if an error occurred (implies "element" was omitted or not found, or "name" was not recognized).
  308. //
  309. function ui(skypeUri) {
  310. this.name = null;
  311. if ((skypeUri.name !== undefined) && (skypeUri.name !== null)) {
  312. this.name = skypeUri.name;
  313. }
  314. if ((skypeUri.element !== undefined) && (skypeUri.element !== null)) {
  315. this.element = skypeUri.element;
  316. }
  317. if ((skypeUri.participants !== undefined) && (skypeUri.participants !== null)) {
  318. this.participants = skypeUri.participants;
  319. }
  320. if ((skypeUri.listParticipants !== undefined) && (skypeUri.listParticipants !== null)) {
  321. this.listParticipants = skypeUri.listParticipants;
  322. }
  323. if ((skypeUri.video !== undefined) && (skypeUri.video !== null)) {
  324. this.video = skypeUri.video;
  325. }
  326. if ((skypeUri.topic !== undefined) && (skypeUri.topic !== null)) {
  327. this.topic = skypeUri.topic;
  328. }
  329. if ((skypeUri.listTopic !== undefined) && (skypeUri.listTopic !== null)) {
  330. this.listTopic = skypeUri.listTopic;
  331. }
  332. if ((skypeUri.imageSize !== undefined) && (skypeUri.imageSize !== null)) {
  333. this.imageSize = skypeUri.imageSize;
  334. }
  335. if ((skypeUri.imageColor !== undefined) && (skypeUri.imageColor !== null)) {
  336. this.imageColor = skypeUri.imageColor;
  337. }
  338. if ((skypeUri.useDetection !== undefined) && (skypeUri.useDetection !== null)) {
  339. this.useDetection = skypeUri.useDetection;
  340. }
  341. else
  342. {
  343. this.useDetection = "true";
  344. }
  345. if ((skypeUri.protocol !== undefined) && (skypeUri.protocol !== null)) {
  346. this.protocol = skypeUri.protocol;
  347. }
  348. else
  349. {
  350. this.protocol = "skype:";
  351. }
  352. /* saving off analytics for when button is clicked */
  353. var _tPostScript = {};
  354. _tPostScript.prop0 = this.name; // overloading this to save button type
  355. _tPostScript.prop3 = "image size / color: " + this.imageSize + " / " + this.imageColor;
  356. _tPostScript.prop4 = "video / list participants / list topic: " + this.video + " / " + this.listParticipants + " / " + this.listTopic;
  357. _tPostScript.prop5 = "target(s): " + this.participants;
  358. _tPostScript.prop6 = "user agent: " + navigator.userAgent;
  359. _tPostScript.prop7 = "detected protocol: " + window.location.protocol;
  360. _tPostScript.prop8 = "detected platform: " + this.detectedPlatform;
  361. _tPostScript.prop9 = "detected browser: " + this.detectedBrowser;
  362. _tPostScript.prop10 = this.version;
  363. this.analyzeCrumbs.push(_tPostScript);
  364. this.analyzeCrumbIndex += 1;
  365. var tStr;
  366. // We must always have an explicit element!
  367. // Remember, an omitted argument has a value of undefined, not a value of null.
  368. tStr = this.trimString(skypeUri.element);
  369. if (tStr.length !== 0) {
  370. var uriParent = document.getElementById(tStr);
  371. if (uriParent === null) {
  372. alert("Sorry! Could not find Skype URI parent element: " + tStr + " ('" + skypeUri.element + "')");
  373. return (false);
  374. } else if (((skypeUri.name !== undefined) && (skypeUri.name !== null)) && ((skypeUri.participants === undefined) || (skypeUri.participants === null))) {
  375. alert("Error! Required member \"participants\" omitted or specified as null");
  376. return (false);
  377. }
  378. }
  379. else {
  380. alert("Error! Required member \"element\" (Skype URI parent element) omitted or specified as null");
  381. return (false);
  382. }
  383. // Set the assets size/color to use for this request
  384. this.setImageAttributes(skypeUri.imageSize, this.trimString(skypeUri.imageColor));
  385. // Concatenate the target Skype Names with the base Skype URI string, separating each with a semi-colon.
  386. // The Skype URI string always starts with the Skype scheme.
  387. if ((skypeUri.protocol !== undefined) && (skypeUri.protocol !== null)) {
  388. this.protocol = skypeUri.protocol;
  389. }
  390. var uriStr = this.protocol;
  391. var participantsStr = "";
  392. var participantsIdx = 0;
  393. var multiParticipants = false;
  394. if ((skypeUri.participants !== undefined) && (skypeUri.participants !== null)) {
  395. while (participantsIdx < skypeUri.participants.length) {
  396. if (skypeUri.participants[participantsIdx] !== null) {
  397. tStr = this.trimString(skypeUri.participants[participantsIdx]);
  398. if (tStr.length !== 0) {
  399. if (participantsIdx !== 0) {
  400. uriStr += ";";
  401. participantsStr += ", ";
  402. multiParticipants = true;
  403. }
  404. uriStr += tStr;
  405. participantsStr += tStr;
  406. }
  407. }
  408. participantsIdx++;
  409. }
  410. }
  411. // Concatenate the Skype URI name (if any) with the href string, preceeding it with a "?".
  412. // Re-set the button image if it's an implied audio call or explicit group chat.
  413. var uriName = this.focusLinks.name;
  414. var uriLinkImage = this.focusLinks.linkImage;
  415. var uriLinkImageAltTag = this.focusLinks.linkImageAltTag;
  416. var uriLinkRole = this.focusLinks.role;
  417. var isExplicitCall = false;
  418. tStr = this.trimString(skypeUri.name);
  419. if (tStr.length !== 0) {
  420. uriName = tStr;
  421. if (uriName === this.callLinks.name) {
  422. isExplicitCall = true;
  423. // Assume an audio call for now...
  424. uriLinkImage = this.callLinks.linkImage;
  425. uriLinkImageAltTag = this.callLinks.linkImageAltTag;
  426. uriLinkRole = this.callLinks.role;
  427. }
  428. else if (uriName === this.chatLinks.name) {
  429. if (multiParticipants) {
  430. uriLinkImage = this.multiChatLinks.linkImage;
  431. uriLinkImageAltTag = this.multiChatLinks.linkImageAltTag;
  432. uriLinkRole = this.multiChatLinks.role;
  433. }
  434. else {
  435. uriLinkImage = this.chatLinks.linkImage;
  436. uriLinkImageAltTag = this.chatLinks.linkImageAltTag;
  437. uriLinkRole = this.chatLinks.role;
  438. }
  439. }
  440. else if (uriName === this.dropdownLinks.name) {
  441. uriLinkImage = this.dropdownLinks.linkImage;
  442. uriLinkImageAltTag = this.dropdownLinks.linkImageAltTag;
  443. uriLinkRole = this.dropdownLinks.role;
  444. }
  445. else {
  446. alert("Unrecognized Skype URI name: " + uriName + " ('" + skypeUri.name + "') -- " + this.callLinks.name + "/" + this.chatLinks.name);
  447. return (false);
  448. }
  449. uriStr += "?" + uriName;
  450. }
  451. else if (participantsStr.length > 0) {
  452. uriLinkImage = this.callLinks.linkImage;
  453. uriLinkImageAltTag = this.callLinks.linkImageAltTag;
  454. uriLinkRole = this.callLinks.role;
  455. }
  456. // Concatenate the argument name/value pairs (if any) with the href string, preceeding each with an "&".
  457. // Re-set the button image if it's a video call.
  458. if (isExplicitCall) {
  459. tStr = this.trimString(skypeUri.video);
  460. if (tStr === "true") {
  461. uriLinkImage = this.videoLinks.linkImage;
  462. uriLinkImageAltTag = this.videoLinks.linkImageAltTag;
  463. uriLinkRole = this.videoLinks.role;
  464. uriStr += "&video=" + tStr;
  465. }
  466. }
  467. var topicStr = null;
  468. if ((multiParticipants) &&
  469. ((isExplicitCall) || (uriName === this.chatLinks.name))) {
  470. tStr = this.trimString(skypeUri.topic);
  471. if (tStr.length > 0) {
  472. topicStr = tStr;
  473. uriStr += "&topic=" + escapeString(topicStr);
  474. }
  475. }
  476. if (skypeUri.useDetection === "false") {
  477. this.useDetection = "false";
  478. }
  479. // Use the Skype URI to create the anchor's onclick attribute
  480. // if the Skype client detection is enabled. Otherwise, use the
  481. // Skype URI directly as the anchor's href attribute.
  482. var uriAnchor = document.createElement("a");
  483. var onclickStr = "";
  484. var hrefStr = "";
  485. //uriAnchor.setAttribute("style", "text-decoration: none;");
  486. // no detection, use a regular href link
  487. if (!this.useDetection || (this.isWin8 && this.isIE10) || this.isIE7 || this.isIE6) {
  488. hrefStr = uriStr;
  489. // no detection and display not-supported msg
  490. } else if ((this.isWinPhone8 && this.isIE10) || (this.isAndroid && this.isAndroidBrowser) || (this.isAndroid && this.isChrome)) {
  491. hrefStr = "javascript://";
  492. onclickStr += " Skype.displayNotSupportedMsg();";
  493. // using detection
  494. } else {
  495. tStr = "Skype.trySkypeUri_Generic";
  496. if (this.isIE10 || this.isIE9 || this.isIE8) {
  497. tStr = "Skype.trySkypeUri_IE9_IE8";
  498. }
  499. else if ((this.isIOS6 || this.isIOS5 || this.isIOS4) && this.isSafari) {
  500. tStr = "Skype.trySkypeUri_IOS_Safari";
  501. }
  502. else if (this.isAndroid && this.isFF) {
  503. tStr = "Skype.trySkypeUri_Android_Firefox";
  504. }
  505. if (this.detectSkypeClientFrameId === null) {
  506. this.createDetectionFrame(uriParent);
  507. }
  508. hrefStr = "javascript://";
  509. onclickStr += tStr + "('" + uriStr + "', '" + this.detectSkypeClientFrameId + "', '" + this.analyzeCrumbIndex + "'); return false;";
  510. }
  511. var uriImage = document.createElement("img");
  512. // Adjust the style attribute for link borders on your image or
  513. // to align your image with your text, or simply eliminate it.
  514. uriImage.setAttribute("src", uriLinkImage);
  515. uriImage.setAttribute("alt", uriLinkImageAltTag);
  516. uriImage.setAttribute("role", uriLinkRole);
  517. uriImage.setAttribute("style", ("border:0; margin:" + this.assetMargin + "px; vertical-align:" + this.assetSizeMap[("size" + this.assetSize)].verticalOffset + "px;"));
  518. if (this.name === this.dropdownLinks.name) {
  519. uriImage.setAttribute("onmouseover", "Skype.showDropdown('dropdown_" + this.element + "'); return false;");
  520. uriImage.setAttribute("onmouseout", "Skype.hideDropdown('dropdown_" + this.element + "'); return false;");
  521. uriAnchor.setAttribute("style", "cursor: text;");
  522. // enables accessibility via keystrokes
  523. uriAnchor.setAttribute("onfocus", "Skype.showDropdown('dropdown_" + this.element + "'); return false;");
  524. uriAnchor.setAttribute("onblur", "Skype.hideDropdown('dropdown_" + this.element + "'); return false;");
  525. uriAnchor.setAttribute("href", "javascript://");
  526. uriAnchor.setAttribute("onclick", "return false;");
  527. } else {
  528. if (this.name === this.chatLinks.name) {
  529. onclickStr = "Skype.tryAnalyzeSkypeUri('chat', '" + this.analyzeCrumbIndex + "');" + onclickStr;
  530. } else {
  531. onclickStr = "Skype.tryAnalyzeSkypeUri('call', '" + this.analyzeCrumbIndex + "');" + onclickStr;
  532. }
  533. uriAnchor.setAttribute("href", hrefStr);
  534. uriAnchor.setAttribute("onclick", onclickStr);
  535. }
  536. uriAnchor.appendChild(uriImage);
  537. uriPara = document.createElement("p");
  538. uriPara.setAttribute("id", (skypeUri.element + "_paraElement"));
  539. uriPara.setAttribute("style", ("font-size:" + (this.assetSize - 2) + "px; color:" + this.assetColor.font));
  540. uriPara.appendChild(uriAnchor);
  541. if (this.name === this.dropdownLinks.name) {
  542. var ulEMarginTop = "-10";
  543. var ulEMarginLeft = "15";
  544. if (this.assetSize == "10") {
  545. ulEMarginLeft = "15";
  546. }
  547. else if (this.assetSize == "12") {
  548. ulEMarginLeft = "15";
  549. }
  550. else if (this.assetSize == "14") {
  551. ulEMarginLeft = "15";
  552. }
  553. else if (this.assetSize == "16") {
  554. ulEMarginLeft = "15";
  555. }
  556. else if (this.assetSize == "24") {
  557. ulEMarginTop = "-20";
  558. ulEMarginLeft = "25";
  559. }
  560. else if (this.assetSize == "32") {
  561. ulEMarginTop = "-30";
  562. ulEMarginLeft = "30";
  563. }
  564. var ulE = document.createElement("ul");
  565. ulE.id = "dropdown_" + this.element;
  566. ulE.setAttribute("style", "display: none; position: absolute; margin-top: " + ulEMarginTop + "px; margin-left: " + ulEMarginLeft + "px; width: 200px; padding-left: 20px; padding-right: 20px; border: 2px solid #00AFF0; background-color: white; color: #00AFF0; line-height: 50px; list-style: none; list-style-type: none;");
  567. ulE.setAttribute("onmouseover", "Skype.showDropdown('dropdown_" + this.element + "'); return false;");
  568. ulE.setAttribute("onmouseout", "Skype.hideDropdown('dropdown_" + this.element + "'); return false;");
  569. var liECall = document.createElement("li");
  570. liECall.setAttribute("style", "list-style: none; list-style-type: none;");
  571. var liEChat = document.createElement("li");
  572. liEChat.setAttribute("style", "list-style: none; list-style-type: none;");
  573. var dropdownOnclickStr = "";
  574. var aECall = document.createElement("a");
  575. aECall.href = "javascript://";
  576. aECall.setAttribute("style", "text-decoration: none; color: #00AFF0; font-size: 16px;");
  577. aECall.setAttribute("href", hrefStr);
  578. dropdownOnclickStr = "Skype.tryAnalyzeSkypeUri('dropdownCall', '" + this.analyzeCrumbIndex + "');" + onclickStr;
  579. aECall.setAttribute("onclick", dropdownOnclickStr.replace("?" + this.dropdownLinks.name, "?" + this.callLinks.name));
  580. aECall.setAttribute("onmouseover", "this.style.textDecoration = 'underline'");
  581. aECall.setAttribute("onmouseout", "this.style.textDecoration = 'none'");
  582. aECall.setAttribute("role", "Menu item");
  583. aECall.setAttribute("onfocus", "Skype.showDropdown('dropdown_" + this.element + "'); return false;");
  584. aECall.setAttribute("onblur", "Skype.hideDropdown('dropdown_" + this.element + "'); return false;");
  585. var aEChat = document.createElement("a");
  586. aEChat.href = "javascript://";
  587. aEChat.setAttribute("style", "text-decoration: none; color: #00AFF0; font-size: 16px;");
  588. aEChat.setAttribute("href", hrefStr);
  589. dropdownOnclickStr = "Skype.tryAnalyzeSkypeUri('dropdownChat', '" + this.analyzeCrumbIndex + "');" + onclickStr;
  590. aEChat.setAttribute("onclick", dropdownOnclickStr.replace("?" + this.dropdownLinks.name, "?" + this.chatLinks.name));
  591. aEChat.setAttribute("onmouseover", "this.style.textDecoration = 'underline'");
  592. aEChat.setAttribute("onmouseout", "this.style.textDecoration = 'none'");
  593. aECall.setAttribute("role", "Menu item");
  594. aEChat.setAttribute("onfocus", "Skype.showDropdown('dropdown_" + this.element + "'); return false;");
  595. aEChat.setAttribute("onblur", "Skype.hideDropdown('dropdown_" + this.element + "'); return false;");
  596. aECall.innerHTML = "Call";
  597. liECall.appendChild(aECall);
  598. aEChat.innerHTML = "Chat";
  599. liEChat.appendChild(aEChat);
  600. ulE.appendChild(liECall);
  601. ulE.appendChild(liEChat);
  602. uriPara.appendChild(ulE);
  603. }
  604. // Create and append any participant names and topic as the text of
  605. // the enclosing paragraph, if requested.
  606. // Can't have a topic without participants!
  607. tStr = null;
  608. if (participantsStr.length !== 0) {
  609. if (this.trimString(skypeUri.listParticipants) === "true") {
  610. tStr = " " + participantsStr;
  611. }
  612. if ((topicStr !== null) && (this.trimString(skypeUri.listTopic) === "true")) {
  613. if ((tStr === null) || (tStr.length === 0)) {
  614. tStr = " RE: " + topicStr
  615. }
  616. else {
  617. tStr += ("; RE: " + topicStr);
  618. }
  619. }
  620. // Some browsers may display null unless blanked out
  621. if (tStr === null) {
  622. tStr = "";
  623. }
  624. uriPara.appendChild(document.createTextNode(tStr));
  625. }
  626. uriParent.appendChild(uriPara);
  627. this.tryAnalyzeSkypeUri('init', this.analyzeCrumbIndex);
  628. return (true);
  629. }
  630. // Update the URL size and/or color of the graphical assets (buttons).
  631. //
  632. // Arguments
  633. // =========
  634. // size:
  635. // The size (in pixels) to use for the assets:
  636. // o undefined, null, or the empty string -- use the default asset size.
  637. // o a supported size -- use it.
  638. // o an unsupported size -- silently use the default size.
  639. // color:
  640. // The text color to use for the assets. Recognized colors are:
  641. // o undefined, null, or the empty string -- use the default asset color.
  642. // o "skype" -- use the Skype color assets.
  643. // o "black" -- use the black assets.
  644. // o "white" -- use the white assets.
  645. // o an unrecognized value -- silently use the default color.
  646. function setImageAttributes(size, color) {
  647. this.assetSize = this.assetSizeDefault;
  648. this.assetMargin = (this.assetSize >= this.assetMarginMinimum) ? this.assetSize : this.assetMarginMinimum;
  649. var i;
  650. var j = this.assetSizeArray.length;
  651. for (i = 0; i < j; i++) {
  652. if (size === this.assetSizeArray[i]) {
  653. this.assetSize = size;
  654. break;
  655. }
  656. }
  657. this.assetMargin = (this.assetSize >= this.assetMarginMinimum) ? this.assetSize : this.assetMarginMinimum;
  658. this.assetColor.path = this.assetColorPathDefault;
  659. this.assetColor.font = this.assetColorFontDefault;
  660. if (color.length > 0) {
  661. if (color === "skype") {
  662. this.assetColor.path = this.assetColorPathSkype;
  663. this.assetColor.font = this.assetColorFontSkype;
  664. }
  665. else if (color === "white") {
  666. this.assetColor.path = this.assetColorPathWhite;
  667. this.assetColor.font = this.assetColorFontWhite
  668. }
  669. }
  670. this.focusLinks.linkImage = this.assetPrefix + "Skypeicon" + this.assetColor.path + this.assetSize + "px.png";
  671. this.callLinks.linkImage = this.assetPrefix + "callbutton" + this.assetColor.path + this.assetSize + "px.png";
  672. this.videoLinks.linkImage = this.assetPrefix + "callbutton" + this.assetColor.path + this.assetSize + "px.png";
  673. this.chatLinks.linkImage = this.assetPrefix + "chatbutton" + this.assetColor.path + this.assetSize + "px.png";
  674. this.multiChatLinks.linkImage = this.assetPrefix + "chatbutton" + this.assetColor.path + this.assetSize + "px.png";
  675. this.dropdownLinks.linkImage = this.assetPrefix + "dropdowncallbutton" + this.assetColor.path + this.assetSize + "px.png";
  676. this.focusLinks.linkImageAltTag = "Open Skype";
  677. this.callLinks.linkImageAltTag = "Skype call" ;
  678. this.videoLinks.linkImageAltTag = "Skype call";
  679. this.chatLinks.linkImageAltTag = "Skype chat, instant message";
  680. this.multiChatLinks.linkImageAltTag = "Skype chat, instant message";
  681. this.dropdownLinks.linkImageAltTag = "Call options";
  682. this.focusLinks.role = "Button";
  683. this.callLinks.role = "Button";
  684. this.videoLinks.role = "Button";
  685. this.chatLinks.role = "Button";
  686. this.multiChatLinks.role = "Button";
  687. this.dropdownLinks.role = "Pop up menu";
  688. }
  689. // Trim trailing whitespace from a string, and return the resultant string.
  690. // For the purposes of this function, "whitespace" is defined as
  691. // space, tab, carriage return, and newline.
  692. //
  693. // Arguments
  694. // =========
  695. // stringToTrim:
  696. // The target string, which might be null.
  697. //
  698. // Returns
  699. // =======
  700. // A copy of the input string with all trailing whitespace characters removed.
  701. // An input string value that is undefined, null, or composed of all
  702. // whitespace characters returns the "empty" string.
  703. //
  704. function trimString(stringToTrim) {
  705. // Handle any undefined or null input.
  706. if ((stringToTrim === undefined) || (stringToTrim === null)) {
  707. return ("");
  708. }
  709. var strLgth = stringToTrim.length;
  710. var strIdx = strLgth - 1;
  711. var foundNonWhiteSpaceChar = false;
  712. while ((!foundNonWhiteSpaceChar) && (strLgth > 0)) {
  713. switch (stringToTrim[strIdx]) {
  714. case ' ':
  715. case '\t':
  716. case '\n':
  717. case '\r':
  718. strLgth--;
  719. break;
  720. default:
  721. foundNonWhiteSpaceChar = true;
  722. break;
  723. }
  724. strIdx--;
  725. }
  726. if (strLgth > 0) {
  727. return (stringToTrim.substr(0, strLgth));
  728. }
  729. return ("");
  730. }
  731. // Escape any URL and path characters that might confuse the Skype client
  732. // when processing the Skype URI, that is:
  733. // -- embedded whitespace characters escaped as %20
  734. // -- colons escaped as %3A
  735. // -- forward slashes escaped as %2F
  736. // -- backward slashes escaped as %5C
  737. //
  738. function escapeString(stringToEscape) {
  739. // Handle any undefined or null input.
  740. if ((stringToEscape === undefined) || (stringToEscape === null)) {
  741. return ("");
  742. }
  743. var escapedStr = stringToEscape.replace(/\s/g, "%20");
  744. escapedStr = escapedStr.replace(/:/g, "%3A");
  745. escapedStr = escapedStr.replace(/\x2F/g, "%2F");
  746. return (escapedStr.replace(/\x5C/g, "%5C"));
  747. }
  748. // Create frame for use in detecting "missing" Skype client
  749. function createDetectionFrame(parentElement) {
  750. var d = new Date();
  751. this.detectSkypeClientFrameId = "_detectSkypeClient_" + d.getTime().toString();
  752. var uriFrame = document.createElement("iframe");
  753. uriFrame.setAttribute("style", "display:none;");
  754. uriFrame.setAttribute("id", this.detectSkypeClientFrameId);
  755. parentElement.appendChild(uriFrame);
  756. }
  757. // Also works for IE10 that is not on the Win8 or WinPhone8 platform
  758. function trySkypeUri_IE9_IE8(skypeUriString, frameId, crumbIndex) {
  759. var t__skypeExists = false;
  760. var t__detectionWindow = window.open('', '_blank', 'width=100, height=100');
  761. var uriFrame = t__detectionWindow.document.createElement("iframe");
  762. uriFrame.setAttribute("src", skypeUriString);
  763. t__detectionWindow.document.body.appendChild(uriFrame);
  764. setTimeout(function () {
  765. try {
  766. t__detectionWindow.location.href;
  767. t__skypeExists = true;
  768. }
  769. catch (e) {
  770. // handle exceptions...
  771. }
  772. if (t__skypeExists) {
  773. t__detectionWindow.setTimeout('window.close()', 10);
  774. }
  775. else {
  776. t__detectionWindow.close();
  777. alert(Skype.installSkypeMsg);
  778. Skype.tryAnalyzeSkypeUri('redirect', crumbIndex);
  779. window.location = Skype.SkypeClientDownloadUrl;
  780. }
  781. }, 100);
  782. }
  783. function trySkypeUri_IOS_Safari(skypeUriString, frameId, crumbIndex) {
  784. var t_frame = document.getElementById(frameId);
  785. var t_focus = true;
  786. window.addEventListener("pagehide", function () {
  787. t_focus = false;
  788. }, false);
  789. if (t_frame !== null) {
  790. t_frame.src = skypeUriString;
  791. }
  792. setTimeout(function () {
  793. if (t_focus) {
  794. alert(Skype.installSkypeMsg);
  795. Skype.tryAnalyzeSkypeUri('redirect', crumbIndex);
  796. window.location = Skype.SkypeClientDownloadUrl;
  797. }
  798. }, 2000);
  799. }
  800. function trySkypeUri_Android_Firefox(skypeUriString, frameId, crumbIndex) {
  801. var isSupported = false;
  802. var t_frame = document.getElementById(frameId);
  803. if (t_frame !== null) {
  804. try {
  805. t_frame.contentWindow.location.href = skypeUriString;
  806. isSupported = true;
  807. } catch (e) {
  808. isSupported = false;
  809. }
  810. }
  811. setTimeout(function () {
  812. if (!isSupported) {
  813. alert(Skype.installSkypeMsg);
  814. Skype.tryAnalyzeSkypeUri('redirect', crumbIndex);
  815. window.location = Skype.SkypeClientDownloadUrl;
  816. }
  817. }, 2000);
  818. }
  819. // FF, Chrome, Desktop Safari, and Generic
  820. function trySkypeUri_Generic(skypeUriString, frameId, crumbIndex) {
  821. var t_focus = true;
  822. window.onblur = function () {
  823. t_focus = false;
  824. }
  825. var t_frame = document.getElementById(frameId);
  826. if (t_frame !== null) {
  827. t_frame.src = skypeUriString;
  828. }
  829. setTimeout(function () {
  830. if (t_focus) {
  831. alert(Skype.installSkypeMsg);
  832. Skype.tryAnalyzeSkypeUri('redirect', crumbIndex);
  833. window.location = Skype.SkypeClientDownloadUrl;
  834. }
  835. }, 2000);
  836. }
  837. }