personal.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. /**
  2. * Copyright (c) 2011, Robin Appelman <icewind1991@gmail.com>
  3. * 2013, Morris Jobke <morris.jobke@gmail.com>
  4. * This file is licensed under the Affero General Public License version 3 or later.
  5. * See the COPYING-README file.
  6. */
  7. /* global OC, t */
  8. /**
  9. * The callback will be fired as soon as enter is pressed by the
  10. * user or 1 second after the last data entry
  11. *
  12. * @param callback
  13. * @param allowEmptyValue if this is set to true the callback is also called when the value is empty
  14. */
  15. jQuery.fn.keyUpDelayedOrEnter = function (callback, allowEmptyValue) {
  16. var cb = callback;
  17. var that = this;
  18. this.keyup(_.debounce(function (event) {
  19. // enter is already handled in keypress
  20. if (event.keyCode === 13) {
  21. return;
  22. }
  23. if (allowEmptyValue || that.val() !== '') {
  24. cb();
  25. }
  26. }, 1000));
  27. this.keypress(function (event) {
  28. if (event.keyCode === 13 && (allowEmptyValue || that.val() !== '')) {
  29. event.preventDefault();
  30. cb();
  31. }
  32. });
  33. };
  34. /**
  35. * Post the email address change to the server.
  36. */
  37. function changeEmailAddress () {
  38. var emailInfo = $('#email');
  39. if (emailInfo.val() === emailInfo.defaultValue) {
  40. return;
  41. }
  42. emailInfo.defaultValue = emailInfo.val();
  43. OC.msg.startSaving('#lostpassword .msg');
  44. var post = $("#lostpassword").serializeArray();
  45. $.ajax({
  46. type: 'PUT',
  47. url: OC.generateUrl('/settings/users/{id}/mailAddress', {id: OC.currentUser}),
  48. data: {
  49. mailAddress: post[0].value
  50. }
  51. }).done(function(result){
  52. // I know the following 4 lines look weird, but that is how it works
  53. // in jQuery - for success the first parameter is the result
  54. // for failure the first parameter is the result object
  55. OC.msg.finishedSaving('#lostpassword .msg', result);
  56. }).fail(function(result){
  57. OC.msg.finishedSaving('#lostpassword .msg', result.responseJSON);
  58. });
  59. }
  60. /**
  61. * Post the display name change to the server.
  62. */
  63. function changeDisplayName () {
  64. if ($('#displayName').val() !== '') {
  65. OC.msg.startSaving('#displaynameform .msg');
  66. // Serialize the data
  67. var post = $("#displaynameform").serialize();
  68. // Ajax foo
  69. $.post('ajax/changedisplayname.php', post, function (data) {
  70. if (data.status === "success") {
  71. $('#oldDisplayName').val($('#displayName').val());
  72. // update displayName on the top right expand button
  73. $('#expandDisplayName').text($('#displayName').val());
  74. updateAvatar();
  75. }
  76. else {
  77. $('#newdisplayname').val(data.data.displayName);
  78. }
  79. OC.msg.finishedSaving('#displaynameform .msg', data);
  80. });
  81. }
  82. }
  83. function updateAvatar (hidedefault) {
  84. var $headerdiv = $('#header .avatardiv');
  85. var $displaydiv = $('#displayavatar .avatardiv');
  86. if (hidedefault) {
  87. $headerdiv.hide();
  88. $('#header .avatardiv').removeClass('avatardiv-shown');
  89. } else {
  90. $headerdiv.css({'background-color': ''});
  91. $headerdiv.avatar(OC.currentUser, 32, true);
  92. $('#header .avatardiv').addClass('avatardiv-shown');
  93. }
  94. $displaydiv.css({'background-color': ''});
  95. $displaydiv.avatar(OC.currentUser, 128, true);
  96. $('#removeavatar').show();
  97. }
  98. function showAvatarCropper () {
  99. var $cropper = $('#cropper');
  100. $cropper.prepend("<img>");
  101. var $cropperImage = $('#cropper img');
  102. $cropperImage.attr('src',
  103. OC.generateUrl('/avatar/tmp') + '?requesttoken=' + encodeURIComponent(oc_requesttoken) + '#' + Math.floor(Math.random() * 1000));
  104. // Looks weird, but on('load', ...) doesn't work in IE8
  105. $cropperImage.ready(function () {
  106. $('#displayavatar').hide();
  107. $cropper.show();
  108. $cropperImage.Jcrop({
  109. onChange: saveCoords,
  110. onSelect: saveCoords,
  111. aspectRatio: 1,
  112. boxHeight: 500,
  113. boxWidth: 500,
  114. setSelect: [0, 0, 300, 300]
  115. });
  116. });
  117. }
  118. function sendCropData () {
  119. cleanCropper();
  120. var cropperData = $('#cropper').data();
  121. var data = {
  122. x: cropperData.x,
  123. y: cropperData.y,
  124. w: cropperData.w,
  125. h: cropperData.h
  126. };
  127. $.post(OC.generateUrl('/avatar/cropped'), {crop: data}, avatarResponseHandler);
  128. }
  129. function saveCoords (c) {
  130. $('#cropper').data(c);
  131. }
  132. function cleanCropper () {
  133. var $cropper = $('#cropper');
  134. $('#displayavatar').show();
  135. $cropper.hide();
  136. $('.jcrop-holder').remove();
  137. $('#cropper img').removeData('Jcrop').removeAttr('style').removeAttr('src');
  138. $('#cropper img').remove();
  139. }
  140. function avatarResponseHandler (data) {
  141. var $warning = $('#avatar .warning');
  142. $warning.hide();
  143. if (data.status === "success") {
  144. updateAvatar();
  145. } else if (data.data === "notsquare") {
  146. showAvatarCropper();
  147. } else {
  148. $warning.show();
  149. $warning.text(data.data.message);
  150. }
  151. }
  152. $(document).ready(function () {
  153. if($('#pass2').length) {
  154. $('#pass2').showPassword().keyup();
  155. }
  156. $("#passwordbutton").click(function () {
  157. var isIE8or9 = $('html').hasClass('lte9');
  158. // FIXME - TODO - once support for IE8 and IE9 is dropped
  159. // for IE8 and IE9 this will check additionally if the typed in password
  160. // is different from the placeholder, because in IE8/9 the placeholder
  161. // is simply set as the value to look like a placeholder
  162. if ($('#pass1').val() !== '' && $('#pass2').val() !== ''
  163. && !(isIE8or9 && $('#pass2').val() === $('#pass2').attr('placeholder'))) {
  164. // Serialize the data
  165. var post = $("#passwordform").serialize();
  166. $('#passwordchanged').hide();
  167. $('#passworderror').hide();
  168. // Ajax foo
  169. $.post(OC.generateUrl('/settings/personal/changepassword'), post, function (data) {
  170. if (data.status === "success") {
  171. $('#pass1').val('');
  172. $('#pass2').val('');
  173. // Hide a possible errormsg and show successmsg
  174. $('#password-changed').removeClass('hidden').addClass('inlineblock');
  175. $('#password-error').removeClass('inlineblock').addClass('hidden');
  176. } else {
  177. if (typeof(data.data) !== "undefined") {
  178. $('#passworderror').html(data.data.message);
  179. } else {
  180. $('#passworderror').html(t('Unable to change password'));
  181. }
  182. // Hide a possible successmsg and show errormsg
  183. $('#password-changed').removeClass('inlineblock').addClass('hidden');
  184. $('#password-error').removeClass('hidden').addClass('inlineblock');
  185. }
  186. });
  187. return false;
  188. } else {
  189. // Hide a possible successmsg and show errormsg
  190. $('#password-changed').removeClass('inlineblock').addClass('hidden');
  191. $('#password-error').removeClass('hidden').addClass('inlineblock');
  192. return false;
  193. }
  194. });
  195. $('#displayName').keyUpDelayedOrEnter(changeDisplayName);
  196. $('#email').keyUpDelayedOrEnter(changeEmailAddress, true);
  197. $("#languageinput").change(function () {
  198. // Serialize the data
  199. var post = $("#languageinput").serialize();
  200. // Ajax foo
  201. $.post('ajax/setlanguage.php', post, function (data) {
  202. if (data.status === "success") {
  203. location.reload();
  204. }
  205. else {
  206. $('#passworderror').html(data.data.message);
  207. }
  208. });
  209. return false;
  210. });
  211. var uploadparms = {
  212. done: function (e, data) {
  213. avatarResponseHandler(data.result);
  214. }
  215. };
  216. $('#uploadavatarbutton').click(function () {
  217. $('#uploadavatar').click();
  218. });
  219. $('#uploadavatar').fileupload(uploadparms);
  220. $('#selectavatar').click(function () {
  221. OC.dialogs.filepicker(
  222. t('settings', "Select a profile picture"),
  223. function (path) {
  224. $.post(OC.generateUrl('/avatar/'), {path: path}, avatarResponseHandler);
  225. },
  226. false,
  227. ["image/png", "image/jpeg"]
  228. );
  229. });
  230. $('#removeavatar').click(function () {
  231. $.ajax({
  232. type: 'DELETE',
  233. url: OC.generateUrl('/avatar/'),
  234. success: function () {
  235. updateAvatar(true);
  236. $('#removeavatar').hide();
  237. }
  238. });
  239. });
  240. $('#abortcropperbutton').click(function () {
  241. cleanCropper();
  242. });
  243. $('#sendcropperbutton').click(function () {
  244. sendCropData();
  245. });
  246. $('#pass2').strengthify({
  247. zxcvbn: OC.linkTo('core','vendor/zxcvbn/zxcvbn.js'),
  248. titles: [
  249. t('core', 'Very weak password'),
  250. t('core', 'Weak password'),
  251. t('core', 'So-so password'),
  252. t('core', 'Good password'),
  253. t('core', 'Strong password')
  254. ]
  255. });
  256. // does the user have a custom avatar? if he does hide #removeavatar
  257. // needs to be this complicated because we can't check yet if an avatar has been loaded, because it's async
  258. var url = OC.generateUrl(
  259. '/avatar/{user}/{size}',
  260. {user: OC.currentUser, size: 1}
  261. ) + '?requesttoken=' + encodeURIComponent(oc_requesttoken);
  262. $.get(url, function (result) {
  263. if (typeof(result) === 'object') {
  264. $('#removeavatar').hide();
  265. }
  266. });
  267. $('#sslCertificate').on('click', 'td.remove > img', function () {
  268. var row = $(this).parent().parent();
  269. $.ajax(OC.generateUrl('settings/personal/certificate/{certificate}', {certificate: row.data('name')}), {
  270. type: 'DELETE'
  271. });
  272. row.remove();
  273. if ($('#sslCertificate > tbody > tr').length === 0) {
  274. $('#sslCertificate').hide();
  275. }
  276. return true;
  277. });
  278. $('#sslCertificate tr > td').tipsy({gravity: 'n', live: true});
  279. $('#rootcert_import').fileupload({
  280. success: function (data) {
  281. var issueDate = new Date(data.validFrom * 1000);
  282. var expireDate = new Date(data.validTill * 1000);
  283. var now = new Date();
  284. var isExpired = !(issueDate <= now && now <= expireDate);
  285. var row = $('<tr/>');
  286. row.data('name', data.name);
  287. row.addClass(isExpired? 'expired': 'valid');
  288. row.append($('<td/>').attr('title', data.organization).text(data.commonName));
  289. row.append($('<td/>').attr('title', t('core,', 'Valid until {date}', {date: data.validTillString}))
  290. .text(data.validTillString));
  291. row.append($('<td/>').attr('title', data.issuerOrganization).text(data.issuer));
  292. row.append($('<td/>').addClass('remove').append(
  293. $('<img/>').attr({
  294. alt: t('core', 'Delete'),
  295. title: t('core', 'Delete'),
  296. src: OC.imagePath('core', 'actions/delete.svg')
  297. }).addClass('action')
  298. ));
  299. $('#sslCertificate tbody').append(row);
  300. $('#sslCertificate').show();
  301. },
  302. fail: function () {
  303. OC.Notification.showTemporary(
  304. t('settings', 'An error occurred. Please upload an ASCII-encoded PEM certificate.'));
  305. }
  306. });
  307. $('#rootcert_import_button').click(function () {
  308. $('#rootcert_import').click();
  309. });
  310. if ($('#sslCertificate > tbody > tr').length === 0) {
  311. $('#sslCertificate').hide();
  312. }
  313. });
  314. if (!OC.Encryption) {
  315. OC.Encryption = {};
  316. }
  317. OC.Encryption.msg = {
  318. start: function (selector, msg) {
  319. var spinner = '<img src="' + OC.imagePath('core', 'loading-small.gif') + '">';
  320. $(selector)
  321. .html(msg + ' ' + spinner)
  322. .removeClass('success')
  323. .removeClass('error')
  324. .stop(true, true)
  325. .show();
  326. },
  327. finished: function (selector, data) {
  328. if (data.status === "success") {
  329. $(selector).html(data.data.message)
  330. .addClass('success')
  331. .stop(true, true)
  332. .delay(3000);
  333. } else {
  334. $(selector).html(data.data.message).addClass('error');
  335. }
  336. }
  337. };