utils.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. var multipleClustersSupported = false;
  2. /* Super-handy augmentation to Function that allows 'this' to be bound
  3. * statically.
  4. *
  5. * Primarily used when creating objects whose methods will be used as
  6. * callbacks in unknown contexts.
  7. *
  8. * Look at txnUtils.js for sample usage.
  9. */
  10. Function.prototype.bind = function(scope) {
  11. var _function = this;
  12. return function() {
  13. return _function.apply(scope, arguments);
  14. }
  15. }
  16. /* Belongs with createInformationalPanel() */
  17. var customizedYuiPanelCss = false;
  18. /* XXX Ugly, ugly hack to emulate a singleton - users are NEVER supposed
  19. * to use this, and should only access the createInformationalPanel() and
  20. * destroyInformationalPanel() methods below.
  21. */
  22. var globalSingletonInformationalPanel;
  23. function createInformationalPanel( containerNodeId, headerContentString ) {
  24. /* XXX This should check that globalSingletonInformationalPanel is within
  25. * containerNodeId, and only then perform this cleanup, but this whole
  26. * panel-related section needs to be rewritten anyway - for now, we only
  27. * support the one globalSingletonInformationalPanel, and passing in
  28. * anything other than #informationalPanelContainerDivId as containerNodeId
  29. * is not guaranteed to work.
  30. */
  31. if( globalSingletonInformationalPanel ) {
  32. destroyInformationalPanel( globalSingletonInformationalPanel );
  33. }
  34. globalYui.one( containerNodeId ).append('<div id="informationalPanelInnerContainerDivId"></div>');
  35. globalYui.one( '#informationalPanelInnerContainerDivId' ).append( '<div class="yui3-widget-hd"></div>' );
  36. globalYui.one( '#informationalPanelInnerContainerDivId' ).append( '<div class="yui3-widget-bd"></div>' );
  37. globalYui.one( '#informationalPanelInnerContainerDivId' ).append( '<div class="yui3-widget-ft"></div>' );
  38. var newPanel = new globalYui.Panel({
  39. srcNode: '#informationalPanelInnerContainerDivId',
  40. headerContent: headerContentString,
  41. width: 800,
  42. height: 400,
  43. centered: true,
  44. render: true,
  45. modal: true,
  46. zIndex: 100,
  47. visible: false
  48. });
  49. if( !customizedYuiPanelCss ) {
  50. /* Needs to be called one time only.
  51. *
  52. * We do this here instead of creating a static entry in a CSS file
  53. * because the first invocation of globalYui.Panel (above) pulls in all
  54. * the necessary additional styling information that is applied to the
  55. * panel - since this new styling information comes in at runtime, it
  56. * overrides any static CSS we might have had, so adding our overrides
  57. * at runtime (*after* globalYui.Panel) is the only way out.
  58. */
  59. globalYui.StyleSheet('KewlApp').set( '.yui3-skin-sam .yui3-panel-content .yui3-widget-hd', {
  60. background: 'rgb(50,185,50)',
  61. textAlign: 'center',
  62. fontWeight: 'bold',
  63. fontSize: '150%'
  64. });
  65. globalYui.StyleSheet('KewlApp').set( '.yui3-skin-sam .yui3-panel-content .yui3-button-icon', {
  66. backgroundColor: 'white',
  67. border: 'medium solid gray'
  68. });
  69. globalYui.StyleSheet('KewlApp').set( '.yui3-skin-sam .yui3-panel-content .yui3-widget-ft', {
  70. background: 'rgb(50,185,50)',
  71. });
  72. globalYui.StyleSheet('KewlApp').set( '.yui3-skin-sam .yui3-panel-content .yui3-widget-ft .yui3-button', {
  73. fontWeight: 'bold',
  74. fontSize: '135%',
  75. color: 'white',
  76. margin: '0pt 6px',
  77. padding: '4px 8px',
  78. textDecoration: 'underline',
  79. background: 'none',
  80. border: '0px'
  81. });
  82. customizedYuiPanelCss = true;
  83. }
  84. globalSingletonInformationalPanel = newPanel;
  85. return newPanel;
  86. }
  87. function destroyInformationalPanel( theInformationalPanelInstance ) {
  88. if( theInformationalPanelInstance ) {
  89. theInformationalPanelInstance.hide();
  90. theInformationalPanelInstance.destroy();
  91. if( theInformationalPanelInstance === globalSingletonInformationalPanel ) {
  92. globalSingletonInformationalPanel = null;
  93. }
  94. }
  95. }
  96. function showLoadingImg() {
  97. globalYui.one("#loadingDivId").setStyle('display','block');
  98. //globalYui.one("#blackScreenDivId").setStyle('display','block');
  99. //globalYui.one("#loadingImgId").setStyle('display','block');
  100. }
  101. function hideLoadingImg() {
  102. globalYui.one("#loadingDivId").setStyle('display','none');
  103. //globalYui.one("#loadingImgId").setStyle('display','none');
  104. //globalYui.one("#blackScreenDivId").setStyle('display','none');
  105. }
  106. function swapStageVisibilities( currentStageDivSelector, newStageDivSelector ) {
  107. globalYui.log("In swapStageVisibilities: " + currentStageDivSelector + "->" + newStageDivSelector);
  108. /* Hide the current stage. */
  109. globalYui.one(currentStageDivSelector).setStyle('display','none');
  110. /* Show the new stage. */
  111. globalYui.one(newStageDivSelector).setStyle('display','block');
  112. }
  113. /* TODO XXX Consider bundling the last 3 parameters into their own NewStage object.
  114. * TODO XXX Do the same for the first 2 parameters and a CurrentStage object.
  115. */
  116. function transitionToNextStage( currentStageDivSelector, currentStageData, newStageDivSelector, newStageData, newStageRenderFunction ) {
  117. clearFormStatus();
  118. globalYui.one(currentStageDivSelector).setStyle('display','none');
  119. /* Render the next stage. */
  120. newStageRenderFunction(newStageData);
  121. globalYui.log("In transitionToNextStage: " + currentStageDivSelector + "->" + newStageDivSelector);
  122. //// tshooter: No longer doing this given dynamic rendering on stages. Only hide current stage.
  123. /* And make it visibly replace the currently showing one. */
  124. ///// tshooter: commented: swapStageVisibilities(currentStageDivSelector, newStageDivSelector);
  125. /* And now, handle the updates to addNodesWizardStages... */
  126. /* There can be only one 'current' stage at a time. */
  127. var currentStage = globalYui.one('.installationWizardCurrentStage');
  128. var nextStage = null;
  129. /* Check to make sure we haven't reached the last stage. */
  130. if( nextStage = currentStage.next('.installationWizardUnvisitedStage') ) {
  131. /* Mark this up-until-now 'current' stage as 'visited'. */
  132. currentStage.replaceClass( 'installationWizardCurrentStage', 'installationWizardVisitedStage' );
  133. /* Mark the stage after that as the new 'current' stage. */
  134. nextStage.replaceClass( 'installationWizardUnvisitedStage', 'installationWizardCurrentStage' );
  135. }
  136. }
  137. function clearFormStatus() {
  138. var formStatusDiv = globalYui.all("#formStatusDivId");
  139. // formStatusDiv.setContent("");
  140. formStatusDiv.setStyle("visibility", "hidden");
  141. formStatusDiv.setStyle("display", "none");
  142. formStatusDiv.set('className','');
  143. formStatusDiv.addClass("formStatusBar");
  144. }
  145. function setFormStatus(statusString, isError, noFade) {
  146. var formStatusDivCssClass;
  147. if (isError) {
  148. formStatusDivCssClass = 'statusError';
  149. } else {
  150. formStatusDivCssClass = 'statusOk';
  151. }
  152. var formStatusDiv = globalYui.all("#formStatusDivId");
  153. formStatusDiv.setStyle("visibility", "visible");
  154. formStatusDiv.setStyle("display", "block");
  155. formStatusDiv.set('className','');
  156. formStatusDiv.addClass("formStatusBar");
  157. formStatusDiv.addClass(formStatusDivCssClass);
  158. formStatusDiv.setContent(statusString);
  159. if (!isError && !noFade) {
  160. //setTimeout(fadeFormStatus, 1000);
  161. }
  162. }
  163. function fadeFormStatus() {
  164. var formStatusDiv = globalYui.one("#formStatusDivId");
  165. formStatusDiv.addClass("formStatusBarZeroOpacity");
  166. }
  167. function convertDisplayType (displayType) {
  168. switch (displayType) {
  169. case "NODISPLAY":
  170. return "NODISPLAY";
  171. case "TEXT":
  172. return "text";
  173. case "SECRET":
  174. return "password";
  175. default:
  176. return "text";
  177. }
  178. }
  179. function executeStage(inputUrl, renderStageFunction) {
  180. globalYui.io(inputUrl, {
  181. method: 'GET',
  182. timeout : 10000,
  183. on: {
  184. success: function (x,o) {
  185. globalYui.log("RAW JSON DATA: " + o.responseText);
  186. // Process the JSON data returned from the server
  187. try {
  188. responseJson = globalYui.JSON.parse(o.responseText);
  189. }
  190. catch (e) {
  191. hideLoadingImg();
  192. alert("JSON Parse failed!");
  193. return;
  194. }
  195. globalYui.log("PARSED DATA: " + globalYui.Lang.dump(responseJson));
  196. if (responseJson.result != 0) {
  197. hideLoadingImg();
  198. // Error!
  199. alert("Got error during getting data: " + responseJson.error);
  200. return;
  201. }
  202. responseJson = responseJson.response;
  203. renderStageFunction(responseJson);
  204. hideLoadingImg();
  205. return;
  206. },
  207. failure: function (x,o) {
  208. alert("Async call failed!");
  209. return;
  210. }
  211. }
  212. });
  213. }
  214. function submitDataAndProgressToNextScreen(url, requestData, submitButton, thisScreenId, nextScreenId, nextScreenRenderFunction, errorHandlerFunction) {
  215. showLoadingImg();
  216. globalYui.io(url, {
  217. method: 'POST',
  218. data: globalYui.JSON.stringify(requestData),
  219. timeout : 10000,
  220. on: {
  221. start: function(x, o) {
  222. submitButton.set('disabled', true);
  223. globalYui.log("In start function");
  224. // showLoadingImg();
  225. },
  226. complete: function(x, o) {
  227. submitButton.set('disabled', false);
  228. globalYui.log("In stop function");
  229. // hideLoadingImg();
  230. },
  231. success: function (x,o) {
  232. submitButton.set('disabled', false);
  233. globalYui.log("RAW JSON DATA: " + o.responseText);
  234. // Process the JSON data returned from the server
  235. try {
  236. responseJson = globalYui.JSON.parse(o.responseText);
  237. }
  238. catch (e) {
  239. submitButton.set('disabled', false);
  240. hideLoadingImg();
  241. alert("JSON Parse failed!");
  242. return;
  243. }
  244. globalYui.log("PARSED DATA: " + globalYui.Lang.dump(responseJson));
  245. if (responseJson.result != 0) {
  246. submitButton.set('disabled', false);
  247. hideLoadingImg();
  248. // Error!
  249. globalYui.log("Got error during submit data!" + responseJson.error);
  250. if ( errorHandlerFunction ) {
  251. globalYui.log("Invoking error handler function");
  252. errorHandlerFunction(responseJson);
  253. } else {
  254. alert("Got error during submit data!" + responseJson.error);
  255. }
  256. return;
  257. }
  258. responseJson = responseJson.response;
  259. /* Done with this stage, transition to the next. */
  260. transitionToNextStage( thisScreenId, requestData, nextScreenId, responseJson, nextScreenRenderFunction );
  261. },
  262. failure: function (x,o) {
  263. submitButton.set('disabled', false);
  264. alert("Async call failed!");
  265. }
  266. }
  267. });
  268. }
  269. function PeriodicDataPoller( dataSourceContext, responseHandler ) {
  270. this.dataSourceContext = dataSourceContext;
  271. /* Smoothe out the optional bits of this.dataSourceContext. */
  272. if( !this.dataSourceContext.pollInterval ) {
  273. /* How often we poll. */
  274. this.dataSourceContext.pollInterval = 5000;
  275. }
  276. if( !this.dataSourceContext.maxFailedAttempts ) {
  277. /* How many failed attempts before we stop polling. */
  278. this.dataSourceContext.maxFailedAttempts = 5;
  279. }
  280. this.responseHandler = responseHandler;
  281. this.dataSource = new globalYui.DataSource.IO ({
  282. source: this.dataSourceContext.source
  283. });
  284. this.dataSource.plug(globalYui.Plugin.DataSourceJSONSchema, {
  285. schema: this.dataSourceContext.schema
  286. });
  287. this.dataSourcePollFailureCount = 0;
  288. /* Set when start() is invoked. */
  289. this.dataSourcePollHandle = null;
  290. this.dataSourcePollRequestContext = {
  291. request: this.dataSourceContext.request,
  292. callback: {
  293. success: function (e) {
  294. /* Reset our failure count every time we succeed. */
  295. this.dataSourcePollFailureCount = 0;
  296. /* Invoke user-pluggable code. */
  297. if( this.responseHandler.success ) {
  298. this.responseHandler.success( e, this );
  299. }
  300. }.bind(this),
  301. failure: function (e) {
  302. ++this.dataSourcePollFailureCount;
  303. if( this.dataSourcePollFailureCount > this.dataSourceContext.maxFailedAttempts ) {
  304. /* Invoke user-pluggable code. */
  305. if( this.responseHandler.failure ) {
  306. this.responseHandler.failure( e, this );
  307. }
  308. /* No point making any more attempts. */
  309. this.stop();
  310. }
  311. }.bind(this)
  312. }
  313. };
  314. }
  315. /* Start polling. */
  316. PeriodicDataPoller.prototype.start = function() {
  317. this.dataSourcePollHandle = this.dataSource.setInterval( this.dataSourceContext.pollInterval, this.dataSourcePollRequestContext );
  318. }
  319. /* Stop polling. */
  320. PeriodicDataPoller.prototype.stop = function() {
  321. this.dataSource.clearInterval( this.dataSourcePollHandle );
  322. }
  323. function titleCase(word){
  324. return word.substr(0,1).toUpperCase() + word.substr(1).toLowerCase();
  325. }