Fork of the espurna firmware for `mhsw` switches
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

857 lines
24 KiB

8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
  1. var websock;
  2. var password = false;
  3. var maxNetworks;
  4. var useWhite = false;
  5. var messages = [];
  6. var webhost;
  7. // http://www.the-art-of-web.com/javascript/validate-password/
  8. function checkPassword(str) {
  9. // at least one number, one lowercase and one uppercase letter
  10. // at least eight characters that are letters, numbers or the underscore
  11. var re = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])\w{8,}$/;
  12. return re.test(str);
  13. }
  14. function validateForm(form) {
  15. // password
  16. var adminPass1 = $("input[name='adminPass1']", form).val();
  17. if (adminPass1.length > 0 && !checkPassword(adminPass1)) {
  18. alert("The password you have entered is not valid, it must have at least 8 characters, 1 lower and 1 uppercase and 1 number!");
  19. return false;
  20. }
  21. var adminPass2 = $("input[name='adminPass2']", form).val();
  22. if (adminPass1 != adminPass2) {
  23. alert("Passwords are different!");
  24. return false;
  25. }
  26. return true;
  27. }
  28. function valueSet(data, name, value) {
  29. for (var i in data) {
  30. if (data[i]['name'] == name) {
  31. data[i]['value'] = value;
  32. return;
  33. }
  34. }
  35. data.push({'name': name, 'value': value});
  36. }
  37. function zeroPad(number, positions) {
  38. return ("0".repeat(positions) + number).slice(-positions);
  39. }
  40. function doUpdate() {
  41. var form = $("#formSave");
  42. if (validateForm(form)) {
  43. // Get data
  44. var data = form.serializeArray();
  45. // Post-process
  46. delete(data['filename']);
  47. $("input[type='checkbox']").each(function() {
  48. var name = $(this).attr("name");
  49. if (name) {
  50. valueSet(data, name, $(this).is(':checked') ? 1 : 0);
  51. }
  52. });
  53. websock.send(JSON.stringify({'config': data}));
  54. $(".pwrExpected").val(0);
  55. $("input[name='pwrResetCalibration']")
  56. .prop("checked", false)
  57. .iphoneStyle("refresh");
  58. }
  59. return false;
  60. }
  61. function doUpgrade() {
  62. var contents = $("input[name='upgrade']")[0].files[0];
  63. if (typeof contents == 'undefined') {
  64. alert("First you have to select a file from your computer.");
  65. return false;
  66. }
  67. var filename = $("input[name='upgrade']").val().split('\\').pop();
  68. var data = new FormData();
  69. data.append('upgrade', contents, filename);
  70. $.ajax({
  71. // Your server script to process the upload
  72. url: webhost + 'upgrade',
  73. type: 'POST',
  74. // Form data
  75. data: data,
  76. // Tell jQuery not to process data or worry about content-type
  77. // You *must* include these options!
  78. cache: false,
  79. contentType: false,
  80. processData: false,
  81. success: function(data, text) {
  82. $("#upgrade-progress").hide();
  83. if (data == 'OK') {
  84. alert("Firmware image uploaded, board rebooting. This page will be refreshed in 5 seconds.");
  85. setTimeout(function() {
  86. window.location.reload();
  87. }, 5000);
  88. } else {
  89. alert("There was an error trying to upload the new image, please try again (" + data + ").");
  90. }
  91. },
  92. // Custom XMLHttpRequest
  93. xhr: function() {
  94. $("#upgrade-progress").show();
  95. var myXhr = $.ajaxSettings.xhr();
  96. if (myXhr.upload) {
  97. // For handling the progress of the upload
  98. myXhr.upload.addEventListener('progress', function(e) {
  99. if (e.lengthComputable) {
  100. $('progress').attr({ value: e.loaded, max: e.total });
  101. }
  102. } , false);
  103. }
  104. return myXhr;
  105. },
  106. });
  107. return false;
  108. }
  109. function doUpdatePassword() {
  110. var form = $("#formPassword");
  111. if (validateForm(form)) {
  112. var data = form.serializeArray();
  113. websock.send(JSON.stringify({'config': data}));
  114. }
  115. return false;
  116. }
  117. function doReset() {
  118. var response = window.confirm("Are you sure you want to reset the device?");
  119. if (response == false) return false;
  120. websock.send(JSON.stringify({'action': 'reset'}));
  121. return false;
  122. }
  123. function doReconnect() {
  124. var response = window.confirm("Are you sure you want to disconnect from the current WIFI network?");
  125. if (response == false) return false;
  126. websock.send(JSON.stringify({'action': 'reconnect'}));
  127. return false;
  128. }
  129. function doToggle(element, value) {
  130. var relayID = parseInt(element.attr("data"));
  131. websock.send(JSON.stringify({'action': 'relay', 'data': { 'id': relayID, 'status': value ? 1 : 0 }}));
  132. return false;
  133. }
  134. function backupSettings() {
  135. document.getElementById('downloader').src = webhost + 'config';
  136. return false;
  137. }
  138. function onFileUpload(event) {
  139. var inputFiles = this.files;
  140. if (inputFiles == undefined || inputFiles.length == 0) return false;
  141. var inputFile = inputFiles[0];
  142. this.value = "";
  143. var response = window.confirm("Previous settings will be overwritten. Are you sure you want to restore this settings?");
  144. if (response == false) return false;
  145. var reader = new FileReader();
  146. reader.onload = function(e) {
  147. var data = getJson(e.target.result);
  148. if (data) {
  149. websock.send(JSON.stringify({'action': 'restore', 'data': data}));
  150. } else {
  151. alert(messages[4]);
  152. }
  153. };
  154. reader.readAsText(inputFile);
  155. return false;
  156. }
  157. function restoreSettings() {
  158. if (typeof window.FileReader !== 'function') {
  159. alert("The file API isn't supported on this browser yet.");
  160. } else {
  161. $("#uploader").click();
  162. }
  163. return false;
  164. }
  165. function randomString(length, chars) {
  166. var mask = '';
  167. if (chars.indexOf('a') > -1) mask += 'abcdefghijklmnopqrstuvwxyz';
  168. if (chars.indexOf('A') > -1) mask += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  169. if (chars.indexOf('#') > -1) mask += '0123456789';
  170. if (chars.indexOf('@') > -1) mask += 'ABCDEF';
  171. if (chars.indexOf('!') > -1) mask += '~`!@#$%^&*()_+-={}[]:";\'<>?,./|\\';
  172. var result = '';
  173. for (var i = length; i > 0; --i) result += mask[Math.round(Math.random() * (mask.length - 1))];
  174. return result;
  175. }
  176. function doGenerateAPIKey() {
  177. var apikey = randomString(16, '@#');
  178. $("input[name=\"apiKey\"]").val(apikey);
  179. return false;
  180. }
  181. function showPanel() {
  182. $(".panel").hide();
  183. $("#" + $(this).attr("data")).show();
  184. if ($("#layout").hasClass('active')) toggleMenu();
  185. $("input[type='checkbox']").iphoneStyle("calculateDimensions").iphoneStyle("refresh");
  186. };
  187. function toggleMenu() {
  188. $("#layout").toggleClass('active');
  189. $("#menu").toggleClass('active');
  190. $("#menuLink").toggleClass('active');
  191. }
  192. function createRelays(count) {
  193. var current = $("#relays > div").length;
  194. if (current > 0) return;
  195. var template = $("#relayTemplate .pure-g")[0];
  196. for (var relayID=0; relayID<count; relayID++) {
  197. var line = $(template).clone();
  198. $(line).find("input").each(function() {
  199. $(this).attr("data", relayID);
  200. });
  201. if (count > 1) $(".relay_id", line).html(" " + (relayID+1));
  202. line.appendTo("#relays");
  203. $(":checkbox", line).iphoneStyle({
  204. onChange: doToggle,
  205. resizeContainer: true,
  206. resizeHandle: true,
  207. checkedLabel: 'ON',
  208. uncheckedLabel: 'OFF'
  209. });
  210. }
  211. }
  212. function createIdxs(count) {
  213. var current = $("#idxs > div").length;
  214. if (current > 0) return;
  215. var template = $("#idxTemplate .pure-g")[0];
  216. for (var id=0; id<count; id++) {
  217. var line = $(template).clone();
  218. $(line).find("input").each(function() {
  219. $(this).attr("data", id).attr("tabindex", 40+id);
  220. });
  221. if (count > 1) $(".id", line).html(" " + id);
  222. line.appendTo("#idxs");
  223. }
  224. }
  225. function delNetwork() {
  226. var parent = $(this).parents(".pure-g");
  227. $(parent).remove();
  228. }
  229. function moreNetwork() {
  230. var parent = $(this).parents(".pure-g");
  231. $("div.more", parent).toggle();
  232. }
  233. function addNetwork() {
  234. var numNetworks = $("#networks > div").length;
  235. if (numNetworks >= maxNetworks) {
  236. alert("Max number of networks reached");
  237. return;
  238. }
  239. var tabindex = 200 + numNetworks * 10;
  240. var template = $("#networkTemplate").children();
  241. var line = $(template).clone();
  242. $(line).find("input").each(function() {
  243. $(this).attr("tabindex", tabindex++);
  244. });
  245. $(line).find(".button-del-network").on('click', delNetwork);
  246. $(line).find(".button-more-network").on('click', moreNetwork);
  247. line.appendTo("#networks");
  248. return line;
  249. }
  250. function initColor() {
  251. // check if already initialized
  252. var done = $("#colors > div").length;
  253. if (done > 0) return;
  254. // add template
  255. var template = $("#colorTemplate").children();
  256. var line = $(template).clone();
  257. line.appendTo("#colors");
  258. // init color wheel
  259. $('input[name="color"]').wheelColorPicker({
  260. sliders: 'wrgbp'
  261. }).on('sliderup', function() {
  262. var value = $(this).wheelColorPicker('getValue', 'css');
  263. websock.send(JSON.stringify({'action': 'color', 'data' : value}));
  264. });
  265. // init bright slider
  266. noUiSlider.create($("#brightness").get(0), {
  267. start: 255,
  268. connect: [true, false],
  269. tooltips: true,
  270. format: {
  271. to: function (value) { return parseInt(value); },
  272. from: function (value) { return value; }
  273. },
  274. orientation: "horizontal",
  275. range: { 'min': 0, 'max': 255}
  276. }).on("change", function() {
  277. var value = parseInt(this.get());
  278. websock.send(JSON.stringify({'action': 'brightness', 'data' : value}));
  279. });
  280. }
  281. function initColorHsv() {
  282. // check if already initialized
  283. var done = $("#colors > div").length;
  284. if (done > 0) return;
  285. // add template
  286. var template = $("#colorHsvTemplate").children();
  287. var line = $(template).clone();
  288. line.appendTo("#colors");
  289. // init color wheel
  290. $('input[name="color"]').wheelColorPicker({
  291. sliders: 'whsvp'
  292. }).on('sliderup', function() {
  293. var color_all = $(this).wheelColorPicker('getColor');
  294. var color_hsv ={};
  295. color_hsv.h =Math.floor(color_all.h * 255);
  296. color_hsv.s =Math.floor(color_all.s * 255);
  297. color_hsv.v =Math.floor(color_all.v * 255);
  298. websock.send(JSON.stringify({'action': 'color_hsv', 'data' : color_hsv}));
  299. });
  300. }
  301. function initColorsExtras() {
  302. // check if already initialized
  303. var done = $("#colorsExtras > div").length;
  304. if (done > 0) return;
  305. // add template
  306. var template = $("#colorsExtrasTemplate").children();
  307. var line = $(template).clone();
  308. line.appendTo("#colorsExtras");
  309. // init anim mode
  310. $("#animMode").on('change', function() {
  311. var select = this.value;
  312. websock.send(JSON.stringify( {'action': 'anim_mode', 'data' : select }));
  313. });
  314. // init anim speed slider
  315. noUiSlider.create($("#animSpeed").get(0), {
  316. start: 500,
  317. connect: [true, false],
  318. tooltips: true,
  319. format: {
  320. to: function (value) { return parseInt(value); },
  321. from: function (value) { return value; }
  322. },
  323. orientation: "horizontal",
  324. range: { 'min': 0, 'max': 1000}
  325. }).on("change", function() {
  326. var value = parseInt(this.get());
  327. websock.send(JSON.stringify({'action': 'anim_speed', 'data' : value}));
  328. });
  329. }
  330. function initChannels(num) {
  331. // check if already initialized
  332. var done = $("#channels > div").length > 0;
  333. if (done) return;
  334. // does it have color channels?
  335. var colors = $("#colors > div").length > 0;
  336. // calculate channels to create
  337. var max = num;
  338. if (colors) {
  339. max = num % 3;
  340. if ((max > 0) & useWhite) max--;
  341. }
  342. var start = num - max;
  343. // add templates
  344. var template = $("#channelTemplate").children();
  345. for (var i=0; i<max; i++) {
  346. var channel_id = start + i;
  347. var line = $(template).clone();
  348. $(".slider", line).attr("data", channel_id);
  349. $("label", line).html("Channel " + (channel_id + 1));
  350. noUiSlider.create($(".slider", line).get(0), {
  351. start: 0,
  352. connect: [true, false],
  353. tooltips: true,
  354. format: {
  355. to: function (value) { return parseInt(value); },
  356. from: function (value) { return value; }
  357. },
  358. orientation: "horizontal",
  359. range: { 'min': 0, 'max': 255 }
  360. }).on("change", function() {
  361. var id = $(this.target).attr("data");
  362. var value = parseInt(this.get());
  363. websock.send(JSON.stringify({'action': 'channel', 'data': { 'id': id, 'value': value }}));
  364. });
  365. line.appendTo("#channels");
  366. }
  367. }
  368. function addRfbNode() {
  369. var numNodes = $("#rfbNodes > fieldset").length;
  370. var template = $("#rfbNodeTemplate").children();
  371. var line = $(template).clone();
  372. var status = true;
  373. $("span", line).html(numNodes+1);
  374. $(line).find("input").each(function() {
  375. $(this).attr("data_id", numNodes);
  376. $(this).attr("data_status", status ? 1 : 0);
  377. status = !status;
  378. });
  379. $(line).find(".button-rfb-learn").on('click', rfbLearn);
  380. $(line).find(".button-rfb-forget").on('click', rfbForget);
  381. $(line).find(".button-rfb-send").on('click', rfbSend);
  382. line.appendTo("#rfbNodes");
  383. return line;
  384. }
  385. function rfbLearn() {
  386. var parent = $(this).parents(".pure-g");
  387. var input = $("input", parent);
  388. websock.send(JSON.stringify({'action': 'rfblearn', 'data' : {'id' : input.attr("data_id"), 'status': input.attr("data_status")}}));
  389. }
  390. function rfbForget() {
  391. var parent = $(this).parents(".pure-g");
  392. var input = $("input", parent);
  393. websock.send(JSON.stringify({'action': 'rfbforget', 'data' : {'id' : input.attr("data_id"), 'status': input.attr("data_status")}}));
  394. }
  395. function rfbSend() {
  396. var parent = $(this).parents(".pure-g");
  397. var input = $("input", parent);
  398. websock.send(JSON.stringify({'action': 'rfbsend', 'data' : {'id' : input.attr("data_id"), 'status': input.attr("data_status"), 'data': input.val()}}));
  399. }
  400. function forgetCredentials() {
  401. $.ajax({
  402. 'method': 'GET',
  403. 'url': '/',
  404. 'async': false,
  405. 'username': "logmeout",
  406. 'password': "123456",
  407. 'headers': { "Authorization": "Basic xxx" }
  408. }).done(function(data) {
  409. return false;
  410. // If we don't get an error, we actually got an error as we expect an 401!
  411. }).fail(function(){
  412. // We expect to get an 401 Unauthorized error! In this case we are successfully
  413. // logged out and we redirect the user.
  414. return true;
  415. });
  416. }
  417. function processData(data) {
  418. // title
  419. if ("app" in data) {
  420. var title = data.app;
  421. if ("version" in data) {
  422. title = title + " " + data.version;
  423. }
  424. $(".pure-menu-heading").html(title);
  425. if ("hostname" in data) {
  426. title = data.hostname + " - " + title;
  427. }
  428. document.title = title;
  429. }
  430. Object.keys(data).forEach(function(key) {
  431. // Web Modes
  432. if (key == "webMode") {
  433. password = data.webMode == 1;
  434. $("#layout").toggle(data.webMode == 0);
  435. $("#password").toggle(data.webMode == 1);
  436. $("#credentials").hide();
  437. }
  438. // Actions
  439. if (key == "action") {
  440. if (data.action == "reload") {
  441. if (password) forgetCredentials();
  442. setTimeout(function() {
  443. window.location.reload();
  444. }, 1000);
  445. }
  446. if (data.action == "rfbLearn") {
  447. // Nothing to do?
  448. }
  449. if (data.action == "rfbTimeout") {
  450. // Nothing to do?
  451. }
  452. return;
  453. }
  454. if (key == "rfbCount") {
  455. for (var i=0; i<data.rfbCount; i++) addRfbNode();
  456. return;
  457. }
  458. if (key == "rfb") {
  459. var nodes = data.rfb;
  460. for (var i in nodes) {
  461. var node = nodes[i];
  462. var element = $("input[name=rfbcode][data_id=" + node["id"] + "][data_status=" + node["status"] + "]");
  463. if (element.length) element.val(node["data"]);
  464. }
  465. return;
  466. }
  467. if (key == "color") {
  468. initColor();
  469. $("input[name='color']").wheelColorPicker('setValue', data[key], true);
  470. return;
  471. }
  472. if (key == "color_hsv") {
  473. initColorHsv();
  474. var color_hsv ={};
  475. color_hsv.h = data[key]['h'] / 255;
  476. color_hsv.s = data[key]['s'] / 255;
  477. color_hsv.v = data[key]['v'] / 255;
  478. $("input[name='color']").wheelColorPicker('setColor', color_hsv);
  479. return;
  480. }
  481. if (key == "anim_mode") {
  482. initColorsExtras();
  483. $("[name='animation']").val(data[key]);
  484. return;
  485. }
  486. if (key == "anim_speed") {
  487. initColorsExtras();
  488. var slider = $("#animSpeed");
  489. if (slider.length) slider.get(0).noUiSlider.set(data[key]);
  490. return;
  491. }
  492. if (key == "brightness") {
  493. var slider = $("#brightness");
  494. if (slider.length) slider.get(0).noUiSlider.set(data[key]);
  495. return;
  496. }
  497. if (key == "channels") {
  498. var len = data[key].length;
  499. initChannels(len);
  500. for (var i=0; i<len; i++) {
  501. var slider = $("div.channels[data=" + i + "]");
  502. if (slider.length) slider.get(0).noUiSlider.set(data[key][i]);
  503. }
  504. return;
  505. }
  506. if (key == "uptime") {
  507. var uptime = parseInt(data[key]);
  508. var seconds = uptime % 60; uptime = parseInt(uptime / 60);
  509. var minutes = uptime % 60; uptime = parseInt(uptime / 60);
  510. var hours = uptime % 24; uptime = parseInt(uptime / 24);
  511. var days = uptime;
  512. data[key] = days + 'd ' + zeroPad(hours, 2) + 'h ' + zeroPad(minutes, 2) + 'm ' + zeroPad(seconds, 2) + 's';
  513. }
  514. if (key == "useWhite") {
  515. useWhite = data[key];
  516. }
  517. if (key == "maxNetworks") {
  518. maxNetworks = parseInt(data.maxNetworks);
  519. return;
  520. }
  521. // Wifi
  522. if (key == "wifi") {
  523. var networks = data.wifi;
  524. for (var i in networks) {
  525. // add a new row
  526. var line = addNetwork();
  527. // fill in the blanks
  528. var wifi = data.wifi[i];
  529. Object.keys(wifi).forEach(function(key) {
  530. var element = $("input[name=" + key + "]", line);
  531. if (element.length) element.val(wifi[key]);
  532. });
  533. }
  534. return;
  535. }
  536. // Relay status
  537. if (key == "relayStatus") {
  538. var relays = data.relayStatus;
  539. createRelays(relays.length);
  540. for (var relayID in relays) {
  541. var element = $(".relayStatus[data=" + relayID + "]");
  542. if (element.length > 0) {
  543. element
  544. .prop("checked", relays[relayID])
  545. .iphoneStyle("refresh");
  546. }
  547. }
  548. return;
  549. }
  550. // Domoticz
  551. if (key == "dczRelayIdx") {
  552. var idxs = data.dczRelayIdx;
  553. createIdxs(idxs.length);
  554. for (var i in idxs) {
  555. var element = $(".dczRelayIdx[data=" + i + "]");
  556. if (element.length > 0) element.val(idxs[i]);
  557. }
  558. return;
  559. }
  560. // Messages
  561. if (key == "message") {
  562. window.alert(messages[data.message]);
  563. return;
  564. }
  565. // Enable options
  566. if (key.endsWith("Visible")) {
  567. var module = key.slice(0,-7);
  568. $(".module-" + module).show();
  569. return;
  570. }
  571. // Pre-process
  572. if (key == "network") {
  573. data.network = data.network.toUpperCase();
  574. }
  575. if (key == "mqttStatus") {
  576. data.mqttStatus = data.mqttStatus ? "CONNECTED" : "NOT CONNECTED";
  577. }
  578. if (key == "ntpStatus") {
  579. data.ntpStatus = data.ntpStatus ? "SYNC'D" : "NOT SYNC'D";
  580. }
  581. if (key == "tmpUnits") {
  582. $("span#tmpUnit").html(data[key] == 1 ? "ºF" : "ºC");
  583. }
  584. // Look for INPUTs
  585. var element = $("input[name=" + key + "]");
  586. if (element.length > 0) {
  587. if (element.attr('type') == 'checkbox') {
  588. element
  589. .prop("checked", data[key])
  590. .iphoneStyle("refresh");
  591. } else if (element.attr('type') == 'radio') {
  592. element.val([data[key]]);
  593. } else {
  594. var pre = element.attr("pre") || "";
  595. var post = element.attr("post") || "";
  596. element.val(pre + data[key] + post);
  597. }
  598. return;
  599. }
  600. // Look for SPANs
  601. var element = $("span[name=" + key + "]");
  602. if (element.length > 0) {
  603. var pre = element.attr("pre") || "";
  604. var post = element.attr("post") || "";
  605. element.html(pre + data[key] + post);
  606. return;
  607. }
  608. // Look for SELECTs
  609. var element = $("select[name=" + key + "]");
  610. if (element.length > 0) {
  611. element.val(data[key]);
  612. return;
  613. }
  614. });
  615. // Auto generate an APIKey if none defined yet
  616. if ($("input[name='apiKey']").val() == "") {
  617. doGenerateAPIKey();
  618. }
  619. }
  620. function getJson(str) {
  621. try {
  622. return JSON.parse(str);
  623. } catch (e) {
  624. return false;
  625. }
  626. }
  627. function connect(host) {
  628. if (typeof host === 'undefined') {
  629. host = window.location.href.replace('#', '');
  630. } else {
  631. if (!host.startsWith("http")) {
  632. host = 'http://' + host + '/';
  633. }
  634. }
  635. webhost = host;
  636. wshost = host.replace('http', 'ws') + 'ws';
  637. if (websock) websock.close();
  638. websock = new WebSocket(wshost);
  639. websock.onopen = function(evt) {
  640. console.log("Connected");
  641. };
  642. websock.onclose = function(evt) {
  643. console.log("Disconnected");
  644. };
  645. websock.onerror = function(evt) {
  646. console.log("Error: ", evt);
  647. };
  648. websock.onmessage = function(evt) {
  649. var data = getJson(evt.data);
  650. if (data) processData(data);
  651. };
  652. }
  653. function initMessages() {
  654. messages[01] = "Remote update started";
  655. messages[02] = "OTA update started";
  656. messages[03] = "Error parsing data!";
  657. messages[04] = "The file does not look like a valid configuration backup or is corrupted";
  658. messages[05] = "Changes saved. You should reboot your board now";
  659. messages[06] = "Home Assistant auto-discovery message sent";
  660. messages[07] = "Passwords do not match!";
  661. messages[08] = "Changes saved";
  662. messages[09] = "No changes detected";
  663. messages[10] = "Session expired, please reload page...";
  664. }
  665. function init() {
  666. initMessages();
  667. $("#menuLink").on('click', toggleMenu);
  668. $(".button-update").on('click', doUpdate);
  669. $(".button-update-password").on('click', doUpdatePassword);
  670. $(".button-reset").on('click', doReset);
  671. $(".button-reconnect").on('click', doReconnect);
  672. $(".button-settings-backup").on('click', backupSettings);
  673. $(".button-settings-restore").on('click', restoreSettings);
  674. $('#uploader').on('change', onFileUpload);
  675. $(".button-apikey").on('click', doGenerateAPIKey);
  676. $(".button-upgrade").on('click', doUpgrade);
  677. $(".button-upgrade-browse").on('click', function() {
  678. $("input[name='upgrade']")[0].click();
  679. return false;
  680. });
  681. $("input[name='upgrade']").change(function (){
  682. var fileName = $(this).val();
  683. $("input[name='filename']").val(fileName.replace(/^.*[\\\/]/, ''));
  684. });
  685. $('progress').attr({ value: 0, max: 100 });
  686. $(".pure-menu-link").on('click', showPanel);
  687. $(".button-add-network").on('click', function() {
  688. $("div.more", addNetwork()).toggle();
  689. });
  690. $(".button-ha-send").on('click', function() {
  691. websock.send(JSON.stringify({'action': 'ha_send', 'data': $("input[name='haPrefix']").val()}));
  692. });
  693. $.ajax({
  694. 'method': 'GET',
  695. 'url': window.location.href + 'auth'
  696. }).done(function(data) {
  697. connect();
  698. }).fail(function(){
  699. $("#credentials").show();
  700. });
  701. }
  702. $(init);