Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 
 
 

406 rader
10 KiB

  1. // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
  2. // MIT License. See license.txt
  3. frappe.provide("website");
  4. frappe.provide("frappe.search_path");
  5. cur_frm = null;
  6. $.extend(frappe, {
  7. boot: {},
  8. _assets_loaded: [],
  9. require: function(url) {
  10. if(frappe._assets_loaded.indexOf(url)!==-1) return;
  11. $.ajax({
  12. url: url,
  13. async: false,
  14. dataType: "text",
  15. success: function(data) {
  16. if(url.split(".").splice(-1) == "js") {
  17. var el = document.createElement('script');
  18. } else {
  19. var el = document.createElement('style');
  20. }
  21. el.appendChild(document.createTextNode(data));
  22. document.getElementsByTagName('head')[0].appendChild(el);
  23. frappe._assets_loaded.push(url);
  24. }
  25. });
  26. },
  27. hide_message: function(text) {
  28. $('.message-overlay').remove();
  29. },
  30. call: function(opts) {
  31. // opts = {"method": "PYTHON MODULE STRING", "args": {}, "callback": function(r) {}}
  32. frappe.prepare_call(opts);
  33. if(opts.freeze) { frappe.freeze(); }
  34. return $.ajax({
  35. type: opts.type || "POST",
  36. url: "/",
  37. data: opts.args,
  38. dataType: "json",
  39. headers: { "X-Frappe-CSRF-Token": frappe.csrf_token },
  40. statusCode: opts.statusCode || {
  41. 404: function(xhr) {
  42. frappe.msgprint(__("Not found"));
  43. },
  44. 403: function(xhr) {
  45. frappe.msgprint(__("Not permitted"));
  46. },
  47. 200: function(data, xhr) {
  48. if(opts.callback)
  49. opts.callback(data);
  50. if(opts.success)
  51. opts.success(data);
  52. }
  53. }
  54. }).always(function(data) {
  55. if(opts.freeze) {
  56. frappe.unfreeze();
  57. }
  58. // executed before statusCode functions
  59. if(data.responseText) {
  60. data = JSON.parse(data.responseText);
  61. }
  62. frappe.process_response(opts, data);
  63. });
  64. },
  65. prepare_call: function(opts) {
  66. if(opts.btn) {
  67. $(opts.btn).prop("disabled", true);
  68. }
  69. if(opts.msg) {
  70. $(opts.msg).toggle(false);
  71. }
  72. if(!opts.args) opts.args = {};
  73. // method
  74. if(opts.method) {
  75. opts.args.cmd = opts.method;
  76. }
  77. // stringify
  78. $.each(opts.args, function(key, val) {
  79. if(typeof val != "string") {
  80. opts.args[key] = JSON.stringify(val);
  81. }
  82. });
  83. if(!opts.no_spinner) {
  84. //NProgress.start();
  85. }
  86. },
  87. process_response: function(opts, data) {
  88. //if(!opts.no_spinner) NProgress.done();
  89. if(opts.btn) {
  90. $(opts.btn).prop("disabled", false);
  91. }
  92. if (data._server_messages) {
  93. var server_messages = JSON.parse(data._server_messages || '[]');
  94. server_messages = $.map(server_messages, function(v) {
  95. // temp fix for messages sent as dict
  96. try {
  97. return JSON.parse(v).message;
  98. } catch (e) {
  99. return v;
  100. }
  101. }).join('<br>');
  102. if(opts.error_msg) {
  103. $(opts.error_msg).html(server_messages).toggle(true);
  104. } else {
  105. frappe.msgprint(server_messages);
  106. }
  107. }
  108. if(data.exc) {
  109. if(opts.btn) {
  110. $(opts.btn).addClass($(opts.btn).is('button') || $(opts.btn).hasClass('btn') ? "btn-danger" : "text-danger");
  111. setTimeout(function() { $(opts.btn).removeClass("btn-danger text-danger"); }, 1000);
  112. }
  113. try {
  114. var err = JSON.parse(data.exc);
  115. if($.isArray(err)) {
  116. err = err.join("\n");
  117. }
  118. console.error ? console.error(err) : console.log(err);
  119. } catch(e) {
  120. console.log(data.exc);
  121. }
  122. } else{
  123. if(opts.btn) {
  124. $(opts.btn).addClass($(opts.btn).is('button') || $(opts.btn).hasClass('btn') ? "btn-success" : "text-success");
  125. setTimeout(function() { $(opts.btn).removeClass("btn-success text-success"); }, 1000);
  126. }
  127. }
  128. if(opts.msg && data.message) {
  129. $(opts.msg).html(data.message).toggle(true);
  130. }
  131. if(opts.always) {
  132. opts.always(data);
  133. }
  134. },
  135. show_message: function(text, icon) {
  136. if(!icon) icon="icon-refresh icon-spin";
  137. frappe.hide_message();
  138. $('<div class="message-overlay"></div>')
  139. .html('<div class="content"><i class="'+icon+' text-muted"></i><br>'
  140. +text+'</div>').appendTo(document.body);
  141. },
  142. hide_message: function(text) {
  143. $('.message-overlay').remove();
  144. },
  145. get_sid: function() {
  146. var sid = getCookie("sid");
  147. return sid && sid!=="Guest";
  148. },
  149. get_modal: function(title, body_html) {
  150. var modal = $('<div class="modal" style="overflow: auto;" tabindex="-1">\
  151. <div class="modal-dialog">\
  152. <div class="modal-content">\
  153. <div class="modal-header">\
  154. <a type="button" class="close"\
  155. data-dismiss="modal" aria-hidden="true">&times;</a>\
  156. <h4 class="modal-title">'+title+'</h4>\
  157. </div>\
  158. <div class="modal-body ui-front">'+body_html+'\
  159. </div>\
  160. </div>\
  161. </div>\
  162. </div>').appendTo(document.body);
  163. return modal;
  164. },
  165. msgprint: function(html, title) {
  166. if(html.substr(0,1)==="[") html = JSON.parse(html);
  167. if($.isArray(html)) {
  168. html = html.join("<hr>")
  169. }
  170. return frappe.get_modal(title || "Message", html).modal("show");
  171. },
  172. send_message: function(opts, btn) {
  173. return frappe.call({
  174. type: "POST",
  175. method: "frappe.www.contact.send_message",
  176. btn: btn,
  177. args: opts,
  178. callback: opts.callback
  179. });
  180. },
  181. has_permission: function(doctype, docname, perm_type, callback) {
  182. return frappe.call({
  183. type: "GET",
  184. method: "frappe.client.has_permission",
  185. no_spinner: true,
  186. args: {doctype: doctype, docname: docname, perm_type: perm_type},
  187. callback: function(r) {
  188. if(!r.exc && r.message.has_permission) {
  189. if(callback) { return callback(r); }
  190. }
  191. }
  192. });
  193. },
  194. render_user: function() {
  195. var sid = frappe.get_cookie("sid");
  196. if(sid && sid!=="Guest") {
  197. $(".btn-login-area").toggle(false);
  198. $(".logged-in").toggle(true);
  199. $(".full-name").html(frappe.get_cookie("full_name"));
  200. $(".user-image").attr("src", frappe.get_cookie("user_image"));
  201. $('.user-image-wrapper').html(frappe.avatar(null, 'avatar-small'));
  202. $('.user-image-sidebar').html(frappe.avatar(null, 'avatar-small'));
  203. $('.user-image-myaccount').html(frappe.avatar(null, 'avatar-large'));
  204. }
  205. },
  206. freeze_count: 0,
  207. freeze: function(msg) {
  208. // blur
  209. if(!$('#freeze').length) {
  210. var freeze = $('<div id="freeze" class="modal-backdrop fade"></div>')
  211. .appendTo("body");
  212. freeze.html(repl('<div class="freeze-message-container"><div class="freeze-message">%(msg)s</div></div>',
  213. {msg: msg || ""}));
  214. setTimeout(function() { freeze.addClass("in") }, 1);
  215. } else {
  216. $("#freeze").addClass("in");
  217. }
  218. frappe.freeze_count++;
  219. },
  220. unfreeze: function() {
  221. if(!frappe.freeze_count) return; // anything open?
  222. frappe.freeze_count--;
  223. if(!frappe.freeze_count) {
  224. var freeze = $('#freeze').removeClass("in");
  225. setTimeout(function() {
  226. if(!frappe.freeze_count) { freeze.remove(); }
  227. }, 150);
  228. }
  229. },
  230. trigger_ready: function() {
  231. var ready_functions = frappe.page_ready_events[location.pathname];
  232. if (ready_functions && ready_functions.length) {
  233. for (var i=0, l=ready_functions.length; i < l; i++) {
  234. var ready = ready_functions[i];
  235. ready && ready();
  236. }
  237. }
  238. // remove them so that they aren't fired again and again!
  239. delete frappe.page_ready_events[location.pathname];
  240. },
  241. highlight_code_blocks: function() {
  242. if(hljs) {
  243. $('pre code').each(function(i, block) {
  244. hljs.highlightBlock(block);
  245. });
  246. }
  247. },
  248. bind_filters: function() {
  249. // set in select
  250. $(".filter").each(function() {
  251. var key = $(this).attr("data-key");
  252. var val = get_url_arg(key).replace(/\+/g, " ");
  253. if(val) $(this).val(val);
  254. });
  255. // search url
  256. var search = function() {
  257. var args = {};
  258. $(".filter").each(function() {
  259. var val = $(this).val();
  260. if(val) args[$(this).attr("data-key")] = val;
  261. });
  262. window.location.href = location.pathname + "?" + $.param(args);
  263. }
  264. $(".filter").on("change", function() {
  265. search();
  266. });
  267. },
  268. bind_navbar_search: function() {
  269. frappe.get_navbar_search().on("keypress", function(e) {
  270. var val = $(this).val();
  271. if(e.which===13 && val) {
  272. $(this).val("").blur();
  273. frappe.do_search(val);
  274. return false;
  275. }
  276. });
  277. },
  278. do_search: function(val) {
  279. var path = (frappe.search_path && frappe.search_path[location.pathname]
  280. || window.search_path || location.pathname);
  281. window.location.href = path + "?txt=" + encodeURIComponent(val);
  282. },
  283. set_search_path: function(path) {
  284. frappe.search_path[location.pathname] = path;
  285. },
  286. make_navbar_active: function() {
  287. var pathname = window.location.pathname;
  288. $(".navbar-nav a.active").removeClass("active");
  289. $(".navbar-nav a").each(function() {
  290. var href = $(this).attr("href");
  291. if(href===pathname) {
  292. $(this).addClass("active");
  293. return false;
  294. }
  295. })
  296. },
  297. get_navbar_search: function() {
  298. return $(".navbar .search, .sidebar .search");
  299. },
  300. is_user_logged_in: function() {
  301. return window.full_name ? true : false;
  302. }
  303. });
  304. // Utility functions
  305. function valid_email(id) {
  306. return (id.toLowerCase().search("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?")==-1) ? 0 : 1;
  307. }
  308. var validate_email = valid_email;
  309. function cstr(s) {
  310. return s==null ? '' : s+'';
  311. }
  312. function is_null(v) {
  313. if(v===null || v===undefined || cstr(v).trim()==="") return true;
  314. }
  315. function is_html(txt) {
  316. if(txt.indexOf("<br>")==-1 && txt.indexOf("<p")==-1
  317. && txt.indexOf("<img")==-1 && txt.indexOf("<div")==-1) {
  318. return false;
  319. }
  320. return true;
  321. }
  322. function ask_to_login() {
  323. if(!frappe.is_user_logged_in()) {
  324. if(localStorage) {
  325. localStorage.setItem("last_visited",
  326. window.location.href.replace(window.location.origin, ""));
  327. }
  328. window.location.href = "login";
  329. }
  330. }
  331. // check if logged in?
  332. $(document).ready(function() {
  333. window.full_name = getCookie("full_name");
  334. window.logged_in = getCookie("sid") && getCookie("sid")!=="Guest";
  335. $("#website-login").toggleClass("hide", logged_in ? true : false);
  336. $("#website-post-login").toggleClass("hide", logged_in ? false : true);
  337. $(".logged-in").toggleClass("hide", logged_in ? false : true);
  338. frappe.bind_navbar_search();
  339. // switch to app link
  340. if(getCookie("system_user")==="yes" && logged_in) {
  341. $("#website-post-login .dropdown-menu").append('<li><a href="/desk">Switch To Desk</a></li>');
  342. $(".navbar-header .dropdown .dropdown-menu").append('<li><a href="/desk">Switch To Desk</a></li>');
  343. }
  344. frappe.render_user();
  345. $(document).trigger("page-change");
  346. });
  347. $(document).on("page-change", function() {
  348. $(document).trigger("apply_permissions");
  349. $('.dropdown-toggle').dropdown();
  350. $.extend(frappe, getCookies());
  351. frappe.session = {'user': frappe.user_id};
  352. frappe.datetime.refresh_when();
  353. frappe.trigger_ready();
  354. frappe.bind_filters();
  355. frappe.highlight_code_blocks();
  356. frappe.make_navbar_active();
  357. // scroll to hash
  358. if (window.location.hash) {
  359. var element = document.getElementById(window.location.hash.substring(1));
  360. element && element.scrollIntoView(true);
  361. }
  362. });