utils.js 13 KB

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