style.js 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986
  1. $axure.internal(function($ax) {
  2. var _style = {};
  3. $ax.style = _style;
  4. var _disabledWidgets = {};
  5. var _selectedWidgets = {};
  6. // A table to cache the outerHTML of the _rtf elements before the rollover state is applied.
  7. var _originalTextCache = {};
  8. // A table to exclude the normal style from adaptive overrides
  9. var _shapesWithSetRichText = {};
  10. // just a listing of shape ids
  11. var _adaptiveStyledWidgets = {};
  12. var _setLinkStyle = function(id, styleName) {
  13. var textId = $ax.style.GetTextIdFromLink(id);
  14. var style = _computeAllOverrides(id, textId, styleName, $ax.adaptive.currentViewId);
  15. if(!_originalTextCache[textId]) {
  16. $ax.style.CacheOriginalText(textId);
  17. }
  18. if($.isEmptyObject(style)) return;
  19. var parentObjectCache = _originalTextCache[textId].styleCache;
  20. _transformTextWithVerticalAlignment(textId, function() {
  21. var cssProps = _getCssStyleProperties(style);
  22. $('#' + id).find('*').andSelf().each(function(index, element) {
  23. element.setAttribute('style', parentObjectCache[element.id]);
  24. _applyCssProps(element, cssProps);
  25. });
  26. });
  27. };
  28. var _resetLinkStyle = function(id) {
  29. var textId = $ax.style.GetTextIdFromLink(id);
  30. var parentObjectCache = _originalTextCache[textId].styleCache;
  31. _transformTextWithVerticalAlignment(textId, function() {
  32. $('#' + id).find('*').andSelf().each(function(index, element) {
  33. element.style.cssText = parentObjectCache[element.id];
  34. });
  35. });
  36. if($ax.event.mouseDownObjectId) {
  37. $ax.style.SetWidgetMouseDown($ax.event.mouseDownObjectId, true);
  38. } else if($ax.event.mouseOverObjectId) {
  39. $ax.style.SetWidgetHover($ax.event.mouseOverObjectId, true);
  40. }
  41. };
  42. $ax.style.SetLinkHover = function(id) {
  43. _setLinkStyle(id, MOUSE_OVER);
  44. };
  45. $ax.style.SetLinkNotHover = function(id) {
  46. _resetLinkStyle(id);
  47. };
  48. $ax.style.SetLinkMouseDown = function(id) {
  49. _setLinkStyle(id, MOUSE_DOWN);
  50. };
  51. $ax.style.SetLinkNotMouseDown = function(id) {
  52. _resetLinkStyle(id);
  53. var style = _computeAllOverrides(id, $ax.event.mouseOverObjectId, MOUSE_OVER, $ax.adaptive.currentViewId);
  54. if(!$.isEmptyObject(style)) $ax.style.SetLinkHover(id);
  55. //we dont do anything here because the widget not mouse down has taken over here
  56. };
  57. var _widgetHasState = function(id, state) {
  58. if($ax.style.getElementImageOverride(id, state)) return true;
  59. var diagramObject = $ax.getObjectFromElementId(id);
  60. var adaptiveIdChain = $ax.adaptive.getAdaptiveIdChain($ax.adaptive.currentViewId);
  61. for(var i = 0; i < adaptiveIdChain.length; i++) {
  62. var viewId = adaptiveIdChain[i];
  63. var adaptiveStyle = diagramObject.adaptiveStyles[viewId];
  64. if(adaptiveStyle && adaptiveStyle.stateStyles && adaptiveStyle.stateStyles[state]) return true;
  65. }
  66. if(diagramObject.style.stateStyles) return diagramObject.style.stateStyles[state];
  67. return false;
  68. };
  69. // Returns what overrides the hover, or false if nothing.
  70. var _hoverOverride = function(id) {
  71. if($ax.style.IsWidgetDisabled(id)) return DISABLED;
  72. if($ax.style.IsWidgetSelected(id)) return SELECTED;
  73. var obj = $ax.getObjectFromElementId(id);
  74. if(!obj.isContained) return false;
  75. var path = $ax.getPathFromScriptId($ax.repeater.getScriptIdFromElementId(id));
  76. path[path.length - 1] = obj.parent.id;
  77. var itemId = $ax.repeater.getItemIdFromElementId(id);
  78. return _hoverOverride($ax.getElementIdFromPath(path, { itemNum: itemId }));
  79. };
  80. $ax.style.SetWidgetHover = function(id, value) {
  81. var override = _hoverOverride(id);
  82. if(override == DISABLED) return;
  83. if(!_widgetHasState(id, MOUSE_OVER)) return;
  84. var valToSet = value || _isRolloverOverride(id);
  85. var state = _generateMouseState(id, valToSet ? MOUSE_OVER : NORMAL, override == SELECTED);
  86. _applyImageAndTextJson(id, state);
  87. _updateElementIdImageStyle(id, state);
  88. };
  89. var _rolloverOverrides = [];
  90. var _isRolloverOverride = function(id) {
  91. return _rolloverOverrides.indexOf(id) != -1;
  92. };
  93. $ax.style.AddRolloverOverride = function(id) {
  94. if(_isRolloverOverride(id)) return;
  95. _rolloverOverrides[_rolloverOverrides.length] = id;
  96. if($ax.event.mouseOverIds.indexOf(id) == -1) $ax.style.SetWidgetHover(id, true);
  97. };
  98. $ax.style.RemoveRolloverOverride = function(id) {
  99. var index = _rolloverOverrides.indexOf(id);
  100. if(index == -1) return;
  101. $ax.splice(_rolloverOverrides, index, 1);
  102. if($ax.event.mouseOverIds.indexOf(id) == -1) $ax.style.SetWidgetHover(id, false);
  103. };
  104. // function GetWidgetCurrentState(id) {
  105. // if($ax.style.IsWidgetDisabled(id)) return "disabled";
  106. // if($ax.style.IsWidgetSelected(id)) return "selected";
  107. // if($ax.event.mouseOverObjectId == id) return "mouseOver";
  108. // if($ax.event.mouseDownObjectId == id) return "mouseDown";
  109. // return "normal";
  110. // }
  111. $ax.style.ObjHasMouseDown = function(id) {
  112. var obj = $obj(id);
  113. return $ax.style.getElementImageOverride(id, 'mouseDown') || obj.style && obj.style.stateStyles && obj.style.stateStyles.mouseDown;
  114. };
  115. $ax.style.SetWidgetMouseDown = function(id, value) {
  116. if($ax.style.IsWidgetDisabled(id)) return;
  117. if(!_widgetHasState(id, MOUSE_DOWN)) return;
  118. // ApplyImageAndTextJson(id, value ? 'mouseDown' : !$.isEmptyObject(GetStyleForState(id, null, 'mouseOver')) ? 'mouseOver' : 'normal');
  119. var state = _generateMouseState(id, value ? MOUSE_DOWN : MOUSE_OVER, $ax.style.IsWidgetSelected(id));
  120. _applyImageAndTextJson(id, state);
  121. _updateElementIdImageStyle(id, state);
  122. };
  123. var _generateMouseState = function(id, mouseState, selected) {
  124. if(selected) {
  125. var viewChain = $ax.adaptive.getAdaptiveIdChain($ax.adaptive.currentViewId);
  126. viewChain[viewChain.length] = '';
  127. var obj = $obj(id);
  128. if(obj.type == "dynamicPanel") return SELECTED;
  129. var any = function(dict) {
  130. for(var key in dict) return true;
  131. return false;
  132. };
  133. for(var i = 0; i < viewChain.length; i++) {
  134. var viewId = viewChain[i];
  135. // Need to check seperately for images.
  136. if(obj.adaptiveStyles && obj.adaptiveStyles[viewId] && any(obj.adaptiveStyles[viewId])
  137. || obj.images && obj.images['selected~' + viewId]) return SELECTED;
  138. }
  139. var selectedStyle = obj.style && obj.style.stateStyles && obj.style.stateStyles.selected;
  140. if(selectedStyle && any(selectedStyle)) return SELECTED;
  141. }
  142. // Not using selected
  143. return mouseState;
  144. };
  145. $ax.style.SetWidgetSelected = function(id, value, alwaysApply) {
  146. if($ax.style.IsWidgetDisabled(id)) return;
  147. if(value) {
  148. var group = $('#' + id).attr('selectiongroup');
  149. if(group) {
  150. $("[selectiongroup='" + group + "']").each(function() {
  151. var otherId = this.id;
  152. if(otherId == id) return;
  153. $ax.style.SetWidgetSelected(otherId, false);
  154. });
  155. }
  156. }
  157. var obj = $obj(id);
  158. if(obj) {
  159. if(obj.type == 'dynamicPanel') {
  160. var children = $axure('#' + id).getChildren()[0].children;
  161. for(var i = 0; i < children.length; i++) {
  162. var childId = children[i];
  163. // Special case for trees
  164. var childObj = $jobj(childId);
  165. if(childObj.hasClass('treeroot')) {
  166. var treenodes = childObj.find('.treenode');
  167. for(var j = 0; j < treenodes.length; j++) {
  168. $axure('#' + treenodes[j].id).selected(value);
  169. }
  170. } else $axure('#' + childId).selected(value);
  171. }
  172. } else {
  173. while(obj.isContained && !_widgetHasState(id, 'selected')) obj = obj.parent;
  174. var itemId = $ax.repeater.getItemIdFromElementId(id);
  175. var path = $ax.getPathFromScriptId($ax.repeater.getScriptIdFromElementId(id));
  176. path[path.length - 1] = obj.id;
  177. id = $ax.getElementIdFromPath(path, { itemNum: itemId });
  178. if(alwaysApply || _widgetHasState(id, SELECTED)) {
  179. var state = _generateSelectedState(id, value);
  180. _applyImageAndTextJson(id, state);
  181. _updateElementIdImageStyle(id, state);
  182. }
  183. }
  184. }
  185. // ApplyImageAndTextJson(id, value ? 'selected' : 'normal');
  186. _selectedWidgets[id] = value;
  187. };
  188. var _generateSelectedState = function(id, selected) {
  189. var mouseState = $ax.event.mouseDownObjectId == id ? MOUSE_DOWN : $ax.event.mouseOverIds.indexOf(id) != -1 ? MOUSE_OVER : NORMAL;
  190. return _generateMouseState(id, mouseState, selected);
  191. };
  192. $ax.style.IsWidgetSelected = function(id) {
  193. return Boolean(_selectedWidgets[id]);
  194. };
  195. $ax.style.SetWidgetEnabled = function(id, value) {
  196. _disabledWidgets[id] = !value;
  197. $('#' + id).find('a').css('cursor', value ? 'pointer' : 'default');
  198. if(!_widgetHasState(id, DISABLED)) return;
  199. if(!value) {
  200. _applyImageAndTextJson(id, DISABLED);
  201. _updateElementIdImageStyle(id, DISABLED);
  202. } else $ax.style.SetWidgetSelected(id, $ax.style.IsWidgetSelected(id), true);
  203. };
  204. $ax.style.SetWidgetPlaceholder = function(id, value, text, password) {
  205. var inputId = $ax.repeater.applySuffixToElementId(id, '_input');
  206. // Right now this is the only style on the widget. If other styles (ex. Rollover), are allowed
  207. // on TextBox/TextArea, or Placeholder is applied to more widgets, this may need to do more.
  208. var obj = $jobj(inputId);
  209. if(!value) {
  210. obj.attr('style', '');
  211. try { //ie8 and below error
  212. if(password) document.getElementById(inputId).type = 'password';
  213. } catch(e) { }
  214. } else {
  215. var style = _computeAllOverrides(id, undefined, HINT, $ax.adaptive.currentViewId);
  216. var styleProperties = _getCssStyleProperties(style);
  217. //moved this out of GetCssStyleProperties for now because it was breaking un/rollovers with gradient fills
  218. if(style.fill) styleProperties.runProps.backgroundColor = _getColorFromFill(style.fill);
  219. _applyCssProps($('#' + inputId)[0], styleProperties);
  220. try { //ie8 and below error
  221. if(password) document.getElementById(inputId).type = 'text';
  222. } catch(e) { }
  223. }
  224. obj.val(text);
  225. };
  226. var _isWidgetDisabled = $ax.style.IsWidgetDisabled = function(id) {
  227. return Boolean(_disabledWidgets[id]);
  228. };
  229. var _elementIdsToImageOverrides = {};
  230. $ax.style.mapElementIdToImageOverrides = function(elementId, override) {
  231. _elementIdsToImageOverrides[elementId] = override;
  232. };
  233. $ax.style.deleteElementIdToImageOverride = function(elementId) {
  234. delete _elementIdsToImageOverrides[elementId];
  235. };
  236. $ax.style.getElementImageOverride = function(elementId, state) {
  237. var url = _elementIdsToImageOverrides[elementId] && _elementIdsToImageOverrides[elementId][state];
  238. return url;
  239. };
  240. $ax.style.elementHasAnyImageOverride = function(elementId) {
  241. return Boolean(_elementIdsToImageOverrides[elementId]);
  242. };
  243. var NORMAL = 'normal';
  244. var MOUSE_OVER = 'mouseOver';
  245. var MOUSE_DOWN = 'mouseDown';
  246. var SELECTED = 'selected';
  247. var DISABLED = 'disabled';
  248. var HINT = 'hint';
  249. var _generateState = _style.generateState = function(id) {
  250. return _style.IsWidgetDisabled(id) ? DISABLED : _generateSelectedState(id, _style.IsWidgetSelected(id));
  251. };
  252. var _progressState = _style.progessState = function(state) {
  253. if(state == NORMAL) return false;
  254. if(state == MOUSE_DOWN) return MOUSE_OVER;
  255. return NORMAL;
  256. };
  257. var _unprogressState = function(state, goal) {
  258. state = state || NORMAL;
  259. if(state == goal) return undefined;
  260. if(state == NORMAL && goal == MOUSE_DOWN) return MOUSE_OVER;
  261. return goal;
  262. };
  263. var _updateElementIdImageStyle = _style.updateElementIdImageStyle = function(elementId, state) {
  264. if(!_style.elementHasAnyImageOverride(elementId)) return;
  265. if(!state) state = _generateState(elementId);
  266. var obj = $obj(elementId);
  267. var style = obj.style;
  268. var stateStyle = state == NORMAL ? style : style && style.stateStyles && style.stateStyles[state];
  269. if(!stateStyle && !_style.getElementImageOverride(elementId, state)) {
  270. state = _progressState(state);
  271. if(state) _updateElementIdImageStyle(elementId, state);
  272. return;
  273. }
  274. var computedStyle = _style.computeAllOverrides(elementId, undefined, state, $ax.adaptive.currentViewId);
  275. var defaultStyle = $ax.document.stylesheet.defaultStyles[obj.type];
  276. var query = $jobj($ax.repeater.applySuffixToElementId(elementId, '_img'));
  277. var borderId = $ax.repeater.applySuffixToElementId(elementId, '_border');
  278. var borderQuery = $jobj(borderId);
  279. if(!borderQuery.length) {
  280. borderQuery = $('<div></div>');
  281. borderQuery.attr('id', borderId);
  282. query.after(borderQuery);
  283. }
  284. borderQuery.attr('style', '');
  285. borderQuery.css('position', 'absolute');
  286. query.attr('style', '');
  287. var borderWidth = Number(computedStyle.borderWidth || style.borderWidth || defaultStyle.borderWidth);
  288. var hasBorderWidth = borderWidth > 0;
  289. if(hasBorderWidth) {
  290. borderQuery.css('border-style', 'solid');
  291. borderQuery.css('border-width', borderWidth + 'px');
  292. borderQuery.css('width', style.size.width - borderWidth * 2);
  293. borderQuery.css('height', style.size.height - borderWidth * 2);
  294. }
  295. var linePattern = computedStyle.linePattern || style.linePattern || defaultStyle.linePattern;
  296. if(hasBorderWidth && linePattern) borderQuery.css('border-style', linePattern);
  297. var borderFill = computedStyle.borderFill || style.borderFill || defaultStyle.borderFill;
  298. if(hasBorderWidth && borderFill) {
  299. var color = borderFill.fillType == 'solid' ? borderFill.color :
  300. borderFill.fillType == 'linearGradient' ? borderFill.colors[0].color : 0;
  301. var alpha = Math.floor(color / 256 / 256 / 256);
  302. color -= alpha * 256 * 256 * 256;
  303. alpha = alpha / 255;
  304. var red = Math.floor(color / 256 / 256);
  305. color -= red * 256 * 256;
  306. var green = Math.floor(color / 256);
  307. var blue = color - green * 256;
  308. borderQuery.css('border-color', _rgbaToFunc(red, green, blue, alpha));
  309. }
  310. var cornerRadiusTopLeft = computedStyle.cornerRadiusTopLeft || style.cornerRadiusTopLeft || defaultStyle.cornerRadiusTopLeft;
  311. if(cornerRadiusTopLeft) {
  312. query.css('border-radius', cornerRadiusTopLeft + 'px');
  313. borderQuery.css('border-radius', cornerRadiusTopLeft + 'px');
  314. }
  315. var outerShadow = computedStyle.outerShadow || style.outerShadow || defaultStyle.outerShadow;
  316. if(outerShadow && outerShadow.on) {
  317. var arg = '';
  318. arg += outerShadow.offsetX + 'px' + ' ' + outerShadow.offsetY + 'px' + ' ';
  319. var rgba = outerShadow.color;
  320. arg += outerShadow.blurRadius + 'px' + ' 0px ' + _rgbaToFunc(rgba.r, rgba.g, rgba.b, rgba.a);
  321. query.css('-moz-box-shadow', arg);
  322. query.css('-wibkit-box-shadow', arg);
  323. query.css('box-shadow', arg);
  324. query.css('width', style.size.width);
  325. query.css('height', style.size.height);
  326. query.css('left', '0px');
  327. query.css('top', '0px');
  328. }
  329. };
  330. var _rgbaToFunc = function(red, green, blue, alpha) {
  331. return 'rgba(' + red + ',' + green + ',' + blue + ',' + alpha + ')';
  332. };
  333. //function $ax.style.GetTextIdFromShape(id) {
  334. // return $.grep(
  335. // $('#' + id).children().map(function (i, obj) { return obj.id; }), // all the child ids
  336. // function (item) { return item.indexOf(id) < 0; })[0]; // that are not similar to the parent
  337. //}
  338. var _getButtonShapeId = function(id) {
  339. var obj = $obj(id);
  340. return obj.type == 'treeNodeObject' ? $ax.getElementIdFromPath([obj.buttonShapeId], { relativeTo: id }) : id;
  341. };
  342. var _getButtonShape = function(id) {
  343. var obj = $obj(id);
  344. // some treeNodeObjects don't have button shapes
  345. return $jobj(obj.type == 'treeNodeObject' && obj.buttonShapeId ? $ax.getElementIdFromPath([obj.buttonShapeId], { relativeTo: id }) : id);
  346. };
  347. var _getTextIdFromShape = $ax.style.GetTextIdFromShape = function(id) {
  348. return _getButtonShape(id).find('.text').attr('id');
  349. };
  350. $ax.style.GetTextIdFromLink = function(id) {
  351. return $jobj(id).parentsUntil('.text').parent().attr('id');
  352. };
  353. var _getShapeIdFromText = $ax.style.GetShapeIdFromText = function(id) {
  354. if(!id) return undefined; // this is to prevent an infinite loop.
  355. //return $jobj(id).parent().attr('id');
  356. var current = $jobj(id).parent();
  357. while(!current.is("body")) {
  358. var id = current.attr('id');
  359. if(id && id != 'base') return id;
  360. current = current.parent();
  361. }
  362. return undefined;
  363. };
  364. $ax.style.GetImageIdFromShape = function(id) {
  365. var image = _getButtonShape(id).find('img[id$=img]');
  366. if(!image.length) image = $jobj(id).find('img[id$=image_sketch]');
  367. return image.attr('id');
  368. };
  369. var _applyImageAndTextJson = function(id, event) {
  370. var textId = $ax.style.GetTextIdFromShape(id);
  371. _resetTextJson(id, textId);
  372. // This should never be the case
  373. //if(event != '') {
  374. var imgQuery = $jobj($ax.style.GetImageIdFromShape(id));
  375. var e = imgQuery.data('events');
  376. if(e && e[event]) imgQuery.trigger(event);
  377. var imageUrl = $ax.adaptive.getImageForStateAndView(id, event);
  378. if(imageUrl) _applyImage(id, imageUrl, event);
  379. var style = _computeAllOverrides(id, undefined, event, $ax.adaptive.currentViewId);
  380. if(!$.isEmptyObject(style)) {
  381. _applyTextStyle(textId, style);
  382. }
  383. };
  384. /* -------------------
  385. here's the algorithm in a nutshell:
  386. [DOWN] -- refers to navigation down the view inheritance heirarchy (default to most specific)
  387. [UP] -- navigate up the heirarchy
  388. ComputeAllOverrides (object):
  389. All view styles [DOWN]
  390. If hyperlink
  391. - DO ComputeStateStyle for parent object
  392. - if (MouseOver || MouseDown)
  393. - linkMouseOver Style
  394. - if (MouseDown)
  395. - linkMouseDown style
  396. - ComputeStateStyleForViewChain (parent, STATE)
  397. if (MouseDown) DO ComputeStateStyleForViewChain for object, mouseOver
  398. DO ComputeStateStyleForViewChain for object, style
  399. ComputeStateStyleForViewChain (object, STATE)
  400. FIRST STATE state style [UP] the chain OR default object STATE style
  401. ------------------- */
  402. var FONT_PROPS = {
  403. 'typeface': true,
  404. 'fontName': true,
  405. 'fontWeight': true,
  406. 'fontStyle': true,
  407. 'fontStretch': true,
  408. 'fontSize': true,
  409. 'underline': true,
  410. 'foreGroundFill': true,
  411. 'horizontalAlignment': true
  412. };
  413. var _computeAllOverrides = $ax.style.computeAllOverrides = function(id, parentId, state, currentViewId) {
  414. var computedStyle = {};
  415. var diagramObject = $ax.getObjectFromElementId(id);
  416. var viewIdChain = $ax.adaptive.getAdaptiveIdChain(currentViewId);
  417. var excludeFont = _shapesWithSetRichText[id];
  418. for(var i = 0; i < viewIdChain.length; i++) {
  419. var viewId = viewIdChain[i];
  420. var style = diagramObject.adaptiveStyles[viewId];
  421. if(style) {
  422. // we want to exclude the normal font style for shapes where the rich text has been set with an interaction
  423. // so we copy the style so we don't modify the original, then delete all the font props.
  424. if(excludeFont) {
  425. style = $ax.deepCopy(style);
  426. for(var prop in FONT_PROPS) delete style[prop];
  427. }
  428. if(style) {
  429. var customStyle = style.baseStyle && $ax.document.stylesheet.stylesById[style.baseStyle];
  430. //make sure not to extend the customStyle this can mutate it for future use
  431. $.extend(computedStyle, customStyle);
  432. }
  433. $.extend(computedStyle, style);
  434. }
  435. }
  436. var isHyperlink = Boolean(parentId);
  437. var currState = NORMAL;
  438. while(currState) {
  439. if(isHyperlink && (currState == MOUSE_DOWN || currState == MOUSE_OVER)) {
  440. var key = currState == MOUSE_OVER ? 'hyperlinkMouseOver' : 'hyperlinkMouseDown';
  441. $.extend(computedStyle, $ax.document.stylesheet.defaultStyles[key]);
  442. }
  443. $.extend(computedStyle, _computeStateStyleForViewChain(diagramObject, currState, viewIdChain, true));
  444. currState = _unprogressState(currState, state);
  445. }
  446. return _removeUnsupportedProperties(computedStyle, diagramObject.type);
  447. };
  448. var _computeStateStyleForViewChain = function(diagramObject, state, viewIdChain, excludeNormal) {
  449. var styleObject = diagramObject;
  450. while(styleObject.isContained) styleObject = styleObject.parent;
  451. var adaptiveStyles = styleObject.adaptiveStyles;
  452. for(var i = viewIdChain.length - 1; i >= 0; i--) {
  453. var viewId = viewIdChain[i];
  454. var viewStyle = adaptiveStyles[viewId];
  455. var stateStyle = viewStyle && _getFullStateStyle(viewStyle, state, excludeNormal);
  456. if(stateStyle) return $.extend({}, stateStyle);
  457. }
  458. // we dont want to actually include the object style because those are not overrides, hence the true for "excludeNormal" and not passing the val through
  459. var stateStyleFromDefault = _getFullStateStyle(styleObject.style, state, true);
  460. return $.extend({}, stateStyleFromDefault);
  461. };
  462. // returns the full effective style for an object in a state state and view
  463. var _computeFullStyle = function(id, state, currentViewId) {
  464. var obj = $obj(id);
  465. var overrides = _computeAllOverrides(id, undefined, state, currentViewId);
  466. // todo: account for image box
  467. var objStyle = obj.style;
  468. var customStyle = objStyle.baseStyle && $ax.document.stylesheet.stylesById[objStyle.baseStyle];
  469. var returnVal = $.extend({}, $ax.document.stylesheet.defaultStyles[obj.styleType], customStyle, objStyle, overrides);
  470. return _removeUnsupportedProperties(returnVal, obj.type);
  471. };
  472. var _removeUnsupportedProperties = function(style, objectType) {
  473. // for now all we need to do is remove padding from checkboxes and radio buttons
  474. if(objectType == 'radioButton' || objectType == 'checkbox') {
  475. style.paddingTop = 0;
  476. style.paddingLeft = 0;
  477. style.paddingRight = 0;
  478. style.paddingBottom = 0;
  479. }
  480. return style;
  481. };
  482. var _getFullStateStyle = function(style, state, excludeNormal) {
  483. //'normal' is needed because now DiagramObjects get their image from the Style and unapplying a rollover needs the image
  484. var stateStyle = state == 'normal' && !excludeNormal ? style : style && style.stateStyles && style.stateStyles[state];
  485. if(stateStyle) {
  486. var customStyle = stateStyle.baseStyle && $ax.document.stylesheet.stylesById[stateStyle.baseStyle];
  487. //make sure not to extend the customStyle this can mutate it for future use
  488. return $.extend({}, customStyle, stateStyle);
  489. }
  490. return undefined;
  491. };
  492. // commented this out for now... we actually will probably need it for ie
  493. var _applyOpacityFromStyle = $ax.style.applyOpacityFromStyle = function(id, style) {
  494. return;
  495. var opacity = style.opacity || '';
  496. $jobj(id).children().css('opacity', opacity);
  497. };
  498. var _initialize = function() {
  499. //being handled at on window.load
  500. //$ax.style.initializeObjectTextAlignment($ax('*'));
  501. };
  502. $ax.style.initialize = _initialize;
  503. var _initTextAlignment = function(elementId) {
  504. var textId = _getTextIdFromShape(elementId);
  505. _storeIdToAlignProps(textId);
  506. // now handle vertical alignment
  507. if(_getObjVisible(textId)) {
  508. _setTextAlignment(textId, _idToAlignProps[textId], false);
  509. }
  510. };
  511. $ax.style.initializeObjectTextAlignment = function(query) {
  512. query.filter(function(diagramObject) {
  513. return diagramObject.type == 'buttonShape' || diagramObject.type == 'flowShape' || diagramObject.type == 'imageBox';
  514. }).each(function(diagramObject, elementId) {
  515. if($jobj(elementId).length == 0) return;
  516. _initTextAlignment(elementId);
  517. });
  518. };
  519. var _storeIdToAlignProps = function(textId) {
  520. var shapeId = _getShapeIdFromText(textId);
  521. var state = _generateState(shapeId);
  522. var style = _computeFullStyle(shapeId, state, $ax.adaptive.currentViewId);
  523. var vAlign = style.verticalAlignment || 'middle';
  524. var paddingTop = style.paddingTop || 0;
  525. var paddingBottom = style.paddingBottom || 0;
  526. _idToAlignProps[textId] = { vAlign: vAlign, paddingTop: paddingTop, paddingBottom: paddingBottom };
  527. };
  528. var ALL_STATES = ['mouseOver', 'mouseDown', 'selected', 'disabled'];
  529. var _applyImage = $ax.style.applyImage = function(id, imgUrl, state) {
  530. var imgQuery = $jobj($ax.style.GetImageIdFromShape(id));
  531. var idQuery = $jobj(id);
  532. var _updateClass = function() {
  533. for(var i = 0; i < ALL_STATES.length; i++) {
  534. idQuery.removeClass(ALL_STATES[i]);
  535. imgQuery.removeClass(ALL_STATES[i]);
  536. }
  537. if(state != 'normal') {
  538. idQuery.addClass(state);
  539. imgQuery.addClass(state);
  540. }
  541. };
  542. if(imgQuery.attr('src') != imgUrl) {
  543. imgQuery[0].onload = function() {
  544. _updateClass();
  545. // IE 8 can't set onload to undefined
  546. if(IE && BROWSER_VERSION <= 8) imgQuery[0].onload = function() { };
  547. else imgQuery[0].onload = undefined;
  548. };
  549. } else {
  550. _updateClass();
  551. }
  552. imgQuery.attr('src', imgUrl);
  553. if(imgQuery.parents('a.basiclink').length > 0) imgQuery.css('border', 'none');
  554. if(imgUrl.indexOf(".png") > -1) $ax.utils.fixPng(imgQuery[0]);
  555. };
  556. var _resetTextJson = function(id, textid) {
  557. // reset the opacity
  558. $jobj(id).children().css('opacity', '');
  559. var cacheObject = _originalTextCache[textid];
  560. if(cacheObject) {
  561. _transformTextWithVerticalAlignment(textid, function() {
  562. var styleCache = cacheObject.styleCache;
  563. var textQuery = $('#' + textid);
  564. textQuery.find('*').each(function(index, element) {
  565. element.style.cssText = styleCache[element.id];
  566. });
  567. });
  568. }
  569. };
  570. // Preserves the alingment for the element textid after executing transformFn
  571. var _getRtfElementHeight = function(rtfElement) {
  572. if(rtfElement.innerHTML == '') rtfElement.innerHTML = '&nbsp;';
  573. // To handle render text as image
  574. var images = $(rtfElement).children('img');
  575. if(images.length) return images.height();
  576. return rtfElement.offsetHeight;
  577. };
  578. // why microsoft decided to default to round to even is beyond me...
  579. var _roundToEven = function(number) {
  580. var numString = number.toString();
  581. var parts = numString.split('.');
  582. if(parts.length == 1) return number;
  583. if(parts[1].length == 1 && parts[1] == '5') {
  584. var wholePart = Number(parts[0]);
  585. return wholePart % 2 == 0 ? wholePart : wholePart + 1;
  586. } else return Math.round(number);
  587. };
  588. var _transformTextWithVerticalAlignment = $ax.style.transformTextWithVerticalAlignment = function(textId, transformFn) {
  589. if(!_originalTextCache[textId]) {
  590. $ax.style.CacheOriginalText(textId);
  591. }
  592. var rtfElement = window.document.getElementById(textId);
  593. if(!rtfElement) return;
  594. transformFn();
  595. _storeIdToAlignProps(textId);
  596. $ax.style.updateTextAlignmentForVisibility(textId);
  597. };
  598. // this is for vertical alignments set on hidden objects
  599. var _idToAlignProps = {};
  600. $ax.style.updateTextAlignmentForVisibility = function(textId) {
  601. var alignProps = _idToAlignProps[textId];
  602. if(!alignProps || !_getObjVisible(textId)) return;
  603. _setTextAlignment(textId, alignProps);
  604. };
  605. var _getObjVisible = _style.getObjVisible = function(id) {
  606. var element = document.getElementById(id);
  607. return element && (element.offsetWidth || element.offsetHeight);
  608. };
  609. var _setTextAlignment = function(textId, alignProps, updateProps) {
  610. if(updateProps) {
  611. _storeIdToAlignProps(textId);
  612. }
  613. if(!alignProps) return;
  614. var vAlign = alignProps.vAlign;
  615. var paddingTop = Number(alignProps.paddingTop);
  616. var paddingBottom = Number(alignProps.paddingBottom);
  617. var textObj = $jobj(textId);
  618. var textHeight = _getRtfElementHeight(textObj[0]);
  619. var textObjParent = textObj.parent();
  620. var containerHeight = textObjParent.height();
  621. var newTop = 0;
  622. if(vAlign == "middle") {
  623. newTop = _roundToEven((containerHeight - textHeight + paddingTop - paddingBottom) / 2);
  624. } else if(vAlign == "bottom") {
  625. newTop = _roundToEven(containerHeight - textHeight - paddingBottom);
  626. } else { // else top align
  627. newTop = _roundToEven(paddingTop);
  628. }
  629. var oldTop = $jobj(textId).css('top').replace('px', '');
  630. if(oldTop != newTop) {
  631. textObj.css('top', newTop + 'px');
  632. _updateTransformOrigin(textId);
  633. }
  634. };
  635. var _updateTransformOrigin = function(textId) {
  636. var textObj = $jobj(textId);
  637. var transformOrigin = textObj.css('-webkit-transform-origin') ||
  638. textObj.css('-moz-transform-origin') ||
  639. textObj.css('-ms-transform-origin') ||
  640. textObj.css('transform-origin');
  641. if(transformOrigin) {
  642. var textObjParent = textObj.parent();
  643. var newX = (textObjParent.width() / 2 - textObj.css('left').replace('px', ''));
  644. var newY = (textObjParent.height() / 2 - textObj.css('top').replace('px', ''));
  645. var newOrigin = newX + 'px ' + newY + 'px';
  646. textObj.css('-webkit-transform-origin', newOrigin);
  647. textObj.css('-moz-transform-origin', newOrigin);
  648. textObj.css('-ms-transform-origin', newOrigin);
  649. textObj.css('transform-origin', newOrigin);
  650. }
  651. };
  652. $ax.style.clearAdaptiveStyles = function() {
  653. for(var shapeId in _adaptiveStyledWidgets) {
  654. var elementIds = [shapeId];
  655. var repeaterId = $ax.getParentRepeaterFromScriptId(shapeId);
  656. if(repeaterId) {
  657. var itemIds = $ax.getItemIdsForRepeater(repeaterId);
  658. elementIds = [];
  659. for(var i = 0; i < itemIds; i++) elementIds.push($ax.repeater.createElementId(shapeId, itemIds[i]));
  660. }
  661. for(var index = 0; index < elementIds.length; index++) {
  662. var elementId = _getButtonShapeId(elementIds[index]);
  663. if(elementId) {
  664. var textId = $ax.style.GetTextIdFromShape(elementId);
  665. _resetTextJson(elementId, textId);
  666. _applyImageAndTextJson(elementId, $ax.style.generateState(elementId));
  667. }
  668. }
  669. }
  670. _adaptiveStyledWidgets = {};
  671. };
  672. $ax.style.setAdaptiveStyle = function(shapeId, style) {
  673. _adaptiveStyledWidgets[$ax.repeater.getScriptIdFromElementId(shapeId)] = style;
  674. var textId = $ax.style.GetTextIdFromShape(shapeId);
  675. if(textId) _applyTextStyle(textId, style);
  676. // removing this for now
  677. // if(style.location) {
  678. // $jobj(shapeId).css('top', style.location.x + "px")
  679. // .css('left', style.location.y + "px");
  680. // }
  681. };
  682. //-------------------------------------------------------------------------
  683. // _applyTextStyle
  684. //
  685. // Applies a rollover style to a text element.
  686. // id : the id of the text object to set.
  687. // styleProperties : an object mapping style properties to values. eg:
  688. // { 'fontWeight' : 'bold',
  689. // 'fontStyle' : 'italic' }
  690. //-------------------------------------------------------------------------
  691. var _applyTextStyle = function(id, style) {
  692. _transformTextWithVerticalAlignment(id, function() {
  693. var styleProperties = _getCssStyleProperties(style);
  694. $('#' + id).find('*').each(function(index, element) {
  695. _applyCssProps(element, styleProperties);
  696. });
  697. });
  698. };
  699. var _applyCssProps = function(element, styleProperties) {
  700. var nodeName = element.nodeName.toLowerCase();
  701. if(nodeName == 'p') {
  702. var parProps = styleProperties.parProps;
  703. for(var prop in parProps) element.style[prop] = parProps[prop];
  704. } else if(nodeName != 'a') {
  705. var runProps = styleProperties.runProps;
  706. for(prop in runProps) element.style[prop] = runProps[prop];
  707. }
  708. };
  709. var _getCssShadow = function(shadow) {
  710. return !shadow.on ? "none"
  711. : shadow.offsetX + "px " + shadow.offsetY + "px " + shadow.blurRadius + "px " + _getCssColor(shadow.color);
  712. };
  713. var _getCssStyleProperties = function(style) {
  714. var toApply = {};
  715. toApply.runProps = {};
  716. toApply.parProps = {};
  717. if(style.fontName) toApply.runProps.fontFamily = style.fontName;
  718. // we need to set font size on both runs and pars because otherwise it well mess up the measure and thereby vertical alignment
  719. if(style.fontSize) toApply.runProps.fontSize = toApply.parProps.fontSize = style.fontSize;
  720. if(style.fontWeight !== undefined) toApply.runProps.fontWeight = style.fontWeight;
  721. if(style.fontStyle !== undefined) toApply.runProps.fontStyle = style.fontStyle;
  722. if(style.underline !== undefined) toApply.runProps.textDecoration = style.underline ? 'underline' : 'none';
  723. if(style.foreGroundFill) {
  724. toApply.runProps.color = _getColorFromFill(style.foreGroundFill);
  725. if(style.foreGroundFill.opacity) toApply.runProps.opacity = style.foreGroundFill.opacity;
  726. }
  727. if(style.horizontalAlignment) toApply.parProps.textAlign = style.horizontalAlignment;
  728. if(style.lineSpacing) toApply.parProps.lineHeight = style.lineSpacing;
  729. if(style.textShadow) toApply.parProps.textShadow = _getCssShadow(style.textShadow);
  730. return toApply;
  731. };
  732. var _getColorFromFill = function(fill) {
  733. var fillString = '00000' + fill.color.toString(16);
  734. return '#' + fillString.substring(fillString.length - 6);
  735. };
  736. var _getCssColor = function(rgbaObj) {
  737. return "rgba(" + rgbaObj.r + ", " + rgbaObj.g + ", " + rgbaObj.b + ", " + rgbaObj.a + ")";
  738. };
  739. // //--------------------------------------------------------------------------
  740. // // ApplyStyleRecursive
  741. // //
  742. // // Applies a style recursively to all span and div tags including elementNode
  743. // // and all of its children.
  744. // //
  745. // // element : the element to apply the style to
  746. // // styleName : the name of the style property to set (eg. 'font-weight')
  747. // // styleValue : the value of the style to set (eg. 'bold')
  748. // //--------------------------------------------------------------------------
  749. // function ApplyStyleRecursive(element, styleName, styleValue) {
  750. // var nodeName = element.nodeName.toLowerCase();
  751. // if (nodeName == 'div' || nodeName == 'span' || nodeName == 'p') {
  752. // element.style[styleName] = styleValue;
  753. // }
  754. // for (var i = 0; i < element.childNodes.length; i++) {
  755. // ApplyStyleRecursive(element.childNodes[i], styleName, styleValue);
  756. // }
  757. // }
  758. // //---------------------------------------------------------------------------
  759. // // ApplyTextProperty
  760. // //
  761. // // Applies a text property to rtfElement.
  762. // //
  763. // // rtfElement : the the root text element of the rtf object (this is the
  764. // // element named <id>_rtf
  765. // // prop : the style property to set.
  766. // // value : the style value to set.
  767. // //---------------------------------------------------------------------------
  768. // function ApplyTextProperty(rtfElement, prop, value) {
  769. // /*
  770. // var oldHtml = rtfElement.innerHTML;
  771. // if (prop == 'fontWeight') {
  772. // rtfElement.innerHTML = oldHtml.replace(/< *b *\/?>/gi, "");
  773. // } else if (prop == 'fontStyle') {
  774. // rtfElement.innerHTML = oldHtml.replace(/< *i *\/?>/gi, "");
  775. // } else if (prop == 'textDecoration') {
  776. // rtfElement.innerHTML = oldHtml.replace(/< *u *\/?>/gi, "");
  777. // }
  778. // */
  779. // for (var i = 0; i < rtfElement.childNodes.length; i++) {
  780. // ApplyStyleRecursive(rtfElement.childNodes[i], prop, value);
  781. // }
  782. // }
  783. //}
  784. //---------------------------------------------------------------------------
  785. // GetAndCacheOriginalText
  786. //
  787. // Gets the html for the pre-rollover state and returns the Html representing
  788. // the Rich text.
  789. //---------------------------------------------------------------------------
  790. var CACHE_COUNTER = 0;
  791. $ax.style.CacheOriginalText = function(textId, hasRichTextBeenSet) {
  792. var rtfQuery = $('#' + textId);
  793. if(rtfQuery.length > 0) {
  794. var styleCache = {};
  795. rtfQuery.find('*').each(function(index, element) {
  796. var elementId = element.id;
  797. if(!elementId) element.id = elementId = 'cache' + CACHE_COUNTER++;
  798. styleCache[elementId] = element.style.cssText;
  799. });
  800. _originalTextCache[textId] = {
  801. styleCache: styleCache
  802. };
  803. if(hasRichTextBeenSet) {
  804. var shapeId = _getShapeIdFromText(textId);
  805. _shapesWithSetRichText[shapeId] = true;
  806. }
  807. }
  808. };
  809. $ax.style.ClearCacheForRepeater = function(repeaterId) {
  810. for(var elementId in _originalTextCache) {
  811. var scriptId = $ax.repeater.getScriptIdFromElementId(elementId);
  812. if($ax.getParentRepeaterFromScriptId(scriptId) == repeaterId) delete _originalTextCache[elementId];
  813. }
  814. };
  815. $ax.style.prefetch = function() {
  816. var scriptIds = $ax.getAllScriptIds();
  817. var image = new Image();
  818. for(var i = 0; i < scriptIds.length; i++) {
  819. var obj = $obj(scriptIds[i]);
  820. if(obj.type != 'imageBox') continue;
  821. var images = obj.images;
  822. for(var key in images) image.src = images[key];
  823. }
  824. };
  825. });