messagecenter.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. if (typeof console == 'undefined') console = {
  2. log: function () { }
  3. };
  4. // sniff chrome
  5. var CHROME_5_LOCAL = false;
  6. var CHROME = false;
  7. var SAFARI = false;
  8. var FIREFOX = false;
  9. var WEBKIT = false;
  10. var QQ = false;
  11. var UC = false;
  12. var OS_MAC = false;
  13. var IOS = false;
  14. var ANDROID = false;
  15. var MOBILE_DEVICE = false;
  16. var SHARE_APP = false;
  17. var IE = false;
  18. var IE_10_AND_BELOW = false; //ie 10 and lower
  19. var IE_11_AND_ABOVE = false; //ie 11 and above
  20. var BROWSER_VERSION = 5000;
  21. (function () {
  22. if(!window.$axure) window.$axure = function() {};
  23. var useragent = window.navigator.userAgent;
  24. IOS = useragent.match(/iPhone/i) || useragent.match(/iPad/i) || useragent.match(/iPod/i);
  25. ANDROID = useragent.match(/Android/i);
  26. MOBILE_DEVICE = ANDROID || IOS
  27. || navigator.userAgent.match(/webOS/i)
  28. || navigator.userAgent.match(/BlackBerry/i)
  29. || navigator.userAgent.match(/Tablet PC/i)
  30. || navigator.userAgent.match(/Windows Phone/i);
  31. var edgeRegex = /Edge\/([0-9]+)/g;
  32. var edgeMatch = edgeRegex.exec(useragent);
  33. $axure.browser = { isEdge: Boolean(edgeMatch) };
  34. if ($axure.browser.isEdge) BROWSER_VERSION = Number(edgeMatch[1]);
  35. if(!$axure.browser.isEdge) {
  36. var chromeRegex = /Chrome\/([0-9]+).([0-9]+)/g;
  37. var chromeMatch = chromeRegex.exec(useragent);
  38. CHROME = Boolean(chromeMatch);
  39. CHROME_5_LOCAL = chromeMatch &&
  40. Number(chromeMatch[1]) >= 5 &&
  41. location.href.indexOf('file://') >= 0 &&
  42. !MOBILE_DEVICE; // Otherwise, Android webview will show up as CHROME_5_LOCAL
  43. if (CHROME) BROWSER_VERSION = Number(chromeMatch[1]);
  44. }
  45. var safariRegex = /Safari\/([0-9]+)/g;
  46. var safariMatch = safariRegex.exec(useragent);
  47. SAFARI = Boolean(safariMatch) && !CHROME && !$axure.browser.isEdge; //because chrome also inserts safari string into user agent
  48. if (SAFARI) BROWSER_VERSION = Number(safariMatch[1]);
  49. var webkitRegex = /WebKit\//g ;
  50. WEBKIT = Boolean(webkitRegex.exec(useragent));
  51. var firefoxRegex = /Firefox\/([0-9]+)/g;
  52. var firefoxMatch = firefoxRegex.exec(useragent);
  53. FIREFOX = useragent.toLowerCase().indexOf('firefox') > -1;
  54. if (FIREFOX) BROWSER_VERSION = Number(firefoxMatch[1]);
  55. QQ = useragent.toLowerCase().indexOf('qqbrowser') > -1;
  56. UC = useragent.toLowerCase().indexOf('ucbrowser') > -1 || useragent.toLowerCase().indexOf('ubrowser') > -1;
  57. SHARE_APP = useragent.toLowerCase().indexOf('shareapp') > -1;
  58. var macRegex = /Mac/g ;
  59. OS_MAC = Boolean(macRegex.exec(window.navigator.platform));
  60. if($.browser) {
  61. if($.browser.msie) IE_10_AND_BELOW = true;
  62. else IE_11_AND_ABOVE = useragent.toLowerCase().indexOf('trident') > -1;
  63. BROWSER_VERSION = $.browser.version;
  64. }
  65. IE_11_AND_ABOVE = useragent.toLowerCase().indexOf('trident') > -1;
  66. IE_10_AND_BELOW = !IE_11_AND_ABOVE && useragent.toLowerCase().indexOf('msie') > -1;
  67. IE = IE_10_AND_BELOW || IE_11_AND_ABOVE;
  68. var _supports = $axure.mobileSupport = {};
  69. if(MOBILE_DEVICE || navigator.maxTouchPoints || navigator.msMaxTouchPoints) {
  70. _supports.touchstart = typeof window.ontouchstart !== 'undefined';
  71. _supports.touchmove = typeof window.ontouchmove !== 'undefined';
  72. _supports.touchend = typeof window.ontouchend !== 'undefined';
  73. _supports.pointerdown = typeof window.onpointerdown !== 'undefined';
  74. _supports.pointerup = typeof window.onpointerup !== 'undefined';
  75. _supports.pointermove = typeof window.onpointermove !== 'undefined';
  76. }
  77. _supports.mobile = _supports.touchstart && _supports.touchend && _supports.touchmove;
  78. var _eventNames = $axure.eventNames = {};
  79. _eventNames.mouseDownName = _supports.touchstart ? 'touchstart' : _supports.pointerdown ? 'pointerdown' : 'mousedown';
  80. _eventNames.mouseUpName = _supports.touchend ? 'touchend' : _supports.pointerup ? 'pointerup' : 'mouseup';
  81. _eventNames.mouseMoveName = _supports.touchmove ? 'touchmove' : _supports.pointermove ? 'pointermove' : 'mousemove';
  82. //Used by sitemap and variables.js getLinkUrl functions so that they know
  83. //whether to embed global variables in URL as query string or hash string
  84. //_shouldSendVars persists the value for sitemap instead of re-checking every time
  85. var _shouldSendVars;
  86. var _shouldSendVarsToServer = function(url) {
  87. if(typeof _shouldSendVars != 'undefined') {
  88. return _shouldSendVars;
  89. }
  90. if(SAFARI || (IE_10_AND_BELOW && BROWSER_VERSION < 10)) {
  91. var urlToCheck = typeof url != 'undefined' ? url : window.location.href;
  92. var serverRegex = /http:\/\/127\.0\.0\.1:[0-9]{5}/g;
  93. var serverMatch = serverRegex.exec(urlToCheck);
  94. var previewRegex = /[0-9]{2}\.[0-9]{2}\.[0-9]{2}/g;
  95. var previewMatch = previewRegex.exec(urlToCheck);
  96. if(Boolean(serverMatch) && Boolean(previewMatch)) {
  97. _shouldSendVars = true;
  98. return _shouldSendVars;
  99. }
  100. }
  101. _shouldSendVars = false;
  102. return _shouldSendVars;
  103. };
  104. $axure.shouldSendVarsToServer = _shouldSendVarsToServer;
  105. })();
  106. (function () {
  107. var matched, browser;
  108. // Use of jQuery.browser is frowned upon.
  109. // More details: http://api.jquery.com/jQuery.browser
  110. // jQuery.uaMatch maintained for back-compat
  111. jQuery.uaMatch = function (ua) {
  112. ua = ua.toLowerCase();
  113. var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
  114. /(webkit)[ \/]([\w.]+)/.exec(ua) ||
  115. /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
  116. /(msie) ([\w.]+)/.exec(ua) ||
  117. ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
  118. [];
  119. return {
  120. browser: match[1] || "",
  121. version: match[2] || "0"
  122. };
  123. };
  124. matched = jQuery.uaMatch(navigator.userAgent);
  125. browser = {};
  126. if (matched.browser) {
  127. browser[matched.browser] = true;
  128. browser.version = matched.version;
  129. }
  130. // Chrome is Webkit, but Webkit is also Safari.
  131. if (browser.chrome) {
  132. browser.webkit = true;
  133. } else if (browser.webkit) {
  134. browser.safari = true;
  135. }
  136. jQuery.browser = browser;
  137. jQuery.sub = function () {
  138. function jQuerySub(selector, context) {
  139. return new jQuerySub.fn.init(selector, context);
  140. }
  141. jQuery.extend(true, jQuerySub, this);
  142. jQuerySub.superclass = this;
  143. jQuerySub.fn = jQuerySub.prototype = this();
  144. jQuerySub.fn.constructor = jQuerySub;
  145. jQuerySub.sub = this.sub;
  146. jQuerySub.fn.init = function init(selector, context) {
  147. if (context && context instanceof jQuery && !(context instanceof jQuerySub)) {
  148. context = jQuerySub(context);
  149. }
  150. return jQuery.fn.init.call(this, selector, context, rootjQuerySub);
  151. };
  152. jQuerySub.fn.init.prototype = jQuerySub.fn;
  153. var rootjQuerySub = jQuerySub(document);
  154. return jQuerySub;
  155. };
  156. })();
  157. (function() {
  158. var _topMessageCenter;
  159. var _messageCenter = {};
  160. var _listeners = [];
  161. var _stateListeners = [];
  162. var _state = {};
  163. var _eventObject = null;
  164. var _queuedMessages = [];
  165. var _initialized = false;
  166. // this is for the non Chrome 5 local scenarios. The "top" message center will dispatch to all the bottom ones
  167. var _childrenMessageCenters = [];
  168. // create $axure if it hasn't been created
  169. if(!window.$axure) window.$axure = function() {};
  170. $axure.messageCenter = _messageCenter;
  171. // isolate scope, and initialize _topMessageCenter.
  172. (function() {
  173. if(!CHROME_5_LOCAL) {
  174. var topAxureWindow = window;
  175. try {
  176. while(topAxureWindow.parent && topAxureWindow.parent !== topAxureWindow && topAxureWindow.parent.$axure)
  177. topAxureWindow = topAxureWindow.parent;
  178. } catch(e) {
  179. }
  180. _topMessageCenter = topAxureWindow.$axure.messageCenter;
  181. }
  182. })();
  183. if (CHROME_5_LOCAL) {
  184. document.addEventListener("DOMContentLoaded", function () {
  185. $('body').append("<div id='axureEventReceiverDiv' style='display:none'></div>" +
  186. "<div id='axureEventSenderDiv' style='display:none'></div>");
  187. _eventObject = window.document.createEvent('Event');
  188. _eventObject.initEvent('axureMessageSenderEvent', true, true);
  189. $('#axureEventReceiverDiv')[0].addEventListener('axureMessageReceiverEvent',
  190. function () {
  191. var request = JSON.parse($(this).text());
  192. _handleRequest(request);
  193. });
  194. });
  195. } else {
  196. $(window.document).ready(function () {
  197. if (_topMessageCenter != _messageCenter) {
  198. _topMessageCenter.addChildMessageCenter(_messageCenter);
  199. console.log('adding from ' + window.location.toString());
  200. }
  201. });
  202. }
  203. var _handleRequest = function (request) {
  204. // route the request to all the listeners
  205. for(var i = 0; i < _listeners.length; i++) _listeners[i](request.message, request.data);
  206. // now handle the queued messages if we're initializing
  207. if (request.message == 'initialize') {
  208. _initialized = true;
  209. // send all the queued messages and return
  210. for (var i = 0; i < _queuedMessages.length; i++) {
  211. var qRequest = _queuedMessages[i];
  212. _messageCenter.postMessage(qRequest.message, qRequest.data);
  213. }
  214. _queuedMessages = [];
  215. }
  216. // and then handle the set state messages, if necessary
  217. if (request.message == 'setState') {
  218. _state[request.data.key] = request.data.value;
  219. for (var i = 0; i < _stateListeners.length; i++) {
  220. var keyListener = _stateListeners[i];
  221. // if thep passed a null or empty value, always post the message
  222. if (!keyListener.key || keyListener.key == request.data.key) {
  223. keyListener.listener(request.data.key, request.data.value);
  224. }
  225. }
  226. }
  227. };
  228. // -----------------------------------------------------------------------------------------
  229. // This method allows for dispatching messages in the non-chromelocal scenario.
  230. // Each child calls this on _topMessageCenter
  231. // -----------------------------------------------------------------------------------------
  232. _messageCenter.addChildMessageCenter = function(messageCenter) {
  233. _childrenMessageCenters[_childrenMessageCenters.length] = messageCenter;
  234. };
  235. // -----------------------------------------------------------------------------------------
  236. // This method allows for dispatching messages in the non-chromelocal scenario.
  237. // Each child calls this on _topMessageCenter
  238. // -----------------------------------------------------------------------------------------
  239. _messageCenter.dispatchMessage = function(message, data) {
  240. _handleRequest({
  241. message: message,
  242. data: data
  243. });
  244. };
  245. // -----------------------------------------------------------------------------------------
  246. // -----------------------------------------------------------------------------------------
  247. _messageCenter.dispatchMessageRecursively = function(message, data) {
  248. console.log("dispatched to " + window.location.toString());
  249. // dispatch to the top center first
  250. _messageCenter.dispatchMessage(message, data);
  251. $('iframe').each(function(index, frame) {
  252. //try,catch to handle permissions error in FF when loading pages from another domain
  253. try {
  254. if (frame.contentWindow.$axure && frame.contentWindow.$axure.messageCenter) {
  255. frame.contentWindow.$axure.messageCenter.dispatchMessageRecursively(message, data);
  256. }
  257. }catch(e) {}
  258. });
  259. };
  260. var _combineEventMessages = false;
  261. var _compositeEventMessageData = [];
  262. _messageCenter.startCombineEventMessages = function() {
  263. _combineEventMessages = true;
  264. }
  265. _messageCenter.endCombineEventMessages = function () {
  266. _messageCenter.sendCompositeEventMessage();
  267. _combineEventMessages = false;
  268. }
  269. _messageCenter.sendCompositeEventMessage = function () {
  270. _messageCenter.postMessage('axCompositeEventMessage', _compositeEventMessageData);
  271. _compositeEventMessageData = [];
  272. }
  273. _messageCenter.postMessage = function (message, data) {
  274. if(_combineEventMessages) {
  275. if(message == 'axEvent' || message == 'axCase' || message == 'axAction' || message == 'axEventComplete') {
  276. _compositeEventMessageData.push({ 'message': message, 'data': data });
  277. if(_compositeEventMessageData.length >= 10) _messageCenter.sendCompositeEventMessage();
  278. return;
  279. }
  280. }
  281. if(!CHROME_5_LOCAL) {
  282. _topMessageCenter.dispatchMessageRecursively(message, data);
  283. } else {
  284. var request = {
  285. message: message,
  286. data: data
  287. };
  288. if(_initialized) {
  289. var senderDiv = window.document.getElementById('axureEventSenderDiv');
  290. var messageText = JSON.stringify(request);
  291. // console.log('sending event: ' + messageText);
  292. senderDiv.innerText = messageText;
  293. senderDiv.dispatchEvent(_eventObject);
  294. // console.log('event sent');
  295. } else {
  296. _queuedMessages[_queuedMessages.length] = request;
  297. }
  298. }
  299. };
  300. _messageCenter.setState = function(key, value) {
  301. var data = {
  302. key: key,
  303. value: value
  304. };
  305. _messageCenter.postMessage('setState', data);
  306. };
  307. _messageCenter.getState = function(key) {
  308. return _state[key];
  309. };
  310. _messageCenter.addMessageListener = function(listener) {
  311. _listeners[_listeners.length] = listener;
  312. };
  313. _messageCenter.addStateListener = function(key, listener) {
  314. _stateListeners[_stateListeners.length] = {
  315. key: key,
  316. listener: listener
  317. };
  318. };
  319. })();