;
(function () {
var initializing = false,
fnTest = /xyz/.test(function () {
xyz;
}) ? /\b_super\b/ : /.*/;
this.Class = function () {};
Class.extend = function (prop) {
var _super = this.prototype;
initializing = true;
var prototype = new this();
initializing = false;
for (var name in prop) {
prototype[name] = typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name]) ? function (name, fn) {
return function () {
var tmp = this._super;
this._super = _super[name];
var ret = fn.apply(this, arguments);
this._super = tmp;
return ret;
};
}(name, prop[name]) : prop[name];
}
function Class() {
this._type = "instance";
if (!initializing && this.init) this.init.apply(this, arguments);
}
Class.prototype = prototype;
Class._type = "class";
Class.prototype.constructor = Class;
Class.extend = arguments.callee;
return Class;
};
})();
if (!window.frappe) window.frappe = {};
frappe.provide = function (namespace) {
var nsl = namespace.split('.');
var parent = window;
for (var i = 0; i < nsl.length; i++) {
var n = nsl[i];
if (!parent[n]) {
parent[n] = {};
}
parent = parent[n];
}
return parent;
};
frappe.provide("locals");
frappe.provide("frappe.flags");
frappe.provide("frappe.settings");
frappe.provide("frappe.utils");
frappe.provide("frappe.ui");
frappe.provide("frappe.modules");
frappe.provide("frappe.templates");
frappe.provide("frappe.test_data");
frappe.require = function (items, callback) {
if (typeof items === "string") {
items = [items];
}
frappe.assets.execute(items, callback);
};
frappe.assets = {
check: function check() {
if (window._version_number != localStorage.getItem("_version_number")) {
frappe.assets.clear_local_storage();
console.log("Cleared App Cache.");
}
if (localStorage._last_load) {
var not_updated_since = new Date() - new Date(localStorage._last_load);
if (not_updated_since < 10000 || not_updated_since > 86400000) {
frappe.assets.clear_local_storage();
}
} else {
frappe.assets.clear_local_storage();
}
frappe.assets.init_local_storage();
},
init_local_storage: function init_local_storage() {
localStorage._last_load = new Date();
localStorage._version_number = window._version_number;
if (frappe.boot) localStorage.metadata_version = frappe.boot.metadata_version;
},
clear_local_storage: function clear_local_storage() {
$.each(["_last_load", "_version_number", "metadata_version", "page_info", "last_visited"], function (i, key) {
localStorage.removeItem(key);
});
for (var key in localStorage) {
if (key.indexOf("desk_assets:") === 0 || key.indexOf("_page:") === 0 || key.indexOf("_doctype:") === 0 || key.indexOf("preferred_breadcrumbs:") === 0) {
localStorage.removeItem(key);
}
}
console.log("localStorage cleared");
},
executed_: [],
execute: function execute(items, callback) {
var to_fetch = [];
for (var i = 0, l = items.length; i < l; i++) {
if (!frappe.assets.exists(items[i])) {
to_fetch.push(items[i]);
}
}
if (to_fetch.length) {
frappe.assets.fetch(to_fetch, function () {
frappe.assets.eval_assets(items, callback);
});
} else {
frappe.assets.eval_assets(items, callback);
}
},
eval_assets: function eval_assets(items, callback) {
for (var i = 0, l = items.length; i < l; i++) {
var path = items[i];
if (frappe.assets.executed_.indexOf(path) === -1) {
frappe.assets.handler[frappe.assets.extn(path)](frappe.assets.get(path), path);
frappe.assets.executed_.push(path);
}
}
callback();
},
exists: function exists(src) {
if (frappe.assets.executed_.indexOf(src) !== -1) {
return true;
}
if (frappe.boot.developer_mode) {
return false;
}
if (frappe.assets.get(src)) {
return true;
} else {
return false;
}
},
fetch: function fetch(items, _callback) {
frappe.call({
type: "GET",
method: "frappe.client.get_js",
args: {
"items": items
},
callback: function callback(r) {
$.each(items, function (i, src) {
frappe.assets.add(src, r.message[i]);
});
_callback();
},
freeze: true
});
},
add: function add(src, txt) {
if ('localStorage' in window) {
try {
frappe.assets.set(src, txt);
} catch (e) {
frappe.assets.clear_local_storage();
frappe.assets.set(src, txt);
}
}
},
get: function get(src) {
return localStorage.getItem("desk_assets:" + src);
},
set: function set(src, txt) {
localStorage.setItem("desk_assets:" + src, txt);
},
extn: function extn(src) {
if (src.indexOf('?') != -1) {
src = src.split('?').slice(-1)[0];
}
return src.split('.').slice(-1)[0];
},
handler: {
js: function js(txt, src) {
frappe.dom.eval(txt);
},
css: function css(txt, src) {
frappe.dom.set_style(txt);
}
}
};
function format(str, args) {
if (str == undefined) return str;
this.unkeyed_index = 0;
return str.replace(/\{(\w*)\}/g, function (match, key) {
if (key === '') {
key = this.unkeyed_index;
this.unkeyed_index++;
}
if (key == +key) {
return args[key] !== undefined ? args[key] : match;
}
}.bind(this));
}
if (jQuery) {
jQuery.format = format;
}
frappe.provide("frappe.form.formatters");
frappe.form.link_formatters = {};
frappe.form.formatters = {
_right: function _right(value, options) {
if (options && options.inline) {
return value;
} else {
return "
" + value + "
";
}
},
Data: function Data(value) {
return value == null ? "" : value;
},
Select: function Select(value) {
return __(frappe.form.formatters["Data"](value));
},
Float: function Float(value, docfield, options, doc) {
var precision = docfield.precision || cint(frappe.boot.sysdefaults.float_precision) || null;
if (docfield.options && docfield.options.trim()) {
docfield.precision = precision;
return frappe.form.formatters.Currency(value, docfield, options, doc);
} else {
if (!(options || {}).always_show_decimals && !is_null(value)) {
var temp = cstr(value).split(".");
if (temp[1] == undefined || cint(temp[1]) === 0) {
precision = 0;
}
}
return frappe.form.formatters._right(value == null || value === "" ? "" : format_number(value, null, precision), options);
}
},
Int: function Int(value, docfield, options) {
return frappe.form.formatters._right(value == null ? "" : cint(value), options);
},
Percent: function Percent(value, docfield, options) {
return frappe.form.formatters._right(flt(value, 2) + "%", options);
},
Currency: function Currency(value, docfield, options, doc) {
var currency = frappe.meta.get_field_currency(docfield, doc);
var precision = docfield.precision || cint(frappe.boot.sysdefaults.currency_precision) || 2;
if (precision > 2) {
var parts = cstr(value).split('.');
var decimals = parts.length > 1 ? parts[1] : '';
if (decimals.length < 3) {
precision = 2;
} else if (decimals.length < precision) {
precision = decimals.length;
}
}
value = value == null || value === "" ? "" : format_currency(value, currency, precision);
if (options && options.only_value) {
return value;
} else {
return frappe.form.formatters._right(value, options);
}
},
Check: function Check(value) {
if (value) {
return ' ';
} else {
return ' ';
}
},
Link: function Link(value, docfield, options, doc) {
var doctype = docfield._options || docfield.options;
var original_value = value;
if (value && value.match(/^['"].*['"]$/)) {
value.replace(/^.(.*).$/, "$1");
}
if (options && (options.for_print || options.only_value)) {
return value;
}
if (frappe.form.link_formatters[doctype]) {
value = frappe.form.link_formatters[doctype](value, doc);
}
if (!value) {
return "";
}
if (value[0] == "'" && value[value.length - 1] == "'") {
return value.substring(1, value.length - 1);
}
if (docfield && docfield.link_onclick) {
return repl('%(value)s ', { onclick: docfield.link_onclick.replace(/"/g, '"'), value: value });
} else if (docfield && doctype) {
return repl('%(label)s ', {
doctype: encodeURIComponent(doctype),
name: encodeURIComponent(original_value),
label: __(options && options.label || value)
});
} else {
return value;
}
},
Date: function Date(value) {
if (value) {
value = frappe.datetime.str_to_user(value);
if (value === "Invalid date") {
value = null;
}
}
return value || "";
},
DateRange: function DateRange(value) {
if ($.isArray(value)) {
return __("{0} to {1}").format([frappe.datetime.str_to_user(value[0]), frappe.datetime.str_to_user(value[1])]);
} else {
return value || "";
}
},
Datetime: function Datetime(value) {
if (value) {
var m = moment(frappe.datetime.convert_to_user_tz(value));
if (frappe.boot.sysdefaults.time_zone) {
m = m.tz(frappe.boot.sysdefaults.time_zone);
}
return m.format(frappe.boot.sysdefaults.date_format.toUpperCase() + ', h:mm a z');
} else {
return "";
}
},
Text: function Text(value) {
if (value) {
var tags = ["' + v + '';
});
return html;
},
Comment: function Comment(value) {
var html = "";
$.each(JSON.parse(value || "[]"), function (i, v) {
if (v) html += '' + v.comment + ' ';
});
return html;
},
Assign: function Assign(value) {
var html = "";
$.each(JSON.parse(value || "[]"), function (i, v) {
if (v) html += '' + v + ' ';
});
return html;
},
SmallText: function SmallText(value) {
return frappe.form.formatters.Text(value);
},
TextEditor: function TextEditor(value) {
return frappe.form.formatters.Text(value);
},
Code: function Code(value) {
return "
" + (value == null ? "" : $("").text(value).html()) + "";
},
WorkflowState: function WorkflowState(value) {
var workflow_state = frappe.get_doc("Workflow State", value);
if (workflow_state) {
return repl("
\
%(value)s ", {
value: value,
style: workflow_state.style.toLowerCase(),
icon: workflow_state.icon
});
} else {
return "
" + value + " ";
}
},
Email: function Email(value) {
return $("
").text(value).html();
}
};
frappe.form.get_formatter = function (fieldtype) {
if (!fieldtype) fieldtype = "Data";
return frappe.form.formatters[fieldtype.replace(/ /g, "")] || frappe.form.formatters.Data;
};
frappe.format = function (value, df, options, doc) {
if (!df) df = { "fieldtype": "Data" };
var fieldtype = df.fieldtype || "Data";
if (fieldtype === "Dynamic Link") {
fieldtype = "Link";
df._options = doc ? doc[df.options] : null;
}
var formatter = df.formatter || frappe.form.get_formatter(fieldtype);
var formatted = formatter(value, df, options, doc);
if (typeof formatted == "string") formatted = frappe.dom.remove_script_and_style(formatted);
return formatted;
};
frappe.get_format_helper = function (doc) {
var helper = {
get_formatted: function get_formatted(fieldname) {
var df = frappe.meta.get_docfield(doc.doctype, fieldname);
if (!df) {
console.log("fieldname not found: " + fieldname);
}
return frappe.format(doc[fieldname], df, { inline: 1 }, doc);
}
};
$.extend(helper, doc);
return helper;
};frappe.templates['modal'] = '
';
frappe.provide('frappe.dom');
frappe.dom = {
id_count: 0,
freeze_count: 0,
by_id: function by_id(id) {
return document.getElementById(id);
},
set_unique_id: function set_unique_id(ele) {
var $ele = $(ele);
if ($ele.attr('id')) {
return $ele.attr('id');
}
var id = 'unique-' + frappe.dom.id_count;
$ele.attr('id', id);
frappe.dom.id_count++;
return id;
},
eval: function _eval(txt) {
if (!txt) return;
var el = document.createElement('script');
el.appendChild(document.createTextNode(txt));
document.getElementsByTagName('head')[0].appendChild(el);
},
remove_script_and_style: function remove_script_and_style(txt) {
var div = document.createElement('div');
div.innerHTML = txt;
var found = false;
["script", "style", "noscript", "title", "meta", "base", "head"].forEach(function (e, i) {
var elements = div.getElementsByTagName(e);
var i = elements.length;
while (i--) {
found = true;
elements[i].parentNode.removeChild(elements[i]);
}
});
var elements = div.getElementsByTagName('link');
var i = elements.length;
while (i--) {
if (elements[i].getAttribute("rel") == "stylesheet") {
found = true;
elements[i].parentNode.removeChild(elements[i]);
}
}
if (found) {
return div.innerHTML;
} else {
return txt;
}
},
is_element_in_viewport: function is_element_in_viewport(el) {
if (typeof jQuery === "function" && el instanceof jQuery) {
el = el[0];
}
var rect = el.getBoundingClientRect();
return rect.top >= 0 && rect.left >= 0;
},
set_style: function set_style(txt, id) {
if (!txt) return;
var se = document.createElement('style');
se.type = "text/css";
if (id) {
var element = document.getElementById(id);
if (element) {
element.parentNode.removeChild(element);
}
se.id = id;
}
if (se.styleSheet) {
se.styleSheet.cssText = txt;
} else {
se.appendChild(document.createTextNode(txt));
}
document.getElementsByTagName('head')[0].appendChild(se);
},
add: function add(parent, newtag, className, cs, innerHTML, onclick) {
if (parent && parent.substr) parent = frappe.dom.by_id(parent);
var c = document.createElement(newtag);
if (parent) parent.appendChild(c);
if (className) {
if (newtag.toLowerCase() == 'img') c.src = className;else c.className = className;
}
if (cs) frappe.dom.css(c, cs);
if (innerHTML) c.innerHTML = innerHTML;
if (onclick) c.onclick = onclick;
return c;
},
css: function css(ele, s) {
if (ele && s) {
$.extend(ele.style, s);
}
return ele;
},
freeze: function freeze(msg, css_class) {
if (!$('#freeze').length) {
var freeze = $('
').on("click", function () {
if (cur_frm && cur_frm.cur_grid) {
cur_frm.cur_grid.toggle_view();
return false;
}
}).appendTo("#body_div");
freeze.html(repl('
', { msg: msg || "" }));
setTimeout(function () {
freeze.addClass("in");
}, 1);
} else {
$("#freeze").addClass("in");
}
if (css_class) {
$("#freeze").addClass(css_class);
}
frappe.dom.freeze_count++;
},
unfreeze: function unfreeze() {
if (!frappe.dom.freeze_count) return;
frappe.dom.freeze_count--;
if (!frappe.dom.freeze_count) {
var freeze = $('#freeze').removeClass("in").remove();
}
},
save_selection: function save_selection() {
if (window.getSelection) {
var sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
var ranges = [];
for (var i = 0, len = sel.rangeCount; i < len; ++i) {
ranges.push(sel.getRangeAt(i));
}
return ranges;
}
} else if (document.selection && document.selection.createRange) {
return document.selection.createRange();
}
return null;
},
restore_selection: function restore_selection(savedSel) {
if (savedSel) {
if (window.getSelection) {
var sel = window.getSelection();
sel.removeAllRanges();
for (var i = 0, len = savedSel.length; i < len; ++i) {
sel.addRange(savedSel[i]);
}
} else if (document.selection && savedSel.select) {
savedSel.select();
}
}
},
is_touchscreen: function is_touchscreen() {
return 'ontouchstart' in window;
}
};
frappe.ellipsis = function (text, max) {
if (!max) max = 20;
text = cstr(text);
if (text.length > max) {
text = text.substr(0, max) + '...';
}
return text;
};
frappe.run_serially = function (tasks) {
var result = Promise.resolve();
tasks.forEach(function (task) {
if (task) {
result = result.then ? result.then(task) : Promise.resolve();
}
});
return result;
};
frappe.timeout = function (seconds) {
return new Promise(function (resolve) {
setTimeout(function () {
return resolve();
}, seconds * 1000);
});
};
frappe.scrub = function (text) {
return text.replace(/ /g, "_").toLowerCase();
};
frappe.get_modal = function (title, content) {
return $(frappe.render_template("modal", { title: title, content: content })).appendTo(document.body);
};
(function ($) {
$.fn.add_options = function (options_list) {
for (var i = 0; i < options_list.length; i++) {
var v = options_list[i];
if (is_null(v)) {
var value = null;
var label = null;
} else {
var is_value_null = is_null(v.value);
var is_label_null = is_null(v.label);
if (is_value_null && is_label_null) {
var value = v;
var label = __(v);
} else {
var value = is_value_null ? "" : v.value;
var label = is_label_null ? __(value) : __(v.label);
}
}
$('
').html(cstr(label)).attr('value', value).appendTo(this);
}
this.selectedIndex = 0;
return $(this);
};
$.fn.set_working = function () {
this.prop('disabled', true);
};
$.fn.done_working = function () {
this.prop('disabled', false);
};
})(jQuery);
(function ($) {
function pasteIntoInput(el, text) {
el.focus();
if (typeof el.selectionStart == "number") {
var val = el.value;
var selStart = el.selectionStart;
el.value = val.slice(0, selStart) + text + val.slice(el.selectionEnd);
el.selectionEnd = el.selectionStart = selStart + text.length;
} else if (typeof document.selection != "undefined") {
var textRange = document.selection.createRange();
textRange.text = text;
textRange.collapse(false);
textRange.select();
}
}
function allowTabChar(el) {
$(el).keydown(function (e) {
if (e.which == 9) {
pasteIntoInput(this, "\t");
return false;
}
});
$(el).keypress(function (e) {
if (e.which == 9) {
return false;
}
});
}
$.fn.allowTabs = function () {
if (this.jquery) {
this.each(function () {
if (this.nodeType == 1) {
var nodeName = this.nodeName.toLowerCase();
if (nodeName == "textarea" || nodeName == "input" && this.type == "text") {
allowTabChar(this);
}
}
});
}
return this;
};
})(jQuery);
frappe.provide("frappe.messages");
frappe.messages.waiting = function (parent, msg) {
return $(frappe.messages.get_waiting_message(msg)).appendTo(parent);
};
frappe.messages.get_waiting_message = function (msg) {
return repl('', { msg: msg });
};
frappe.throw = function (msg) {
if (typeof msg === 'string') {
msg = { message: msg, title: __('Error') };
}
if (!msg.indicator) msg.indicator = 'red';
frappe.msgprint(msg);
throw new Error(msg.message);
};
frappe.confirm = function (message, ifyes, ifno) {
var d = new frappe.ui.Dialog({
title: __("Confirm"),
fields: [{ fieldtype: "HTML", options: "" + message + "
" }],
primary_action_label: __("Yes"),
primary_action: function primary_action() {
if (ifyes) ifyes();
d.hide();
},
secondary_action_label: __("No")
});
d.show();
d.confirm_dialog = true;
if (ifno) {
d.onhide = function () {
if (!d.primary_action_fulfilled) {
ifno();
}
};
}
return d;
};
frappe.prompt = function (fields, callback, title, primary_label) {
if (typeof fields === "string") {
fields = [{
label: fields,
fieldname: "value",
fieldtype: "Data",
reqd: 1
}];
}
if (!$.isArray(fields)) fields = [fields];
var d = new frappe.ui.Dialog({
fields: fields,
title: title || __("Enter Value")
});
d.set_primary_action(primary_label || __("Submit"), function () {
var values = d.get_values();
if (!values) {
return;
}
d.hide();
callback(values);
});
d.show();
return d;
};
var msg_dialog = null;
frappe.msgprint = function (msg, title) {
if (!msg) return;
if ($.isPlainObject(msg)) {
var data = msg;
} else {
if (typeof msg === 'string' && msg.substr(0, 1) === '{') {
var data = JSON.parse(msg);
} else {
var data = { 'message': msg, 'title': title };
}
}
if (!data.indicator) {
data.indicator = 'blue';
}
if (data.message instanceof Array) {
data.message.forEach(function (m) {
frappe.msgprint(m);
});
return;
}
if (data.alert) {
frappe.show_alert(data);
return;
}
if (!msg_dialog) {
msg_dialog = new frappe.ui.Dialog({
title: __("Message"),
onhide: function onhide() {
if (msg_dialog.custom_onhide) {
msg_dialog.custom_onhide();
}
msg_dialog.msg_area.empty();
}
});
msg_dialog.msg_area = $('').appendTo(msg_dialog.body);
msg_dialog.loading_indicator = $('
\
').appendTo(msg_dialog.body);
msg_dialog.clear = function () {
msg_dialog.msg_area.empty();
};
msg_dialog.indicator = msg_dialog.header.find('.indicator');
}
if (data.message == null) {
data.message = '';
}
if (data.message.search(/
|
|
/) == -1) {
msg = replace_newlines(data.message);
}
var msg_exists = false;
if (data.clear) {
msg_dialog.msg_area.empty();
} else {
msg_exists = msg_dialog.msg_area.html();
}
if (data.title || !msg_exists) {
msg_dialog.set_title(data.title || __('Message'));
}
if (data.indicator) {
msg_dialog.indicator.removeClass().addClass('indicator ' + data.indicator);
} else {
msg_dialog.indicator.removeClass().addClass('hidden');
}
if (msg_exists) {
msg_dialog.msg_area.append(" ");
}
msg_dialog.msg_area.append(data.message);
msg_dialog.loading_indicator.addClass("hide");
msg_dialog.show_loading = function () {
msg_dialog.loading_indicator.removeClass("hide");
};
msg_dialog.$wrapper.css("z-index", 2000);
msg_dialog.show();
return msg_dialog;
};
Object.defineProperty(window, 'msgprint', {
get: function get() {
console.warn('Please use `frappe.msgprint` instead of `msgprint`. It will be deprecated soon.');
return frappe.msgprint;
}
});
frappe.hide_msgprint = function (instant) {
if (msg_dialog && msg_dialog.msg_area) {
msg_dialog.msg_area.empty();
}
if (msg_dialog && msg_dialog.$wrapper.is(":visible")) {
if (instant) {
msg_dialog.$wrapper.removeClass("fade");
}
msg_dialog.hide();
if (instant) {
msg_dialog.$wrapper.addClass("fade");
}
}
};
frappe.update_msgprint = function (html) {
if (!msg_dialog || msg_dialog && !msg_dialog.$wrapper.is(":visible")) {
frappe.msgprint(html);
} else {
msg_dialog.msg_area.html(html);
}
};
frappe.verify_password = function (_callback) {
frappe.prompt({
fieldname: "password",
label: __("Enter your password"),
fieldtype: "Password",
reqd: 1
}, function (data) {
frappe.call({
method: "frappe.core.doctype.user.user.verify_password",
args: {
password: data.password
},
callback: function callback(r) {
if (!r.exc) {
_callback();
}
}
});
}, __("Verify Password"), __("Verify"));
};
frappe.show_progress = function (title, count, total) {
if (frappe.cur_progress && frappe.cur_progress.title === title && frappe.cur_progress.$wrapper.is(":visible")) {
var dialog = frappe.cur_progress;
} else {
var dialog = new frappe.ui.Dialog({
title: title
});
dialog.progress = $('').appendTo(dialog.body);
dialog.progress_bar = dialog.progress.css({ "margin-top": "10px" }).find(".progress-bar");
dialog.$wrapper.removeClass("fade");
dialog.show();
frappe.cur_progress = dialog;
}
dialog.progress_bar.css({ "width": cint(flt(count) * 100 / total) + "%" });
};
frappe.hide_progress = function () {
if (frappe.cur_progress) {
frappe.cur_progress.hide();
frappe.cur_progress = null;
}
};
frappe.show_alert = function (message) {
var seconds = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 7;
if (typeof message === 'string') {
message = {
message: message
};
}
if (!$('#dialog-container').length) {
$('').appendTo('body');
}
var message_html;
if (message.indicator) {
message_html = $(' ').append(message.message);
} else {
message_html = message.message;
}
var div = $('\n\t\t');
div.find('.alert-message').append(message_html);
div.hide().appendTo("#alert-container").fadeIn(300);
div.find('.close').click(function () {
$(this).parent().remove();
return false;
});
div.delay(seconds * 1000).fadeOut(300);
return div;
};
Object.defineProperty(window, 'show_alert', {
get: function get() {
console.warn('Please use `frappe.show_alert` instead of `show_alert`. It will be deprecated soon.');
return frappe.show_alert;
}
});
frappe.provide('frappe.ui.keys.handlers');
frappe.ui.keys.setup = function () {
$(window).on('keydown', function (e) {
var key = frappe.ui.keys.get_key(e);
if (frappe.ui.keys.handlers[key]) {
var out = null;
for (var i = 0, l = frappe.ui.keys.handlers[key].length; i < l; i++) {
var handler = frappe.ui.keys.handlers[key][i];
var _out = handler.apply(this, [e]);
if (_out === false) {
out = _out;
}
}
return out;
}
});
};
frappe.ui.keys.get_key = function (e) {
var keycode = e.keyCode || e.which;
var key = frappe.ui.keys.key_map[keycode] || String.fromCharCode(keycode);
if (e.ctrlKey || e.metaKey) {
key = 'ctrl+' + key;
}
if (e.shiftKey) {
key = 'shift+' + key;
}
return key.toLowerCase();
};
frappe.ui.keys.on = function (key, handler) {
if (!frappe.ui.keys.handlers[key]) {
frappe.ui.keys.handlers[key] = [];
}
frappe.ui.keys.handlers[key].push(handler);
};
frappe.ui.keys.on('ctrl+s', function (e) {
frappe.app.trigger_primary_action();
e.preventDefault();
return false;
});
frappe.ui.keys.on('ctrl+g', function (e) {
$("#navbar-search").focus();
e.preventDefault();
return false;
});
frappe.ui.keys.on('ctrl+b', function (e) {
var route = frappe.get_route();
if (route[0] === 'Form' || route[0] === 'List') {
frappe.new_doc(route[1], true);
e.preventDefault();
return false;
}
});
frappe.ui.keys.on('escape', function (e) {
close_grid_and_dialog();
});
frappe.ui.keys.on('esc', function (e) {
close_grid_and_dialog();
});
frappe.ui.keys.on('Enter', function (e) {
if (cur_dialog && cur_dialog.confirm_dialog) {
cur_dialog.get_primary_btn().trigger('click');
}
});
frappe.ui.keys.on('ctrl+down', function (e) {
var grid_row = frappe.ui.form.get_open_grid_form();
grid_row && grid_row.toggle_view(false, function () {
grid_row.open_next();
});
});
frappe.ui.keys.on('ctrl+up', function (e) {
var grid_row = frappe.ui.form.get_open_grid_form();
grid_row && grid_row.toggle_view(false, function () {
grid_row.open_prev();
});
});
frappe.ui.keys.on('shift+ctrl+r', function (e) {
frappe.ui.toolbar.clear_cache();
});
frappe.ui.keys.key_map = {
8: 'backspace',
9: 'tab',
13: 'enter',
16: 'shift',
17: 'ctrl',
91: 'meta',
18: 'alt',
27: 'escape',
37: 'left',
39: 'right',
38: 'up',
40: 'down',
32: 'space'
};
frappe.ui.keyCode = {
ESCAPE: 27,
LEFT: 37,
RIGHT: 39,
UP: 38,
DOWN: 40,
ENTER: 13,
TAB: 9,
SPACE: 32
};
function close_grid_and_dialog() {
var open_row = $(".grid-row-open");
if (open_row.length) {
var grid_row = open_row.data("grid_row");
grid_row.toggle_view(false);
return false;
}
if (cur_dialog && !cur_dialog.no_cancel_flag) {
cur_dialog.cancel();
return false;
}
}
frappe.ui.get_emoji = function (keyword) {
if (!keyword.includes(':')) keyword = ':' + keyword + ':';
return frappe.ui.emoji_map[keyword];
};
frappe.ui.emojis = ["๐", "๐", "๐
ฐ", "๐
ฑ", "๐
พ", "๐
ฟ", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐ฆ๐จ", "๐ฆ๐ฉ", "๐ฆ๐ช", "๐ฆ๐ซ", "๐ฆ๐ฌ", "๐ฆ๐ฎ", "๐ฆ๐ฑ", "๐ฆ๐ฒ", "๐ฆ๐ด", "๐ฆ๐ถ", "๐ฆ๐ท", "๐ฆ๐ธ", "๐ฆ๐น", "๐ฆ๐บ", "๐ฆ๐ผ", "๐ฆ๐ฝ", "๐ฆ๐ฟ", "๐ฆ", "๐ง๐ฆ", "๐ง๐ง", "๐ง๐ฉ", "๐ง๐ช", "๐ง๐ซ", "๐ง๐ฌ", "๐ง๐ญ", "๐ง๐ฎ", "๐ง๐ฏ", "๐ง๐ฑ", "๐ง๐ฒ", "๐ง๐ณ", "๐ง๐ด", "๐ง๐ถ", "๐ง๐ท", "๐ง๐ธ", "๐ง๐น", "๐ง๐ป", "๐ง๐ผ", "๐ง๐พ", "๐ง๐ฟ", "๐ง", "๐จ๐ฆ", "๐จ๐จ", "๐จ๐ฉ", "๐จ๐ซ", "๐จ๐ฌ", "๐จ๐ญ", "๐จ๐ฎ", "๐จ๐ฐ", "๐จ๐ฑ", "๐จ๐ฒ", "๐จ๐ณ", "๐จ๐ด", "๐จ๐ต", "๐จ๐ท", "๐จ๐บ", "๐จ๐ป", "๐จ๐ผ", "๐จ๐ฝ", "๐จ๐พ", "๐จ๐ฟ", "๐จ", "๐ฉ๐ช", "๐ฉ๐ฌ", "๐ฉ๐ฏ", "๐ฉ๐ฐ", "๐ฉ๐ฒ", "๐ฉ๐ด", "๐ฉ๐ฟ", "๐ฉ", "๐ช๐ฆ", "๐ช๐จ", "๐ช๐ช", "๐ช๐ฌ", "๐ช๐ญ", "๐ช๐ท", "๐ช๐ธ", "๐ช๐น", "๐ช๐บ", "๐ช", "๐ซ๐ฎ", "๐ซ๐ฏ", "๐ซ๐ฐ", "๐ซ๐ฒ", "๐ซ๐ด", "๐ซ๐ท", "๐ซ", "๐ฌ๐ฆ", "๐ฌ๐ง", "๐ฌ๐ฉ", "๐ฌ๐ช", "๐ฌ๐ซ", "๐ฌ๐ฌ", "๐ฌ๐ญ", "๐ฌ๐ฎ", "๐ฌ๐ฑ", "๐ฌ๐ฒ", "๐ฌ๐ณ", "๐ฌ๐ต", "๐ฌ๐ถ", "๐ฌ๐ท", "๐ฌ๐ธ", "๐ฌ๐น", "๐ฌ๐บ", "๐ฌ๐ผ", "๐ฌ๐พ", "๐ฌ", "๐ญ๐ฐ", "๐ญ๐ฒ", "๐ญ๐ณ", "๐ญ๐ท", "๐ญ๐น", "๐ญ๐บ", "๐ญ", "๐ฎ๐จ", "๐ฎ๐ฉ", "๐ฎ๐ช", "๐ฎ๐ฑ", "๐ฎ๐ฒ", "๐ฎ๐ณ", "๐ฎ๐ด", "๐ฎ๐ถ", "๐ฎ๐ท", "๐ฎ๐ธ", "๐ฎ๐น", "๐ฎ", "๐ฏ๐ช", "๐ฏ๐ฒ", "๐ฏ๐ด", "๐ฏ๐ต", "๐ฏ", "๐ฐ๐ช", "๐ฐ๐ฌ", "๐ฐ๐ญ", "๐ฐ๐ฎ", "๐ฐ๐ฒ", "๐ฐ๐ณ", "๐ฐ๐ต", "๐ฐ๐ท", "๐ฐ๐ผ", "๐ฐ๐พ", "๐ฐ๐ฟ", "๐ฐ", "๐ฑ๐ฆ", "๐ฑ๐ง", "๐ฑ๐จ", "๐ฑ๐ฎ", "๐ฑ๐ฐ", "๐ฑ๐ท", "๐ฑ๐ธ", "๐ฑ๐น", "๐ฑ๐บ", "๐ฑ๐ป", "๐ฑ๐พ", "๐ฑ", "๐ฒ๐ฆ", "๐ฒ๐จ", "๐ฒ๐ฉ", "๐ฒ๐ช", "๐ฒ๐ซ", "๐ฒ๐ฌ", "๐ฒ๐ญ", "๐ฒ๐ฐ", "๐ฒ๐ฑ", "๐ฒ๐ฒ", "๐ฒ๐ณ", "๐ฒ๐ด", "๐ฒ๐ต", "๐ฒ๐ถ", "๐ฒ๐ท", "๐ฒ๐ธ", "๐ฒ๐น", "๐ฒ๐บ", "๐ฒ๐ป", "๐ฒ๐ผ", "๐ฒ๐ฝ", "๐ฒ๐พ", "๐ฒ๐ฟ", "๐ฒ", "๐ณ๐ฆ", "๐ณ๐จ", "๐ณ๐ช", "๐ณ๐ซ", "๐ณ๐ฌ", "๐ณ๐ฎ", "๐ณ๐ฑ", "๐ณ๐ด", "๐ณ๐ต", "๐ณ๐ท", "๐ณ๐บ", "๐ณ๐ฟ", "๐ณ", "๐ด๐ฒ", "๐ด", "๐ต๐ฆ", "๐ต๐ช", "๐ต๐ซ", "๐ต๐ฌ", "๐ต๐ญ", "๐ต๐ฐ", "๐ต๐ฑ", "๐ต๐ฒ", "๐ต๐ณ", "๐ต๐ท", "๐ต๐ธ", "๐ต๐น", "๐ต๐ผ", "๐ต๐พ", "๐ต", "๐ถ๐ฆ", "๐ถ", "๐ท๐ช", "๐ท๐ด", "๐ท๐ธ", "๐ท๐บ", "๐ท๐ผ", "๐ท", "๐ธ๐ฆ", "๐ธ๐ง", "๐ธ๐จ", "๐ธ๐ฉ", "๐ธ๐ช", "๐ธ๐ฌ", "๐ธ๐ญ", "๐ธ๐ฎ", "๐ธ๐ฏ", "๐ธ๐ฐ", "๐ธ๐ฑ", "๐ธ๐ฒ", "๐ธ๐ณ", "๐ธ๐ด", "๐ธ๐ท", "๐ธ๐ธ", "๐ธ๐น", "๐ธ๐ป", "๐ธ๐ฝ", "๐ธ๐พ", "๐ธ๐ฟ", "๐ธ", "๐น๐ฆ", "๐น๐จ", "๐น๐ฉ", "๐น๐ซ", "๐น๐ฌ", "๐น๐ญ", "๐น๐ฏ", "๐น๐ฐ", "๐น๐ฑ", "๐น๐ฒ", "๐น๐ณ", "๐น๐ด", "๐น๐ท", "๐น๐น", "๐น๐ป", "๐น๐ผ", "๐น๐ฟ", "๐น", "๐บ๐ฆ", "๐บ๐ฌ", "๐บ๐ฒ", "๐บ๐ณ", "๐บ๐ธ", "๐บ๐พ", "๐บ๐ฟ", "๐บ", "๐ป๐ฆ", "๐ป๐จ", "๐ป๐ช", "๐ป๐ฌ", "๐ป๐ฎ", "๐ป๐ณ", "๐ป๐บ", "๐ป", "๐ผ๐ซ", "๐ผ๐ธ", "๐ผ", "๐ฝ๐ฐ", "๐ฝ", "๐พ๐ช", "๐พ๐น", "๐พ", "๐ฟ๐ฆ", "๐ฟ๐ฒ", "๐ฟ๐ผ", "๐ฟ", "๐", "๐", "๐", "๐ฏ", "๐ฒ", "๐ณ", "๐ด", "๐ต", "๐ถ", "๐ท", "๐ธ", "๐น", "๐บ", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐
", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐ ", "๐ก", "๐ค", "๐ฅ", "๐ฆ", "๐ง", "๐จ", "๐ฉ", "๐ช", "๐ซ", "๐ฌ", "๐ญ", "๐ฎ", "๐ฏ", "๐ฐ", "๐ฑ", "๐ฒ", "๐ณ", "๐ด", "๐ต", "๐ถ", "๐ท", "๐ธ", "๐น", "๐บ", "๐ป", "๐ผ", "๐ฝ", "๐พ", "๐ฟ", "๐", "๐", "๐", "๐", "๐", "๐
", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐ ", "๐ก", "๐ข", "๐ฃ", "๐ค", "๐ฅ", "๐ฆ", "๐ง", "๐จ", "๐ฉ", "๐ช", "๐ซ", "๐ฌ", "๐ญ", "๐ฎ", "๐ฏ", "๐ฐ", "๐ฑ", "๐ฒ", "๐ณ", "๐ด", "๐ต", "๐ถ", "๐ท", "๐ธ", "๐น", "๐บ", "๐ป", "๐ผ", "๐ฝ", "๐พ", "๐ฟ", "๐", "๐", "๐", "๐", "๐", "๐
๐ป", "๐
๐ผ", "๐
๐ฝ", "๐
๐พ", "๐
๐ฟ", "๐
", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐ ", "๐ก", "๐ข", "๐ฃ", "๐ค", "๐ฅ", "๐ฆ", "๐ง", "๐จ", "๐ฉ", "๐ช", "๐ซ", "๐ฌ", "๐ญ", "๐ฎ", "๐ฏ", "๐ฐ", "๐ฑ", "๐ฒ", "๐ณ", "๐ด", "๐ต", "๐ถ", "๐ท", "๐ธ", "๐น", "๐บ", "๐ป", "๐ผ", "๐ฝ", "๐พ", "๐ฟ", "๐", "๐", "๐๐ป", "๐๐ผ", "๐๐ฝ", "๐๐พ", "๐๐ฟ", "๐", "๐๐ปโโ๏ธ", "๐๐ปโโ๏ธ", "๐๐ป", "๐๐ผโโ๏ธ", "๐๐ผโโ๏ธ", "๐๐ผ", "๐๐ฝโโ๏ธ", "๐๐ฝโโ๏ธ", "๐๐ฝ", "๐๐พโโ๏ธ", "๐๐พโโ๏ธ", "๐๐พ", "๐๐ฟโโ๏ธ", "๐๐ฟโโ๏ธ", "๐๐ฟ", "๐โโ๏ธ", "๐โโ๏ธ", "๐", "๐๐ปโโ๏ธ", "๐๐ปโโ๏ธ", "๐๐ป", "๐๐ผโโ๏ธ", "๐๐ผโโ๏ธ", "๐๐ผ", "๐๐ฝโโ๏ธ", "๐๐ฝโโ๏ธ", "๐๐ฝ", "๐๐พโโ๏ธ", "๐๐พโโ๏ธ", "๐๐พ", "๐๐ฟโโ๏ธ", "๐๐ฟโโ๏ธ", "๐๐ฟ", "๐โโ๏ธ", "๐โโ๏ธ", "๐", "๐
", "๐", "๐๐ป", "๐๐ผ", "๐๐ฝ", "๐๐พ", "๐๐ฟ", "๐", "๐", "๐", "๐๐ปโโ๏ธ", "๐๐ปโโ๏ธ", "๐๐ป", "๐๐ผโโ๏ธ", "๐๐ผโโ๏ธ", "๐๐ผ", "๐๐ฝโโ๏ธ", "๐๐ฝโโ๏ธ", "๐๐ฝ", "๐๐พโโ๏ธ", "๐๐พโโ๏ธ", "๐๐พ", "๐๐ฟโโ๏ธ", "๐๐ฟโโ๏ธ", "๐๐ฟ", "๐โโ๏ธ", "๐โโ๏ธ", "๐", "๐๐ปโโ๏ธ", "๐๐ปโโ๏ธ", "๐๐ป", "๐๐ผโโ๏ธ", "๐๐ผโโ๏ธ", "๐๐ผ", "๐๐ฝโโ๏ธ", "๐๐ฝโโ๏ธ", "๐๐ฝ", "๐๐พโโ๏ธ", "๐๐พโโ๏ธ", "๐๐พ", "๐๐ฟโโ๏ธ", "๐๐ฟโโ๏ธ", "๐๐ฟ", "๐๏ธโโ๏ธ", "๐๏ธโโ๏ธ", "๐", "๐๐ปโโ๏ธ", "๐๐ปโโ๏ธ", "๐๐ป", "๐๐ผโโ๏ธ", "๐๐ผโโ๏ธ", "๐๐ผ", "๐๐ฝโโ๏ธ", "๐๐ฝโโ๏ธ", "๐๐ฝ", "๐๐พโโ๏ธ", "๐๐พโโ๏ธ", "๐๐พ", "๐๐ฟโโ๏ธ", "๐๐ฟโโ๏ธ", "๐๐ฟ", "๐๏ธโโ๏ธ", "๐๏ธโโ๏ธ", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐ ", "๐ก", "๐ข", "๐ฃ", "๐ค", "๐ฅ", "๐ฆ", "๐ง", "๐จ", "๐ฉ", "๐ช", "๐ซ", "๐ฌ", "๐ญ", "๐ฎ", "๐ฏ", "๐ฐ", "๐ณ๏ธโ๐", "๐ณ", "๐ดโโ ๏ธ", "๐ด", "๐ต", "๐ท", "๐ธ", "๐น", "๐บ", "๐ป", "๐ผ", "๐ฝ", "๐พ", "๐ฟ", "๐", "๐", "๐", "๐", "๐", "๐
", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐ ", "๐ก", "๐ข", "๐ฃ", "๐ค", "๐ฅ", "๐ฆ", "๐ง", "๐จ", "๐ฉ", "๐ช", "๐ซ", "๐ฌ", "๐ญ", "๐ฎ", "๐ฏ", "๐ฐ", "๐ฑ", "๐ฒ", "๐ณ", "๐ด", "๐ต", "๐ถ", "๐ท", "๐ธ", "๐น", "๐บ", "๐ป", "๐ผ", "๐ฝ", "๐พ", "๐ฟ", "๐", "๐โ๐จ", "๐", "๐๐ป", "๐๐ผ", "๐๐ฝ", "๐๐พ", "๐๐ฟ", "๐", "๐๐ป", "๐๐ผ", "๐๐ฝ", "๐๐พ", "๐๐ฟ", "๐", "๐", "๐
", "๐๐ป", "๐๐ผ", "๐๐ฝ", "๐๐พ", "๐๐ฟ", "๐", "๐๐ป", "๐๐ผ", "๐๐ฝ", "๐๐พ", "๐๐ฟ", "๐", "๐๐ป", "๐๐ผ", "๐๐ฝ", "๐๐พ", "๐๐ฟ", "๐", "๐๐ป", "๐๐ผ", "๐๐ฝ", "๐๐พ", "๐๐ฟ", "๐", "๐๐ป", "๐๐ผ", "๐๐ฝ", "๐๐พ", "๐๐ฟ", "๐", "๐๐ป", "๐๐ผ", "๐๐ฝ", "๐๐พ", "๐๐ฟ", "๐", "๐๐ป", "๐๐ผ", "๐๐ฝ", "๐๐พ", "๐๐ฟ", "๐", "๐๐ป", "๐๐ผ", "๐๐ฝ", "๐๐พ", "๐๐ฟ", "๐", "๐๐ป", "๐๐ผ", "๐๐ฝ", "๐๐พ", "๐๐ฟ", "๐", "๐๐ป", "๐๐ผ", "๐๐ฝ", "๐๐พ", "๐๐ฟ", "๐", "๐๐ป", "๐๐ผ", "๐๐ฝ", "๐๐พ", "๐๐ฟ", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐ ", "๐ก", "๐ข", "๐ฃ", "๐ค", "๐ฅ", "๐ฆ๐ป", "๐ฆ๐ผ", "๐ฆ๐ฝ", "๐ฆ๐พ", "๐ฆ๐ฟ", "๐ฆ", "๐ง๐ป", "๐ง๐ผ", "๐ง๐ฝ", "๐ง๐พ", "๐ง๐ฟ", "๐ง", "๐จ๐ปโ๐พ", "๐จ๐ปโ๐ณ", "๐จ๐ปโ๐", "๐จ๐ปโ๐ค", "๐จ๐ปโ๐จ", "๐จ๐ปโ๐ซ", "๐จ๐ปโ๐ญ", "๐จ๐ปโ๐ป", "๐จ๐ปโ๐ผ", "๐จ๐ปโ๐ง", "๐จ๐ปโ๐ฌ", "๐จ๐ปโ๐", "๐จ๐ปโ๐", "๐จ๐ปโโ๏ธ", "๐จ๐ปโโ๏ธ", "๐จ๐ปโโ๏ธ", "๐จ๐ป", "๐จ๐ผโ๐พ", "๐จ๐ผโ๐ณ", "๐จ๐ผโ๐", "๐จ๐ผโ๐ค", "๐จ๐ผโ๐จ", "๐จ๐ผโ๐ซ", "๐จ๐ผโ๐ญ", "๐จ๐ผโ๐ป", "๐จ๐ผโ๐ผ", "๐จ๐ผโ๐ง", "๐จ๐ผโ๐ฌ", "๐จ๐ผโ๐", "๐จ๐ผโ๐", "๐จ๐ผโโ๏ธ", "๐จ๐ผโโ๏ธ", "๐จ๐ผโโ๏ธ", "๐จ๐ผ", "๐จ๐ฝโ๐พ", "๐จ๐ฝโ๐ณ", "๐จ๐ฝโ๐", "๐จ๐ฝโ๐ค", "๐จ๐ฝโ๐จ", "๐จ๐ฝโ๐ซ", "๐จ๐ฝโ๐ญ", "๐จ๐ฝโ๐ป", "๐จ๐ฝโ๐ผ", "๐จ๐ฝโ๐ง", "๐จ๐ฝโ๐ฌ", "๐จ๐ฝโ๐", "๐จ๐ฝโ๐", "๐จ๐ฝโโ๏ธ", "๐จ๐ฝโโ๏ธ", "๐จ๐ฝโโ๏ธ", "๐จ๐ฝ", "๐จ๐พโ๐พ", "๐จ๐พโ๐ณ", "๐จ๐พโ๐", "๐จ๐พโ๐ค", "๐จ๐พโ๐จ", "๐จ๐พโ๐ซ", "๐จ๐พโ๐ญ", "๐จ๐พโ๐ป", "๐จ๐พโ๐ผ", "๐จ๐พโ๐ง", "๐จ๐พโ๐ฌ", "๐จ๐พโ๐", "๐จ๐พโ๐", "๐จ๐พโโ๏ธ", "๐จ๐พโโ๏ธ", "๐จ๐พโโ๏ธ", "๐จ๐พ", "๐จ๐ฟโ๐พ", "๐จ๐ฟโ๐ณ", "๐จ๐ฟโ๐", "๐จ๐ฟโ๐ค", "๐จ๐ฟโ๐จ", "๐จ๐ฟโ๐ซ", "๐จ๐ฟโ๐ญ", "๐จ๐ฟโ๐ป", "๐จ๐ฟโ๐ผ", "๐จ๐ฟโ๐ง", "๐จ๐ฟโ๐ฌ", "๐จ๐ฟโ๐", "๐จ๐ฟโ๐", "๐จ๐ฟโโ๏ธ", "๐จ๐ฟโโ๏ธ", "๐จ๐ฟโโ๏ธ", "๐จ๐ฟ", "๐จโ๐พ", "๐จโ๐ณ", "๐จโ๐", "๐จโ๐ค", "๐จโ๐จ", "๐จโ๐ซ", "๐จโ๐ญ", "๐จโ๐ฆโ๐ฆ", "๐จโ๐ฆ", "๐จโ๐งโ๐ฆ", "๐จโ๐งโ๐ง", "๐จโ๐ง", "๐จโ๐จโ๐ฆโ๐ฆ", "๐จโ๐จโ๐ฆ", "๐จโ๐จโ๐งโ๐ฆ", "๐จโ๐จโ๐งโ๐ง", "๐จโ๐จโ๐ง", "๐จโ๐ฉโ๐ฆโ๐ฆ", "๐จโ๐ฉโ๐ฆ", "๐จโ๐ฉโ๐งโ๐ฆ", "๐จโ๐ฉโ๐งโ๐ง", "๐จโ๐ฉโ๐ง", "๐จโ๐ป", "๐จโ๐ผ", "๐จโ๐ง", "๐จโ๐ฌ", "๐จโ๐", "๐จโ๐", "๐จโโ๏ธ", "๐จโโ๏ธ", "๐จโโ๏ธ", "๐จโโค๏ธโ๐จ", "๐จโโค๏ธโ๐โ๐จ", "๐จ", "๐ฉ๐ปโ๐พ", "๐ฉ๐ปโ๐ณ", "๐ฉ๐ปโ๐", "๐ฉ๐ปโ๐ค", "๐ฉ๐ปโ๐จ", "๐ฉ๐ปโ๐ซ", "๐ฉ๐ปโ๐ญ", "๐ฉ๐ปโ๐ป", "๐ฉ๐ปโ๐ผ", "๐ฉ๐ปโ๐ง", "๐ฉ๐ปโ๐ฌ", "๐ฉ๐ปโ๐", "๐ฉ๐ปโ๐", "๐ฉ๐ปโโ๏ธ", "๐ฉ๐ปโโ๏ธ", "๐ฉ๐ปโโ๏ธ", "๐ฉ๐ป", "๐ฉ๐ผโ๐พ", "๐ฉ๐ผโ๐ณ", "๐ฉ๐ผโ๐", "๐ฉ๐ผโ๐ค", "๐ฉ๐ผโ๐จ", "๐ฉ๐ผโ๐ซ", "๐ฉ๐ผโ๐ญ", "๐ฉ๐ผโ๐ป", "๐ฉ๐ผโ๐ผ", "๐ฉ๐ผโ๐ง", "๐ฉ๐ผโ๐ฌ", "๐ฉ๐ผโ๐", "๐ฉ๐ผโ๐", "๐ฉ๐ผโโ๏ธ", "๐ฉ๐ผโโ๏ธ", "๐ฉ๐ผโโ๏ธ", "๐ฉ๐ผ", "๐ฉ๐ฝโ๐พ", "๐ฉ๐ฝโ๐ณ", "๐ฉ๐ฝโ๐", "๐ฉ๐ฝโ๐ค", "๐ฉ๐ฝโ๐จ", "๐ฉ๐ฝโ๐ซ", "๐ฉ๐ฝโ๐ญ", "๐ฉ๐ฝโ๐ป", "๐ฉ๐ฝโ๐ผ", "๐ฉ๐ฝโ๐ง", "๐ฉ๐ฝโ๐ฌ", "๐ฉ๐ฝโ๐", "๐ฉ๐ฝโ๐", "๐ฉ๐ฝโโ๏ธ", "๐ฉ๐ฝโโ๏ธ", "๐ฉ๐ฝโโ๏ธ", "๐ฉ๐ฝ", "๐ฉ๐พโ๐พ", "๐ฉ๐พโ๐ณ", "๐ฉ๐พโ๐", "๐ฉ๐พโ๐ค", "๐ฉ๐พโ๐จ", "๐ฉ๐พโ๐ซ", "๐ฉ๐พโ๐ญ", "๐ฉ๐พโ๐ป", "๐ฉ๐พโ๐ผ", "๐ฉ๐พโ๐ง", "๐ฉ๐พโ๐ฌ", "๐ฉ๐พโ๐", "๐ฉ๐พโ๐", "๐ฉ๐พโโ๏ธ", "๐ฉ๐พโโ๏ธ", "๐ฉ๐พโโ๏ธ", "๐ฉ๐พ", "๐ฉ๐ฟโ๐พ", "๐ฉ๐ฟโ๐ณ", "๐ฉ๐ฟโ๐", "๐ฉ๐ฟโ๐ค", "๐ฉ๐ฟโ๐จ", "๐ฉ๐ฟโ๐ซ", "๐ฉ๐ฟโ๐ญ", "๐ฉ๐ฟโ๐ป", "๐ฉ๐ฟโ๐ผ", "๐ฉ๐ฟโ๐ง", "๐ฉ๐ฟโ๐ฌ", "๐ฉ๐ฟโ๐", "๐ฉ๐ฟโ๐", "๐ฉ๐ฟโโ๏ธ", "๐ฉ๐ฟโโ๏ธ", "๐ฉ๐ฟโโ๏ธ", "๐ฉ๐ฟ", "๐ฉโ๐พ", "๐ฉโ๐ณ", "๐ฉโ๐", "๐ฉโ๐ค", "๐ฉโ๐จ", "๐ฉโ๐ซ", "๐ฉโ๐ญ", "๐ฉโ๐ฆโ๐ฆ", "๐ฉโ๐ฆ", "๐ฉโ๐งโ๐ฆ", "๐ฉโ๐งโ๐ง", "๐ฉโ๐ง", "๐ฉโ๐ฉโ๐ฆโ๐ฆ", "๐ฉโ๐ฉโ๐ฆ", "๐ฉโ๐ฉโ๐งโ๐ฆ", "๐ฉโ๐ฉโ๐งโ๐ง", "๐ฉโ๐ฉโ๐ง", "๐ฉโ๐ป", "๐ฉโ๐ผ", "๐ฉโ๐ง", "๐ฉโ๐ฌ", "๐ฉโ๐", "๐ฉโ๐", "๐ฉโโ๏ธ", "๐ฉโโ๏ธ", "๐ฉโโ๏ธ", "๐ฉโโค๏ธโ๐จ", "๐ฉโโค๏ธโ๐ฉ", "๐ฉโโค๏ธโ๐โ๐จ", "๐ฉโโค๏ธโ๐โ๐ฉ", "๐ฉ", "๐ช๐ป", "๐ช๐ผ", "๐ช๐ฝ", "๐ช๐พ", "๐ช๐ฟ", "๐ช", "๐ซ๐ป", "๐ซ๐ผ", "๐ซ๐ฝ", "๐ซ๐พ", "๐ซ๐ฟ", "๐ซ", "๐ฌ๐ป", "๐ฌ๐ผ", "๐ฌ๐ฝ", "๐ฌ๐พ", "๐ฌ๐ฟ", "๐ฌ", "๐ญ๐ป", "๐ญ๐ผ", "๐ญ๐ฝ", "๐ญ๐พ", "๐ญ๐ฟ", "๐ญ", "๐ฎ๐ปโโ๏ธ", "๐ฎ๐ปโโ๏ธ", "๐ฎ๐ป", "๐ฎ๐ผโโ๏ธ", "๐ฎ๐ผโโ๏ธ", "๐ฎ๐ผ", "๐ฎ๐ฝโโ๏ธ", "๐ฎ๐ฝโโ๏ธ", "๐ฎ๐ฝ", "๐ฎ๐พโโ๏ธ", "๐ฎ๐พโโ๏ธ", "๐ฎ๐พ", "๐ฎ๐ฟโโ๏ธ", "๐ฎ๐ฟโโ๏ธ", "๐ฎ๐ฟ", "๐ฎโโ๏ธ", "๐ฎโโ๏ธ", "๐ฎ", "๐ฏ๐ปโโ๏ธ", "๐ฏ๐ปโโ๏ธ", "๐ฏ๐ป", "๐ฏ๐ผโโ๏ธ", "๐ฏ๐ผโโ๏ธ", "๐ฏ๐ผ", "๐ฏ๐ฝโโ๏ธ", "๐ฏ๐ฝโโ๏ธ", "๐ฏ๐ฝ", "๐ฏ๐พโโ๏ธ", "๐ฏ๐พโโ๏ธ", "๐ฏ๐พ", "๐ฏ๐ฟโโ๏ธ", "๐ฏ๐ฟโโ๏ธ", "๐ฏ๐ฟ", "๐ฏโโ๏ธ", "๐ฏโโ๏ธ", "๐ฏ", "๐ฐ๐ป", "๐ฐ๐ผ", "๐ฐ๐ฝ", "๐ฐ๐พ", "๐ฐ๐ฟ", "๐ฐ", "๐ฑ๐ปโโ๏ธ", "๐ฑ๐ปโโ๏ธ", "๐ฑ๐ป", "๐ฑ๐ผโโ๏ธ", "๐ฑ๐ผโโ๏ธ", "๐ฑ๐ผ", "๐ฑ๐ฝโโ๏ธ", "๐ฑ๐ฝโโ๏ธ", "๐ฑ๐ฝ", "๐ฑ๐พโโ๏ธ", "๐ฑ๐พโโ๏ธ", "๐ฑ๐พ", "๐ฑ๐ฟโโ๏ธ", "๐ฑ๐ฟโโ๏ธ", "๐ฑ๐ฟ", "๐ฑโโ๏ธ", "๐ฑโโ๏ธ", "๐ฑ", "๐ฒ๐ป", "๐ฒ๐ผ", "๐ฒ๐ฝ", "๐ฒ๐พ", "๐ฒ๐ฟ", "๐ฒ", "๐ณ๐ปโโ๏ธ", "๐ณ๐ปโโ๏ธ", "๐ณ๐ป", "๐ณ๐ผโโ๏ธ", "๐ณ๐ผโโ๏ธ", "๐ณ๐ผ", "๐ณ๐ฝโโ๏ธ", "๐ณ๐ฝโโ๏ธ", "๐ณ๐ฝ", "๐ณ๐พโโ๏ธ", "๐ณ๐พโโ๏ธ", "๐ณ๐พ", "๐ณ๐ฟโโ๏ธ", "๐ณ๐ฟโโ๏ธ", "๐ณ๐ฟ", "๐ณโโ๏ธ", "๐ณโโ๏ธ", "๐ณ", "๐ด๐ป", "๐ด๐ผ", "๐ด๐ฝ", "๐ด๐พ", "๐ด๐ฟ", "๐ด", "๐ต๐ป", "๐ต๐ผ", "๐ต๐ฝ", "๐ต๐พ", "๐ต๐ฟ", "๐ต", "๐ถ๐ป", "๐ถ๐ผ", "๐ถ๐ฝ", "๐ถ๐พ", "๐ถ๐ฟ", "๐ถ", "๐ท๐ปโโ๏ธ", "๐ท๐ปโโ๏ธ", "๐ท๐ป", "๐ท๐ผโโ๏ธ", "๐ท๐ผโโ๏ธ", "๐ท๐ผ", "๐ท๐ฝโโ๏ธ", "๐ท๐ฝโโ๏ธ", "๐ท๐ฝ", "๐ท๐พโโ๏ธ", "๐ท๐พโโ๏ธ", "๐ท๐พ", "๐ท๐ฟโโ๏ธ", "๐ท๐ฟโโ๏ธ", "๐ท๐ฟ", "๐ทโโ๏ธ", "๐ทโโ๏ธ", "๐ท", "๐ธ๐ป", "๐ธ๐ผ", "๐ธ๐ฝ", "๐ธ๐พ", "๐ธ๐ฟ", "๐ธ", "๐น", "๐บ", "๐ป", "๐ผ๐ป", "๐ผ๐ผ", "๐ผ๐ฝ", "๐ผ๐พ", "๐ผ๐ฟ", "๐ผ", "๐ฝ", "๐พ", "๐ฟ", "๐", "๐๐ปโโ๏ธ", "๐๐ปโโ๏ธ", "๐๐ป", "๐๐ผโโ๏ธ", "๐๐ผโโ๏ธ", "๐๐ผ", "๐๐ฝโโ๏ธ", "๐๐ฝโโ๏ธ", "๐๐ฝ", "๐๐พโโ๏ธ", "๐๐พโโ๏ธ", "๐๐พ", "๐๐ฟโโ๏ธ", "๐๐ฟโโ๏ธ", "๐๐ฟ", "๐โโ๏ธ", "๐โโ๏ธ", "๐", "๐๐ปโโ๏ธ", "๐๐ปโโ๏ธ", "๐๐ป", "๐๐ผโโ๏ธ", "๐๐ผโโ๏ธ", "๐๐ผ", "๐๐ฝโโ๏ธ", "๐๐ฝโโ๏ธ", "๐๐ฝ", "๐๐พโโ๏ธ", "๐๐พโโ๏ธ", "๐๐พ", "๐๐ฟโโ๏ธ", "๐๐ฟโโ๏ธ", "๐๐ฟ", "๐โโ๏ธ", "๐โโ๏ธ", "๐", "๐๐ป", "๐๐ผ", "๐๐ฝ", "๐๐พ", "๐๐ฟ", "๐", "๐", "๐
๐ป", "๐
๐ผ", "๐
๐ฝ", "๐
๐พ", "๐
๐ฟ", "๐
", "๐๐ปโโ๏ธ", "๐๐ปโโ๏ธ", "๐๐ป", "๐๐ผโโ๏ธ", "๐๐ผโโ๏ธ", "๐๐ผ", "๐๐ฝโโ๏ธ", "๐๐ฝโโ๏ธ", "๐๐ฝ", "๐๐พโโ๏ธ", "๐๐พโโ๏ธ", "๐๐พ", "๐๐ฟโโ๏ธ", "๐๐ฟโโ๏ธ", "๐๐ฟ", "๐โโ๏ธ", "๐โโ๏ธ", "๐", "๐๐ปโโ๏ธ", "๐๐ปโโ๏ธ", "๐๐ป", "๐๐ผโโ๏ธ", "๐๐ผโโ๏ธ", "๐๐ผ", "๐๐ฝโโ๏ธ", "๐๐ฝโโ๏ธ", "๐๐ฝ", "๐๐พโโ๏ธ", "๐๐พโโ๏ธ", "๐๐พ", "๐๐ฟโโ๏ธ", "๐๐ฟโโ๏ธ", "๐๐ฟ", "๐โโ๏ธ", "๐โโ๏ธ", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐ ", "๐ก", "๐ข", "๐ฃ", "๐ค", "๐ฅ", "๐ฆ", "๐ง", "๐จ", "๐ฉ", "๐ช๐ป", "๐ช๐ผ", "๐ช๐ฝ", "๐ช๐พ", "๐ช๐ฟ", "๐ช", "๐ซ", "๐ฌ", "๐ญ", "๐ฎ", "๐ฏ", "๐ฐ", "๐ฑ", "๐ฒ", "๐ณ", "๐ด", "๐ต", "๐ถ", "๐ท", "๐ธ", "๐น", "๐บ", "๐ป", "๐ผ", "๐ฝ", "๐พ", "๐ฟ", "๐", "๐", "๐", "๐", "๐", "๐
", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐ ", "๐ก", "๐ข", "๐ฃ", "๐ค", "๐ฅ", "๐ฆ", "๐ง", "๐จ", "๐ฉ", "๐ช", "๐ซ", "๐ฌ", "๐ญ", "๐ฎ", "๐ฏ", "๐ฐ", "๐ฑ", "๐ฒ", "๐ณ", "๐ด", "๐ต", "๐ถ", "๐ท", "๐ธ", "๐น", "๐บ", "๐ป", "๐ผ", "๐ฝ", "๐ฟ", "๐", "๐", "๐", "๐", "๐", "๐
", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐ ", "๐ก", "๐ข", "๐ฃ", "๐ค", "๐ฅ", "๐ฆ", "๐ง", "๐จ", "๐ฉ", "๐ช", "๐ซ", "๐ฌ", "๐ญ", "๐ฎ", "๐ฏ", "๐ฐ", "๐ฑ", "๐ฒ", "๐ณ", "๐ด", "๐ต", "๐ถ", "๐ท", "๐ธ", "๐น", "๐บ", "๐ป", "๐ผ", "๐ฝ", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐ ", "๐ก", "๐ข", "๐ฃ", "๐ค", "๐ฅ", "๐ฆ", "๐ง", "๐ฏ", "๐ฐ", "๐ณ", "๐ด๐ป", "๐ด๐ผ", "๐ด๐ฝ", "๐ด๐พ", "๐ด๐ฟ", "๐ด", "๐ต๐ปโโ๏ธ", "๐ต๐ปโโ๏ธ", "๐ต๐ป", "๐ต๐ผโโ๏ธ", "๐ต๐ผโโ๏ธ", "๐ต๐ผ", "๐ต๐ฝโโ๏ธ", "๐ต๐ฝโโ๏ธ", "๐ต๐ฝ", "๐ต๐พโโ๏ธ", "๐ต๐พโโ๏ธ", "๐ต๐พ", "๐ต๐ฟโโ๏ธ", "๐ต๐ฟโโ๏ธ", "๐ต๐ฟ", "๐ต๏ธโโ๏ธ", "๐ต๏ธโโ๏ธ", "๐ต", "๐ถ", "๐ท", "๐ธ", "๐น", "๐บ๐ป", "๐บ๐ผ", "๐บ๐ฝ", "๐บ๐พ", "๐บ๐ฟ", "๐บ", "๐", "๐", "๐", "๐", "๐", "๐๐ป", "๐๐ผ", "๐๐ฝ", "๐๐พ", "๐๐ฟ", "๐", "๐๐ป", "๐๐ผ", "๐๐ฝ", "๐๐พ", "๐๐ฟ", "๐", "๐๐ป", "๐๐ผ", "๐๐ฝ", "๐๐พ", "๐๐ฟ", "๐", "๐ค", "๐ฅ", "๐จ", "๐ฑ", "๐ฒ", "๐ผ", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐ก", "๐ฃ", "๐จ", "๐ฏ", "๐ณ", "๐บ", "๐ป", "๐ผ", "๐ฝ", "๐พ", "๐ฟ", "๐", "๐", "๐", "๐", "๐", "๐
", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐ ", "๐ก", "๐ข", "๐ฃ", "๐ค", "๐ฅ", "๐ฆ", "๐ง", "๐จ", "๐ฉ", "๐ช", "๐ซ", "๐ฌ", "๐ญ", "๐ฎ", "๐ฏ", "๐ฐ", "๐ฑ", "๐ฒ", "๐ณ", "๐ด", "๐ต", "๐ถ", "๐ท", "๐ธ", "๐น", "๐บ", "๐ป", "๐ผ", "๐ฝ", "๐พ", "๐ฟ", "๐", "๐", "๐", "๐", "๐", "๐
๐ปโโ๏ธ", "๐
๐ปโโ๏ธ", "๐
๐ป", "๐
๐ผโโ๏ธ", "๐
๐ผโโ๏ธ", "๐
๐ผ", "๐
๐ฝโโ๏ธ", "๐
๐ฝโโ๏ธ", "๐
๐ฝ", "๐
๐พโโ๏ธ", "๐
๐พโโ๏ธ", "๐
๐พ", "๐
๐ฟโโ๏ธ", "๐
๐ฟโโ๏ธ", "๐
๐ฟ", "๐
โโ๏ธ", "๐
โโ๏ธ", "๐
", "๐๐ปโโ๏ธ", "๐๐ปโโ๏ธ", "๐๐ป", "๐๐ผโโ๏ธ", "๐๐ผโโ๏ธ", "๐๐ผ", "๐๐ฝโโ๏ธ", "๐๐ฝโโ๏ธ", "๐๐ฝ", "๐๐พโโ๏ธ", "๐๐พโโ๏ธ", "๐๐พ", "๐๐ฟโโ๏ธ", "๐๐ฟโโ๏ธ", "๐๐ฟ", "๐โโ๏ธ", "๐โโ๏ธ", "๐", "๐๐ปโโ๏ธ", "๐๐ปโโ๏ธ", "๐๐ป", "๐๐ผโโ๏ธ", "๐๐ผโโ๏ธ", "๐๐ผ", "๐๐ฝโโ๏ธ", "๐๐ฝโโ๏ธ", "๐๐ฝ", "๐๐พโโ๏ธ", "๐๐พโโ๏ธ", "๐๐พ", "๐๐ฟโโ๏ธ", "๐๐ฟโโ๏ธ", "๐๐ฟ", "๐โโ๏ธ", "๐โโ๏ธ", "๐", "๐", "๐", "๐", "๐๐ปโโ๏ธ", "๐๐ปโโ๏ธ", "๐๐ป", "๐๐ผโโ๏ธ", "๐๐ผโโ๏ธ", "๐๐ผ", "๐๐ฝโโ๏ธ", "๐๐ฝโโ๏ธ", "๐๐ฝ", "๐๐พโโ๏ธ", "๐๐พโโ๏ธ", "๐๐พ", "๐๐ฟโโ๏ธ", "๐๐ฟโโ๏ธ", "๐๐ฟ", "๐โโ๏ธ", "๐โโ๏ธ", "๐", "๐๐ป", "๐๐ผ", "๐๐ฝ", "๐๐พ", "๐๐ฟ", "๐", "๐๐ปโโ๏ธ", "๐๐ปโโ๏ธ", "๐๐ป", "๐๐ผโโ๏ธ", "๐๐ผโโ๏ธ", "๐๐ผ", "๐๐ฝโโ๏ธ", "๐๐ฝโโ๏ธ", "๐๐ฝ", "๐๐พโโ๏ธ", "๐๐พโโ๏ธ", "๐๐พ", "๐๐ฟโโ๏ธ", "๐๐ฟโโ๏ธ", "๐๐ฟ", "๐โโ๏ธ", "๐โโ๏ธ", "๐", "๐๐ปโโ๏ธ", "๐๐ปโโ๏ธ", "๐๐ป", "๐๐ผโโ๏ธ", "๐๐ผโโ๏ธ", "๐๐ผ", "๐๐ฝโโ๏ธ", "๐๐ฝโโ๏ธ", "๐๐ฝ", "๐๐พโโ๏ธ", "๐๐พโโ๏ธ", "๐๐พ", "๐๐ฟโโ๏ธ", "๐๐ฟโโ๏ธ", "๐๐ฟ", "๐โโ๏ธ", "๐โโ๏ธ", "๐", "๐๐ป", "๐๐ผ", "๐๐ฝ", "๐๐พ", "๐๐ฟ", "๐", "๐", "๐", "๐", "๐", "๐", "๐
", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐ ", "๐ก", "๐ข", "๐ฃ๐ปโโ๏ธ", "๐ฃ๐ปโโ๏ธ", "๐ฃ๐ป", "๐ฃ๐ผโโ๏ธ", "๐ฃ๐ผโโ๏ธ", "๐ฃ๐ผ", "๐ฃ๐ฝโโ๏ธ", "๐ฃ๐ฝโโ๏ธ", "๐ฃ๐ฝ", "๐ฃ๐พโโ๏ธ", "๐ฃ๐พโโ๏ธ", "๐ฃ๐พ", "๐ฃ๐ฟโโ๏ธ", "๐ฃ๐ฟโโ๏ธ", "๐ฃ๐ฟ", "๐ฃโโ๏ธ", "๐ฃโโ๏ธ", "๐ฃ", "๐ค", "๐ฅ", "๐ฆ", "๐ง", "๐จ", "๐ฉ", "๐ช", "๐ซ", "๐ฌ", "๐ญ", "๐ฎ", "๐ฏ", "๐ฐ", "๐ฑ", "๐ฒ", "๐ณ", "๐ด๐ปโโ๏ธ", "๐ด๐ปโโ๏ธ", "๐ด๐ป", "๐ด๐ผโโ๏ธ", "๐ด๐ผโโ๏ธ", "๐ด๐ผ", "๐ด๐ฝโโ๏ธ", "๐ด๐ฝโโ๏ธ", "๐ด๐ฝ", "๐ด๐พโโ๏ธ", "๐ด๐พโโ๏ธ", "๐ด๐พ", "๐ด๐ฟโโ๏ธ", "๐ด๐ฟโโ๏ธ", "๐ด๐ฟ", "๐ดโโ๏ธ", "๐ดโโ๏ธ", "๐ด", "๐ต๐ปโโ๏ธ", "๐ต๐ปโโ๏ธ", "๐ต๐ป", "๐ต๐ผโโ๏ธ", "๐ต๐ผโโ๏ธ", "๐ต๐ผ", "๐ต๐ฝโโ๏ธ", "๐ต๐ฝโโ๏ธ", "๐ต๐ฝ", "๐ต๐พโโ๏ธ", "๐ต๐พโโ๏ธ", "๐ต๐พ", "๐ต๐ฟโโ๏ธ", "๐ต๐ฟโโ๏ธ", "๐ต๐ฟ", "๐ตโโ๏ธ", "๐ตโโ๏ธ", "๐ต", "๐ถ๐ปโโ๏ธ", "๐ถ๐ปโโ๏ธ", "๐ถ๐ป", "๐ถ๐ผโโ๏ธ", "๐ถ๐ผโโ๏ธ", "๐ถ๐ผ", "๐ถ๐ฝโโ๏ธ", "๐ถ๐ฝโโ๏ธ", "๐ถ๐ฝ", "๐ถ๐พโโ๏ธ", "๐ถ๐พโโ๏ธ", "๐ถ๐พ", "๐ถ๐ฟโโ๏ธ", "๐ถ๐ฟโโ๏ธ", "๐ถ๐ฟ", "๐ถโโ๏ธ", "๐ถโโ๏ธ", "๐ถ", "๐ท", "๐ธ", "๐น", "๐บ", "๐ป", "๐ผ", "๐ฝ", "๐พ", "๐ฟ", "๐๐ป", "๐๐ผ", "๐๐ฝ", "๐๐พ", "๐๐ฟ", "๐", "๐", "๐", "๐", "๐", "๐
", "๐", "๐๐ป", "๐๐ผ", "๐๐ฝ", "๐๐พ", "๐๐ฟ", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐ ", "๐ก", "๐ข", "๐ฃ", "๐ค", "๐ฅ", "๐ฉ", "๐ซ", "๐ฌ", "๐ฐ", "๐ณ", "๐ด", "๐ต", "๐ถ", "๐ค", "๐ค", "๐ค", "๐ค", "๐ค", "๐ค", "๐ค", "๐ค", "๐ค๐ป", "๐ค๐ผ", "๐ค๐ฝ", "๐ค๐พ", "๐ค๐ฟ", "๐ค", "๐ค๐ป", "๐ค๐ผ", "๐ค๐ฝ", "๐ค๐พ", "๐ค๐ฟ", "๐ค", "๐ค๐ป", "๐ค๐ผ", "๐ค๐ฝ", "๐ค๐พ", "๐ค๐ฟ", "๐ค", "๐ค๐ป", "๐ค๐ผ", "๐ค๐ฝ", "๐ค๐พ", "๐ค๐ฟ", "๐ค", "๐ค๐ป", "๐ค๐ผ", "๐ค๐ฝ", "๐ค๐พ", "๐ค๐ฟ", "๐ค", "๐ค๐ป", "๐ค๐ผ", "๐ค๐ฝ", "๐ค๐พ", "๐ค๐ฟ", "๐ค", "๐ค๐ป", "๐ค๐ผ", "๐ค๐ฝ", "๐ค๐พ", "๐ค๐ฟ", "๐ค", "๐ค ", "๐คก", "๐คข", "๐คฃ", "๐คค", "๐คฅ", "๐คฆ๐ปโโ๏ธ", "๐คฆ๐ปโโ๏ธ", "๐คฆ๐ป", "๐คฆ๐ผโโ๏ธ", "๐คฆ๐ผโโ๏ธ", "๐คฆ๐ผ", "๐คฆ๐ฝโโ๏ธ", "๐คฆ๐ฝโโ๏ธ", "๐คฆ๐ฝ", "๐คฆ๐พโโ๏ธ", "๐คฆ๐พโโ๏ธ", "๐คฆ๐พ", "๐คฆ๐ฟโโ๏ธ", "๐คฆ๐ฟโโ๏ธ", "๐คฆ๐ฟ", "๐คฆโโ๏ธ", "๐คฆโโ๏ธ", "๐คฆ", "๐คง", "๐คฐ๐ป", "๐คฐ๐ผ", "๐คฐ๐ฝ", "๐คฐ๐พ", "๐คฐ๐ฟ", "๐คฐ", "๐คณ๐ป", "๐คณ๐ผ", "๐คณ๐ฝ", "๐คณ๐พ", "๐คณ๐ฟ", "๐คณ", "๐คด๐ป", "๐คด๐ผ", "๐คด๐ฝ", "๐คด๐พ", "๐คด๐ฟ", "๐คด", "๐คต๐ป", "๐คต๐ผ", "๐คต๐ฝ", "๐คต๐พ", "๐คต๐ฟ", "๐คต", "๐คถ๐ป", "๐คถ๐ผ", "๐คถ๐ฝ", "๐คถ๐พ", "๐คถ๐ฟ", "๐คถ", "๐คท๐ปโโ๏ธ", "๐คท๐ปโโ๏ธ", "๐คท๐ป", "๐คท๐ผโโ๏ธ", "๐คท๐ผโโ๏ธ", "๐คท๐ผ", "๐คท๐ฝโโ๏ธ", "๐คท๐ฝโโ๏ธ", "๐คท๐ฝ", "๐คท๐พโโ๏ธ", "๐คท๐พโโ๏ธ", "๐คท๐พ", "๐คท๐ฟโโ๏ธ", "๐คท๐ฟโโ๏ธ", "๐คท๐ฟ", "๐คทโโ๏ธ", "๐คทโโ๏ธ", "๐คท", "๐คธ๐ปโโ๏ธ", "๐คธ๐ปโโ๏ธ", "๐คธ๐ป", "๐คธ๐ผโโ๏ธ", "๐คธ๐ผโโ๏ธ", "๐คธ๐ผ", "๐คธ๐ฝโโ๏ธ", "๐คธ๐ฝโโ๏ธ", "๐คธ๐ฝ", "๐คธ๐พโโ๏ธ", "๐คธ๐พโโ๏ธ", "๐คธ๐พ", "๐คธ๐ฟโโ๏ธ", "๐คธ๐ฟโโ๏ธ", "๐คธ๐ฟ", "๐คธโโ๏ธ", "๐คธโโ๏ธ", "๐คธ", "๐คน๐ปโโ๏ธ", "๐คน๐ปโโ๏ธ", "๐คน๐ป", "๐คน๐ผโโ๏ธ", "๐คน๐ผโโ๏ธ", "๐คน๐ผ", "๐คน๐ฝโโ๏ธ", "๐คน๐ฝโโ๏ธ", "๐คน๐ฝ", "๐คน๐พโโ๏ธ", "๐คน๐พโโ๏ธ", "๐คน๐พ", "๐คน๐ฟโโ๏ธ", "๐คน๐ฟโโ๏ธ", "๐คน๐ฟ", "๐คนโโ๏ธ", "๐คนโโ๏ธ", "๐คน", "๐คบ", "๐คผ๐ปโโ๏ธ", "๐คผ๐ปโโ๏ธ", "๐คผ๐ป", "๐คผ๐ผโโ๏ธ", "๐คผ๐ผโโ๏ธ", "๐คผ๐ผ", "๐คผ๐ฝโโ๏ธ", "๐คผ๐ฝโโ๏ธ", "๐คผ๐ฝ", "๐คผ๐พโโ๏ธ", "๐คผ๐พโโ๏ธ", "๐คผ๐พ", "๐คผ๐ฟโโ๏ธ", "๐คผ๐ฟโโ๏ธ", "๐คผ๐ฟ", "๐คผโโ๏ธ", "๐คผโโ๏ธ", "๐คผ", "๐คฝ๐ปโโ๏ธ", "๐คฝ๐ปโโ๏ธ", "๐คฝ๐ป", "๐คฝ๐ผโโ๏ธ", "๐คฝ๐ผโโ๏ธ", "๐คฝ๐ผ", "๐คฝ๐ฝโโ๏ธ", "๐คฝ๐ฝโโ๏ธ", "๐คฝ๐ฝ", "๐คฝ๐พโโ๏ธ", "๐คฝ๐พโโ๏ธ", "๐คฝ๐พ", "๐คฝ๐ฟโโ๏ธ", "๐คฝ๐ฟโโ๏ธ", "๐คฝ๐ฟ", "๐คฝโโ๏ธ", "๐คฝโโ๏ธ", "๐คฝ", "๐คพ๐ปโโ๏ธ", "๐คพ๐ปโโ๏ธ", "๐คพ๐ป", "๐คพ๐ผโโ๏ธ", "๐คพ๐ผโโ๏ธ", "๐คพ๐ผ", "๐คพ๐ฝโโ๏ธ", "๐คพ๐ฝโโ๏ธ", "๐คพ๐ฝ", "๐คพ๐พโโ๏ธ", "๐คพ๐พโโ๏ธ", "๐คพ๐พ", "๐คพ๐ฟโโ๏ธ", "๐คพ๐ฟโโ๏ธ", "๐คพ๐ฟ", "๐คพโโ๏ธ", "๐คพโโ๏ธ", "๐คพ", "๐ฅ", "๐ฅ", "๐ฅ", "๐ฅ", "๐ฅ", "๐ฅ
", "๐ฅ", "๐ฅ", "๐ฅ", "๐ฅ", "๐ฅ", "๐ฅ", "๐ฅ", "๐ฅ", "๐ฅ", "๐ฅ", "๐ฅ", "๐ฅ", "๐ฅ", "๐ฅ", "๐ฅ", "๐ฅ", "๐ฅ", "๐ฅ", "๐ฅ", "๐ฅ", "๐ฆ", "๐ฆ", "๐ฆ", "๐ฆ", "๐ฆ", "๐ฆ
", "๐ฆ", "๐ฆ", "๐ฆ", "๐ฆ", "๐ฆ", "๐ฆ", "๐ฆ", "๐ฆ", "๐ฆ", "๐ฆ", "๐ฆ", "๐ฆ", "๐ง", "โผ", "โ", "โข", "โน", "โ", "โ", "โ", "โ", "โ", "โ", "โฉ", "โช", "#โฃ", "โ", "โ", "โจ", "โ", "โฉ", "โช", "โซ", "โฌ", "โญ", "โฎ", "โฏ", "โฐ", "โฑ", "โฒ", "โณ", "โธ", "โน", "โบ", "โ", "โช", "โซ", "โถ", "โ", "โป", "โผ", "โฝ", "โพ", "โ", "โ", "โ", "โ", "โ", "โ", "โ", "โ", "โ", "โ", "โ๐ป", "โ๐ผ", "โ๐ฝ", "โ๐พ", "โ๐ฟ", "โ", "โ ", "โข", "โฃ", "โฆ", "โช", "โฎ", "โฏ", "โธ", "โน", "โบ", "โ", "โ", "โ", "โ", "โ", "โ", "โ", "โ", "โ", "โ", "โ", "โ", "โ", "โ", "โ ", "โฃ", "โฅ", "โฆ", "โจ", "โป", "โฟ", "โ", "โ", "โ", "โ", "โ", "โ", "โ", "โ", "โ", "โ ", "โก", "โช", "โซ", "โฐ", "โฑ", "โฝ", "โพ", "โ", "โ
", "โ", "โ", "โ", "โ", "โ", "โ", "โฉ", "โช", "โฐ", "โฑ", "โฒ", "โณ", "โด", "โต", "โท๐ป", "โท๐ผ", "โท๐ฝ", "โท๐พ", "โท๐ฟ", "โท", "โธ", "โน๐ปโโ๏ธ", "โน๐ปโโ๏ธ", "โน๐ป", "โน๐ผโโ๏ธ", "โน๐ผโโ๏ธ", "โน๐ผ", "โน๐ฝโโ๏ธ", "โน๐ฝโโ๏ธ", "โน๐ฝ", "โน๐พโโ๏ธ", "โน๐พโโ๏ธ", "โน๐พ", "โน๐ฟโโ๏ธ", "โน๐ฟโโ๏ธ", "โน๐ฟ", "โน๏ธโโ๏ธ", "โน๏ธโโ๏ธ", "โน", "โบ", "โฝ", "โ", "โ
", "โ", "โ", "โ๐ป", "โ๐ผ", "โ๐ฝ", "โ๐พ", "โ๐ฟ", "โ", "โ๐ป", "โ๐ผ", "โ๐ฝ", "โ๐พ", "โ๐ฟ", "โ", "โ๐ป", "โ๐ผ", "โ๐ฝ", "โ๐พ", "โ๐ฟ", "โ", "โ๐ป", "โ๐ผ", "โ๐ฝ", "โ๐พ", "โ๐ฟ", "โ", "โ", "โ", "โ", "โ", "โ", "โก", "โจ", "โณ", "โด", "โ", "โ", "โ", "โ", "โ", "โ", "โ", "โ", "โฃ", "โค", "โ", "โ", "โ", "โก", "โฐ", "โฟ", "โคด", "โคต", "*โฃ", "โฌ
", "โฌ", "โฌ", "โฌ", "โฌ", "โญ", "โญ", "0โฃ", "ใฐ", "ใฝ", "1โฃ", "2โฃ", "ใ", "ใ", "3โฃ", "4โฃ", "5โฃ", "6โฃ", "7โฃ", "8โฃ", "9โฃ", "ยฉ", "ยฎ", "๎"];
frappe.ui.emoji_keywords = [":mahjong:", ":black_joker:", ":a:", ":b:", ":o2:", ":parking:", ":ab:", ":cl:", ":cool:", ":free:", ":id:", ":new:", ":ng:", ":ok:", ":sos:", ":up:", ":vs:", ":flag_ac:", ":flag_ad:", ":flag_ae:", ":flag_af:", ":flag_ag:", ":flag_ai:", ":flag_al:", ":flag_am:", ":flag_ao:", ":flag_aq:", ":flag_ar:", ":flag_as:", ":flag_at:", ":flag_au:", ":flag_aw:", ":flag_ax:", ":flag_az:", ":regional_indicator_a:", ":flag_ba:", ":flag_bb:", ":flag_bd:", ":flag_be:", ":flag_bf:", ":flag_bg:", ":flag_bh:", ":flag_bi:", ":flag_bj:", ":flag_bl:", ":flag_bm:", ":flag_bn:", ":flag_bo:", ":flag_bq:", ":flag_br:", ":flag_bs:", ":flag_bt:", ":flag_bv:", ":flag_bw:", ":flag_by:", ":flag_bz:", ":regional_indicator_b:", ":flag_ca:", ":flag_cc:", ":flag_cd:", ":flag_cf:", ":flag_cg:", ":flag_ch:", ":flag_ci:", ":flag_ck:", ":flag_cl:", ":flag_cm:", ":flag_cn:", ":flag_co:", ":flag_cp:", ":flag_cr:", ":flag_cu:", ":flag_cv:", ":flag_cw:", ":flag_cx:", ":flag_cy:", ":flag_cz:", ":regional_indicator_c:", ":flag_de:", ":flag_dg:", ":flag_dj:", ":flag_dk:", ":flag_dm:", ":flag_do:", ":flag_dz:", ":regional_indicator_d:", ":flag_ea:", ":flag_ec:", ":flag_ee:", ":flag_eg:", ":flag_eh:", ":flag_er:", ":flag_es:", ":flag_et:", ":flag_eu:", ":regional_indicator_e:", ":flag_fi:", ":flag_fj:", ":flag_fk:", ":flag_fm:", ":flag_fo:", ":flag_fr:", ":regional_indicator_f:", ":flag_ga:", ":flag_gb:", ":flag_gd:", ":flag_ge:", ":flag_gf:", ":flag_gg:", ":flag_gh:", ":flag_gi:", ":flag_gl:", ":flag_gm:", ":flag_gn:", ":flag_gp:", ":flag_gq:", ":flag_gr:", ":flag_gs:", ":flag_gt:", ":flag_gu:", ":flag_gw:", ":flag_gy:", ":regional_indicator_g:", ":flag_hk:", ":flag_hm:", ":flag_hn:", ":flag_hr:", ":flag_ht:", ":flag_hu:", ":regional_indicator_h:", ":flag_ic:", ":flag_id:", ":flag_ie:", ":flag_il:", ":flag_im:", ":flag_in:", ":flag_io:", ":flag_iq:", ":flag_ir:", ":flag_is:", ":flag_it:", ":regional_indicator_i:", ":flag_je:", ":flag_jm:", ":flag_jo:", ":flag_jp:", ":regional_indicator_j:", ":flag_ke:", ":flag_kg:", ":flag_kh:", ":flag_ki:", ":flag_km:", ":flag_kn:", ":flag_kp:", ":flag_kr:", ":flag_kw:", ":flag_ky:", ":flag_kz:", ":regional_indicator_k:", ":flag_la:", ":flag_lb:", ":flag_lc:", ":flag_li:", ":flag_lk:", ":flag_lr:", ":flag_ls:", ":flag_lt:", ":flag_lu:", ":flag_lv:", ":flag_ly:", ":regional_indicator_l:", ":flag_ma:", ":flag_mc:", ":flag_md:", ":flag_me:", ":flag_mf:", ":flag_mg:", ":flag_mh:", ":flag_mk:", ":flag_ml:", ":flag_mm:", ":flag_mn:", ":flag_mo:", ":flag_mp:", ":flag_mq:", ":flag_mr:", ":flag_ms:", ":flag_mt:", ":flag_mu:", ":flag_mv:", ":flag_mw:", ":flag_mx:", ":flag_my:", ":flag_mz:", ":regional_indicator_m:", ":flag_na:", ":flag_nc:", ":flag_ne:", ":flag_nf:", ":flag_ng:", ":flag_ni:", ":flag_nl:", ":flag_no:", ":flag_np:", ":flag_nr:", ":flag_nu:", ":flag_nz:", ":regional_indicator_n:", ":flag_om:", ":regional_indicator_o:", ":flag_pa:", ":flag_pe:", ":flag_pf:", ":flag_pg:", ":flag_ph:", ":flag_pk:", ":flag_pl:", ":flag_pm:", ":flag_pn:", ":flag_pr:", ":flag_ps:", ":flag_pt:", ":flag_pw:", ":flag_py:", ":regional_indicator_p:", ":flag_qa:", ":regional_indicator_q:", ":flag_re:", ":flag_ro:", ":flag_rs:", ":flag_ru:", ":flag_rw:", ":regional_indicator_r:", ":flag_sa:", ":flag_sb:", ":flag_sc:", ":flag_sd:", ":flag_se:", ":flag_sg:", ":flag_sh:", ":flag_si:", ":flag_sj:", ":flag_sk:", ":flag_sl:", ":flag_sm:", ":flag_sn:", ":flag_so:", ":flag_sr:", ":flag_ss:", ":flag_st:", ":flag_sv:", ":flag_sx:", ":flag_sy:", ":flag_sz:", ":regional_indicator_s:", ":flag_ta:", ":flag_tc:", ":flag_td:", ":flag_tf:", ":flag_tg:", ":flag_th:", ":flag_tj:", ":flag_tk:", ":flag_tl:", ":flag_tm:", ":flag_tn:", ":flag_to:", ":flag_tr:", ":flag_tt:", ":flag_tv:", ":flag_tw:", ":flag_tz:", ":regional_indicator_t:", ":flag_ua:", ":flag_ug:", ":flag_um:", ":regional_indicator_u::regional_indicator_n:", ":flag_us:", ":flag_uy:", ":flag_uz:", ":regional_indicator_u:", ":flag_va:", ":flag_vc:", ":flag_ve:", ":flag_vg:", ":flag_vi:", ":flag_vn:", ":flag_vu:", ":regional_indicator_v:", ":flag_wf:", ":flag_ws:", ":regional_indicator_w:", ":flag_xk:", ":regional_indicator_x:", ":flag_ye:", ":flag_yt:", ":regional_indicator_y:", ":flag_za:", ":flag_zm:", ":flag_zw:", ":regional_indicator_z:", ":koko:", ":sa:", ":u7121:", ":u6307:", ":u7981:", ":u7a7a:", ":u5408:", ":u6e80:", ":u6709:", ":u6708:", ":u7533:", ":u5272:", ":u55b6:", ":ideograph_advantage:", ":accept:", ":cyclone:", ":foggy:", ":closed_umbrella:", ":night_with_stars:", ":sunrise_over_mountains:", ":sunrise:", ":city_dusk:", ":city_sunset:", ":rainbow:", ":bridge_at_night:", ":ocean:", ":volcano:", ":milky_way:", ":earth_africa:", ":earth_americas:", ":earth_asia:", ":globe_with_meridians:", ":new_moon:", ":waxing_crescent_moon:", ":first_quarter_moon:", ":waxing_gibbous_moon:", ":full_moon:", ":waning_gibbous_moon:", ":last_quarter_moon:", ":waning_crescent_moon:", ":crescent_moon:", ":new_moon_with_face:", ":first_quarter_moon_with_face:", ":last_quarter_moon_with_face:", ":full_moon_with_face:", ":sun_with_face:", ":star2:", ":stars:", ":thermometer:", ":white_sun_small_cloud:", ":white_sun_cloud:", ":white_sun_rain_cloud:", ":cloud_rain:", ":cloud_snow:", ":cloud_lightning:", ":cloud_tornado:", ":fog:", ":wind_blowing_face:", ":hotdog:", ":taco:", ":burrito:", ":chestnut:", ":seedling:", ":evergreen_tree:", ":deciduous_tree:", ":palm_tree:", ":cactus:", ":hot_pepper:", ":tulip:", ":cherry_blossom:", ":rose:", ":hibiscus:", ":sunflower:", ":blossom:", ":corn:", ":ear_of_rice:", ":herb:", ":four_leaf_clover:", ":maple_leaf:", ":fallen_leaf:", ":leaves:", ":mushroom:", ":tomato:", ":eggplant:", ":grapes:", ":melon:", ":watermelon:", ":tangerine:", ":lemon:", ":banana:", ":pineapple:", ":apple:", ":green_apple:", ":pear:", ":peach:", ":cherries:", ":strawberry:", ":hamburger:", ":pizza:", ":meat_on_bone:", ":poultry_leg:", ":rice_cracker:", ":rice_ball:", ":rice:", ":curry:", ":ramen:", ":spaghetti:", ":bread:", ":fries:", ":sweet_potato:", ":dango:", ":oden:", ":sushi:", ":fried_shrimp:", ":fish_cake:", ":icecream:", ":shaved_ice:", ":ice_cream:", ":doughnut:", ":cookie:", ":chocolate_bar:", ":candy:", ":lollipop:", ":custard:", ":honey_pot:", ":cake:", ":bento:", ":stew:", ":cooking:", ":fork_and_knife:", ":tea:", ":sake:", ":wine_glass:", ":cocktail:", ":tropical_drink:", ":beer:", ":beers:", ":baby_bottle:", ":fork_knife_plate:", ":champagne:", ":popcorn:", ":ribbon:", ":gift:", ":birthday:", ":jack_o_lantern:", ":christmas_tree:", ":santa_tone1:", ":santa_tone2:", ":santa_tone3:", ":santa_tone4:", ":santa_tone5:", ":santa:", ":fireworks:", ":sparkler:", ":balloon:", ":tada:", ":confetti_ball:", ":tanabata_tree:", ":crossed_flags:", ":bamboo:", ":dolls:", ":flags:", ":wind_chime:", ":rice_scene:", ":school_satchel:", ":mortar_board:", ":military_medal:", ":reminder_ribbon:", ":microphone2:", ":level_slider:", ":control_knobs:", ":film_frames:", ":tickets:", ":carousel_horse:", ":ferris_wheel:", ":roller_coaster:", ":fishing_pole_and_fish:", ":microphone:", ":movie_camera:", ":cinema:", ":headphones:", ":art:", ":tophat:", ":circus_tent:", ":ticket:", ":clapper:", ":performing_arts:", ":video_game:", ":dart:", ":slot_machine:", ":8ball:", ":game_die:", ":bowling:", ":flower_playing_cards:", ":musical_note:", ":notes:", ":saxophone:", ":guitar:", ":musical_keyboard:", ":trumpet:", ":violin:", ":musical_score:", ":running_shirt_with_sash:", ":tennis:", ":ski:", ":basketball:", ":checkered_flag:", ":snowboarder::tone1:", ":snowboarder::tone2:", ":snowboarder::tone3:", ":snowboarder::tone4:", ":snowboarder::tone5:", ":snowboarder:", ":runner_tone1:โโ๏ธ", ":runner_tone1:โโ๏ธ", ":runner_tone1:", ":runner_tone2:โโ๏ธ", ":runner_tone2:โโ๏ธ", ":runner_tone2:", ":runner_tone3:โโ๏ธ", ":runner_tone3:โโ๏ธ", ":runner_tone3:", ":runner_tone4:โโ๏ธ", ":runner_tone4:โโ๏ธ", ":runner_tone4:", ":runner_tone5:โโ๏ธ", ":runner_tone5:โโ๏ธ", ":runner_tone5:", ":runner:โโ๏ธ", ":runner:โโ๏ธ", ":runner:", ":surfer_tone1:โโ๏ธ", ":surfer_tone1:โโ๏ธ", ":surfer_tone1:", ":surfer_tone2:โโ๏ธ", ":surfer_tone2:โโ๏ธ", ":surfer_tone2:", ":surfer_tone3:โโ๏ธ", ":surfer_tone3:โโ๏ธ", ":surfer_tone3:", ":surfer_tone4:โโ๏ธ", ":surfer_tone4:โโ๏ธ", ":surfer_tone4:", ":surfer_tone5:โโ๏ธ", ":surfer_tone5:โโ๏ธ", ":surfer_tone5:", ":surfer:โโ๏ธ", ":surfer:โโ๏ธ", ":surfer:", ":medal:", ":trophy:", ":horse_racing_tone1:", ":horse_racing_tone2:", ":horse_racing_tone3:", ":horse_racing_tone4:", ":horse_racing_tone5:", ":horse_racing:", ":football:", ":rugby_football:", ":swimmer_tone1:โโ๏ธ", ":swimmer_tone1:โโ๏ธ", ":swimmer_tone1:", ":swimmer_tone2:โโ๏ธ", ":swimmer_tone2:โโ๏ธ", ":swimmer_tone2:", ":swimmer_tone3:โโ๏ธ", ":swimmer_tone3:โโ๏ธ", ":swimmer_tone3:", ":swimmer_tone4:โโ๏ธ", ":swimmer_tone4:โโ๏ธ", ":swimmer_tone4:", ":swimmer_tone5:โโ๏ธ", ":swimmer_tone5:โโ๏ธ", ":swimmer_tone5:", ":swimmer:โโ๏ธ", ":swimmer:โโ๏ธ", ":swimmer:", ":lifter_tone1:โโ๏ธ", ":lifter_tone1:โโ๏ธ", ":lifter_tone1:", ":lifter_tone2:โโ๏ธ", ":lifter_tone2:โโ๏ธ", ":lifter_tone2:", ":lifter_tone3:โโ๏ธ", ":lifter_tone3:โโ๏ธ", ":lifter_tone3:", ":lifter_tone4:โโ๏ธ", ":lifter_tone4:โโ๏ธ", ":lifter_tone4:", ":lifter_tone5:โโ๏ธ", ":lifter_tone5:โโ๏ธ", ":lifter_tone5:", ":lifter:โโ๏ธ", ":lifter:โโ๏ธ", ":lifter:", ":golfer::tone1:โโ๏ธ", ":golfer::tone1:โโ๏ธ", ":golfer::tone1:", ":golfer::tone2:โโ๏ธ", ":golfer::tone2:โโ๏ธ", ":golfer::tone2:", ":golfer::tone3:โโ๏ธ", ":golfer::tone3:โโ๏ธ", ":golfer::tone3:", ":golfer::tone4:โโ๏ธ", ":golfer::tone4:โโ๏ธ", ":golfer::tone4:", ":golfer::tone5:โโ๏ธ", ":golfer::tone5:โโ๏ธ", ":golfer::tone5:", ":golfer:โโ๏ธ", ":golfer:โโ๏ธ", ":golfer:", ":motorcycle:", ":race_car:", ":cricket:", ":volleyball:", ":field_hockey:", ":hockey:", ":ping_pong:", ":mountain_snow:", ":camping:", ":beach:", ":construction_site:", ":homes:", ":cityscape:", ":house_abandoned:", ":classical_building:", ":desert:", ":island:", ":park:", ":stadium:", ":house:", ":house_with_garden:", ":office:", ":post_office:", ":european_post_office:", ":hospital:", ":bank:", ":atm:", ":hotel:", ":love_hotel:", ":convenience_store:", ":school:", ":department_store:", ":factory:", ":izakaya_lantern:", ":japanese_castle:", ":european_castle:", ":flag_white:โ:rainbow:", ":flag_white:", ":flag_black:โ:skull_crossbones:", ":flag_black:", ":rosette:", ":label:", ":badminton:", ":bow_and_arrow:", ":amphora:", ":tone1:", ":tone2:", ":tone3:", ":tone4:", ":tone5:", ":rat:", ":mouse2:", ":ox:", ":water_buffalo:", ":cow2:", ":tiger2:", ":leopard:", ":rabbit2:", ":cat2:", ":dragon:", ":crocodile:", ":whale2:", ":snail:", ":snake:", ":racehorse:", ":ram:", ":goat:", ":sheep:", ":monkey:", ":rooster:", ":chicken:", ":dog2:", ":pig2:", ":boar:", ":elephant:", ":octopus:", ":shell:", ":bug:", ":ant:", ":bee:", ":beetle:", ":fish:", ":tropical_fish:", ":blowfish:", ":turtle:", ":hatching_chick:", ":baby_chick:", ":hatched_chick:", ":bird:", ":penguin:", ":koala:", ":poodle:", ":dromedary_camel:", ":camel:", ":dolphin:", ":mouse:", ":cow:", ":tiger:", ":rabbit:", ":cat:", ":dragon_face:", ":whale:", ":horse:", ":monkey_face:", ":dog:", ":pig:", ":frog:", ":hamster:", ":wolf:", ":bear:", ":panda_face:", ":pig_nose:", ":feet:", ":chipmunk:", ":eyes:", ":eye_in_speech_bubble:", ":eye:", ":ear_tone1:", ":ear_tone2:", ":ear_tone3:", ":ear_tone4:", ":ear_tone5:", ":ear:", ":nose_tone1:", ":nose_tone2:", ":nose_tone3:", ":nose_tone4:", ":nose_tone5:", ":nose:", ":lips:", ":tongue:", ":point_up_2_tone1:", ":point_up_2_tone2:", ":point_up_2_tone3:", ":point_up_2_tone4:", ":point_up_2_tone5:", ":point_up_2:", ":point_down_tone1:", ":point_down_tone2:", ":point_down_tone3:", ":point_down_tone4:", ":point_down_tone5:", ":point_down:", ":point_left_tone1:", ":point_left_tone2:", ":point_left_tone3:", ":point_left_tone4:", ":point_left_tone5:", ":point_left:", ":point_right_tone1:", ":point_right_tone2:", ":point_right_tone3:", ":point_right_tone4:", ":point_right_tone5:", ":point_right:", ":punch_tone1:", ":punch_tone2:", ":punch_tone3:", ":punch_tone4:", ":punch_tone5:", ":punch:", ":wave_tone1:", ":wave_tone2:", ":wave_tone3:", ":wave_tone4:", ":wave_tone5:", ":wave:", ":ok_hand_tone1:", ":ok_hand_tone2:", ":ok_hand_tone3:", ":ok_hand_tone4:", ":ok_hand_tone5:", ":ok_hand:", ":thumbsup_tone1:", ":thumbsup_tone2:", ":thumbsup_tone3:", ":thumbsup_tone4:", ":thumbsup_tone5:", ":thumbsup:", ":thumbsdown_tone1:", ":thumbsdown_tone2:", ":thumbsdown_tone3:", ":thumbsdown_tone4:", ":thumbsdown_tone5:", ":thumbsdown:", ":clap_tone1:", ":clap_tone2:", ":clap_tone3:", ":clap_tone4:", ":clap_tone5:", ":clap:", ":open_hands_tone1:", ":open_hands_tone2:", ":open_hands_tone3:", ":open_hands_tone4:", ":open_hands_tone5:", ":open_hands:", ":crown:", ":womans_hat:", ":eyeglasses:", ":necktie:", ":shirt:", ":jeans:", ":dress:", ":kimono:", ":bikini:", ":womans_clothes:", ":purse:", ":handbag:", ":pouch:", ":mans_shoe:", ":athletic_shoe:", ":high_heel:", ":sandal:", ":boot:", ":footprints:", ":bust_in_silhouette:", ":busts_in_silhouette:", ":boy_tone1:", ":boy_tone2:", ":boy_tone3:", ":boy_tone4:", ":boy_tone5:", ":boy:", ":girl_tone1:", ":girl_tone2:", ":girl_tone3:", ":girl_tone4:", ":girl_tone5:", ":girl:", ":man_tone1:โ:ear_of_rice:", ":man_tone1:โ:cooking:", ":man_tone1:โ:mortar_board:", ":man_tone1:โ:microphone:", ":man_tone1:โ:art:", ":man_tone1:โ:school:", ":man_tone1:โ:factory:", ":man_tone1:โ:computer:", ":man_tone1:โ:briefcase:", ":man_tone1:โ:wrench:", ":man_tone1:โ:microscope:", ":man_tone1:โ:rocket:", ":man_tone1:โ:fire_engine:", ":man_tone1:โโ๏ธ", ":man_tone1:โ:scales:", ":man_tone1:โ:airplane:", ":man_tone1:", ":man_tone2:โ:ear_of_rice:", ":man_tone2:โ:cooking:", ":man_tone2:โ:mortar_board:", ":man_tone2:โ:microphone:", ":man_tone2:โ:art:", ":man_tone2:โ:school:", ":man_tone2:โ:factory:", ":man_tone2:โ:computer:", ":man_tone2:โ:briefcase:", ":man_tone2:โ:wrench:", ":man_tone2:โ:microscope:", ":man_tone2:โ:rocket:", ":man_tone2:โ:fire_engine:", ":man_tone2:โโ๏ธ", ":man_tone2:โ:scales:", ":man_tone2:โ:airplane:", ":man_tone2:", ":man_tone3:โ:ear_of_rice:", ":man_tone3:โ:cooking:", ":man_tone3:โ:mortar_board:", ":man_tone3:โ:microphone:", ":man_tone3:โ:art:", ":man_tone3:โ:school:", ":man_tone3:โ:factory:", ":man_tone3:โ:computer:", ":man_tone3:โ:briefcase:", ":man_tone3:โ:wrench:", ":man_tone3:โ:microscope:", ":man_tone3:โ:rocket:", ":man_tone3:โ:fire_engine:", ":man_tone3:โโ๏ธ", ":man_tone3:โ:scales:", ":man_tone3:โ:airplane:", ":man_tone3:", ":man_tone4:โ:ear_of_rice:", ":man_tone4:โ:cooking:", ":man_tone4:โ:mortar_board:", ":man_tone4:โ:microphone:", ":man_tone4:โ:art:", ":man_tone4:โ:school:", ":man_tone4:โ:factory:", ":man_tone4:โ:computer:", ":man_tone4:โ:briefcase:", ":man_tone4:โ:wrench:", ":man_tone4:โ:microscope:", ":man_tone4:โ:rocket:", ":man_tone4:โ:fire_engine:", ":man_tone4:โโ๏ธ", ":man_tone4:โ:scales:", ":man_tone4:โ:airplane:", ":man_tone4:", ":man_tone5:โ:ear_of_rice:", ":man_tone5:โ:cooking:", ":man_tone5:โ:mortar_board:", ":man_tone5:โ:microphone:", ":man_tone5:โ:art:", ":man_tone5:โ:school:", ":man_tone5:โ:factory:", ":man_tone5:โ:computer:", ":man_tone5:โ:briefcase:", ":man_tone5:โ:wrench:", ":man_tone5:โ:microscope:", ":man_tone5:โ:rocket:", ":man_tone5:โ:fire_engine:", ":man_tone5:โโ๏ธ", ":man_tone5:โ:scales:", ":man_tone5:โ:airplane:", ":man_tone5:", ":man:โ:ear_of_rice:", ":man:โ:cooking:", ":man:โ:mortar_board:", ":man:โ:microphone:", ":man:โ:art:", ":man:โ:school:", ":man:โ:factory:", ":man:โ:boy:โ:boy:", ":man:โ:boy:", ":man:โ:girl:โ:boy:", ":man:โ:girl:โ:girl:", ":man:โ:girl:", ":family_mmbb:", ":family_mmb:", ":family_mmgb:", ":family_mmgg:", ":family_mmg:", ":family_mwbb:", ":man:โ:woman:โ:boy:", ":family_mwgb:", ":family_mwgg:", ":family_mwg:", ":man:โ:computer:", ":man:โ:briefcase:", ":man:โ:wrench:", ":man:โ:microscope:", ":man:โ:rocket:", ":man:โ:fire_engine:", ":man:โโ๏ธ", ":man:โ:scales:", ":man:โ:airplane:", ":couple_mm:", ":kiss_mm:", ":man:", ":woman_tone1:โ:ear_of_rice:", ":woman_tone1:โ:cooking:", ":woman_tone1:โ:mortar_board:", ":woman_tone1:โ:microphone:", ":woman_tone1:โ:art:", ":woman_tone1:โ:school:", ":woman_tone1:โ:factory:", ":woman_tone1:โ:computer:", ":woman_tone1:โ:briefcase:", ":woman_tone1:โ:wrench:", ":woman_tone1:โ:microscope:", ":woman_tone1:โ:rocket:", ":woman_tone1:โ:fire_engine:", ":woman_tone1:โโ๏ธ", ":woman_tone1:โ:scales:", ":woman_tone1:โ:airplane:", ":woman_tone1:", ":woman_tone2:โ:ear_of_rice:", ":woman_tone2:โ:cooking:", ":woman_tone2:โ:mortar_board:", ":woman_tone2:โ:microphone:", ":woman_tone2:โ:art:", ":woman_tone2:โ:school:", ":woman_tone2:โ:factory:", ":woman_tone2:โ:computer:", ":woman_tone2:โ:briefcase:", ":woman_tone2:โ:wrench:", ":woman_tone2:โ:microscope:", ":woman_tone2:โ:rocket:", ":woman_tone2:โ:fire_engine:", ":woman_tone2:โโ๏ธ", ":woman_tone2:โ:scales:", ":woman_tone2:โ:airplane:", ":woman_tone2:", ":woman_tone3:โ:ear_of_rice:", ":woman_tone3:โ:cooking:", ":woman_tone3:โ:mortar_board:", ":woman_tone3:โ:microphone:", ":woman_tone3:โ:art:", ":woman_tone3:โ:school:", ":woman_tone3:โ:factory:", ":woman_tone3:โ:computer:", ":woman_tone3:โ:briefcase:", ":woman_tone3:โ:wrench:", ":woman_tone3:โ:microscope:", ":woman_tone3:โ:rocket:", ":woman_tone3:โ:fire_engine:", ":woman_tone3:โโ๏ธ", ":woman_tone3:โ:scales:", ":woman_tone3:โ:airplane:", ":woman_tone3:", ":woman_tone4:โ:ear_of_rice:", ":woman_tone4:โ:cooking:", ":woman_tone4:โ:mortar_board:", ":woman_tone4:โ:microphone:", ":woman_tone4:โ:art:", ":woman_tone4:โ:school:", ":woman_tone4:โ:factory:", ":woman_tone4:โ:computer:", ":woman_tone4:โ:briefcase:", ":woman_tone4:โ:wrench:", ":woman_tone4:โ:microscope:", ":woman_tone4:โ:rocket:", ":woman_tone4:โ:fire_engine:", ":woman_tone4:โโ๏ธ", ":woman_tone4:โ:scales:", ":woman_tone4:โ:airplane:", ":woman_tone4:", ":woman_tone5:โ:ear_of_rice:", ":woman_tone5:โ:cooking:", ":woman_tone5:โ:mortar_board:", ":woman_tone5:โ:microphone:", ":woman_tone5:โ:art:", ":woman_tone5:โ:school:", ":woman_tone5:โ:factory:", ":woman_tone5:โ:computer:", ":woman_tone5:โ:briefcase:", ":woman_tone5:โ:wrench:", ":woman_tone5:โ:microscope:", ":woman_tone5:โ:rocket:", ":woman_tone5:โ:fire_engine:", ":woman_tone5:โโ๏ธ", ":woman_tone5:โ:scales:", ":woman_tone5:โ:airplane:", ":woman_tone5:", ":woman:โ:ear_of_rice:", ":woman:โ:cooking:", ":woman:โ:mortar_board:", ":woman:โ:microphone:", ":woman:โ:art:", ":woman:โ:school:", ":woman:โ:factory:", ":woman:โ:boy:โ:boy:", ":woman:โ:boy:", ":woman:โ:girl:โ:boy:", ":woman:โ:girl:โ:girl:", ":woman:โ:girl:", ":family_wwbb:", ":family_wwb:", ":family_wwgb:", ":family_wwgg:", ":family_wwg:", ":woman:โ:computer:", ":woman:โ:briefcase:", ":woman:โ:wrench:", ":woman:โ:microscope:", ":woman:โ:rocket:", ":woman:โ:fire_engine:", ":woman:โโ๏ธ", ":woman:โ:scales:", ":woman:โ:airplane:", ":woman:โ:heart:โ:man:", ":couple_ww:", ":woman:โ:heart:โ:kiss:โ:man:", ":kiss_ww:", ":woman:", ":family::tone1:", ":family::tone2:", ":family::tone3:", ":family::tone4:", ":family::tone5:", ":family:", ":couple::tone1:", ":couple::tone2:", ":couple::tone3:", ":couple::tone4:", ":couple::tone5:", ":couple:", ":two_men_holding_hands::tone1:", ":two_men_holding_hands::tone2:", ":two_men_holding_hands::tone3:", ":two_men_holding_hands::tone4:", ":two_men_holding_hands::tone5:", ":two_men_holding_hands:", ":two_women_holding_hands::tone1:", ":two_women_holding_hands::tone2:", ":two_women_holding_hands::tone3:", ":two_women_holding_hands::tone4:", ":two_women_holding_hands::tone5:", ":two_women_holding_hands:", ":cop_tone1:โโ๏ธ", ":cop_tone1:โโ๏ธ", ":cop_tone1:", ":cop_tone2:โโ๏ธ", ":cop_tone2:โโ๏ธ", ":cop_tone2:", ":cop_tone3:โโ๏ธ", ":cop_tone3:โโ๏ธ", ":cop_tone3:", ":cop_tone4:โโ๏ธ", ":cop_tone4:โโ๏ธ", ":cop_tone4:", ":cop_tone5:โโ๏ธ", ":cop_tone5:โโ๏ธ", ":cop_tone5:", ":cop:โโ๏ธ", ":cop:โโ๏ธ", ":cop:", ":dancers::tone1:โโ๏ธ", ":dancers::tone1:โโ๏ธ", ":dancers::tone1:", ":dancers::tone2:โโ๏ธ", ":dancers::tone2:โโ๏ธ", ":dancers::tone2:", ":dancers::tone3:โโ๏ธ", ":dancers::tone3:โโ๏ธ", ":dancers::tone3:", ":dancers::tone4:โโ๏ธ", ":dancers::tone4:โโ๏ธ", ":dancers::tone4:", ":dancers::tone5:โโ๏ธ", ":dancers::tone5:โโ๏ธ", ":dancers::tone5:", ":dancers:โโ๏ธ", ":dancers:โโ๏ธ", ":dancers:", ":bride_with_veil_tone1:", ":bride_with_veil_tone2:", ":bride_with_veil_tone3:", ":bride_with_veil_tone4:", ":bride_with_veil_tone5:", ":bride_with_veil:", ":person_with_blond_hair_tone1:โโ๏ธ", ":person_with_blond_hair_tone1:โโ๏ธ", ":person_with_blond_hair_tone1:", ":person_with_blond_hair_tone2:โโ๏ธ", ":person_with_blond_hair_tone2:โโ๏ธ", ":person_with_blond_hair_tone2:", ":person_with_blond_hair_tone3:โโ๏ธ", ":person_with_blond_hair_tone3:โโ๏ธ", ":person_with_blond_hair_tone3:", ":person_with_blond_hair_tone4:โโ๏ธ", ":person_with_blond_hair_tone4:โโ๏ธ", ":person_with_blond_hair_tone4:", ":person_with_blond_hair_tone5:โโ๏ธ", ":person_with_blond_hair_tone5:โโ๏ธ", ":person_with_blond_hair_tone5:", ":person_with_blond_hair:โโ๏ธ", ":person_with_blond_hair:โโ๏ธ", ":person_with_blond_hair:", ":man_with_gua_pi_mao_tone1:", ":man_with_gua_pi_mao_tone2:", ":man_with_gua_pi_mao_tone3:", ":man_with_gua_pi_mao_tone4:", ":man_with_gua_pi_mao_tone5:", ":man_with_gua_pi_mao:", ":man_with_turban_tone1:โโ๏ธ", ":man_with_turban_tone1:โโ๏ธ", ":man_with_turban_tone1:", ":man_with_turban_tone2:โโ๏ธ", ":man_with_turban_tone2:โโ๏ธ", ":man_with_turban_tone2:", ":man_with_turban_tone3:โโ๏ธ", ":man_with_turban_tone3:โโ๏ธ", ":man_with_turban_tone3:", ":man_with_turban_tone4:โโ๏ธ", ":man_with_turban_tone4:โโ๏ธ", ":man_with_turban_tone4:", ":man_with_turban_tone5:โโ๏ธ", ":man_with_turban_tone5:โโ๏ธ", ":man_with_turban_tone5:", ":man_with_turban:โโ๏ธ", ":man_with_turban:โโ๏ธ", ":man_with_turban:", ":older_man_tone1:", ":older_man_tone2:", ":older_man_tone3:", ":older_man_tone4:", ":older_man_tone5:", ":older_man:", ":older_woman_tone1:", ":older_woman_tone2:", ":older_woman_tone3:", ":older_woman_tone4:", ":older_woman_tone5:", ":older_woman:", ":baby_tone1:", ":baby_tone2:", ":baby_tone3:", ":baby_tone4:", ":baby_tone5:", ":baby:", ":construction_worker_tone1:โโ๏ธ", ":construction_worker_tone1:โโ๏ธ", ":construction_worker_tone1:", ":construction_worker_tone2:โโ๏ธ", ":construction_worker_tone2:โโ๏ธ", ":construction_worker_tone2:", ":construction_worker_tone3:โโ๏ธ", ":construction_worker_tone3:โโ๏ธ", ":construction_worker_tone3:", ":construction_worker_tone4:โโ๏ธ", ":construction_worker_tone4:โโ๏ธ", ":construction_worker_tone4:", ":construction_worker_tone5:โโ๏ธ", ":construction_worker_tone5:โโ๏ธ", ":construction_worker_tone5:", ":construction_worker:โโ๏ธ", ":construction_worker:โโ๏ธ", ":construction_worker:", ":princess_tone1:", ":princess_tone2:", ":princess_tone3:", ":princess_tone4:", ":princess_tone5:", ":princess:", ":japanese_ogre:", ":japanese_goblin:", ":ghost:", ":angel_tone1:", ":angel_tone2:", ":angel_tone3:", ":angel_tone4:", ":angel_tone5:", ":angel:", ":alien:", ":space_invader:", ":imp:", ":skull:", ":information_desk_person_tone1:โโ๏ธ", ":information_desk_person_tone1:โโ๏ธ", ":information_desk_person_tone1:", ":information_desk_person_tone2:โโ๏ธ", ":information_desk_person_tone2:โโ๏ธ", ":information_desk_person_tone2:", ":information_desk_person_tone3:โโ๏ธ", ":information_desk_person_tone3:โโ๏ธ", ":information_desk_person_tone3:", ":information_desk_person_tone4:โโ๏ธ", ":information_desk_person_tone4:โโ๏ธ", ":information_desk_person_tone4:", ":information_desk_person_tone5:โโ๏ธ", ":information_desk_person_tone5:โโ๏ธ", ":information_desk_person_tone5:", ":information_desk_person:โโ๏ธ", ":information_desk_person:โโ๏ธ", ":information_desk_person:", ":guardsman_tone1:โโ๏ธ", ":guardsman_tone1:โโ๏ธ", ":guardsman_tone1:", ":guardsman_tone2:โโ๏ธ", ":guardsman_tone2:โโ๏ธ", ":guardsman_tone2:", ":guardsman_tone3:โโ๏ธ", ":guardsman_tone3:โโ๏ธ", ":guardsman_tone3:", ":guardsman_tone4:โโ๏ธ", ":guardsman_tone4:โโ๏ธ", ":guardsman_tone4:", ":guardsman_tone5:โโ๏ธ", ":guardsman_tone5:โโ๏ธ", ":guardsman_tone5:", ":guardsman:โโ๏ธ", ":guardsman:โโ๏ธ", ":guardsman:", ":dancer_tone1:", ":dancer_tone2:", ":dancer_tone3:", ":dancer_tone4:", ":dancer_tone5:", ":dancer:", ":lipstick:", ":nail_care_tone1:", ":nail_care_tone2:", ":nail_care_tone3:", ":nail_care_tone4:", ":nail_care_tone5:", ":nail_care:", ":massage_tone1:โโ๏ธ", ":massage_tone1:โโ๏ธ", ":massage_tone1:", ":massage_tone2:โโ๏ธ", ":massage_tone2:โโ๏ธ", ":massage_tone2:", ":massage_tone3:โโ๏ธ", ":massage_tone3:โโ๏ธ", ":massage_tone3:", ":massage_tone4:โโ๏ธ", ":massage_tone4:โโ๏ธ", ":massage_tone4:", ":massage_tone5:โโ๏ธ", ":massage_tone5:โโ๏ธ", ":massage_tone5:", ":massage:โโ๏ธ", ":massage:โโ๏ธ", ":massage:", ":haircut_tone1:โโ๏ธ", ":haircut_tone1:โโ๏ธ", ":haircut_tone1:", ":haircut_tone2:โโ๏ธ", ":haircut_tone2:โโ๏ธ", ":haircut_tone2:", ":haircut_tone3:โโ๏ธ", ":haircut_tone3:โโ๏ธ", ":haircut_tone3:", ":haircut_tone4:โโ๏ธ", ":haircut_tone4:โโ๏ธ", ":haircut_tone4:", ":haircut_tone5:โโ๏ธ", ":haircut_tone5:โโ๏ธ", ":haircut_tone5:", ":haircut:โโ๏ธ", ":haircut:โโ๏ธ", ":haircut:", ":barber:", ":syringe:", ":pill:", ":kiss:", ":love_letter:", ":ring:", ":gem:", ":couplekiss:", ":bouquet:", ":couple_with_heart:", ":wedding:", ":heartbeat:", ":broken_heart:", ":two_hearts:", ":sparkling_heart:", ":heartpulse:", ":cupid:", ":blue_heart:", ":green_heart:", ":yellow_heart:", ":purple_heart:", ":gift_heart:", ":revolving_hearts:", ":heart_decoration:", ":diamond_shape_with_a_dot_inside:", ":bulb:", ":anger:", ":bomb:", ":zzz:", ":boom:", ":sweat_drops:", ":droplet:", ":dash:", ":poop:", ":muscle_tone1:", ":muscle_tone2:", ":muscle_tone3:", ":muscle_tone4:", ":muscle_tone5:", ":muscle:", ":dizzy:", ":speech_balloon:", ":thought_balloon:", ":white_flower:", ":100:", ":moneybag:", ":currency_exchange:", ":heavy_dollar_sign:", ":credit_card:", ":yen:", ":dollar:", ":euro:", ":pound:", ":money_with_wings:", ":chart:", ":seat:", ":computer:", ":briefcase:", ":minidisc:", ":floppy_disk:", ":cd:", ":dvd:", ":file_folder:", ":open_file_folder:", ":page_with_curl:", ":page_facing_up:", ":date:", ":calendar:", ":card_index:", ":chart_with_upwards_trend:", ":chart_with_downwards_trend:", ":bar_chart:", ":clipboard:", ":pushpin:", ":round_pushpin:", ":paperclip:", ":straight_ruler:", ":triangular_ruler:", ":bookmark_tabs:", ":ledger:", ":notebook:", ":notebook_with_decorative_cover:", ":closed_book:", ":book:", ":green_book:", ":blue_book:", ":orange_book:", ":books:", ":name_badge:", ":scroll:", ":pencil:", ":telephone_receiver:", ":pager:", ":fax:", ":satellite:", ":loudspeaker:", ":mega:", ":outbox_tray:", ":inbox_tray:", ":package:", ":e-mail:", ":incoming_envelope:", ":envelope_with_arrow:", ":mailbox_closed:", ":mailbox:", ":mailbox_with_mail:", ":mailbox_with_no_mail:", ":postbox:", ":postal_horn:", ":newspaper:", ":iphone:", ":calling:", ":vibration_mode:", ":mobile_phone_off:", ":no_mobile_phones:", ":signal_strength:", ":camera:", ":camera_with_flash:", ":video_camera:", ":tv:", ":radio:", ":vhs:", ":projector:", ":prayer_beads:", ":twisted_rightwards_arrows:", ":repeat:", ":repeat_one:", ":arrows_clockwise:", ":arrows_counterclockwise:", ":low_brightness:", ":high_brightness:", ":mute:", ":speaker:", ":sound:", ":loud_sound:", ":battery:", ":electric_plug:", ":mag:", ":mag_right:", ":lock_with_ink_pen:", ":closed_lock_with_key:", ":key:", ":lock:", ":unlock:", ":bell:", ":no_bell:", ":bookmark:", ":link:", ":radio_button:", ":back:", ":end:", ":on:", ":soon:", ":top:", ":underage:", ":keycap_ten:", ":capital_abcd:", ":abcd:", ":1234:", ":symbols:", ":abc:", ":fire:", ":flashlight:", ":wrench:", ":hammer:", ":nut_and_bolt:", ":knife:", ":gun:", ":microscope:", ":telescope:", ":crystal_ball:", ":six_pointed_star:", ":beginner:", ":trident:", ":black_square_button:", ":white_square_button:", ":red_circle:", ":large_blue_circle:", ":large_orange_diamond:", ":large_blue_diamond:", ":small_orange_diamond:", ":small_blue_diamond:", ":small_red_triangle:", ":small_red_triangle_down:", ":arrow_up_small:", ":arrow_down_small:", ":om_symbol:", ":dove:", ":kaaba:", ":mosque:", ":synagogue:", ":menorah:", ":clock1:", ":clock2:", ":clock3:", ":clock4:", ":clock5:", ":clock6:", ":clock7:", ":clock8:", ":clock9:", ":clock10:", ":clock11:", ":clock12:", ":clock130:", ":clock230:", ":clock330:", ":clock430:", ":clock530:", ":clock630:", ":clock730:", ":clock830:", ":clock930:", ":clock1030:", ":clock1130:", ":clock1230:", ":candle:", ":clock:", ":hole:", ":levitate::tone1:", ":levitate::tone2:", ":levitate::tone3:", ":levitate::tone4:", ":levitate::tone5:", ":levitate:", ":spy_tone1:โโ๏ธ", ":spy_tone1:โโ๏ธ", ":spy_tone1:", ":spy_tone2:โโ๏ธ", ":spy_tone2:โโ๏ธ", ":spy_tone2:", ":spy_tone3:โโ๏ธ", ":spy_tone3:โโ๏ธ", ":spy_tone3:", ":spy_tone4:โโ๏ธ", ":spy_tone4:โโ๏ธ", ":spy_tone4:", ":spy_tone5:โโ๏ธ", ":spy_tone5:โโ๏ธ", ":spy_tone5:", ":spy:โโ๏ธ", ":spy:โโ๏ธ", ":spy:", ":dark_sunglasses:", ":spider:", ":spider_web:", ":joystick:", ":man_dancing_tone1:", ":man_dancing_tone2:", ":man_dancing_tone3:", ":man_dancing_tone4:", ":man_dancing_tone5:", ":man_dancing:", ":paperclips:", ":pen_ballpoint:", ":pen_fountain:", ":paintbrush:", ":crayon:", ":hand_splayed_tone1:", ":hand_splayed_tone2:", ":hand_splayed_tone3:", ":hand_splayed_tone4:", ":hand_splayed_tone5:", ":hand_splayed:", ":middle_finger_tone1:", ":middle_finger_tone2:", ":middle_finger_tone3:", ":middle_finger_tone4:", ":middle_finger_tone5:", ":middle_finger:", ":vulcan_tone1:", ":vulcan_tone2:", ":vulcan_tone3:", ":vulcan_tone4:", ":vulcan_tone5:", ":vulcan:", ":black_heart:", ":desktop:", ":printer:", ":mouse_three_button:", ":trackball:", ":frame_photo:", ":dividers:", ":card_box:", ":file_cabinet:", ":wastebasket:", ":notepad_spiral:", ":calendar_spiral:", ":compression:", ":key2:", ":newspaper2:", ":dagger:", ":speaking_head:", ":speech_left:", ":anger_right:", ":ballot_box:", ":map:", ":mount_fuji:", ":tokyo_tower:", ":statue_of_liberty:", ":japan:", ":moyai:", ":grinning:", ":grin:", ":joy:", ":smiley:", ":smile:", ":sweat_smile:", ":laughing:", ":innocent:", ":smiling_imp:", ":wink:", ":blush:", ":yum:", ":relieved:", ":heart_eyes:", ":sunglasses:", ":smirk:", ":neutral_face:", ":expressionless:", ":unamused:", ":sweat:", ":pensive:", ":confused:", ":confounded:", ":kissing:", ":kissing_heart:", ":kissing_smiling_eyes:", ":kissing_closed_eyes:", ":stuck_out_tongue:", ":stuck_out_tongue_winking_eye:", ":stuck_out_tongue_closed_eyes:", ":disappointed:", ":worried:", ":angry:", ":rage:", ":cry:", ":persevere:", ":triumph:", ":disappointed_relieved:", ":frowning:", ":anguished:", ":fearful:", ":weary:", ":sleepy:", ":tired_face:", ":grimacing:", ":sob:", ":open_mouth:", ":hushed:", ":cold_sweat:", ":scream:", ":astonished:", ":flushed:", ":sleeping:", ":dizzy_face:", ":no_mouth:", ":mask:", ":smile_cat:", ":joy_cat:", ":smiley_cat:", ":heart_eyes_cat:", ":smirk_cat:", ":kissing_cat:", ":pouting_cat:", ":crying_cat_face:", ":scream_cat:", ":slight_frown:", ":slight_smile:", ":upside_down:", ":rolling_eyes:", ":no_good_tone1:โโ๏ธ", ":no_good_tone1:โโ๏ธ", ":no_good_tone1:", ":no_good_tone2:โโ๏ธ", ":no_good_tone2:โโ๏ธ", ":no_good_tone2:", ":no_good_tone3:โโ๏ธ", ":no_good_tone3:โโ๏ธ", ":no_good_tone3:", ":no_good_tone4:โโ๏ธ", ":no_good_tone4:โโ๏ธ", ":no_good_tone4:", ":no_good_tone5:โโ๏ธ", ":no_good_tone5:โโ๏ธ", ":no_good_tone5:", ":no_good:โโ๏ธ", ":no_good:โโ๏ธ", ":no_good:", ":ok_woman_tone1:โโ๏ธ", ":ok_woman_tone1:โโ๏ธ", ":ok_woman_tone1:", ":ok_woman_tone2:โโ๏ธ", ":ok_woman_tone2:โโ๏ธ", ":ok_woman_tone2:", ":ok_woman_tone3:โโ๏ธ", ":ok_woman_tone3:โโ๏ธ", ":ok_woman_tone3:", ":ok_woman_tone4:โโ๏ธ", ":ok_woman_tone4:โโ๏ธ", ":ok_woman_tone4:", ":ok_woman_tone5:โโ๏ธ", ":ok_woman_tone5:โโ๏ธ", ":ok_woman_tone5:", ":ok_woman:โโ๏ธ", ":ok_woman:โโ๏ธ", ":ok_woman:", ":bow_tone1:โโ๏ธ", ":bow_tone1:โโ๏ธ", ":bow_tone1:", ":bow_tone2:โโ๏ธ", ":bow_tone2:โโ๏ธ", ":bow_tone2:", ":bow_tone3:โโ๏ธ", ":bow_tone3:โโ๏ธ", ":bow_tone3:", ":bow_tone4:โโ๏ธ", ":bow_tone4:โโ๏ธ", ":bow_tone4:", ":bow_tone5:โโ๏ธ", ":bow_tone5:โโ๏ธ", ":bow_tone5:", ":bow:โโ๏ธ", ":bow:โโ๏ธ", ":bow:", ":see_no_evil:", ":hear_no_evil:", ":speak_no_evil:", ":raising_hand_tone1:โโ๏ธ", ":raising_hand_tone1:โโ๏ธ", ":raising_hand_tone1:", ":raising_hand_tone2:โโ๏ธ", ":raising_hand_tone2:โโ๏ธ", ":raising_hand_tone2:", ":raising_hand_tone3:โโ๏ธ", ":raising_hand_tone3:โโ๏ธ", ":raising_hand_tone3:", ":raising_hand_tone4:โโ๏ธ", ":raising_hand_tone4:โโ๏ธ", ":raising_hand_tone4:", ":raising_hand_tone5:โโ๏ธ", ":raising_hand_tone5:โโ๏ธ", ":raising_hand_tone5:", ":raising_hand:โโ๏ธ", ":raising_hand:โโ๏ธ", ":raising_hand:", ":raised_hands_tone1:", ":raised_hands_tone2:", ":raised_hands_tone3:", ":raised_hands_tone4:", ":raised_hands_tone5:", ":raised_hands:", ":person_frowning_tone1:โโ๏ธ", ":person_frowning_tone1:โโ๏ธ", ":person_frowning_tone1:", ":person_frowning_tone2:โโ๏ธ", ":person_frowning_tone2:โโ๏ธ", ":person_frowning_tone2:", ":person_frowning_tone3:โโ๏ธ", ":person_frowning_tone3:โโ๏ธ", ":person_frowning_tone3:", ":person_frowning_tone4:โโ๏ธ", ":person_frowning_tone4:โโ๏ธ", ":person_frowning_tone4:", ":person_frowning_tone5:โโ๏ธ", ":person_frowning_tone5:โโ๏ธ", ":person_frowning_tone5:", ":person_frowning:โโ๏ธ", ":person_frowning:โโ๏ธ", ":person_frowning:", ":person_with_pouting_face_tone1:โโ๏ธ", ":person_with_pouting_face_tone1:โโ๏ธ", ":person_with_pouting_face_tone1:", ":person_with_pouting_face_tone2:โโ๏ธ", ":person_with_pouting_face_tone2:โโ๏ธ", ":person_with_pouting_face_tone2:", ":person_with_pouting_face_tone3:โโ๏ธ", ":person_with_pouting_face_tone3:โโ๏ธ", ":person_with_pouting_face_tone3:", ":person_with_pouting_face_tone4:โโ๏ธ", ":person_with_pouting_face_tone4:โโ๏ธ", ":person_with_pouting_face_tone4:", ":person_with_pouting_face_tone5:โโ๏ธ", ":person_with_pouting_face_tone5:โโ๏ธ", ":person_with_pouting_face_tone5:", ":person_with_pouting_face:โโ๏ธ", ":person_with_pouting_face:โโ๏ธ", ":person_with_pouting_face:", ":pray_tone1:", ":pray_tone2:", ":pray_tone3:", ":pray_tone4:", ":pray_tone5:", ":pray:", ":rocket:", ":helicopter:", ":steam_locomotive:", ":railway_car:", ":bullettrain_side:", ":bullettrain_front:", ":train2:", ":metro:", ":light_rail:", ":station:", ":tram:", ":train:", ":bus:", ":oncoming_bus:", ":trolleybus:", ":busstop:", ":minibus:", ":ambulance:", ":fire_engine:", ":police_car:", ":oncoming_police_car:", ":taxi:", ":oncoming_taxi:", ":red_car:", ":oncoming_automobile:", ":blue_car:", ":truck:", ":articulated_lorry:", ":tractor:", ":monorail:", ":mountain_railway:", ":suspension_railway:", ":mountain_cableway:", ":aerial_tramway:", ":ship:", ":rowboat_tone1:โโ๏ธ", ":rowboat_tone1:โโ๏ธ", ":rowboat_tone1:", ":rowboat_tone2:โโ๏ธ", ":rowboat_tone2:โโ๏ธ", ":rowboat_tone2:", ":rowboat_tone3:โโ๏ธ", ":rowboat_tone3:โโ๏ธ", ":rowboat_tone3:", ":rowboat_tone4:โโ๏ธ", ":rowboat_tone4:โโ๏ธ", ":rowboat_tone4:", ":rowboat_tone5:โโ๏ธ", ":rowboat_tone5:โโ๏ธ", ":rowboat_tone5:", ":rowboat:โโ๏ธ", ":rowboat:โโ๏ธ", ":rowboat:", ":speedboat:", ":traffic_light:", ":vertical_traffic_light:", ":construction:", ":rotating_light:", ":triangular_flag_on_post:", ":door:", ":no_entry_sign:", ":smoking:", ":no_smoking:", ":put_litter_in_its_place:", ":do_not_litter:", ":potable_water:", ":non-potable_water:", ":bike:", ":no_bicycles:", ":bicyclist_tone1:โโ๏ธ", ":bicyclist_tone1:โโ๏ธ", ":bicyclist_tone1:", ":bicyclist_tone2:โโ๏ธ", ":bicyclist_tone2:โโ๏ธ", ":bicyclist_tone2:", ":bicyclist_tone3:โโ๏ธ", ":bicyclist_tone3:โโ๏ธ", ":bicyclist_tone3:", ":bicyclist_tone4:โโ๏ธ", ":bicyclist_tone4:โโ๏ธ", ":bicyclist_tone4:", ":bicyclist_tone5:โโ๏ธ", ":bicyclist_tone5:โโ๏ธ", ":bicyclist_tone5:", ":bicyclist:โโ๏ธ", ":bicyclist:โโ๏ธ", ":bicyclist:", ":mountain_bicyclist_tone1:โโ๏ธ", ":mountain_bicyclist_tone1:โโ๏ธ", ":mountain_bicyclist_tone1:", ":mountain_bicyclist_tone2:โโ๏ธ", ":mountain_bicyclist_tone2:โโ๏ธ", ":mountain_bicyclist_tone2:", ":mountain_bicyclist_tone3:โโ๏ธ", ":mountain_bicyclist_tone3:โโ๏ธ", ":mountain_bicyclist_tone3:", ":mountain_bicyclist_tone4:โโ๏ธ", ":mountain_bicyclist_tone4:โโ๏ธ", ":mountain_bicyclist_tone4:", ":mountain_bicyclist_tone5:โโ๏ธ", ":mountain_bicyclist_tone5:โโ๏ธ", ":mountain_bicyclist_tone5:", ":mountain_bicyclist:โโ๏ธ", ":mountain_bicyclist:โโ๏ธ", ":mountain_bicyclist:", ":walking_tone1:โโ๏ธ", ":walking_tone1:โโ๏ธ", ":walking_tone1:", ":walking_tone2:โโ๏ธ", ":walking_tone2:โโ๏ธ", ":walking_tone2:", ":walking_tone3:โโ๏ธ", ":walking_tone3:โโ๏ธ", ":walking_tone3:", ":walking_tone4:โโ๏ธ", ":walking_tone4:โโ๏ธ", ":walking_tone4:", ":walking_tone5:โโ๏ธ", ":walking_tone5:โโ๏ธ", ":walking_tone5:", ":walking:โโ๏ธ", ":walking:โโ๏ธ", ":walking:", ":no_pedestrians:", ":children_crossing:", ":mens:", ":womens:", ":restroom:", ":baby_symbol:", ":toilet:", ":wc:", ":shower:", ":bath_tone1:", ":bath_tone2:", ":bath_tone3:", ":bath_tone4:", ":bath_tone5:", ":bath:", ":bathtub:", ":passport_control:", ":customs:", ":baggage_claim:", ":left_luggage:", ":couch:", ":sleeping_accommodation::tone1:", ":sleeping_accommodation::tone2:", ":sleeping_accommodation::tone3:", ":sleeping_accommodation::tone4:", ":sleeping_accommodation::tone5:", ":sleeping_accommodation:", ":shopping_bags:", ":bellhop:", ":bed:", ":place_of_worship:", ":octagonal_sign:", ":shopping_cart:", ":tools:", ":shield:", ":oil:", ":motorway:", ":railway_track:", ":motorboat:", ":airplane_small:", ":airplane_departure:", ":airplane_arriving:", ":satellite_orbital:", ":cruise_ship:", ":scooter:", ":motor_scooter:", ":canoe:", ":zipper_mouth:", ":money_mouth:", ":thermometer_face:", ":nerd:", ":thinking:", ":head_bandage:", ":robot:", ":hugging:", ":metal_tone1:", ":metal_tone2:", ":metal_tone3:", ":metal_tone4:", ":metal_tone5:", ":metal:", ":call_me_tone1:", ":call_me_tone2:", ":call_me_tone3:", ":call_me_tone4:", ":call_me_tone5:", ":call_me:", ":raised_back_of_hand_tone1:", ":raised_back_of_hand_tone2:", ":raised_back_of_hand_tone3:", ":raised_back_of_hand_tone4:", ":raised_back_of_hand_tone5:", ":raised_back_of_hand:", ":left_facing_fist_tone1:", ":left_facing_fist_tone2:", ":left_facing_fist_tone3:", ":left_facing_fist_tone4:", ":left_facing_fist_tone5:", ":left_facing_fist:", ":right_facing_fist_tone1:", ":right_facing_fist_tone2:", ":right_facing_fist_tone3:", ":right_facing_fist_tone4:", ":right_facing_fist_tone5:", ":right_facing_fist:", ":handshake_tone1:", ":handshake_tone2:", ":handshake_tone3:", ":handshake_tone4:", ":handshake_tone5:", ":handshake:", ":fingers_crossed_tone1:", ":fingers_crossed_tone2:", ":fingers_crossed_tone3:", ":fingers_crossed_tone4:", ":fingers_crossed_tone5:", ":fingers_crossed:", ":cowboy:", ":clown:", ":nauseated_face:", ":rofl:", ":drooling_face:", ":lying_face:", ":face_palm_tone1:โโ๏ธ", ":face_palm_tone1:โโ๏ธ", ":face_palm_tone1:", ":face_palm_tone2:โโ๏ธ", ":face_palm_tone2:โโ๏ธ", ":face_palm_tone2:", ":face_palm_tone3:โโ๏ธ", ":face_palm_tone3:โโ๏ธ", ":face_palm_tone3:", ":face_palm_tone4:โโ๏ธ", ":face_palm_tone4:โโ๏ธ", ":face_palm_tone4:", ":face_palm_tone5:โโ๏ธ", ":face_palm_tone5:โโ๏ธ", ":face_palm_tone5:", ":face_palm:โโ๏ธ", ":face_palm:โโ๏ธ", ":face_palm:", ":sneezing_face:", ":pregnant_woman_tone1:", ":pregnant_woman_tone2:", ":pregnant_woman_tone3:", ":pregnant_woman_tone4:", ":pregnant_woman_tone5:", ":pregnant_woman:", ":selfie_tone1:", ":selfie_tone2:", ":selfie_tone3:", ":selfie_tone4:", ":selfie_tone5:", ":selfie:", ":prince_tone1:", ":prince_tone2:", ":prince_tone3:", ":prince_tone4:", ":prince_tone5:", ":prince:", ":man_in_tuxedo_tone1:", ":man_in_tuxedo_tone2:", ":man_in_tuxedo_tone3:", ":man_in_tuxedo_tone4:", ":man_in_tuxedo_tone5:", ":man_in_tuxedo:", ":mrs_claus_tone1:", ":mrs_claus_tone2:", ":mrs_claus_tone3:", ":mrs_claus_tone4:", ":mrs_claus_tone5:", ":mrs_claus:", ":shrug_tone1:โโ๏ธ", ":shrug_tone1:โโ๏ธ", ":shrug_tone1:", ":shrug_tone2:โโ๏ธ", ":shrug_tone2:โโ๏ธ", ":shrug_tone2:", ":shrug_tone3:โโ๏ธ", ":shrug_tone3:โโ๏ธ", ":shrug_tone3:", ":shrug_tone4:โโ๏ธ", ":shrug_tone4:โโ๏ธ", ":shrug_tone4:", ":shrug_tone5:โโ๏ธ", ":shrug_tone5:โโ๏ธ", ":shrug_tone5:", ":shrug:โโ๏ธ", ":shrug:โโ๏ธ", ":shrug:", ":cartwheel_tone1:โโ๏ธ", ":cartwheel_tone1:โโ๏ธ", ":cartwheel_tone1:", ":cartwheel_tone2:โโ๏ธ", ":cartwheel_tone2:โโ๏ธ", ":cartwheel_tone2:", ":cartwheel_tone3:โโ๏ธ", ":cartwheel_tone3:โโ๏ธ", ":cartwheel_tone3:", ":cartwheel_tone4:โโ๏ธ", ":cartwheel_tone4:โโ๏ธ", ":cartwheel_tone4:", ":cartwheel_tone5:โโ๏ธ", ":cartwheel_tone5:โโ๏ธ", ":cartwheel_tone5:", ":cartwheel:โโ๏ธ", ":cartwheel:โโ๏ธ", ":cartwheel:", ":juggling_tone1:โโ๏ธ", ":juggling_tone1:โโ๏ธ", ":juggling_tone1:", ":juggling_tone2:โโ๏ธ", ":juggling_tone2:โโ๏ธ", ":juggling_tone2:", ":juggling_tone3:โโ๏ธ", ":juggling_tone3:โโ๏ธ", ":juggling_tone3:", ":juggling_tone4:โโ๏ธ", ":juggling_tone4:โโ๏ธ", ":juggling_tone4:", ":juggling_tone5:โโ๏ธ", ":juggling_tone5:โโ๏ธ", ":juggling_tone5:", ":juggling:โโ๏ธ", ":juggling:โโ๏ธ", ":juggling:", ":fencer:", ":wrestlers_tone1:โโ๏ธ", ":wrestlers_tone1:โโ๏ธ", ":wrestlers_tone1:", ":wrestlers_tone2:โโ๏ธ", ":wrestlers_tone2:โโ๏ธ", ":wrestlers_tone2:", ":wrestlers_tone3:โโ๏ธ", ":wrestlers_tone3:โโ๏ธ", ":wrestlers_tone3:", ":wrestlers_tone4:โโ๏ธ", ":wrestlers_tone4:โโ๏ธ", ":wrestlers_tone4:", ":wrestlers_tone5:โโ๏ธ", ":wrestlers_tone5:โโ๏ธ", ":wrestlers_tone5:", ":wrestlers:โโ๏ธ", ":wrestlers:โโ๏ธ", ":wrestlers:", ":water_polo_tone1:โโ๏ธ", ":water_polo_tone1:โโ๏ธ", ":water_polo_tone1:", ":water_polo_tone2:โโ๏ธ", ":water_polo_tone2:โโ๏ธ", ":water_polo_tone2:", ":water_polo_tone3:โโ๏ธ", ":water_polo_tone3:โโ๏ธ", ":water_polo_tone3:", ":water_polo_tone4:โโ๏ธ", ":water_polo_tone4:โโ๏ธ", ":water_polo_tone4:", ":water_polo_tone5:โโ๏ธ", ":water_polo_tone5:โโ๏ธ", ":water_polo_tone5:", ":water_polo:โโ๏ธ", ":water_polo:โโ๏ธ", ":water_polo:", ":handball_tone1:โโ๏ธ", ":handball_tone1:โโ๏ธ", ":handball_tone1:", ":handball_tone2:โโ๏ธ", ":handball_tone2:โโ๏ธ", ":handball_tone2:", ":handball_tone3:โโ๏ธ", ":handball_tone3:โโ๏ธ", ":handball_tone3:", ":handball_tone4:โโ๏ธ", ":handball_tone4:โโ๏ธ", ":handball_tone4:", ":handball_tone5:โโ๏ธ", ":handball_tone5:โโ๏ธ", ":handball_tone5:", ":handball:โโ๏ธ", ":handball:โโ๏ธ", ":handball:", ":wilted_rose:", ":drum:", ":champagne_glass:", ":tumbler_glass:", ":spoon:", ":goal:", ":first_place:", ":second_place:", ":third_place:", ":boxing_glove:", ":martial_arts_uniform:", ":croissant:", ":avocado:", ":cucumber:", ":bacon:", ":potato:", ":carrot:", ":french_bread:", ":salad:", ":shallow_pan_of_food:", ":stuffed_flatbread:", ":egg:", ":milk:", ":peanuts:", ":kiwi:", ":pancakes:", ":crab:", ":lion_face:", ":scorpion:", ":turkey:", ":unicorn:", ":eagle:", ":duck:", ":bat:", ":shark:", ":owl:", ":fox:", ":butterfly:", ":deer:", ":gorilla:", ":lizard:", ":rhino:", ":shrimp:", ":squid:", ":cheese:", ":bangbang:", ":interrobang:", ":tm:", ":information_source:", ":left_right_arrow:", ":arrow_up_down:", ":arrow_upper_left:", ":arrow_upper_right:", ":arrow_lower_right:", ":arrow_lower_left:", ":leftwards_arrow_with_hook:", ":arrow_right_hook:", ":hash:", ":watch:", ":hourglass:", ":keyboard:", ":eject:", ":fast_forward:", ":rewind:", ":arrow_double_up:", ":arrow_double_down:", ":track_next:", ":track_previous:", ":play_pause:", ":alarm_clock:", ":stopwatch:", ":timer:", ":hourglass_flowing_sand:", ":pause_button:", ":stop_button:", ":record_button:", ":m:", ":black_small_square:", ":white_small_square:", ":arrow_forward:", ":arrow_backward:", ":white_medium_square:", ":black_medium_square:", ":white_medium_small_square:", ":black_medium_small_square:", ":sunny:", ":cloud:", ":umbrella2:", ":snowman2:", ":comet:", ":telephone:", ":ballot_box_with_check:", ":umbrella:", ":coffee:", ":shamrock:", ":point_up_tone1:", ":point_up_tone2:", ":point_up_tone3:", ":point_up_tone4:", ":point_up_tone5:", ":point_up:", ":skull_crossbones:", ":radioactive:", ":biohazard:", ":orthodox_cross:", ":star_and_crescent:", ":peace:", ":yin_yang:", ":wheel_of_dharma:", ":frowning2:", ":relaxed:", "โ", "โ", ":aries:", ":taurus:", ":gemini:", ":cancer:", ":leo:", ":virgo:", ":libra:", ":scorpius:", ":sagittarius:", ":capricorn:", ":aquarius:", ":pisces:", ":spades:", ":clubs:", ":hearts:", ":diamonds:", ":hotsprings:", ":recycle:", ":wheelchair:", ":hammer_pick:", ":anchor:", ":crossed_swords:", "โ", ":scales:", ":alembic:", ":gear:", ":atom:", ":fleur-de-lis:", ":warning:", ":zap:", ":white_circle:", ":black_circle:", ":coffin:", ":urn:", ":soccer:", ":baseball:", ":snowman:", ":partly_sunny:", ":thunder_cloud_rain:", ":ophiuchus:", ":pick:", ":helmet_with_cross:", ":chains:", ":no_entry:", ":shinto_shrine:", ":church:", ":mountain:", ":beach_umbrella:", ":fountain:", ":golf:", ":ferry:", ":sailboat:", ":skier::tone1:", ":skier::tone2:", ":skier::tone3:", ":skier::tone4:", ":skier::tone5:", ":skier:", ":ice_skate:", ":basketball_player_tone1:โโ๏ธ", ":basketball_player_tone1:โโ๏ธ", ":basketball_player_tone1:", ":basketball_player_tone2:โโ๏ธ", ":basketball_player_tone2:โโ๏ธ", ":basketball_player_tone2:", ":basketball_player_tone3:โโ๏ธ", ":basketball_player_tone3:โโ๏ธ", ":basketball_player_tone3:", ":basketball_player_tone4:โโ๏ธ", ":basketball_player_tone4:โโ๏ธ", ":basketball_player_tone4:", ":basketball_player_tone5:โโ๏ธ", ":basketball_player_tone5:โโ๏ธ", ":basketball_player_tone5:", ":basketball_player:โโ๏ธ", ":basketball_player:โโ๏ธ", ":basketball_player:", ":tent:", ":fuelpump:", ":scissors:", ":white_check_mark:", ":airplane:", ":envelope:", ":fist_tone1:", ":fist_tone2:", ":fist_tone3:", ":fist_tone4:", ":fist_tone5:", ":fist:", ":raised_hand_tone1:", ":raised_hand_tone2:", ":raised_hand_tone3:", ":raised_hand_tone4:", ":raised_hand_tone5:", ":raised_hand:", ":v_tone1:", ":v_tone2:", ":v_tone3:", ":v_tone4:", ":v_tone5:", ":v:", ":writing_hand_tone1:", ":writing_hand_tone2:", ":writing_hand_tone3:", ":writing_hand_tone4:", ":writing_hand_tone5:", ":writing_hand:", ":pencil2:", ":black_nib:", ":heavy_check_mark:", ":heavy_multiplication_x:", ":cross:", ":star_of_david:", ":sparkles:", ":eight_spoked_asterisk:", ":eight_pointed_black_star:", ":snowflake:", ":sparkle:", ":x:", ":negative_squared_cross_mark:", ":question:", ":grey_question:", ":grey_exclamation:", ":exclamation:", ":heart_exclamation:", ":heart:", ":heavy_plus_sign:", ":heavy_minus_sign:", ":heavy_division_sign:", ":arrow_right:", ":curly_loop:", ":loop:", ":arrow_heading_up:", ":arrow_heading_down:", ":asterisk:", ":arrow_left:", ":arrow_up:", ":arrow_down:", ":black_large_square:", ":white_large_square:", ":star:", ":o:", ":zero:", ":wavy_dash:", ":part_alternation_mark:", ":one:", ":two:", ":congratulations:", ":secret:", ":three:", ":four:", ":five:", ":six:", ":seven:", ":eight:", ":nine:", ":copyright:", ":registered:", "๎"];
frappe.ui.emoji_map = function () {
var map = {};
for (var i = 0; i < frappe.ui.emojis.length; i++) {
map[frappe.ui.emoji_keywords[i]] = frappe.ui.emojis[i];
}
return map;
}();
frappe.provide('frappe.request');
frappe.request.url = '/';
frappe.request.ajax_count = 0;
frappe.request.waiting_for_ajax = [];
frappe.call = function (opts) {
if (opts.quiet) {
opts.no_spinner = true;
}
var args = $.extend({}, opts.args);
if (opts.module && opts.page) {
args.cmd = opts.module + '.page.' + opts.page + '.' + opts.page + '.' + opts.method;
} else if (opts.doc) {
$.extend(args, {
cmd: "runserverobj",
docs: frappe.get_doc(opts.doc.doctype, opts.doc.name),
method: opts.method,
args: opts.args
});
} else if (opts.method) {
args.cmd = opts.method;
}
var callback = function callback(data, response_text) {
if (data.task_id) {
frappe.socket.subscribe(data.task_id, opts);
if (opts.queued) {
opts.queued(data);
}
} else if (opts.callback) {
return opts.callback(data, response_text);
}
};
return frappe.request.call({
type: opts.type || "POST",
args: args,
success: callback,
error: opts.error,
always: opts.always,
btn: opts.btn,
freeze: opts.freeze,
freeze_message: opts.freeze_message,
async: opts.async,
url: opts.url || frappe.request.url
});
};
frappe.request.call = function (opts) {
frappe.request.prepare(opts);
var statusCode = {
200: function _(data, xhr) {
opts.success_callback && opts.success_callback(data, xhr.responseText);
},
401: function _(xhr) {
if (frappe.app.session_expired_dialog && frappe.app.session_expired_dialog.display) {
frappe.app.redirect_to_login();
} else {
frappe.app.handle_session_expired();
}
},
404: function _(xhr) {
frappe.msgprint({ title: __("Not found"), indicator: 'red',
message: __('The resource you are looking for is not available') });
},
403: function _(xhr) {
if (frappe.get_cookie('sid') === 'Guest') {
frappe.app.handle_session_expired();
} else if (xhr.responseJSON && xhr.responseJSON._error_message) {
frappe.msgprint({
title: __("Not permitted"), indicator: 'red',
message: xhr.responseJSON._error_message
});
xhr.responseJSON._server_messages = null;
} else if (xhr.responseJSON && xhr.responseJSON._server_messages) {
var _server_messages = JSON.parse(xhr.responseJSON._server_messages);
if (_server_messages.indexOf(__("Not permitted")) !== -1) {
return;
}
} else {
frappe.msgprint({
title: __("Not permitted"), indicator: 'red',
message: __('You do not have enough permissions to access this resource. Please contact your manager to get access.') });
}
},
508: function _(xhr) {
frappe.utils.play_sound("error");
frappe.msgprint({ title: __('Please try again'), indicator: 'red',
message: __("Another transaction is blocking this one. Please try again in a few seconds.") });
},
413: function _(data, xhr) {
frappe.msgprint({ indicator: 'red', title: __('File too big'), message: __("File size exceeded the maximum allowed size of {0} MB", [(frappe.boot.max_file_size || 5242880) / 1048576]) });
},
417: function _(xhr) {
var r = xhr.responseJSON;
if (!r) {
try {
r = JSON.parse(xhr.responseText);
} catch (e) {
r = xhr.responseText;
}
}
opts.error_callback && opts.error_callback(r);
},
501: function _(data, xhr) {
if (typeof data === "string") data = JSON.parse(data);
opts.error_callback && opts.error_callback(data, xhr.responseText);
},
500: function _(xhr) {
frappe.utils.play_sound("error");
frappe.msgprint({ message: __("Server Error: Please check your server logs or contact tech support."), title: __('Something went wrong'), indicator: 'red' });
opts.error_callback && opts.error_callback();
frappe.request.report_error(xhr, opts);
},
504: function _(xhr) {
frappe.msgprint(__("Request Timed Out"));
opts.error_callback && opts.error_callback();
}
};
var ajax_args = {
url: opts.url || frappe.request.url,
data: opts.args,
type: opts.type,
dataType: opts.dataType || 'json',
async: opts.async,
headers: { "X-Frappe-CSRF-Token": frappe.csrf_token },
cache: false
};
frappe.last_request = ajax_args.data;
return $.ajax(ajax_args).done(function (data, textStatus, xhr) {
try {
if (typeof data === "string") data = JSON.parse(data);
if (data.docs || data.docinfo) {
frappe.model.sync(data);
}
if (data.__messages) {
$.extend(frappe._messages, data.__messages);
}
var status_code_handler = statusCode[xhr.statusCode().status];
if (status_code_handler) {
status_code_handler(data, xhr);
}
} catch (e) {
console.log("Unable to handle success response");
console.trace(e);
}
}).always(function (data, textStatus, xhr) {
try {
if (typeof data === "string") {
data = JSON.parse(data);
}
if (data.responseText) {
var xhr = data;
data = JSON.parse(data.responseText);
}
} catch (e) {
data = null;
}
frappe.request.cleanup(opts, data);
if (opts.always) {
opts.always(data);
}
}).fail(function (xhr, textStatus) {
try {
var status_code_handler = statusCode[xhr.statusCode().status];
if (status_code_handler) {
status_code_handler(xhr);
} else {
opts.error_callback && opts.error_callback(xhr);
}
} catch (e) {
console.log("Unable to handle failed response");
console.trace(e);
}
});
};
frappe.request.prepare = function (opts) {
$("body").attr("data-ajax-state", "triggered");
if (opts.btn) $(opts.btn).prop("disabled", true);
if (opts.freeze) frappe.dom.freeze(opts.freeze_message);
for (var key in opts.args) {
if (opts.args[key] && ($.isPlainObject(opts.args[key]) || $.isArray(opts.args[key]))) {
opts.args[key] = JSON.stringify(opts.args[key]);
}
}
if (!opts.args.cmd && !opts.url) {
console.log(opts);
throw "Incomplete Request";
}
opts.success_callback = opts.success;
opts.error_callback = opts.error;
delete opts.success;
delete opts.error;
};
frappe.request.cleanup = function (opts, r) {
if (opts.btn) {
$(opts.btn).prop("disabled", false);
}
$("body").attr("data-ajax-state", "complete");
if (opts.freeze) frappe.dom.unfreeze();
if (r) {
if (r.session_expired || frappe.get_cookie("sid") === "Guest") {
frappe.app.handle_session_expired();
return;
}
if (r._server_messages && !opts.silent) {
r._server_messages = JSON.parse(r._server_messages);
frappe.hide_msgprint();
frappe.msgprint(r._server_messages);
}
if (r.exc) {
r.exc = JSON.parse(r.exc);
if (r.exc instanceof Array) {
$.each(r.exc, function (i, v) {
if (v) {
console.log(v);
}
});
} else {
console.log(r.exc);
}
}
if (r._debug_messages) {
if (opts.args) {
console.log("======== arguments ========");
console.log(opts.args);
console.log("========");
}
$.each(JSON.parse(r._debug_messages), function (i, v) {
console.log(v);
});
console.log("======== response ========");
delete r._debug_messages;
console.log(r);
console.log("========");
}
}
frappe.last_response = r;
};
frappe.after_server_call = function () {
if (frappe.request.ajax_count) {
return new Promise(function (resolve) {
frappe.request.waiting_for_ajax.push(function () {
resolve();
});
});
} else {
return null;
}
};
frappe.after_ajax = function (fn) {
return new Promise(function (resolve) {
if (frappe.request.ajax_count) {
frappe.request.waiting_for_ajax.push(function () {
if (fn) fn();
resolve();
});
} else {
if (fn) fn();
resolve();
}
});
};
frappe.request.report_error = function (xhr, request_opts) {
var data = JSON.parse(xhr.responseText);
if (data.exc) {
var exc = (JSON.parse(data.exc) || []).join("\n");
delete data.exc;
} else {
var exc = "";
}
if (exc) {
var error_report_email = (frappe.boot.error_report_email || []).join(", ");
var error_message = '';
request_opts = frappe.request.cleanup_request_opts(request_opts);
msg_dialog = frappe.msgprint({ message: error_message, indicator: 'red' });
msg_dialog.msg_area.find(".report-btn").toggle(error_report_email ? true : false).on("click", function () {
var error_report_message = ['Please type some additional information that could help us reproduce this issue: ', '
', ' ', 'App Versions ', '' + JSON.stringify(frappe.boot.versions, null, "\t") + ' ', 'Route ', '' + frappe.get_route_str() + ' ', ' ', 'Error Report ', '' + exc + ' ', ' ', 'Request Data ', '' + JSON.stringify(request_opts, null, "\t") + ' ', ' ', 'Response JSON ', '' + JSON.stringify(data, null, '\t') + ' '].join("\n");
var communication_composer = new frappe.views.CommunicationComposer({
subject: 'Error Report [' + frappe.datetime.nowdate() + ']',
recipients: error_report_email,
message: error_report_message,
doc: {
doctype: "User",
name: frappe.session.user
}
});
communication_composer.dialog.$wrapper.css("z-index", cint(msg_dialog.$wrapper.css("z-index")) + 1);
});
}
};
frappe.request.cleanup_request_opts = function (request_opts) {
var doc = (request_opts.args || {}).doc;
if (doc) {
doc = JSON.parse(doc);
$.each(Object.keys(doc), function (i, key) {
if (key.indexOf("password") !== -1 && doc[key]) {
doc[key] = "*****";
}
});
request_opts.args.doc = JSON.stringify(doc);
}
return request_opts;
};
$(document).ajaxSend(function () {
frappe.request.ajax_count++;
});
$(document).ajaxComplete(function () {
frappe.request.ajax_count--;
if (!frappe.request.ajax_count) {
$.each(frappe.request.waiting_for_ajax || [], function (i, fn) {
fn();
});
frappe.request.waiting_for_ajax = [];
}
});
frappe.socket = {
open_tasks: {},
open_docs: [],
emit_queue: [],
init: function init() {
if (frappe.boot.disable_async) {
return;
}
if (frappe.socket.socket) {
return;
}
if (frappe.boot.developer_mode) {
frappe.socket.setup_file_watchers();
}
if (window.location.protocol == "https:") {
frappe.socket.socket = io.connect(frappe.socket.get_host(), { secure: true });
} else if (window.location.protocol == "http:") {
frappe.socket.socket = io.connect(frappe.socket.get_host());
} else if (window.location.protocol == "file:") {
frappe.socket.socket = io.connect(window.localStorage.server);
}
if (!frappe.socket.socket) {
console.log("Unable to connect to " + frappe.socket.get_host());
return;
}
frappe.socket.socket.on('msgprint', function (message) {
frappe.msgprint(message);
});
frappe.socket.socket.on('eval_js', function (message) {
eval(message);
});
frappe.socket.socket.on('progress', function (data) {
if (data.progress) {
data.percent = flt(data.progress[0]) / data.progress[1] * 100;
}
if (data.percent) {
if (data.percent == 100) {
frappe.hide_progress();
} else {
frappe.show_progress(data.title || __("Progress"), data.percent, 100);
}
}
});
frappe.socket.setup_listeners();
frappe.socket.setup_reconnect();
$(document).on('form-load form-rename', function (e, frm) {
if (frm.is_new()) {
return;
}
for (var i = 0, l = frappe.socket.open_docs.length; i < l; i++) {
var d = frappe.socket.open_docs[i];
if (frm.doctype == d.doctype && frm.docname == d.name) {
return false;
}
}
frappe.socket.doc_subscribe(frm.doctype, frm.docname);
});
$(document).on("form_refresh", function (e, frm) {
if (frm.is_new()) {
return;
}
frappe.socket.doc_open(frm.doctype, frm.docname);
});
$(document).on('form-unload', function (e, frm) {
if (frm.is_new()) {
return;
}
frappe.socket.doc_close(frm.doctype, frm.docname);
});
window.onbeforeunload = function () {
if (!cur_frm || cur_frm.is_new()) {
return;
}
if (cur_frm.doc) {
frappe.socket.doc_close(cur_frm.doctype, cur_frm.docname);
}
};
},
get_host: function get_host() {
var host = window.location.origin;
if (window.dev_server) {
var parts = host.split(":");
var port = frappe.boot.socketio_port || '3000';
if (parts.length > 2) {
host = parts[0] + ":" + parts[1];
}
host = host + ":" + port;
}
return host;
},
subscribe: function subscribe(task_id, opts) {
frappe.socket.socket.emit('task_subscribe', task_id);
frappe.socket.socket.emit('progress_subscribe', task_id);
frappe.socket.open_tasks[task_id] = opts;
},
task_subscribe: function task_subscribe(task_id) {
frappe.socket.socket.emit('task_subscribe', task_id);
},
task_unsubscribe: function task_unsubscribe(task_id) {
frappe.socket.socket.emit('task_unsubscribe', task_id);
},
doc_subscribe: function doc_subscribe(doctype, docname) {
if (frappe.flags.doc_subscribe) {
console.log('throttled');
return;
}
frappe.flags.doc_subscribe = true;
setTimeout(function () {
frappe.flags.doc_subscribe = false;
}, 1000);
frappe.socket.socket.emit('doc_subscribe', doctype, docname);
frappe.socket.open_docs.push({ doctype: doctype, docname: docname });
},
doc_unsubscribe: function doc_unsubscribe(doctype, docname) {
frappe.socket.socket.emit('doc_unsubscribe', doctype, docname);
frappe.socket.open_docs = $.filter(frappe.socket.open_docs, function (d) {
if (d.doctype === doctype && d.name === docname) {
return null;
} else {
return d;
}
});
},
doc_open: function doc_open(doctype, docname) {
if (!frappe.socket.last_doc || frappe.socket.last_doc[0] != doctype && frappe.socket.last_doc[0] != docname) {
frappe.socket.socket.emit('doc_open', doctype, docname);
}
frappe.socket.last_doc = [doctype, docname];
},
doc_close: function doc_close(doctype, docname) {
frappe.socket.socket.emit('doc_close', doctype, docname);
},
setup_listeners: function setup_listeners() {
frappe.socket.socket.on('task_status_change', function (data) {
frappe.socket.process_response(data, data.status.toLowerCase());
});
frappe.socket.socket.on('task_progress', function (data) {
frappe.socket.process_response(data, "progress");
});
},
setup_reconnect: function setup_reconnect() {
frappe.socket.socket.on("connect", function () {
setTimeout(function () {
$.each(frappe.socket.open_tasks, function (task_id, opts) {
frappe.socket.subscribe(task_id, opts);
});
$.each(frappe.socket.open_docs, function (d) {
if (locals[d.doctype] && locals[d.doctype][d.name]) {
frappe.socket.doc_subscribe(d.doctype, d.name);
}
});
if (cur_frm && cur_frm.doc) {
frappe.socket.doc_open(cur_frm.doc.doctype, cur_frm.doc.name);
}
}, 5000);
});
},
setup_file_watchers: function setup_file_watchers() {
var host = window.location.origin;
if (!window.dev_server) {
return;
}
var port = frappe.boot.file_watcher_port || 6787;
var parts = host.split(":");
if (parts.length > 2) {
host = host.split(':').slice(0, -1).join(":");
}
host = host + ':' + port;
frappe.socket.file_watcher = io.connect(host);
frappe.socket.file_watcher.on('reload_css', function (filename) {
var abs_file_path = "assets/" + filename;
var link = $("link[href*=\"" + abs_file_path + "\"]");
abs_file_path = abs_file_path.split('?')[0] + '?v=' + moment();
link.attr('href', abs_file_path);
frappe.show_alert({
indicator: 'orange',
message: filename + ' reloaded'
}, 5);
});
frappe.socket.file_watcher.on('reload_js', function (filename) {
filename = "assets/" + filename;
var msg = $("\n\t\t\t\t" + filename + " changed Click to Reload \n\t\t\t");
msg.find('a').click(frappe.ui.toolbar.clear_cache);
frappe.show_alert({
indicator: 'orange',
message: msg
}, 5);
});
},
process_response: function process_response(data, method) {
if (!data) {
return;
}
var opts = frappe.socket.open_tasks[data.task_id];
if (opts[method]) {
opts[method](data);
}
if (method === "success") {
if (opts.callback) opts.callback(data);
}
frappe.request.cleanup(opts, data);
if (opts.always) {
opts.always(data);
}
if (data.status_code && data.status_code > 400 && opts.error) {
opts.error(data);
}
}
};
frappe.provide("frappe.realtime");
frappe.realtime.on = function (event, callback) {
frappe.socket.socket && frappe.socket.socket.on(event, callback);
};
frappe.realtime.off = function (event, callback) {
frappe.socket.socket && frappe.socket.socket.off(event, callback);
};
frappe.realtime.publish = function (event, message) {
if (frappe.socket.socket) {
frappe.socket.socket.emit(event, message);
}
};
frappe.re_route = { "#login": "" };
frappe.route_titles = {};
frappe.route_flags = {};
frappe.route_history = [];
frappe.view_factory = {};
frappe.view_factories = [];
frappe.route_options = null;
frappe.route = function () {
if (frappe.re_route[window.location.hash] !== undefined) {
var re_route_val = frappe.get_route_str(frappe.re_route[window.location.hash]);
var cur_route_val = frappe.get_route_str(frappe._cur_route);
if (decodeURIComponent(re_route_val) === decodeURIComponent(cur_route_val)) {
window.history.back();
return;
} else {
window.location.hash = frappe.re_route[window.location.hash];
}
}
frappe._cur_route = window.location.hash;
var route = frappe.get_route();
if (route === false) {
return;
}
frappe.route_history.push(route);
if (route[0] && route[1] && frappe.views[route[0] + "Factory"]) {
if (!frappe.view_factory[route[0]]) {
frappe.view_factory[route[0]] = new frappe.views[route[0] + "Factory"]();
}
frappe.view_factory[route[0]].show();
} else {
frappe.views.pageview.show(route[0]);
}
if (frappe.route_titles[window.location.hash]) {
frappe.utils.set_title(frappe.route_titles[window.location.hash]);
} else {
setTimeout(function () {
frappe.route_titles[frappe.get_route_str()] = frappe._original_title || document.title;
}, 1000);
}
if (window.mixpanel) {
window.mixpanel.track(route.slice(0, 2).join(' '));
}
};
frappe.get_route = function (route) {
var route = frappe.get_raw_route_str(route).split('/');
route = $.map(route, frappe._decode_str);
var parts = route[route.length - 1].split("?");
route[route.length - 1] = frappe._decode_str(parts[0]);
if (parts.length > 1) {
var query_params = get_query_params(parts[1]);
frappe.route_options = $.extend(frappe.route_options || {}, query_params);
}
if (route && route[0] === 'Module') {
frappe.set_route('modules', route[1]);
return false;
}
return route;
};
frappe.get_prev_route = function () {
if (frappe.route_history && frappe.route_history.length > 1) {
return frappe.route_history[frappe.route_history.length - 2];
} else {
return [];
}
};
frappe._decode_str = function (r) {
try {
return decodeURIComponent(r);
} catch (e) {
if (e instanceof URIError) {
return r;
} else {
throw e;
}
}
};
frappe.get_raw_route_str = function (route) {
if (!route) route = window.location.hash;
if (route.substr(0, 1) == '#') route = route.substr(1);
if (route.substr(0, 1) == '!') route = route.substr(1);
return route;
};
frappe.get_route_str = function (route) {
var rawRoute = frappe.get_raw_route_str();
route = $.map(rawRoute.split('/'), frappe._decode_str).join('/');
return route;
};
frappe.set_route = function () {
var _arguments = arguments;
return new Promise(function (resolve) {
var params = _arguments;
if (params.length === 1 && $.isArray(params[0])) {
params = params[0];
}
var route = $.map(params, function (a) {
if ($.isPlainObject(a)) {
frappe.route_options = a;
return null;
} else {
return a;
}
}).join('/');
window.location.hash = route;
frappe.app.set_favicon && frappe.app.set_favicon();
setTimeout(function () {
frappe.after_ajax(function () {
resolve();
});
}, 100);
});
};
frappe.set_re_route = function () {
var tmp = window.location.hash;
frappe.set_route.apply(null, arguments);
frappe.re_route[tmp] = window.location.hash;
};
frappe._cur_route = null;
$(window).on('hashchange', function () {
frappe.route_titles[frappe._cur_route] = frappe._original_title || document.title;
if (window.location.hash == frappe._cur_route) return;
if (cur_dialog && cur_dialog.hide_on_page_refresh) {
cur_dialog.hide();
}
frappe.route();
});
frappe.defaults = {
get_user_default: function get_user_default(key) {
var defaults = frappe.boot.user.defaults;
var d = defaults[key];
if (!d && frappe.defaults.is_a_user_permission_key(key)) d = defaults[frappe.model.scrub(key)];
if ($.isArray(d)) d = d[0];
return d;
},
get_user_defaults: function get_user_defaults(key) {
var defaults = frappe.boot.user.defaults;
var d = defaults[key];
if (frappe.defaults.is_a_user_permission_key(key)) {
if (d && $.isArray(d) && d.length === 1) {
d = d[0];
} else {
d = defaults[key] || defaults[frappe.model.scrub(key)];
}
}
if (!$.isArray(d)) d = [d];
return d;
},
get_global_default: function get_global_default(key) {
var d = frappe.sys_defaults[key];
if ($.isArray(d)) d = d[0];
return d;
},
get_global_defaults: function get_global_defaults(key) {
var d = frappe.sys_defaults[key];
if (!$.isArray(d)) d = [d];
return d;
},
set_default: function set_default(key, value, callback) {
if (typeof value !== "string") value = JSON.stringify(value);
frappe.boot.user.defaults[key] = value;
return frappe.call({
method: "frappe.client.set_default",
args: {
key: key,
value: value
},
callback: callback || function (r) {}
});
},
set_user_default_local: function set_user_default_local(key, value) {
frappe.boot.user.defaults[key] = value;
},
get_default: function get_default(key) {
var defaults = frappe.boot.user.defaults;
var value = defaults[key];
if (frappe.defaults.is_a_user_permission_key(key)) {
if (value && $.isArray(value) && value.length === 1) {
value = value[0];
} else {
value = defaults[frappe.model.scrub(key)];
}
}
if (value) {
try {
return JSON.parse(value);
} catch (e) {
return value;
}
}
},
is_a_user_permission_key: function is_a_user_permission_key(key) {
return key.indexOf(":") === -1 && key !== frappe.model.scrub(key);
},
get_user_permissions: function get_user_permissions() {
return frappe.boot.user_permissions;
}
};
frappe.CheckboxEditor = Class.extend({
init: function init(opts) {
$.extend(this, opts);
this.doctype = this.field_mapper.cdt;
this.fieldname = this.field_mapper.child_table_field;
this.item_fieldname = this.field_mapper.item_field;
$(this.wrapper).html('' + __("Loading") + '...
');
if (this.get_items) {
this.get_items();
}
},
render_items: function render_items(callback) {
var me = this;
$(this.wrapper).empty();
if (this.checkbox_selector) {
var toolbar = $(' \
').appendTo($(this.wrapper));
toolbar.find(".btn-add").html(__(this.add_btn_label)).on("click", function () {
$(me.wrapper).find('input[type="checkbox"]').each(function (i, check) {
if (!$(check).is(":checked")) {
check.checked = true;
}
});
});
toolbar.find(".btn-remove").html(__(this.remove_btn_label)).on("click", function () {
$(me.wrapper).find('input[type="checkbox"]').each(function (i, check) {
if ($(check).is(":checked")) {
check.checked = false;
}
});
});
}
$.each(this.items, function (i, item) {
$(me.wrapper).append(frappe.render(me.editor_template, { 'item': item }));
});
$(this.wrapper).find('input[type="checkbox"]').change(function () {
if (me.fieldname && me.doctype && me.item_field) {
me.set_items_in_table();
me.frm.dirty();
}
});
callback && callback();
},
show: function show() {
var me = this;
$(this.wrapper).find('input[type="checkbox"]').each(function (i, checkbox) {
checkbox.checked = false;
});
$.each(me.frm.doc[this.fieldname] || [], function (i, row) {
var selector = repl('[%(attribute)s="%(value)s"] input[type="checkbox"]', {
attribute: me.attribute,
value: row[me.item_fieldname]
});
var checkbox = $(me.wrapper).find(selector).get(0);
if (checkbox) checkbox.checked = true;
});
},
get_selected_unselected_items: function get_selected_unselected_items() {
var checked_items = [];
var unchecked_items = [];
var selector = repl('[%(attribute)s]', { attribute: this.attribute });
var me = this;
$(this.wrapper).find(selector).each(function () {
if ($(this).find('input[type="checkbox"]:checked').length) {
checked_items.push($(this).attr(me.attribute));
} else {
unchecked_items.push($(this).attr(me.attribute));
}
});
return {
checked_items: checked_items,
unchecked_items: unchecked_items
};
},
set_items_in_table: function set_items_in_table() {
var opts = this.get_selected_unselected_items();
var existing_items_map = {};
var existing_items_list = [];
var me = this;
$.each(me.frm.doc[this.fieldname] || [], function (i, row) {
existing_items_map[row[me.item_fieldname]] = row.name;
existing_items_list.push(row[me.item_fieldname]);
});
$.each(opts.unchecked_items, function (i, item) {
if (existing_items_list.indexOf(item) != -1) {
frappe.model.clear_doc(me.doctype, existing_items_map[item]);
}
});
$.each(opts.checked_items, function (i, item) {
if (existing_items_list.indexOf(item) == -1) {
var row = frappe.model.add_child(me.frm.doc, me.doctype, me.fieldname);
row[me.item_fieldname] = item;
}
});
refresh_field(this.fieldname);
}
});
frappe.RoleEditor = Class.extend({
init: function init(wrapper, frm) {
var me = this;
this.frm = frm;
this.wrapper = wrapper;
$(wrapper).html('' + __("Loading") + '...
');
return frappe.call({
method: 'frappe.core.doctype.user.user.get_all_roles',
callback: function callback(r) {
me.roles = r.message;
me.show_roles();
if (me.frm.doc) {
me.frm.roles_editor.show();
}
}
});
},
show_roles: function show_roles() {
var me = this;
$(this.wrapper).empty();
var role_toolbar = $(' \
').appendTo($(this.wrapper));
role_toolbar.find(".btn-add").html(__('Add all roles')).on("click", function () {
$(me.wrapper).find('input[type="checkbox"]').each(function (i, check) {
if (!$(check).is(":checked")) {
check.checked = true;
}
});
});
role_toolbar.find(".btn-remove").html(__('Clear all roles')).on("click", function () {
$(me.wrapper).find('input[type="checkbox"]').each(function (i, check) {
if ($(check).is(":checked")) {
check.checked = false;
}
});
});
$.each(this.roles, function (i, role) {
$(me.wrapper).append(repl('', { role_value: role, role_display: __(role) }));
});
$(this.wrapper).find('input[type="checkbox"]').change(function () {
me.set_roles_in_table();
me.frm.dirty();
});
$(this.wrapper).find('.user-role a').click(function () {
me.show_permissions($(this).parent().attr('data-user-role'));
return false;
});
},
show: function show() {
var me = this;
$(this.wrapper).find('input[type="checkbox"]').each(function (i, checkbox) {
checkbox.checked = false;
});
$.each(me.frm.doc.roles || [], function (i, user_role) {
var checkbox = $(me.wrapper).find('[data-user-role="' + user_role.role + '"] input[type="checkbox"]').get(0);
if (checkbox) checkbox.checked = true;
});
},
set_roles_in_table: function set_roles_in_table() {
var opts = this.get_roles();
var existing_roles_map = {};
var existing_roles_list = [];
var me = this;
$.each(me.frm.doc.roles || [], function (i, user_role) {
existing_roles_map[user_role.role] = user_role.name;
existing_roles_list.push(user_role.role);
});
$.each(opts.unchecked_roles, function (i, role) {
if (existing_roles_list.indexOf(role) != -1) {
frappe.model.clear_doc("Has Role", existing_roles_map[role]);
}
});
$.each(opts.checked_roles, function (i, role) {
if (existing_roles_list.indexOf(role) == -1) {
var user_role = frappe.model.add_child(me.frm.doc, "Has Role", "roles");
user_role.role = role;
}
});
refresh_field("roles");
},
get_roles: function get_roles() {
var checked_roles = [];
var unchecked_roles = [];
$(this.wrapper).find('[data-user-role]').each(function () {
if ($(this).find('input[type="checkbox"]:checked').length) {
checked_roles.push($(this).attr('data-user-role'));
} else {
unchecked_roles.push($(this).attr('data-user-role'));
}
});
return {
checked_roles: checked_roles,
unchecked_roles: unchecked_roles
};
},
show_permissions: function show_permissions(role) {
var me = this;
if (!this.perm_dialog) this.make_perm_dialog();
$(this.perm_dialog.body).empty();
return frappe.call({
method: 'frappe.core.doctype.user.user.get_perm_info',
args: { role: role },
callback: function callback(r) {
var $body = $(me.perm_dialog.body);
$body.append('' + '' + __('Document Type') + ' ' + '' + __('Level') + ' ' + '' + __('Apply User Permissions') + ' ' + '' + __('Read') + ' ' + '' + __('Write') + ' ' + '' + __('Create') + ' ' + '' + __('Delete') + ' ' + '' + __('Submit') + ' ' + '' + __('Cancel') + ' ' + '' + __('Amend') + ' ' + '' + __('Set User Permissions') + ' ' + '
');
for (var i = 0, l = r.message.length; i < l; i++) {
var perm = r.message[i];
for (var key in perm) {
if (key != 'parent' && key != 'permlevel') {
if (perm[key]) {
perm[key] = ' ';
} else {
perm[key] = '';
}
}
}
$body.find('tbody').append(repl('\
%(parent)s \
%(permlevel)s \
%(apply_user_permissions)s \
%(read)s \
%(write)s \
%(create)s \
%(delete)s \
%(submit)s \
%(cancel)s \
%(amend)s ' + '%(set_user_permissions)s \
', perm));
}
me.perm_dialog.show();
}
});
},
make_perm_dialog: function make_perm_dialog() {
this.perm_dialog = new frappe.ui.Dialog({
title: __('Role Permissions')
});
this.perm_dialog.$wrapper.find('.modal-dialog').css("width", "800px");
}
});// Simple JavaScript Templating
// Adapted from John Resig - http://ejohn.org/ - MIT Licensed
frappe.template = {compiled: {}, debug:{}};
frappe.template.compile = function(str, name) {
var key = name || str;
if(!frappe.template.compiled[key]) {
if(str.indexOf("'")!==-1) {
str.replace(/'/g, "\\'");
//console.warn("Warning: Single quotes (') may not work in templates");
}
// replace jinja style tags
str = str.replace(/{{/g, "{%=").replace(/}}/g, "%}");
// {% if not test %} --> {% if (!test) { %}
str = str.replace(/{%\s?if\s?\s?not\s?([^\(][^%{]+)\s?%}/g, "{% if (! $1) { %}")
// {% if test %} --> {% if (test) { %}
str = str.replace(/{%\s?if\s?([^\(][^%{]+)\s?%}/g, "{% if ($1) { %}");
// {% for item in list %}
// --> {% for (var i=0, len=list.length; i {% } %}
str = str.replace(/{%\s?endif\s?%}/g, "{% }; %}");
// {% else %} --> {% } else { %}
str = str.replace(/{%\s?else\s?%}/g, "{% } else { %}");
// {% endif %} --> {% } %}
str = str.replace(/{%\s?endfor\s?%}/g, "{% }; %}");
fn_str = "var _p=[],print=function(){_p.push.apply(_p,arguments)};" +
// Introduce the data as local variables using with(){}
"with(obj){\n_p.push('" +
// Convert the template into pure JavaScript
str
.replace(/[\r\t\n]/g, " ")
.split("{%").join("\t")
.replace(/((^|%})[^\t]*)'/g, "$1\r")
.replace(/\t=(.*?)%}/g, "',$1,'")
.split("\t").join("');\n")
.split("%}").join("\n_p.push('")
.split("\r").join("\\'")
+ "');}return _p.join('');";
frappe.template.debug[name] = fn_str;
try {
frappe.template.compiled[key] = new Function("obj", fn_str);
} catch (e) {
console.log("Error in Template:");
console.log(fn_str);
if(e.lineNumber) {
console.log("Error in Line "+e.lineNumber+", Col "+e.columnNumber+":");
console.log(fn_str.split("\n")[e.lineNumber - 1]);
}
}
}
return frappe.template.compiled[key];
};
frappe.render = function(str, data, name) {
return frappe.template.compile(str, name)(data);
};
frappe.render_template = function(name, data) {
if(name.indexOf(' ')!==-1) {
var template = name;
} else {
var template = frappe.templates[name];
}
if(data===undefined) {
data = {};
}
return frappe.render(template, data, name);
}
frappe.render_grid = function(opts) {
// build context
if(opts.grid) {
opts.columns = opts.grid.getColumns();
if(opts.report) {
opts.data = frappe.slickgrid_tools.get_filtered_items(opts.report.dataView);
} else if(opts.grid) {
opts.data = opts.grid.getData().getItems();
}
} else {
opts.columns = [];
}
// show landscape view if columns more than 10
if (opts.columns && opts.columns.length > 10) {
opts.landscape = true;
} else {
opts.landscape = false;
}
// render content
if(!opts.content) {
opts.content = frappe.render_template("print_grid", opts);
}
// render HTML wrapper page
opts.base_url = frappe.urllib.get_base_url();
opts.print_css = frappe.boot.print_css;
var html = frappe.render_template("print_template", opts);
var w = window.open();
if(!w) {
frappe.msgprint(__("Please enable pop-ups in your browser"))
}
w.document.write(html);
w.document.close();
}
frappe.provide('frappe.desk.form');
frappe.provide('frappe.desk.report');
frappe.provide('frappe.utils');
frappe.provide('frappe.model');
frappe.provide('frappe.user');
frappe.provide('frappe.session');
frappe.provide('locals');
frappe.provide('locals.DocType');
frappe.provide("frappe.listview_settings");
frappe.provide("frappe.listview_parent_route");
frappe.settings.no_history = 1;
var NEWLINE = '\n';
var TAB = 9;
var UP_ARROW = 38;
var DOWN_ARROW = 40;
var _f = {};
var _p = {};
var _r = {};
var frms = {};
var cur_frm = null;
frappe.utils.full_name = function (fn, ln) {
return fn + (ln ? ' ' : '') + (ln ? ln : '');
};
function fmt_money(v, format) {
return format_currency(v, format);
}
function toTitle(str) {
var word_in = str.split(" ");
var word_out = [];
for (var w in word_in) {
word_out[w] = word_in[w].charAt(0).toUpperCase() + word_in[w].slice(1);
}
return word_out.join(" ");
}
function is_null(v) {
if (v === null || v === undefined || cstr(v).trim() === "") return true;
}
function set_value_in(ele, v, ftype, fopt, doc) {
$(ele).html(frappe.format(v, { fieldtype: ftype, options: fopt }, null, doc));
return;
}
var $s = set_value_in;
function copy_dict(d) {
var n = {};
for (var k in d) {
n[k] = d[k];
}return n;
}
function replace_newlines(t) {
return t ? t.replace(/\n/g, ' ') : '';
}
function validate_email(txt) {
return frappe.utils.validate_type(txt, "email");
}
function validate_spl_chars(txt) {
return frappe.utils.validate_type(txt, "alphanum");
}
function cstr(s) {
if (s == null) return '';
return s + '';
}
function nth(number) {
number = cint(number);
var s = 'th';
if ((number + '').substr(-1) == '1') s = 'st';
if ((number + '').substr(-1) == '2') s = 'nd';
if ((number + '').substr(-1) == '3') s = 'rd';
return number + s;
}
function esc_quotes(s) {
if (s == null) s = '';
return s.replace(/'/, "\'");
}
var crop = function crop(s, len) {
if (s.length > len) return s.substr(0, len - 3) + '...';else return s;
};
function has_words(list, item) {
if (!item) return true;
if (!list) return false;
for (var i = 0, j = list.length; i < j; i++) {
if (item.indexOf(list[i]) != -1) return true;
}
return false;
}
function has_common(list1, list2) {
if (!list1 || !list2) return false;
for (var i = 0, j = list1.length; i < j; i++) {
if (in_list(list2, list1[i])) return true;
}
return false;
}
function add_lists(l1, l2) {
return [].concat(l1).concat(l2);
}
function docstring(obj) {
return JSON.stringify(obj);
}
function remove_from_list(list, val) {
if (list.indexOf(val) !== -1) {
list.splice(list.indexOf(val), 1);
}
return list;
}
function empty_select(s) {
if (s.custom_select) {
s.empty();return;
}
if (s.inp) s = s.inp;
if (s) {
var tmplen = s.length;for (var i = 0; i < tmplen; i++) {
s.options[0] = null;
}
}
}
function sel_val(s) {
if (s.custom_select) {
return s.inp.value ? s.inp.value : '';
}
if (s.inp) s = s.inp;
try {
if (s.selectedIndex < s.options.length) return s.options[s.selectedIndex].value;else return '';
} catch (err) {
return '';
}
}
var $n = '\n';
function $a(parent, newtag, className, cs, innerHTML, onclick) {
if (parent && parent.substr) parent = $i(parent);
var c = document.createElement(newtag);
if (parent) parent.appendChild(c);
if (className) {
if (newtag.toLowerCase() == 'img') c.src = className;else c.className = className;
}
if (cs) $y(c, cs);
if (innerHTML) c.innerHTML = innerHTML;
if (onclick) c.onclick = onclick;
return c;
}
function $dh(d) {
if (d && d.substr) d = $i(d);
if (d && d.style.display.toLowerCase() != 'none') d.style.display = 'none';
}
function $ds(d) {
if (d && d.substr) d = $i(d);
var t = 'block';
if (d && in_list(['span', 'img', 'button'], d.tagName.toLowerCase())) t = 'inline';
if (d && d.style.display.toLowerCase() != t) d.style.display = t;
}
function $di(d) {
if (d && d.substr) d = $i(d);if (d) d.style.display = 'inline';
}
function $i(id) {
if (!id) return null;
if (id && id.appendChild) return id;
return document.getElementById(id);
}
function $w(e, w) {
if (e && e.style && w) e.style.width = w;
}
function $h(e, h) {
if (e && e.style && h) e.style.height = h;
}
function $bg(e, w) {
if (e && e.style && w) e.style.backgroundColor = w;
}
function $y(ele, s) {
if (ele && s) {
for (var i in s) {
ele.style[i] = s[i];
}
}
return ele;
}
function make_table(parent, nr, nc, table_width, widths, cell_style, table_style) {
var t = $a(parent, 'table');
t.style.borderCollapse = 'collapse';
if (table_width) t.style.width = table_width;
if (cell_style) t.cell_style = cell_style;
for (var ri = 0; ri < nr; ri++) {
var r = t.insertRow(ri);
for (var ci = 0; ci < nc; ci++) {
var c = r.insertCell(ci);
if (ri == 0 && widths && widths[ci]) {
c.style.width = widths[ci];
}
if (cell_style) {
for (var s in cell_style) {
c.style[s] = cell_style[s];
}
}
}
}
t.append_row = function () {
return append_row(this);
};
if (table_style) $y(t, table_style);
return t;
}
function append_row(t, at, style) {
var r = t.insertRow(at ? at : t.rows.length);
if (t.rows.length > 1) {
for (var i = 0; i < t.rows[0].cells.length; i++) {
var c = r.insertCell(i);
if (style) $y(c, style);
}
}
return r;
}
function $td(t, r, c) {
if (r < 0) r = t.rows.length + r;
if (c < 0) c = t.rows[0].cells.length + c;
return t.rows[r].cells[c];
}
frappe.urllib = {
get_arg: function get_arg(name) {
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regexS = "[\\?&]" + name + "=([^]*)";
var regex = new RegExp(regexS);
var results = regex.exec(window.location.href);
if (results == null) return "";else return decodeURIComponent(results[1]);
},
get_dict: function get_dict() {
var d = {};
var t = window.location.href.split('?')[1];
if (!t) return d;
if (t.indexOf('#') != -1) t = t.split('#')[0];
if (!t) return d;
t = t.split('&');
for (var i = 0; i < t.length; i++) {
var a = t[i].split('=');
d[decodeURIComponent(a[0])] = decodeURIComponent(a[1]);
}
return d;
},
get_base_url: function get_base_url() {
var url = frappe.base_url || window.location.origin;
if (url.substr(url.length - 1, 1) == '/') url = url.substr(0, url.length - 1);
return url;
},
get_full_url: function get_full_url(url) {
if (url.indexOf("http://") === 0 || url.indexOf("https://") === 0) {
return url;
}
return url.substr(0, 1) === "/" ? frappe.urllib.get_base_url() + url : frappe.urllib.get_base_url() + "/" + url;
}
};
window.get_url_arg = frappe.urllib.get_arg;
window.get_url_dict = frappe.urllib.get_dict;
function $c(command, args, callback, error, no_spinner, freeze_msg, btn) {
console.warn("This function '$c' has been deprecated and will be removed soon.");
return frappe.request.call({
type: "POST",
args: $.extend(args, { cmd: command }),
success: callback,
error: error,
btn: btn,
freeze: freeze_msg,
show_spinner: !no_spinner
});
}
function $c_obj(doc, method, arg, callback, no_spinner, freeze_msg, btn) {
console.warn("This function '$c_obj' has been deprecated and will be removed soon.");
if (arg && typeof arg != 'string') arg = JSON.stringify(arg);
var args = {
cmd: 'runserverobj',
args: arg,
method: method
};
if (typeof doc == 'string') {
args.doctype = doc;
} else {
args.docs = doc;
}
return frappe.request.call({
type: "POST",
args: args,
success: callback,
btn: btn,
freeze: freeze_msg,
show_spinner: !no_spinner
});
}
function $c_obj_csv(doc, method, arg) {
console.warn("This function '$c_obj_csv' has been deprecated and will be removed soon.");
var args = {};
args.cmd = 'runserverobj';
args.as_csv = 1;
args.method = method;
args.arg = arg;
if (doc.substr) args.doctype = doc;else args.docs = doc;
open_url_post(frappe.request.url, args);
}
function open_url_post(URL, PARAMS, new_window) {
var temp = document.createElement("form");
temp.action = URL;
temp.method = "POST";
temp.style.display = "none";
if (new_window) {
temp.target = '_blank';
}
PARAMS["csrf_token"] = frappe.csrf_token;
for (var x in PARAMS) {
var opt = document.createElement("textarea");
opt.name = x;
var val = PARAMS[x];
if (typeof val != 'string') val = JSON.stringify(val);
opt.value = val;
temp.appendChild(opt);
}
document.body.appendChild(temp);
temp.submit();
return temp;
}frappe.templates['page'] = ' ## items selected {%= __("Actions") %}
';
frappe.ui.make_app_page = function (opts) {
opts.parent.page = new frappe.ui.Page(opts);
return opts.parent.page;
};
frappe.ui.pages = {};
frappe.ui.Page = Class.extend({
init: function init(opts) {
$.extend(this, opts);
this.set_document_title = true;
this.buttons = {};
this.fields_dict = {};
this.views = {};
this.make();
frappe.ui.pages[frappe.get_route_str()] = this;
},
make: function make() {
this.wrapper = $(this.parent);
$(frappe.render_template("page", {})).appendTo(this.wrapper);
if (this.single_column) {
this.add_view("main", '');
} else {
var main = this.add_view("main", '');
}
this.$title_area = this.wrapper.find("h1");
this.$sub_title_area = this.wrapper.find("h6");
if (this.set_document_title !== undefined) this.set_document_title = this.set_document_title;
if (this.title) this.set_title(this.title);
if (this.icon) this.get_main_icon(this.icon);
this.body = this.main = this.wrapper.find(".layout-main-section");
this.sidebar = this.wrapper.find(".layout-side-section");
this.footer = this.wrapper.find(".layout-footer");
this.indicator = this.wrapper.find(".indicator");
this.page_actions = this.wrapper.find(".page-actions");
this.btn_primary = this.page_actions.find(".primary-action");
this.btn_secondary = this.page_actions.find(".btn-secondary");
this.menu = this.page_actions.find(".menu-btn-group .dropdown-menu");
this.menu_btn_group = this.page_actions.find(".menu-btn-group");
this.actions = this.page_actions.find(".actions-btn-group .dropdown-menu");
this.actions_btn_group = this.page_actions.find(".actions-btn-group");
this.page_form = $('
').prependTo(this.main);
this.inner_toolbar = $('
').prependTo(this.main);
this.icon_group = this.page_actions.find(".page-icon-group");
},
set_indicator: function set_indicator(label, color) {
this.clear_indicator().removeClass("hide").html("" + label + " ").addClass(color);
},
add_action_icon: function add_action_icon(icon, click) {
return $(' ').appendTo(this.icon_group.removeClass("hide")).click(click);
},
clear_indicator: function clear_indicator() {
return this.indicator.removeClass().addClass("indicator hide");
},
get_icon_label: function get_icon_label(icon, label) {
return '' + label + ' ';
},
set_action: function set_action(btn, opts) {
var me = this;
if (opts.icon) {
opts.label = this.get_icon_label(opts.icon, opts.label);
}
this.clear_action_of(btn);
btn.removeClass("hide").prop("disabled", false).html(opts.label).on("click", function () {
var response = opts.click.apply(this);
me.btn_disable_enable(btn, response);
});
if (opts.working_label) {
btn.attr("data-working-label", opts.working_label);
}
},
set_primary_action: function set_primary_action(label, click, icon, working_label) {
this.set_action(this.btn_primary, {
label: label,
click: click,
icon: icon,
working_label: working_label
});
return this.btn_primary;
},
set_secondary_action: function set_secondary_action(label, click, icon, working_label) {
this.set_action(this.btn_secondary, {
label: label,
click: click,
icon: icon,
working_label: working_label
});
return this.btn_secondary;
},
clear_action_of: function clear_action_of(btn) {
btn.addClass("hide").unbind("click").removeAttr("data-working-label");
},
clear_primary_action: function clear_primary_action() {
this.clear_action_of(this.btn_primary);
},
clear_secondary_action: function clear_secondary_action() {
this.clear_action_of(this.btn_secondary);
},
clear_actions: function clear_actions() {
this.clear_primary_action();
this.clear_secondary_action();
},
clear_icons: function clear_icons() {
this.icon_group.addClass("hide").empty();
},
add_menu_item: function add_menu_item(label, click, standard) {
return this.add_dropdown_item(label, click, standard, this.menu);
},
clear_menu: function clear_menu() {
this.clear_btn_group(this.menu);
},
show_menu: function show_menu() {
this.menu_btn_group.removeClass("hide");
},
hide_menu: function hide_menu() {
this.menu_btn_group.addClass("hide");
},
show_icon_group: function show_icon_group() {
this.icon_group.removeClass("hide");
},
hide_icon_group: function hide_icon_group() {
this.icon_group.addClass("hide");
},
add_action_item: function add_action_item(label, click, standard) {
return this.add_dropdown_item(label, click, standard, this.actions);
},
clear_actions_menu: function clear_actions_menu() {
this.clear_btn_group(this.actions);
},
add_dropdown_item: function add_dropdown_item(label, click, standard, parent) {
parent.parent().removeClass("hide");
var $li = $('' + label + ' '),
$link = $li.find("a").on("click", click);
if (standard === true) {
$li.appendTo(parent);
} else {
this.divider = parent.find(".divider");
if (!this.divider.length) {
this.divider = $(' ').prependTo(parent);
}
$li.addClass("user-action").insertBefore(this.divider);
}
return $link;
},
clear_btn_group: function clear_btn_group(parent) {
parent.empty();
parent.parent().addClass("hide");
},
add_divider: function add_divider() {
return $(' ').appendTo(this.menu);
},
get_inner_group_button: function get_inner_group_button(label) {
var $group = this.inner_toolbar.find('.btn-group[data-label="' + label + '"]');
if (!$group.length) {
$group = $('\
\
' + label + ' \
').appendTo(this.inner_toolbar.removeClass("hide"));
}
return $group;
},
set_inner_btn_group_as_primary: function set_inner_btn_group_as_primary(label) {
this.get_inner_group_button(label).find("button").removeClass("btn-default").addClass("btn-primary");
},
btn_disable_enable: function btn_disable_enable(btn, response) {
if (response && response.then) {
btn.prop('disabled', true);
response.then(function () {
btn.prop('disabled', false);
});
} else if (response && response.always) {
btn.prop('disabled', true);
response.always(function () {
btn.prop('disabled', false);
});
}
},
add_inner_button: function add_inner_button(label, action, group) {
var me = this;
var _action = function _action() {
var btn = $(this);
var response = action();
me.btn_disable_enable(btn, response);
};
if (group) {
var $group = this.get_inner_group_button(group);
return $('' + label + ' ').on('click', _action).appendTo($group.find(".dropdown-menu"));
} else {
return $('' + __(label) + '').on("click", _action).appendTo(this.inner_toolbar.removeClass("hide"));
}
},
clear_inner_toolbar: function clear_inner_toolbar() {
this.inner_toolbar.empty().addClass("hide");
},
add_sidebar_item: function add_sidebar_item(label, action, insert_after, prepend) {
var parent = this.sidebar.find(".sidebar-menu.standard-actions");
var li = $('');
var link = $('').html(label).on("click", action).appendTo(li);
if (insert_after) {
li.insertAfter(parent.find(insert_after));
} else {
if (prepend) {
li.prependTo(parent);
} else {
li.appendTo(parent);
}
}
return link;
},
clear_user_actions: function clear_user_actions() {
this.menu.find(".user-action").remove();
},
get_title_area: function get_title_area() {
return this.$title_area;
},
set_title: function set_title(txt, icon) {
if (!txt) txt = "";
txt = strip_html(txt);
this.title = txt;
frappe.utils.set_title(txt);
if (icon) {
txt = ' ' + txt;
}
this.$title_area.find(".title-text").html(txt);
},
set_title_sub: function set_title_sub(txt) {
this.$sub_title_area.html(txt).toggleClass("hide", !!!txt);
},
get_main_icon: function get_main_icon(icon) {
return this.$title_area.find(".title-icon").html(' ').toggle(true);
},
add_help_button: function add_help_button(txt) {},
add_button: function add_button(label, click, icon, is_title) {},
add_dropdown_button: function add_dropdown_button(parent, label, click, icon) {
frappe.ui.toolbar.add_dropdown_button(parent, label, click, icon);
},
add_label: function add_label(label) {
this.show_form();
return $("" + label + " ").appendTo(this.page_form);
},
add_select: function add_select(label, options) {
var field = this.add_field({ label: label, fieldtype: "Select" });
return field.$wrapper.find("select").empty().add_options(options);
},
add_data: function add_data(label) {
var field = this.add_field({ label: label, fieldtype: "Data" });
return field.$wrapper.find("input").attr("placeholder", label);
},
add_date: function add_date(label, date) {
var field = this.add_field({ label: label, fieldtype: "Date", "default": date });
return field.$wrapper.find("input").attr("placeholder", label);
},
add_check: function add_check(label) {
return $(" " + label + "
").appendTo(this.page_form).find("input");
},
add_break: function add_break() {
this.page_form.append('
');
},
add_field: function add_field(df) {
this.show_form();
var f = frappe.ui.form.make_control({
df: df,
parent: this.page_form,
only_input: df.fieldtype == "Check" ? false : true
});
f.refresh();
$(f.wrapper).addClass('col-md-2').attr("title", __(df.label)).tooltip();
if (!f.$input) f.make_input();
f.$input.addClass("input-sm").attr("placeholder", __(df.label));
if (df.fieldtype === "Check") {
$(f.wrapper).find(":first-child").removeClass("col-md-offset-4 col-md-8");
}
if (df.fieldtype == "Button") {
$(f.wrapper).find(".page-control-label").html(" ");
f.$input.addClass("btn-sm").css({ "width": "100%", "margin-top": "-1px" });
}
if (df["default"]) f.set_input(df["default"]);
this.fields_dict[df.fieldname || df.label] = f;
return f;
},
show_form: function show_form() {
this.page_form.removeClass("hide");
},
get_form_values: function get_form_values() {
var values = {};
this.page_form.fields_dict.forEach(function (field, key) {
values[key] = field.get_value();
});
return values;
},
add_view: function add_view(name, html) {
this.views[name] = $(html).appendTo($(this.wrapper).find(".page-content"));
if (!this.current_view) {
this.current_view = this.views[name];
} else {
this.views[name].toggle(false);
}
return this.views[name];
},
set_view: function set_view(name) {
if (this.current_view_name === name) return;
this.current_view && this.current_view.toggle(false);
this.current_view = this.views[name];
this.previous_view_name = this.current_view_name;
this.current_view_name = name;
this.views[name].toggle(true);
this.wrapper.trigger('view-change');
}
});
frappe.ui.scroll = function (element, animate, additional_offset) {
var header_offset = $(".navbar").height() + $(".page-head").height();
var top = $(element).offset().top - header_offset - cint(additional_offset);
if (animate) {
$("html, body").animate({ scrollTop: top });
} else {
$(window).scrollTop(top);
}
};
frappe.find = {
page_primary_action: function page_primary_action() {
return $('.page-actions:visible .btn-primary');
},
field: function field(fieldname, value) {
return new Promise(function (resolve) {
var input = $('[data-fieldname="' + fieldname + '"] :input');
if (value) {
input.val(value).trigger('change');
frappe.after_ajax(function () {
resolve(input);
});
} else {
resolve(input);
}
});
}
};
frappe.ui.IconBar = Class.extend({
init: function init(parent, n_groups) {
this.parent = parent;
this.buttons = {};
this.make(n_groups);
},
make: function make(n_groups) {
this.$wrapper = $('
').appendTo(this.parent);
for (var i = 0; i < n_groups; i++) {
this.get_group(i + 1);
}
},
get_group: function get_group(group) {
var $ul = this.$wrapper.find(".iconbar-" + group + " ul");
if (!$ul.length) $ul = $('').appendTo(this.$wrapper).find("ul");
return $ul;
},
add_btn: function add_btn(group, icon, label, click) {
var $ul = this.get_group(group);
var $li = $(' ').appendTo($ul).on("click", function () {
click.apply(this);
return false;
});
$li.find("i").attr("title", label).tooltip();
this.$wrapper.find(".iconbar-" + group).removeClass("hide");
this.show();
return $li;
},
hide: function hide(group) {
if (group) {
this.$wrapper.find(".iconbar-" + group).addClass("hide");
this.check_if_all_hidden();
} else {
this.$wrapper.addClass("hide").trigger("hidden");
}
},
show: function show(group) {
if (group) {
this.$wrapper.find(".iconbar-" + group).removeClass("hide");
this.show();
} else {
if (this.$wrapper.hasClass("hide")) this.$wrapper.removeClass("hide").trigger("shown");
}
},
clear: function clear(group) {
var me = this;
this.$wrapper.find(".iconbar-" + group).addClass("hide").find("ul").empty();
this.check_if_all_hidden();
},
check_if_all_hidden: function check_if_all_hidden() {
if (!this.$wrapper.find(".iconbar:visible").length) {
this.hide();
}
}
});
frappe.provide("frappe.ui.form");
frappe.ui.form.Layout = Class.extend({
init: function init(opts) {
this.views = {};
this.pages = [];
this.sections = [];
this.fields_list = [];
this.fields_dict = {};
$.extend(this, opts);
},
make: function make() {
if (!this.parent && this.body) {
this.parent = this.body;
}
this.wrapper = $('').appendTo(this.parent);
this.message = $('
').appendTo(this.wrapper);
if (!this.fields) {
this.fields = frappe.meta.sort_docfields(frappe.meta.docfield_map[this.doctype]);
}
this.setup_tabbing();
this.render();
},
show_empty_form_message: function show_empty_form_message() {
if (!(this.wrapper.find(".frappe-control:visible").length || this.wrapper.find(".section-head.collapsed").length)) {
this.show_message(__("This form does not have any input"));
}
},
show_message: function show_message(html) {
if (html) {
if (html.substr(0, 1) !== '<') {
html = '
' + html + '
';
}
$(html).appendTo(this.message.removeClass('hidden'));
} else {
this.message.empty().addClass('hidden');
}
},
render: function render(new_fields) {
var me = this;
var fields = new_fields || this.fields;
this.section = null;
this.column = null;
if (this.with_dashboard) {
this.setup_dashboard_section();
}
if (this.no_opening_section()) {
this.make_section();
}
$.each(fields, function (i, df) {
switch (df.fieldtype) {
case "Fold":
me.make_page(df);
break;
case "Section Break":
me.make_section(df);
break;
case "Column Break":
me.make_column(df);
break;
default:
me.make_field(df);
}
});
},
no_opening_section: function no_opening_section() {
return this.fields[0] && this.fields[0].fieldtype != "Section Break" || !this.fields.length;
},
setup_dashboard_section: function setup_dashboard_section() {
if (this.no_opening_section()) {
this.fields.unshift({ fieldtype: 'Section Break' });
}
this.fields.unshift({
fieldtype: 'Section Break',
fieldname: '_form_dashboard',
label: __('Dashboard'),
cssClass: 'form-dashboard',
collapsible: 1
});
},
make_field: function make_field(df, colspan) {
var render = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
!this.section && this.make_section();
!this.column && this.make_column();
var fieldobj = frappe.ui.form.make_control({
df: df,
doctype: this.doctype,
parent: this.column.wrapper.get(0),
frm: this.frm,
render_input: render
});
fieldobj.layout = this;
this.fields_list.push(fieldobj);
this.fields_dict[df.fieldname] = fieldobj;
if (this.frm) {
fieldobj.perm = this.frm.perm;
}
this.section.fields_list.push(fieldobj);
this.section.fields_dict[df.fieldname] = fieldobj;
},
make_page: function make_page(df) {
var me = this,
head = $('
').appendTo(this.wrapper);
this.page = $('
').appendTo(this.wrapper);
this.fold_btn = head.find(".btn-fold").on("click", function () {
var page = $(this).parent().next();
if (page.hasClass("hide")) {
$(this).removeClass("btn-fold").html(__("Hide details"));
page.removeClass("hide");
frappe.utils.scroll_to($(this), true, 30);
me.folded = false;
} else {
$(this).addClass("btn-fold").html(__("Show more details"));
page.addClass("hide");
me.folded = true;
}
});
this.section = null;
this.folded = true;
},
unfold: function unfold() {
this.fold_btn.trigger('click');
},
make_section: function make_section(df) {
this.section = new frappe.ui.form.Section(this, df);
if (df) {
this.fields_dict[df.fieldname] = this.section;
this.fields_list.push(this.section);
}
this.column = null;
},
make_column: function make_column(df) {
this.column = new frappe.ui.form.Column(this.section, df);
if (df && df.fieldname) {
this.fields_list.push(this.column);
}
},
refresh: function refresh(doc) {
var me = this;
if (doc) this.doc = doc;
if (this.frm) {
this.wrapper.find(".empty-form-alert").remove();
}
me.attach_doc_and_docfields(true);
if (this.frm && this.frm.wrapper) {
$(this.frm.wrapper).trigger("refresh-fields");
}
this.refresh_dependency();
this.refresh_sections();
if (this.frm) {
this.refresh_section_collapse();
}
},
refresh_sections: function refresh_sections() {
var cnt = 0;
this.wrapper.find(".form-section:not(.hide-control)").each(function () {
var $this = $(this).removeClass("empty-section").removeClass("visible-section").removeClass("shaded-section");
if (!$this.find(".frappe-control:not(.hide-control)").length && !$this.hasClass('form-dashboard')) {
$this.addClass("empty-section");
} else {
$this.addClass("visible-section");
if (cnt % 2) {
$this.addClass("shaded-section");
}
cnt++;
}
});
},
refresh_section_collapse: function refresh_section_collapse() {
if (!this.doc) return;
for (var i = 0; i < this.sections.length; i++) {
var section = this.sections[i];
var df = section.df;
if (df && df.collapsible) {
var collapse = true;
if (df.collapsible_depends_on) {
collapse = !this.evaluate_depends_on_value(df.collapsible_depends_on);
}
if (collapse && section.has_missing_mandatory()) {
collapse = false;
}
if (df.fieldname === '_form_dashboard') {
collapse = false;
}
section.collapse(collapse);
}
}
},
attach_doc_and_docfields: function attach_doc_and_docfields(refresh) {
var me = this;
for (var i = 0, l = this.fields_list.length; i < l; i++) {
var fieldobj = this.fields_list[i];
if (me.doc) {
fieldobj.doc = me.doc;
fieldobj.doctype = me.doc.doctype;
fieldobj.docname = me.doc.name;
fieldobj.df = frappe.meta.get_docfield(me.doc.doctype, fieldobj.df.fieldname, me.frm ? me.frm.doc.name : me.doc.name) || fieldobj.df;
if (me.frm) {
fieldobj.perm = me.frm.perm;
}
}
refresh && fieldobj.refresh && fieldobj.refresh();
}
},
refresh_section_count: function refresh_section_count() {
this.wrapper.find(".section-count-label:visible").each(function (i) {
$(this).html(i + 1);
});
},
setup_tabbing: function setup_tabbing() {
var me = this;
this.wrapper.on("keydown", function (ev) {
if (ev.which == 9) {
var current = $(ev.target),
doctype = current.attr("data-doctype"),
fieldname = current.attr("data-fieldname");
if (doctype) return me.handle_tab(doctype, fieldname, ev.shiftKey);
}
});
},
handle_tab: function handle_tab(doctype, fieldname, shift) {
var me = this,
grid_row = null,
prev = null,
fields = me.fields_list,
in_grid = false,
focused = false;
if (doctype != me.doctype) {
grid_row = me.get_open_grid_row();
if (!grid_row || !grid_row.layout) {
return;
}
fields = grid_row.layout.fields_list;
}
for (var i = 0, len = fields.length; i < len; i++) {
if (fields[i].df.fieldname == fieldname) {
if (shift) {
if (prev) {
this.set_focus(prev);
} else {
$(this.primary_button).focus();
}
break;
}
if (i < len - 1) {
focused = me.focus_on_next_field(i, fields);
}
if (focused) {
break;
}
}
if (this.is_visible(fields[i])) prev = fields[i];
}
if (!focused) {
if (grid_row) {
if (grid_row.doc.idx == grid_row.grid.grid_rows.length) {
grid_row.toggle_view(false, function () {
grid_row.grid.frm.layout.handle_tab(grid_row.grid.df.parent, grid_row.grid.df.fieldname);
});
} else {
grid_row.grid.grid_rows[grid_row.doc.idx].toggle_view(true);
}
} else {
$(this.primary_button).focus();
}
}
return false;
},
focus_on_next_field: function focus_on_next_field(start_idx, fields) {
for (var i = start_idx + 1, len = fields.length; i < len; i++) {
var field = fields[i];
if (this.is_visible(field)) {
if (field.df.fieldtype === "Table") {
if (!(field.grid.grid_rows && field.grid.grid_rows.length)) {
field.grid.add_new_row();
}
field.grid.grid_rows[0].show_form();
return true;
} else if (!in_list(frappe.model.no_value_type, field.df.fieldtype)) {
this.set_focus(field);
return true;
}
}
}
},
is_visible: function is_visible(field) {
return field.disp_status === "Write" && field.$wrapper && field.$wrapper.is(":visible");
},
set_focus: function set_focus(field) {
if (field.df.fieldtype == "Table") {
if (!field.grid.grid_rows.length) {
field.grid.add_new_row(1);
} else {
field.grid.grid_rows[0].toggle_view(true);
}
} else if (field.editor) {
field.editor.set_focus();
} else if (field.$input) {
field.$input.focus();
}
},
get_open_grid_row: function get_open_grid_row() {
return $(".grid-row-open").data("grid_row");
},
refresh_dependency: function refresh_dependency() {
var me = this;
var has_dep = false;
for (var fkey in this.fields_list) {
var f = this.fields_list[fkey];
f.dependencies_clear = true;
if (f.df.depends_on) {
has_dep = true;
}
}
if (!has_dep) return;
for (var i = me.fields_list.length - 1; i >= 0; i--) {
var f = me.fields_list[i];
f.guardian_has_value = true;
if (f.df.depends_on) {
f.guardian_has_value = this.evaluate_depends_on_value(f.df.depends_on);
if (f.guardian_has_value) {
if (f.df.hidden_due_to_dependency) {
f.df.hidden_due_to_dependency = false;
f.refresh();
}
} else {
if (!f.df.hidden_due_to_dependency) {
f.df.hidden_due_to_dependency = true;
f.refresh();
}
}
}
}
this.refresh_section_count();
},
evaluate_depends_on_value: function evaluate_depends_on_value(expression) {
var out = null;
var doc = this.doc;
if (!doc && this.get_values) {
var doc = this.get_values(true);
}
if (!doc) {
return;
}
var parent = this.frm ? this.frm.doc : null;
if (expression.substr(0, 5) == 'eval:') {
out = eval(expression.substr(5));
} else if (expression.substr(0, 3) == 'fn:' && this.frm) {
out = this.frm.script_manager.trigger(expression.substr(3), this.doctype, this.docname);
} else {
var value = doc[expression];
if ($.isArray(value)) {
out = !!value.length;
} else {
out = !!value;
}
}
return out;
}
});
frappe.ui.form.Section = Class.extend({
init: function init(layout, df) {
var me = this;
this.layout = layout;
this.df = df || {};
this.fields_list = [];
this.fields_dict = {};
this.make();
this.row = {
wrapper: this.wrapper
};
if (this.df.collapsible) {
this.collapse(true);
}
this.refresh();
},
make: function make() {
if (!this.layout.page) {
this.layout.page = $('
').appendTo(this.layout.wrapper);
}
this.wrapper = $('
').appendTo(this.layout.page);
this.layout.sections.push(this);
if (this.df) {
if (this.df.label) {
this.make_head();
}
if (this.df.description) {
$('
' + __(this.df.description) + '
').appendTo(this.wrapper);
}
if (this.df.cssClass) {
this.wrapper.addClass(this.df.cssClass);
}
}
this.body = $('
').appendTo(this.wrapper);
},
make_head: function make_head() {
var me = this;
if (!this.df.collapsible) {
$('
').appendTo(this.wrapper);
} else {
this.head = $('
').appendTo(this.wrapper);
this.collapse_link = this.head.on("click", function () {
me.collapse();
});
this.indicator = this.head.find(".collapse-indicator");
}
},
refresh: function refresh() {
if (!this.df) return;
var hide = this.df.hidden || this.df.hidden_due_to_dependency;
if (!hide && this.layout && this.layout.frm && !this.layout.frm.get_perm(this.df.permlevel || 0, "read")) {
hide = true;
}
this.wrapper.toggleClass("hide-control", !!hide);
},
collapse: function collapse(hide) {
if (!(this.head && this.body)) {
return;
}
if (hide === undefined) {
hide = !this.body.hasClass("hide");
}
this.body.toggleClass("hide", hide);
this.head.toggleClass("collapsed", hide);
this.indicator.toggleClass("octicon-chevron-down", hide);
this.indicator.toggleClass("octicon-chevron-up", !hide);
},
has_missing_mandatory: function has_missing_mandatory() {
var missing_mandatory = false;
for (var j = 0, l = this.fields_list.length; j < l; j++) {
var section_df = this.fields_list[j].df;
if (section_df.reqd && this.layout.doc[section_df.fieldname] == null) {
missing_mandatory = true;
break;
}
}
return missing_mandatory;
}
});
frappe.ui.form.Column = Class.extend({
init: function init(section, df) {
if (!df) df = {};
this.df = df;
this.section = section;
this.make();
this.resize_all_columns();
},
make: function make() {
this.wrapper = $('
\
\
').appendTo(this.section.body).find("form").on("submit", function () {
return false;
});
if (this.df.label) {
$('
' + __(this.df.label) + ' ').appendTo(this.wrapper);
}
},
resize_all_columns: function resize_all_columns() {
var colspan = cint(12 / this.section.wrapper.find(".form-column").length);
this.section.wrapper.find(".form-column").removeClass().addClass("form-column").addClass("col-sm-" + colspan);
},
refresh: function refresh() {
this.section.refresh();
}
});
frappe.provide('frappe.ui');
frappe.ui.FieldGroup = frappe.ui.form.Layout.extend({
init: function init(opts) {
$.extend(this, opts);
this._super();
$.each(this.fields || [], function (i, f) {
if (!f.fieldname && f.label) {
f.fieldname = f.label.replace(/ /g, "_").toLowerCase();
}
});
if (this.values) {
this.set_values(this.values);
}
},
make: function make() {
var me = this;
if (this.fields) {
this._super();
this.refresh();
$.each(this.fields_list, function (i, field) {
if (field.df["default"]) {
field.set_input(field.df["default"]);
}
});
if (!this.no_submit_on_enter) {
this.catch_enter_as_submit();
}
$(this.body).find('input').on('change', function () {
me.refresh_dependency();
});
$(this.body).find('select').on("change", function () {
me.refresh_dependency();
});
}
},
add_fields: function add_fields(fields) {
this.render(fields);
this.refresh_fields(fields);
},
refresh_fields: function refresh_fields(fields) {
var fieldnames = fields.map(function (field) {
if (field.fieldname) return field.fieldname;
});
this.fields_list.map(function (fieldobj) {
if (fieldnames.includes(fieldobj.df.fieldname)) {
fieldobj.refresh();
if (fieldobj.df["default"]) {
fieldobj.set_input(fieldobj.df["default"]);
}
}
});
},
first_button: false,
catch_enter_as_submit: function catch_enter_as_submit() {
var me = this;
$(this.body).find('input[type="text"], input[type="password"]').keypress(function (e) {
if (e.which == 13) {
if (me.has_primary_action) {
e.preventDefault();
me.get_primary_btn().trigger("click");
}
}
});
},
get_input: function get_input(fieldname) {
var field = this.fields_dict[fieldname];
return $(field.txt ? field.txt : field.input);
},
get_field: function get_field(fieldname) {
return this.fields_dict[fieldname];
},
get_values: function get_values(ignore_errors) {
var ret = {};
var errors = [];
for (var key in this.fields_dict) {
var f = this.fields_dict[key];
if (f.get_value) {
var v = f.get_value();
if (f.df.reqd && is_null(v)) errors.push(__(f.df.label));
if (!is_null(v)) ret[f.df.fieldname] = v;
}
}
if (errors.length && !ignore_errors) {
frappe.msgprint({
title: __('Missing Values Required'),
message: __('Following fields have missing values:') + '
',
indicator: 'orange'
});
return null;
}
return ret;
},
get_value: function get_value(key) {
var f = this.fields_dict[key];
return f && (f.get_value ? f.get_value() : null);
},
set_value: function set_value(key, val) {
var _this = this;
return new Promise(function (resolve) {
var f = _this.fields_dict[key];
if (f) {
f.set_value(val).then(function () {
f.set_input(val);
_this.refresh_dependency();
resolve();
});
} else {
resolve();
}
});
},
set_input: function set_input(key, val) {
return this.set_value(key, val);
},
set_values: function set_values(dict) {
for (var key in dict) {
if (this.fields_dict[key]) {
this.set_value(key, dict[key]);
}
}
},
clear: function clear() {
for (var key in this.fields_dict) {
var f = this.fields_dict[key];
if (f && f.set_input) {
f.set_input(f.df['default'] || '');
}
}
}
});
frappe.ui.form.make_control = function (opts) {
var control_class_name = "Control" + opts.df.fieldtype.replace(/ /g, "");
if (frappe.ui.form[control_class_name]) {
return new frappe.ui.form[control_class_name](opts);
} else {
console.log("Invalid Control Name: " + opts.df.fieldtype);
}
};
frappe.ui.form.Control = Class.extend({
init: function init(opts) {
$.extend(this, opts);
this.make();
if (frappe.boot.user && frappe.boot.user.name === "Administrator" && frappe.boot.developer_mode === 1 && this.$wrapper) {
this.$wrapper.attr("title", __(this.df.fieldname));
}
if (this.render_input) {
this.refresh();
}
},
make: function make() {
this.make_wrapper();
this.$wrapper.attr("data-fieldtype", this.df.fieldtype).attr("data-fieldname", this.df.fieldname);
this.wrapper = this.$wrapper.get(0);
this.wrapper.fieldobj = this;
},
make_wrapper: function make_wrapper() {
this.$wrapper = $("
").appendTo(this.parent);
this.wrapper = this.$wrapper;
},
toggle: function toggle(show) {
this.df.hidden = show ? 0 : 1;
this.refresh();
},
get_status: function get_status(explain) {
if (!this.doctype && !this.docname) {
if (cint(this.df.hidden)) {
if (explain) console.log("By Hidden: None");
return "None";
} else if (cint(this.df.hidden_due_to_dependency)) {
if (explain) console.log("By Hidden Dependency: None");
return "None";
} else if (cint(this.df.read_only)) {
if (explain) console.log("By Read Only: Read");
return "Read";
}
return "Write";
}
var status = frappe.perm.get_field_display_status(this.df, frappe.model.get_doc(this.doctype, this.docname), this.perm || this.frm && this.frm.perm, explain);
if (this.doctype && status === "Read" && !this.only_input && is_null(frappe.model.get_value(this.doctype, this.docname, this.df.fieldname)) && !in_list(["HTML", "Image"], this.df.fieldtype)) {
if (explain) console.log("By Hide Read-only, null fields: None");
status = "None";
}
return status;
},
refresh: function refresh() {
this.disp_status = this.get_status();
this.$wrapper && this.$wrapper.toggleClass("hide-control", this.disp_status == "None") && this.refresh_input && this.refresh_input();
},
get_doc: function get_doc() {
return this.doctype && this.docname && locals[this.doctype] && locals[this.doctype][this.docname] || {};
},
get_model_value: function get_model_value() {
if (this.doc) {
return this.doc[this.df.fieldname];
}
},
set_value: function set_value(value) {
return this.validate_and_set_in_model(value);
},
parse_validate_and_set_in_model: function parse_validate_and_set_in_model(value, e) {
if (this.parse) {
value = this.parse(value);
}
return this.validate_and_set_in_model(value, e);
},
validate_and_set_in_model: function validate_and_set_in_model(value, e) {
var me = this;
if (this.inside_change_event) {
return new Promise.resolve();
}
this.inside_change_event = true;
var set = function set(value) {
me.inside_change_event = false;
return frappe.run_serially([function () {
return me.set_model_value(value);
}, function () {
me.set_mandatory && me.set_mandatory(value);
if (me.df.change || me.df.onchange) {
return (me.df.change || me.df.onchange).apply(me, [e]);
}
}]);
};
value = this.validate(value);
if (value && value.then) {
return value.then(function (value) {
return set(value);
});
} else {
return set(value);
}
},
get_value: function get_value() {
if (this.get_status() === 'Write') {
return this.get_input_value ? this.parse ? this.parse(this.get_input_value()) : this.get_input_value() : undefined;
} else if (this.get_status() === 'Read') {
return this.value || undefined;
} else {
return undefined;
}
},
set_model_value: function set_model_value(value) {
if (this.doctype && this.docname) {
this.last_value = value;
return frappe.model.set_value(this.doctype, this.docname, this.df.fieldname, value, this.df.fieldtype);
} else {
if (this.doc) {
this.doc[this.df.fieldname] = value;
}
this.set_input(value);
return Promise.resolve();
}
},
set_focus: function set_focus() {
if (this.$input) {
this.$input.get(0).focus();
return true;
}
}
});
frappe.ui.form.ControlHTML = frappe.ui.form.Control.extend({
make: function make() {
this._super();
this.disp_area = this.wrapper;
},
refresh_input: function refresh_input() {
var content = this.get_content();
if (content) this.$wrapper.html(content);
},
get_content: function get_content() {
return this.df.options || "";
},
html: function html(_html) {
this.$wrapper.html(_html || this.get_content());
},
set_value: function set_value(html) {
if (html.appendTo) {
html.appendTo(this.$wrapper.empty());
} else {
this.df.options = html;
this.html(html);
}
}
});
frappe.ui.form.ControlHeading = frappe.ui.form.ControlHTML.extend({
get_content: function get_content() {
return "
" + __(this.df.label) + " ";
}
});
frappe.ui.form.ControlImage = frappe.ui.form.Control.extend({
make: function make() {
this._super();
var me = this;
this.$wrapper.css({ "margin": "0px" });
this.$body = $("
").appendTo(this.$wrapper).css({ "margin-bottom": "10px" });
$('
').appendTo(this.$wrapper);
},
refresh_input: function refresh_input() {
this.$body.empty();
var doc = this.get_doc();
if (doc && this.df.options && doc[this.df.options]) {
this.$img = $("
").appendTo(this.$body);
} else {
this.$buffer = $("
").appendTo(this.$body);
}
return false;
}
});
frappe.ui.form.ControlInput = frappe.ui.form.Control.extend({
horizontal: true,
make: function make() {
this._super();
this.set_input_areas();
this.set_max_width();
},
make_wrapper: function make_wrapper() {
if (this.only_input) {
this.$wrapper = $('
').appendTo(this.parent);
} else {
this.$wrapper = $('
').appendTo(this.parent);
}
},
toggle_label: function toggle_label(show) {
this.$wrapper.find(".control-label").toggleClass("hide", !show);
},
toggle_description: function toggle_description(show) {
this.$wrapper.find(".help-box").toggleClass("hide", !show);
},
set_input_areas: function set_input_areas() {
if (this.only_input) {
this.input_area = this.wrapper;
} else {
this.label_area = this.label_span = this.$wrapper.find("label").get(0);
this.input_area = this.$wrapper.find(".control-input").get(0);
this.disp_area = this.$wrapper.find(".control-value").get(0);
}
},
set_max_width: function set_max_width() {
if (this.horizontal) {
this.$wrapper.addClass("input-max-width");
}
},
refresh_input: function refresh_input() {
var me = this;
var make_input = function make_input() {
if (!me.has_input) {
me.make_input();
if (me.df.on_make) {
me.df.on_make(me);
}
}
};
var update_input = function update_input() {
if (me.doctype && me.docname) {
me.set_input(me.value);
} else {
me.set_input(me.value || null);
}
};
if (me.disp_status != "None") {
if (me.doctype && me.docname) {
me.value = frappe.model.get_value(me.doctype, me.docname, me.df.fieldname);
}
if (me.disp_status == "Write") {
me.disp_area && $(me.disp_area).toggle(false);
$(me.input_area).toggle(true);
me.$input && me.$input.prop("disabled", false);
make_input();
update_input();
} else {
if (me.only_input) {
make_input();
update_input();
} else {
$(me.input_area).toggle(false);
if (me.disp_area) {
me.set_disp_area(me.value);
$(me.disp_area).toggle(true);
}
}
me.$input && me.$input.prop("disabled", true);
}
me.set_description();
me.set_label();
me.set_mandatory(me.value);
me.set_bold();
}
},
set_disp_area: function set_disp_area(value) {
if (in_list(["Currency", "Int", "Float"], this.df.fieldtype) && (this.value === 0 || value === 0)) {
value = 0;
} else {
value = this.value || value;
}
this.disp_area && $(this.disp_area).html(frappe.format(value, this.df, { no_icon: true, inline: true }, this.doc || this.frm && this.frm.doc));
},
bind_change_event: function bind_change_event() {
var me = this;
this.$input && this.$input.on("change", this.change || function (e) {
me.parse_validate_and_set_in_model(me.get_input_value(), e);
});
},
bind_focusout: function bind_focusout() {
if (frappe.dom.is_touchscreen()) {
var me = this;
this.$input && this.$input.on("focusout", function () {
if (frappe.dom.is_touchscreen()) {
frappe.utils.scroll_to(me.$wrapper);
}
});
}
},
set_label: function set_label(label) {
if (label) this.df.label = label;
if (this.only_input || this.df.label == this._label) return;
var icon = "";
this.label_span.innerHTML = (icon ? '
' : "") + __(this.df.label) || " ";
this._label = this.df.label;
},
set_description: function set_description() {
if (this.only_input || this.df.description === this._description) return;
if (this.df.description) {
this.$wrapper.find(".help-box").html(__(this.df.description));
} else {
this.set_empty_description();
}
this._description = this.df.description;
},
set_new_description: function set_new_description(description) {
this.$wrapper.find(".help-box").html(description);
},
set_empty_description: function set_empty_description() {
this.$wrapper.find(".help-box").html("");
},
set_mandatory: function set_mandatory(value) {
this.$wrapper.toggleClass("has-error", this.df.reqd && is_null(value) ? true : false);
},
set_bold: function set_bold() {
if (this.$input) {
this.$input.toggleClass("bold", !!(this.df.bold || this.df.reqd));
}
if (this.disp_area) {
$(this.disp_area).toggleClass("bold", !!(this.df.bold || this.df.reqd));
}
}
});
frappe.ui.form.ControlData = frappe.ui.form.ControlInput.extend({
html_element: "input",
input_type: "text",
make_input: function make_input() {
if (this.$input) return;
this.$input = $("<" + this.html_element + ">").attr("type", this.input_type).attr("autocomplete", "off").addClass("input-with-feedback form-control").prependTo(this.input_area);
if (in_list(['Data', 'Link', 'Dynamic Link', 'Password', 'Select', 'Read Only', 'Attach', 'Attach Image'], this.df.fieldtype)) {
this.$input.attr("maxlength", this.df.length || 140);
}
this.set_input_attributes();
this.input = this.$input.get(0);
this.has_input = true;
this.bind_change_event();
this.bind_focusout();
},
set_input_attributes: function set_input_attributes() {
this.$input.attr("data-fieldtype", this.df.fieldtype).attr("data-fieldname", this.df.fieldname).attr("placeholder", this.df.placeholder || "");
if (this.doctype) {
this.$input.attr("data-doctype", this.doctype);
}
if (this.df.input_css) {
this.$input.css(this.df.input_css);
}
if (this.df.input_class) {
this.$input.addClass(this.df.input_class);
}
},
set_input: function set_input(value) {
this.last_value = this.value;
this.value = value;
this.set_formatted_input(value);
this.set_disp_area(value);
this.set_mandatory && this.set_mandatory(value);
},
set_formatted_input: function set_formatted_input(value) {
this.$input && this.$input.val(this.format_for_input(value));
},
get_input_value: function get_input_value() {
return this.$input ? this.$input.val() : undefined;
},
format_for_input: function format_for_input(val) {
return val == null ? "" : val;
},
validate: function validate(v) {
if (this.df.options == 'Phone') {
if (v + '' == '') {
return '';
}
var v1 = '';
v = v.replace(/ /g, '').replace(/-/g, '').replace(/\(/g, '').replace(/\)/g, '');
if (v && v.substr(0, 1) == '+') {
v1 = '+';v = v.substr(1);
}
if (v && v.substr(0, 2) == '00') {
v1 += '00';v = v.substr(2);
}
if (v && v.substr(0, 1) == '0') {
v1 += '0';v = v.substr(1);
}
v1 += cint(v) + '';
return v1;
} else if (this.df.options == 'Email') {
if (v + '' == '') {
return '';
}
var email_list = frappe.utils.split_emails(v);
if (!email_list) {
return '';
} else {
var invalid_email = false;
email_list.forEach(function (email) {
if (!validate_email(email)) {
frappe.msgprint(__("Invalid Email: {0}", [email]));
invalid_email = true;
}
});
if (invalid_email) {
return '';
} else {
return v;
}
}
} else {
return v;
}
}
});
frappe.ui.form.ControlReadOnly = frappe.ui.form.ControlData.extend({
get_status: function get_status(explain) {
var status = this._super(explain);
if (status === "Write") status = "Read";
return;
}
});
frappe.ui.form.ControlPassword = frappe.ui.form.ControlData.extend({
input_type: "password",
make: function make() {
this._super();
},
make_input: function make_input() {
var _this = this;
var me = this;
this._super();
this.$input.parent().append($('
'));
this.$wrapper.find('.control-input-wrapper').append($('
'));
this.indicator = this.$wrapper.find('.password-strength-indicator');
this.message = this.$wrapper.find('.help-box');
this.$input.on('input', function () {
var $this = $(_this);
clearTimeout($this.data('timeout'));
$this.data('timeout', setTimeout(function () {
var txt = me.$input.val();
me.get_password_strength(txt);
}), 300);
});
},
get_password_strength: function get_password_strength(value) {
var me = this;
frappe.call({
type: 'GET',
method: 'frappe.core.doctype.user.user.test_password_strength',
args: {
new_password: value || ''
},
callback: function callback(r) {
if (r.message && r.message.entropy) {
var score = r.message.score,
feedback = r.message.feedback;
feedback.crack_time_display = r.message.crack_time_display;
var indicators = ['grey', 'red', 'orange', 'yellow', 'green'];
me.set_strength_indicator(indicators[score]);
}
}
});
},
set_strength_indicator: function set_strength_indicator(color) {
var message = __("Include symbols, numbers and capital letters in the password");
this.indicator.removeClass().addClass('password-strength-indicator indicator ' + color);
this.message.html(message).removeClass('hidden');
}
});
frappe.ui.form.ControlInt = frappe.ui.form.ControlData.extend({
make: function make() {
this._super();
},
make_input: function make_input() {
var me = this;
this._super();
this.$input.on("focus", function () {
setTimeout(function () {
if (!document.activeElement) return;
document.activeElement.value = me.validate(document.activeElement.value);
document.activeElement.select();
}, 100);
return false;
});
},
parse: function parse(value) {
return cint(value, null);
}
});
frappe.ui.form.ControlFloat = frappe.ui.form.ControlInt.extend({
parse: function parse(value) {
return isNaN(parseFloat(value)) ? null : flt(value, this.get_precision());
},
format_for_input: function format_for_input(value) {
var number_format;
if (this.df.fieldtype === "Float" && this.df.options && this.df.options.trim()) {
number_format = this.get_number_format();
}
var formatted_value = format_number(parseFloat(value), number_format, this.get_precision());
return isNaN(parseFloat(value)) ? "" : formatted_value;
},
get_number_format: function (_get_number_format) {
function get_number_format() {
return _get_number_format.apply(this, arguments);
}
get_number_format.toString = function () {
return _get_number_format.toString();
};
return get_number_format;
}(function () {
var currency = frappe.meta.get_field_currency(this.df, this.get_doc());
return get_number_format(currency);
}),
get_precision: function get_precision() {
return this.df.precision || cint(frappe.boot.sysdefaults.float_precision, null);
}
});
frappe.ui.form.ControlCurrency = frappe.ui.form.ControlFloat.extend({
format_for_input: function format_for_input(value) {
var formatted_value = format_number(parseFloat(value), this.get_number_format(), this.get_precision());
return isNaN(parseFloat(value)) ? "" : formatted_value;
},
get_precision: function get_precision() {
if (!this.df.precision) {
if (frappe.boot.sysdefaults.currency_precision) {
this.df.precision = frappe.boot.sysdefaults.currency_precision;
} else {
this.df.precision = get_number_format_info(this.get_number_format()).precision;
}
}
return this.df.precision;
}
});
frappe.ui.form.ControlPercent = frappe.ui.form.ControlFloat;
frappe.ui.form.ControlColor = frappe.ui.form.ControlData.extend({
make_input: function make_input() {
this._super();
this.colors = ["#ffc4c4", "#ff8989", "#ff4d4d", "#a83333", "#ffe8cd", "#ffd19c", "#ffb868", "#a87945", "#ffd2c2", "#ffa685", "#ff7846", "#a85b5b", "#ffd7d7", "#ffb1b1", "#ff8989", "#a84f2e", "#fffacd", "#fff168", "#fff69c", "#a89f45", "#ebf8cc", "#d9f399", "#c5ec63", "#7b933d", "#cef6d1", "#9deca2", "#6be273", "#428b46", "#d2f8ed", "#a4f3dd", "#77ecca", "#49937e", "#d2f1ff", "#a6e4ff", "#78d6ff", "#4f8ea8", "#d2d2ff", "#a3a3ff", "#7575ff", "#4d4da8", "#dac7ff", "#b592ff", "#8e58ff", "#5e3aa8", "#f8d4f8", "#f3aaf0", "#ec7dea", "#934f92"];
this.make_color_input();
},
make_color_input: function make_color_input() {
this.$wrapper.find('.control-input-wrapper').append("
");
this.$color_pallete = this.$wrapper.find('.color-picker-pallete');
var color_html = this.colors.map(this.get_color_box).join("");
this.$color_pallete.append(color_html);
this.$color_pallete.hide();
this.bind_events();
},
get_color_box: function get_color_box(hex) {
return "
";
},
set_formatted_input: function set_formatted_input(value) {
this._super(value);
this.$input.css({
"background-color": value
});
},
bind_events: function bind_events() {
var _this2 = this;
var mousedown_happened = false;
this.$wrapper.on("click", ".color-box", function (e) {
mousedown_happened = false;
var color_val = $(e.target).data("color");
_this2.set_value(color_val);
_this2.set_focus();
});
this.$wrapper.find(".color-box").mousedown(function () {
mousedown_happened = true;
});
this.$input.on("focus", function () {
_this2.$color_pallete.show();
});
this.$input.on("blur", function () {
if (mousedown_happened) {
mousedown_happened = false;
} else {
$(_this2.$color_pallete).hide();
}
});
},
validate: function validate(value) {
var is_valid = /^#[0-9A-F]{6}$/i.test(value);
if (is_valid) {
return value;
}
frappe.msgprint(__("{0} is not a valid hex color", [value]));
return null;
}
});
frappe.ui.form.ControlDate = frappe.ui.form.ControlData.extend({
make_input: function make_input() {
this._super();
this.set_date_options();
this.set_datepicker();
this.set_t_for_today();
},
set_formatted_input: function set_formatted_input(value) {
this._super(value);
if (value && (this.last_value && this.last_value !== value || !this.datepicker.selectedDates.length)) {
this.datepicker.selectDate(frappe.datetime.str_to_obj(value));
}
},
set_date_options: function set_date_options() {
var _this3 = this;
var me = this;
var lang = frappe.boot.user.language;
if (!$.fn.datepicker.language[lang]) {
lang = 'en';
}
this.today_text = __("Today");
this.datepicker_options = {
language: lang,
autoClose: true,
todayButton: frappe.datetime.now_date(true),
dateFormat: frappe.boot.sysdefaults.date_format || 'yyyy-mm-dd',
startDate: frappe.datetime.now_date(true),
onSelect: function onSelect() {
_this3.$input.trigger('change');
},
onShow: function onShow() {
_this3.datepicker.$datepicker.find('.datepicker--button:visible').text(me.today_text);
_this3.update_datepicker_position();
}
};
},
update_datepicker_position: function update_datepicker_position() {
if (!this.frm) return;
var window_height = $(window).height();
var window_scroll_top = $(window).scrollTop();
var el_offset_top = this.$input.offset().top + 280;
var position = 'top left';
if (window_height + window_scroll_top >= el_offset_top) {
position = 'bottom left';
}
this.datepicker.update('position', position);
},
set_datepicker: function set_datepicker() {
this.$input.datepicker(this.datepicker_options);
this.datepicker = this.$input.data('datepicker');
},
set_t_for_today: function set_t_for_today() {
var me = this;
this.$input.on("keydown", function (e) {
if (e.which === 84) {
if (me.df.fieldtype == 'Date') {
me.set_value(frappe.datetime.nowdate());
}if (me.df.fieldtype == 'Datetime') {
me.set_value(frappe.datetime.now_datetime());
}if (me.df.fieldtype == 'Time') {
me.set_value(frappe.datetime.now_time());
}
return false;
}
});
},
parse: function parse(value) {
if (value) {
return frappe.datetime.user_to_str(value);
}
},
format_for_input: function format_for_input(value) {
if (value) {
return frappe.datetime.str_to_user(value);
}
return "";
},
validate: function validate(value) {
if (value && !frappe.datetime.validate(value)) {
frappe.msgprint(__("Date must be in format: {0}", [frappe.sys_defaults.date_format || "yyyy-mm-dd"]));
return '';
}
return value;
}
});
frappe.ui.form.ControlDatetime = frappe.ui.form.ControlDate.extend({
set_date_options: function set_date_options() {
this._super();
this.today_text = __("Now");
$.extend(this.datepicker_options, {
timepicker: true,
timeFormat: "hh:ii:ss",
todayButton: frappe.datetime.now_datetime(true)
});
},
set_description: function set_description() {
var description = this.df.description;
var time_zone = frappe.sys_defaults.time_zone;
if (!frappe.datetime.is_timezone_same()) {
if (!description) {
this.df.description = time_zone;
} else if (!description.includes(time_zone)) {
this.df.description += '
' + time_zone;
}
}
this._super();
}
});
frappe.ui.form.ControlTime = frappe.ui.form.ControlData.extend({
make_input: function make_input() {
var me = this;
this._super();
this.$input.datepicker({
language: "en",
timepicker: true,
onlyTimepicker: true,
timeFormat: "hh:ii:ss",
startDate: frappe.datetime.now_time(true),
onSelect: function onSelect() {
me.$input.trigger('change');
},
onShow: function onShow() {
$('.datepicker--button:visible').text(__('Now'));
},
todayButton: frappe.datetime.now_time(true)
});
this.datepicker = this.$input.data('datepicker');
this.refresh();
},
set_input: function set_input(value) {
this._super(value);
if (value && (this.last_value && this.last_value !== this.value || !this.datepicker.selectedDates.length)) {
var date_obj = frappe.datetime.moment_to_date_obj(moment(value, 'hh:mm:ss'));
this.datepicker.selectDate(date_obj);
}
},
set_description: function set_description() {
var description = this.df.description;
var time_zone = frappe.sys_defaults.time_zone;
if (!frappe.datetime.is_timezone_same()) {
if (!description) {
this.df.description = time_zone;
} else if (!description.includes(time_zone)) {
this.df.description += '
' + time_zone;
}
}
this._super();
}
});
frappe.ui.form.ControlDateRange = frappe.ui.form.ControlData.extend({
make_input: function make_input() {
this._super();
this.set_date_options();
this.set_datepicker();
this.refresh();
},
set_date_options: function set_date_options() {
var me = this;
this.datepicker_options = {
language: "en",
range: true,
autoClose: true,
toggleSelected: false
};
this.datepicker_options.dateFormat = frappe.boot.sysdefaults.date_format || 'yyyy-mm-dd';
this.datepicker_options.onSelect = function () {
me.$input.trigger('change');
};
},
set_datepicker: function set_datepicker() {
this.$input.datepicker(this.datepicker_options);
this.datepicker = this.$input.data('datepicker');
},
set_input: function set_input(value, value2) {
this.last_value = this.value;
if (value && value2) {
this.value = [value, value2];
} else {
this.value = value;
}
if (this.value) {
var formatted = this.format_for_input(this.value[0], this.value[1]);
this.$input && this.$input.val(formatted);
} else {
this.$input && this.$input.val("");
}
this.set_disp_area(value || '');
this.set_mandatory && this.set_mandatory(value);
},
parse: function parse(value) {
if (value && (value.indexOf(',') !== -1 || value.indexOf('to') !== -1)) {
var vals = value.split(/[( to )(,)]/);
var from_date = moment(frappe.datetime.user_to_obj(vals[0])).format('YYYY-MM-DD');
var to_date = moment(frappe.datetime.user_to_obj(vals[vals.length - 1])).format('YYYY-MM-DD');
return [from_date, to_date];
}
},
format_for_input: function format_for_input(value1, value2) {
if (value1 && value2) {
value1 = frappe.datetime.str_to_user(value1);
value2 = frappe.datetime.str_to_user(value2);
return __("{0} to {1}").format([value1, value2]);
}
return "";
}
});
frappe.ui.form.ControlText = frappe.ui.form.ControlData.extend({
html_element: "textarea",
horizontal: false,
make_wrapper: function make_wrapper() {
this._super();
this.$wrapper.find(".like-disabled-input").addClass("for-description");
},
make_input: function make_input() {
this._super();
this.$input.css({ 'height': '300px' });
}
});
frappe.ui.form.ControlLongText = frappe.ui.form.ControlText;
frappe.ui.form.ControlSmallText = frappe.ui.form.ControlText.extend({
make_input: function make_input() {
this._super();
this.$input.css({ 'height': '150px' });
}
});
frappe.ui.form.ControlCheck = frappe.ui.form.ControlData.extend({
input_type: "checkbox",
make_wrapper: function make_wrapper() {
this.$wrapper = $('
').appendTo(this.parent);
},
set_input_areas: function set_input_areas() {
this.label_area = this.label_span = this.$wrapper.find(".label-area").get(0);
this.input_area = this.$wrapper.find(".input-area").get(0);
this.disp_area = this.$wrapper.find(".disp-area").get(0);
},
make_input: function make_input() {
this._super();
this.$input.removeClass("form-control");
},
get_input_value: function get_input_value() {
return this.input && this.input.checked ? 1 : 0;
},
validate: function validate(value) {
return cint(value);
},
set_input: function set_input(value) {
if (this.input) {
this.input.checked = value ? 1 : 0;
}
this.last_value = value;
this.set_mandatory(value);
this.set_disp_area(value);
}
});
frappe.ui.form.ControlButton = frappe.ui.form.ControlData.extend({
make_input: function make_input() {
var me = this;
this.$input = $('
').prependTo(me.input_area).on("click", function () {
me.onclick();
});
this.input = this.$input.get(0);
this.set_input_attributes();
this.has_input = true;
this.toggle_label(false);
},
onclick: function onclick() {
if (this.frm && this.frm.doc) {
if (this.frm.script_manager.has_handlers(this.df.fieldname, this.doctype)) {
this.frm.script_manager.trigger(this.df.fieldname, this.doctype, this.docname);
} else {
this.frm.runscript(this.df.options, this);
}
} else if (this.df.click) {
this.df.click();
}
},
set_input_areas: function set_input_areas() {
this._super();
$(this.disp_area).removeClass().addClass("hide");
},
set_empty_description: function set_empty_description() {
this.$wrapper.find(".help-box").empty().toggle(false);
},
set_label: function set_label() {
$(this.label_span).html(" ");
this.$input && this.$input.html((this.df.icon ? ' ' : "") + __(this.df.label));
}
});
frappe.ui.form.ControlAttach = frappe.ui.form.ControlData.extend({
make_input: function make_input() {
var me = this;
this.$input = $('').html(__("Attach")).prependTo(me.input_area).on("click", function () {
me.onclick();
});
this.$value = $('').prependTo(me.input_area).toggle(false);
this.input = this.$input.get(0);
this.set_input_attributes();
this.has_input = true;
this.$value.find(".close").on("click", function () {
me.clear_attachment();
});
},
clear_attachment: function clear_attachment() {
var me = this;
if (this.frm) {
me.frm.attachments.remove_attachment_by_filename(me.value, function () {
me.parse_validate_and_set_in_model(null);
me.refresh();
me.frm.save();
});
} else {
this.dataurl = null;
this.fileobj = null;
this.set_input(null);
this.refresh();
}
},
onclick: function onclick() {
var me = this;
if (this.doc) {
var doc = this.doc.parent && frappe.model.get_doc(this.doc.parenttype, this.doc.parent) || this.doc;
if (doc.__islocal) {
frappe.msgprint(__("Please save the document before uploading."));
return;
}
}
if (!this.dialog) {
this.dialog = new frappe.ui.Dialog({
title: __(this.df.label || __("Upload")),
fields: [{ fieldtype: "HTML", fieldname: "upload_area" }, { fieldtype: "HTML", fieldname: "or_attach", options: __("Or") }, { fieldtype: "Select", fieldname: "select", label: __("Select from existing attachments") }, { fieldtype: "Button", fieldname: "clear",
label: __("Clear Attachment"), click: function click() {
me.clear_attachment();
me.dialog.hide();
}
}]
});
}
this.dialog.show();
this.dialog.get_field("upload_area").$wrapper.empty();
var attachments = this.frm && this.frm.attachments.get_attachments() || [];
var select = this.dialog.get_field("select");
if (attachments.length) {
attachments = $.map(attachments, function (o) {
return o.file_url;
});
select.df.options = [""].concat(attachments);
select.toggle(true);
this.dialog.get_field("or_attach").toggle(true);
select.refresh();
} else {
this.dialog.get_field("or_attach").toggle(false);
select.toggle(false);
}
select.$input.val("");
this.dialog.get_field('clear').$wrapper.toggle(this.get_model_value() ? true : false);
this.set_upload_options();
frappe.upload.make(this.upload_options);
},
set_upload_options: function set_upload_options() {
var me = this;
this.upload_options = {
parent: this.dialog.get_field("upload_area").$wrapper,
args: {},
allow_multiple: 0,
max_width: this.df.max_width,
max_height: this.df.max_height,
options: this.df.options,
btn: this.dialog.set_primary_action(__("Upload")),
on_no_attach: function on_no_attach() {
var selected = me.dialog.get_field("select").get_value();
if (selected) {
me.parse_validate_and_set_in_model(selected);
me.dialog.hide();
me.frm.save();
} else {
frappe.msgprint(__("Please attach a file or set a URL"));
}
},
callback: function callback(attachment, r) {
me.on_upload_complete(attachment);
me.dialog.hide();
},
onerror: function onerror() {
me.dialog.hide();
}
};
if ("is_private" in this.df) {
this.upload_options.is_private = this.df.is_private;
}
if (this.frm) {
this.upload_options.args = {
from_form: 1,
doctype: this.frm.doctype,
docname: this.frm.docname
};
} else {
this.upload_options.on_attach = function (fileobj, dataurl) {
me.dialog.hide();
me.fileobj = fileobj;
me.dataurl = dataurl;
if (me.on_attach) {
me.on_attach();
}
if (me.df.on_attach) {
me.df.on_attach(fileobj, dataurl);
}
me.on_upload_complete();
};
}
},
set_input: function set_input(value, dataurl) {
this.value = value;
if (this.value) {
this.$input.toggle(false);
if (this.value.indexOf(",") !== -1) {
var parts = this.value.split(",");
var filename = parts[0];
var dataurl = parts[1];
}
this.$value.toggle(true).find(".attached-file").html(filename || this.value).attr("href", dataurl || this.value);
} else {
this.$input.toggle(true);
this.$value.toggle(false);
}
},
get_value: function get_value() {
if (this.frm) {
return this.value;
} else {
return this.fileobj ? this.fileobj.filename + "," + this.dataurl : null;
}
},
on_upload_complete: function on_upload_complete(attachment) {
if (this.frm) {
this.parse_validate_and_set_in_model(attachment.file_url);
this.refresh();
this.frm.attachments.update_attachment(attachment);
this.frm.save();
} else {
this.value = this.get_value();
this.refresh();
}
}
});
frappe.ui.form.ControlAttachImage = frappe.ui.form.ControlAttach.extend({
make: function make() {
var me = this;
this._super();
this.container = $('').insertAfter($(this.wrapper));
$(this.wrapper).detach();
this.container.attr('data-fieldtype', this.df.fieldtype).append(this.wrapper);
if (this.df.align === 'center') {
this.container.addClass("flex-justify-center");
} else if (this.df.align === 'right') {
this.container.addClass("flex-justify-end");
}
this.img_wrapper = $('
').appendTo(this.wrapper);
this.img_container = $("
");
this.img = $("
").appendTo(this.img_container);
this.img_overlay = $("
\n\t\t\t\tChange \n\t\t\t
").appendTo(this.img_container);
this.remove_image_link = $('
Remove ');
this.img_wrapper.append(this.img_container).append(this.remove_image_link);
this.img_container.toggle(false);
this.remove_image_link.toggle(false);
this.img_wrapper.find(".missing-image").on("click", function () {
me.$input.click();
});
this.img_container.on("click", function () {
me.$input.click();
});
this.remove_image_link.on("click", function () {
me.$value.find(".close").click();
});
this.set_image();
},
refresh_input: function refresh_input() {
this._super();
$(this.wrapper).find('.btn-attach').addClass('hidden');
this.set_image();
if (this.get_status() == "Read") {
$(this.disp_area).toggle(false);
}
},
set_image: function set_image() {
if (this.get_value()) {
$(this.img_wrapper).find(".missing-image").toggle(false);
this.img.attr("src", this.dataurl ? this.dataurl : this.value);
this.img_container.toggle(true);
this.remove_image_link.toggle(true);
} else {
$(this.img_wrapper).find(".missing-image").toggle(true);
this.img_container.toggle(false);
this.remove_image_link.toggle(false);
}
}
});
frappe.ui.form.ControlSelect = frappe.ui.form.ControlData.extend({
html_element: "select",
make_input: function make_input() {
this._super();
this.set_options();
},
set_formatted_input: function set_formatted_input(value) {
if (value == null) value = '';
this.set_options(value);
this._super(value);
var input_value = '';
if (this.$input) {
input_value = this.$input.val();
}
if (value && input_value && value !== input_value) {
this.set_model_value(input_value);
}
},
set_options: function set_options(value) {
var options = this.df.options || [];
if (typeof this.df.options === "string") {
options = this.df.options.split("\n");
}
if (options.toString() === this.last_options) {
return;
}
this.last_options = options.toString();
if (this.$input) {
var selected = this.$input.find(":selected").val();
this.$input.empty().add_options(options || []);
if (value === undefined && selected) {
this.$input.val(selected);
}
}
},
get_file_attachment_list: function get_file_attachment_list() {
if (!this.frm) return;
var fl = frappe.model.docinfo[this.frm.doctype][this.frm.docname];
if (fl && fl.attachments) {
this.set_description("");
var options = [""];
$.each(fl.attachments, function (i, f) {
options.push(f.file_url);
});
return options;
} else {
this.set_description(__("Please attach a file first."));
return [""];
}
}
});
frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({
make_input: function make_input() {
var me = this;
$('
').prependTo(this.input_area);
this.$input_area = $(this.input_area);
this.$input = this.$input_area.find('input');
this.$link = this.$input_area.find('.link-btn');
this.$link_open = this.$link.find('.btn-open');
this.set_input_attributes();
this.$input.on("focus", function () {
setTimeout(function () {
if (me.$input.val() && me.get_options()) {
me.$link.toggle(true);
me.$link_open.attr('href', '#Form/' + me.get_options() + '/' + me.$input.val());
}
if (!me.$input.val()) {
me.$input.val("").trigger("input");
}
}, 500);
});
this.$input.on("blur", function () {
setTimeout(function () {
me.$link.toggle(false);
}, 500);
});
this.input = this.$input.get(0);
this.has_input = true;
this.translate_values = true;
var me = this;
this.setup_buttons();
this.setup_awesomeplete();
if (this.df.change) {
this.$input.on("change", function () {
me.df.change.apply(this);
});
}
},
get_options: function get_options() {
return this.df.options;
},
setup_buttons: function setup_buttons() {
var me = this;
if (this.only_input && !this.with_link_btn) {
this.$input_area.find(".link-btn").remove();
}
},
open_advanced_search: function open_advanced_search() {
var doctype = this.get_options();
if (!doctype) return;
new frappe.ui.form.LinkSelector({
doctype: doctype,
target: this,
txt: this.get_input_value()
});
return false;
},
new_doc: function new_doc() {
var doctype = this.get_options();
var me = this;
if (!doctype) return;
if (this.df.get_route_options_for_new_doc) {
frappe.route_options = this.df.get_route_options_for_new_doc(this);
} else {
frappe.route_options = {};
}
frappe.route_options.name_field = this.get_value();
frappe._from_link = this;
frappe._from_link_scrollY = $(document).scrollTop();
frappe.ui.form.make_quick_entry(doctype, function (doc) {
return me.set_value(doc.name);
});
return false;
},
setup_awesomeplete: function setup_awesomeplete() {
var me = this;
this.$input.cache = {};
this.awesomplete = new Awesomplete(me.input, {
minChars: 0,
maxItems: 99,
autoFirst: true,
list: [],
data: function data(item, input) {
return {
label: item.label || item.value,
value: item.value
};
},
filter: function filter(item, input) {
return true;
},
item: function item(_item, input) {
var d = this.get_item(_item.value);
if (!d.label) {
d.label = d.value;
}
var _label = me.translate_values ? __(d.label) : d.label;
var html = "
" + _label + " ";
if (d.description && d.value !== d.description) {
html += '
' + __(d.description) + ' ';
}
return $('
').data('item.autocomplete', d).prop('aria-selected', 'false').html('
' + html + '
').get(0);
},
sort: function sort(a, b) {
return 0;
}
});
this.$input.on("input", function (e) {
var doctype = me.get_options();
if (!doctype) return;
if (!me.$input.cache[doctype]) {
me.$input.cache[doctype] = {};
}
var term = e.target.value;
if (me.$input.cache[doctype][term] != null) {
me.awesomplete.list = me.$input.cache[doctype][term];
}
var args = {
'txt': term,
'doctype': doctype
};
me.set_custom_query(args);
frappe.call({
type: "GET",
method: 'frappe.desk.search.search_link',
no_spinner: true,
args: args,
callback: function callback(r) {
if (!me.$input.is(":focus")) {
return;
}
if (!me.df.only_select) {
if (frappe.model.can_create(doctype) && me.df.fieldtype !== "Dynamic Link") {
r.results.push({
label: "
" + " " + __("Create a new {0}", [__(me.df.options)]) + " ",
value: "create_new__link_option",
action: me.new_doc
});
}
r.results.push({
label: "
" + " " + __("Advanced Search") + " ",
value: "advanced_search__link_option",
action: me.open_advanced_search
});
}
me.$input.cache[doctype][term] = r.results;
me.awesomplete.list = me.$input.cache[doctype][term];
}
});
});
this.$input.on("blur", function () {
if (me.selected) {
me.selected = false;
return;
}
var value = me.get_input_value();
if (value !== me.last_value) {
me.parse_validate_and_set_in_model(value);
}
});
this.$input.on("awesomplete-open", function (e) {
me.$wrapper.css({ "z-index": 100 });
me.$wrapper.find('ul').css({ "z-index": 100 });
me.autocomplete_open = true;
});
this.$input.on("awesomplete-close", function (e) {
me.$wrapper.css({ "z-index": 1 });
me.autocomplete_open = false;
});
this.$input.on("awesomplete-select", function (e) {
var o = e.originalEvent;
var item = me.awesomplete.get_item(o.text.value);
me.autocomplete_open = false;
var TABKEY = 9;
if (e.keyCode === TABKEY) {
e.preventDefault();
me.awesomplete.close();
return false;
}
if (item.action) {
item.value = "";
item.action.apply(me);
}
if (me.df.remember_last_selected_value) {
frappe.boot.user.last_selected_values[me.df.options] = item.value;
}
me.parse_validate_and_set_in_model(item.value);
});
this.$input.on("awesomplete-selectcomplete", function (e) {
var o = e.originalEvent;
if (o.text.value.indexOf("__link_option") !== -1) {
me.$input.val("");
}
});
},
set_custom_query: function set_custom_query(args) {
var set_nulls = function set_nulls(obj) {
$.each(obj, function (key, value) {
if (value !== undefined) {
obj[key] = value;
}
});
return obj;
};
if (this.get_query || this.df.get_query) {
var get_query = this.get_query || this.df.get_query;
if ($.isPlainObject(get_query)) {
var filters = null;
if (get_query.filters) {
filters = get_query.filters;
} else if (get_query.query) {
args.query = get_query;
} else {
filters = get_query;
}
if (filters) {
var filters = set_nulls(filters);
$.extend(args, filters);
args.filters = filters;
}
} else if (typeof get_query === "string") {
args.query = get_query;
} else {
var q = get_query(this.frm && this.frm.doc || this.doc, this.doctype, this.docname);
if (typeof q === "string") {
args.query = q;
} else if ($.isPlainObject(q)) {
if (q.filters) {
set_nulls(q.filters);
}
if (q.translate_values !== undefined) {
this.translate_values = q.translate_values;
}
$.extend(args, q);
args.filters = q.filters;
}
}
}
if (this.df.filters) {
set_nulls(this.df.filters);
if (!args.filters) args.filters = {};
$.extend(args.filters, this.df.filters);
}
},
validate: function validate(value) {
if (this.df.options == "[Select]" || this.df.ignore_link_validation) {
return value;
}
return this.validate_link_and_fetch(this.df, this.get_options(), this.docname, value);
},
validate_link_and_fetch: function validate_link_and_fetch(df, doctype, docname, value) {
var _this4 = this;
var me = this;
if (value) {
return new Promise(function (resolve) {
var fetch = '';
if (_this4.frm && _this4.frm.fetch_dict[df.fieldname]) {
fetch = _this4.frm.fetch_dict[df.fieldname].columns.join(', ');
}
return frappe.call({
method: 'frappe.desk.form.utils.validate_link',
type: "GET",
args: {
'value': value,
'options': doctype,
'fetch': fetch
},
no_spinner: true,
callback: function callback(r) {
if (r.message == 'Ok') {
if (r.fetch_values && docname) {
me.set_fetch_values(df, docname, r.fetch_values);
}
resolve(r.valid_value);
} else {
resolve("");
}
}
});
});
}
},
set_fetch_values: function set_fetch_values(df, docname, fetch_values) {
var fl = this.frm.fetch_dict[df.fieldname].fields;
for (var i = 0; i < fl.length; i++) {
frappe.model.set_value(df.parent, docname, fl[i], fetch_values[i], df.fieldtype);
}
}
});
if (Awesomplete) {
Awesomplete.prototype.get_item = function (value) {
return this._list.find(function (item) {
return item.value === value;
});
};
}
frappe.ui.form.ControlDynamicLink = frappe.ui.form.ControlLink.extend({
get_options: function get_options() {
if (this.df.get_options) {
return this.df.get_options();
}
if (this.docname == null && cur_dialog) {
return cur_dialog.get_value(this.df.options);
}
if (cur_frm == null && cur_list) {
return cur_list.wrapper.find("input[data-fieldname*=" + this.df.options + "]").val();
}
var options = frappe.model.get_value(this.df.parent, this.docname, this.df.options);
return options;
}
});
frappe.ui.form.ControlCode = frappe.ui.form.ControlText.extend({
make_input: function make_input() {
this._super();
$(this.input_area).find("textarea").allowTabs().css({ "height": "400px", "font-family": "Monaco, \"Courier New\", monospace" });
}
});
frappe.ui.form.ControlTextEditor = frappe.ui.form.ControlCode.extend({
make_input: function make_input() {
this.has_input = true;
this.make_editor();
this.hide_elements_on_mobile();
this.setup_drag_drop();
this.setup_image_dialog();
this.setting_count = 0;
},
make_editor: function make_editor() {
var me = this;
this.editor = $("
").appendTo(this.input_area);
this.editor.summernote({
minHeight: 400,
toolbar: [['magic', ['style']], ['style', ['bold', 'italic', 'underline', 'clear']], ['fontsize', ['fontsize']], ['color', ['color']], ['para', ['ul', 'ol', 'paragraph', 'hr']], ['media', ['link', 'picture', 'video', 'table']], ['misc', ['fullscreen', 'codeview']]],
keyMap: {
pc: {
'CTRL+ENTER': ''
},
mac: {
'CMD+ENTER': ''
}
},
prettifyHtml: true,
dialogsInBody: true,
callbacks: {
onInit: function onInit() {
$(".note-editable[contenteditable='true']").one('focus', function () {
var $this = $(this);
$this.html($this.html() + '
');
});
},
onChange: function onChange(value) {
me.parse_validate_and_set_in_model(value);
},
onKeydown: function onKeydown(e) {
me._last_change_on = new Date();
var key = frappe.ui.keys.get_key(e);
if (['ctrl+b', 'meta+b'].indexOf(key) !== -1) {
e.stopPropagation();
}
if (key.indexOf('escape') !== -1) {
if (me.note_editor.hasClass('fullscreen')) {
me.note_editor.find('.note-btn.btn-fullscreen').trigger('click');
}
}
}
},
icons: {
'align': 'fa fa-align',
'alignCenter': 'fa fa-align-center',
'alignJustify': 'fa fa-align-justify',
'alignLeft': 'fa fa-align-left',
'alignRight': 'fa fa-align-right',
'indent': 'fa fa-indent',
'outdent': 'fa fa-outdent',
'arrowsAlt': 'fa fa-arrows-alt',
'bold': 'fa fa-bold',
'caret': 'caret',
'circle': 'fa fa-circle',
'close': 'fa fa-close',
'code': 'fa fa-code',
'eraser': 'fa fa-eraser',
'font': 'fa fa-font',
'frame': 'fa fa-frame',
'italic': 'fa fa-italic',
'link': 'fa fa-link',
'unlink': 'fa fa-chain-broken',
'magic': 'fa fa-magic',
'menuCheck': 'fa fa-check',
'minus': 'fa fa-minus',
'orderedlist': 'fa fa-list-ol',
'pencil': 'fa fa-pencil',
'picture': 'fa fa-image',
'question': 'fa fa-question',
'redo': 'fa fa-redo',
'square': 'fa fa-square',
'strikethrough': 'fa fa-strikethrough',
'subscript': 'fa fa-subscript',
'superscript': 'fa fa-superscript',
'table': 'fa fa-table',
'textHeight': 'fa fa-text-height',
'trash': 'fa fa-trash',
'underline': 'fa fa-underline',
'undo': 'fa fa-undo',
'unorderedlist': 'fa fa-list-ul',
'video': 'fa fa-video-camera'
}
});
this.note_editor = $(this.input_area).find('.note-editor');
},
setup_drag_drop: function setup_drag_drop() {
var me = this;
this.note_editor.on('dragenter dragover', false).on('drop', function (e) {
var dataTransfer = e.originalEvent.dataTransfer;
if (dataTransfer && dataTransfer.files && dataTransfer.files.length) {
me.note_editor.focus();
var files = [].slice.call(dataTransfer.files);
files.forEach(function (file) {
me.get_image(file, function (url) {
me.editor.summernote('insertImage', url, file.name);
});
});
}
e.preventDefault();
e.stopPropagation();
});
},
get_image: function get_image(fileobj, callback) {
var freader = new FileReader(),
me = this;
freader.onload = function () {
var dataurl = freader.result;
var parts = dataurl.split(",");
parts[0] += ";filename=" + fileobj.name;
dataurl = parts[0] + ',' + parts[1];
callback(dataurl);
};
freader.readAsDataURL(fileobj);
},
hide_elements_on_mobile: function hide_elements_on_mobile() {
this.note_editor.find('.note-btn-underline,\
.note-btn-italic, .note-fontsize,\
.note-color, .note-height, .btn-codeview').addClass('hidden-xs');
if ($('.toggle-sidebar').is(':visible')) {
this.note_editor.find('.note-btn').attr('data-original-title', '');
}
},
get_input_value: function get_input_value() {
return this.editor ? this.editor.summernote('code') : '';
},
parse: function parse(value) {
if (value == null) value = "";
return frappe.dom.remove_script_and_style(value);
},
set_formatted_input: function set_formatted_input(value) {
if (value !== this.get_input_value()) {
this.set_in_editor(value);
}
},
set_in_editor: function set_in_editor(value) {
var _this5 = this;
if (this.setting_count > 2) {
return;
}
this.setting_count += 1;
var time_since_last_keystroke = moment() - moment(this._last_change_on);
if (!this._last_change_on || time_since_last_keystroke > 3000) {
setTimeout(function () {
return _this5.setting_count = 0;
}, 500);
this.editor.summernote('code', value || '');
} else {
this._setting_value = setInterval(function () {
if (time_since_last_keystroke > 3000) {
if (_this5.last_value !== _this5.get_input_value()) {
_this5.editor.summernote('code', _this5.last_value || '');
}
clearInterval(_this5._setting_value);
_this5._setting_value = null;
_this5.setting_count = 0;
}
}, 1000);
}
},
set_focus: function set_focus() {
return this.editor.summernote('focus');
},
set_upload_options: function set_upload_options() {
var me = this;
this.upload_options = {
parent: this.image_dialog.get_field("upload_area").$wrapper,
args: {},
max_width: this.df.max_width,
max_height: this.df.max_height,
options: "Image",
btn: this.image_dialog.set_primary_action(__("Insert")),
on_no_attach: function on_no_attach() {
var selected = me.image_dialog.get_field("select").get_value();
if (selected) {
me.editor.summernote('insertImage', selected);
me.image_dialog.hide();
} else {
frappe.msgprint(__("Please attach a file or set a URL"));
}
},
callback: function callback(attachment, r) {
me.editor.summernote('insertImage', attachment.file_url, attachment.file_name);
me.image_dialog.hide();
},
onerror: function onerror() {
me.image_dialog.hide();
}
};
if ("is_private" in this.df) {
this.upload_options.is_private = this.df.is_private;
}
if (this.frm) {
this.upload_options.args = {
from_form: 1,
doctype: this.frm.doctype,
docname: this.frm.docname
};
} else {
this.upload_options.on_attach = function (fileobj, dataurl) {
me.editor.summernote('insertImage', dataurl);
me.image_dialog.hide();
frappe.hide_progress();
};
}
},
setup_image_dialog: function setup_image_dialog() {
var _this6 = this;
this.note_editor.find('[data-original-title="Image"]').on('click', function (e) {
if (!_this6.image_dialog) {
_this6.image_dialog = new frappe.ui.Dialog({
title: __("Image"),
fields: [{ fieldtype: "HTML", fieldname: "upload_area" }, { fieldtype: "HTML", fieldname: "or_attach", options: __("Or") }, { fieldtype: "Select", fieldname: "select", label: __("Select from existing attachments") }]
});
}
_this6.image_dialog.show();
_this6.image_dialog.get_field("upload_area").$wrapper.empty();
var attachments = _this6.frm && _this6.frm.attachments.get_attachments() || [];
var select = _this6.image_dialog.get_field("select");
if (attachments.length) {
attachments = $.map(attachments, function (o) {
return o.file_url;
});
select.df.options = [""].concat(attachments);
select.toggle(true);
_this6.image_dialog.get_field("or_attach").toggle(true);
select.refresh();
} else {
_this6.image_dialog.get_field("or_attach").toggle(false);
select.toggle(false);
}
select.$input.val("");
_this6.set_upload_options();
frappe.upload.make(_this6.upload_options);
});
}
});
frappe.ui.form.ControlTable = frappe.ui.form.Control.extend({
make: function make() {
this._super();
this.grid = new frappe.ui.form.Grid({
frm: this.frm,
df: this.df,
perm: this.perm || this.frm && this.frm.perm || this.df.perm,
parent: this.wrapper
});
if (this.frm) {
this.frm.grids[this.frm.grids.length] = this;
}
if (this.df.description) {
$('
' + __(this.df.description) + '
').appendTo(this.wrapper);
}
},
refresh_input: function refresh_input() {
this.grid.refresh();
},
get_value: function get_value() {
if (this.grid) {
return this.grid.get_data();
}
}
});
frappe.ui.form.ControlSignature = frappe.ui.form.ControlData.extend({
saving: false,
loading: false,
make: function make() {
var me = this;
this._super();
this.$pad = $('
').appendTo(me.wrapper).jSignature({ height: 300, width: "100%", "lineWidth": 0.8 }).on('change', this.on_save_sign.bind(this));
this.img_wrapper = $("
\n\t\t\t
\n\t\t\t\t \n\t\t\t
").appendTo(this.wrapper);
this.img = $("
").appendTo(this.img_wrapper).toggle(false);
this.$btnWrapper = $("
\n\t\t\t
\n\t\t\t ").appendTo(this.$pad).on("click", '.signature-reset', function () {
me.on_reset_sign();
return false;
});
},
refresh_input: function refresh_input(e) {
this.$wrapper.find(".control-input").toggle(false);
this.set_editable(this.get_status() == "Write");
this.load_pad();
if (this.get_status() == "Read") {
$(this.disp_area).toggle(false);
}
},
set_image: function set_image(value) {
if (value) {
$(this.img_wrapper).find(".missing-image").toggle(false);
this.img.attr("src", value).toggle(true);
} else {
$(this.img_wrapper).find(".missing-image").toggle(true);
this.img.toggle(false);
}
},
load_pad: function load_pad() {
if (this.saving) return;
var value = this.get_value();
if (this.$pad) {
this.loading = true;
this.$pad.jSignature('reset');
if (value) {
try {
this.$pad.jSignature('setData', value);
this.set_image(value);
} catch (e) {
console.log("Cannot set data for signature", value, e);
}
}
this.loading = false;
}
},
set_editable: function set_editable(editable) {
this.$pad.toggle(editable);
this.img_wrapper.toggle(!editable);
this.$btnWrapper.toggle(editable);
if (editable) {
this.$btnWrapper.addClass('editing');
} else {
this.$btnWrapper.removeClass('editing');
}
},
set_my_value: function set_my_value(value) {
if (this.saving || this.loading) return;
this.saving = true;
this.set_value(value);
this.value = value;
this.saving = false;
},
get_value: function get_value() {
return this.value ? this.value : this.get_model_value();
},
on_reset_sign: function on_reset_sign() {
this.$pad.jSignature("reset");
this.set_my_value("");
},
on_save_sign: function on_save_sign() {
if (this.saving || this.loading) return;
var base64_img = this.$pad.jSignature("getData");
this.set_my_value(base64_img);
this.set_image(this.get_value());
}
});
frappe.ui.form.fieldtype_icons = {
"Date": "fa fa-calendar",
"Time": "fa fa-time",
"Datetime": "fa fa-time",
"Code": "fa fa-code",
"Select": "fa fa-flag"
};
frappe.ui.form.LinkSelector = Class.extend({
init: function init(opts) {
$.extend(this, opts);
var me = this;
if (this.doctype != "[Select]") {
frappe.model.with_doctype(this.doctype, function (r) {
me.make();
});
} else {
this.make();
}
},
make: function make() {
var me = this;
this.dialog = new frappe.ui.Dialog({
title: __("Select {0}", [this.doctype == '[Select]' ? __("value") : __(this.doctype)]),
fields: [{
fieldtype: "Data", fieldname: "txt", label: __("Beginning with"),
description: __("You can use wildcard %")
}, {
fieldtype: "HTML", fieldname: "results"
}],
primary_action_label: __("Search"),
primary_action: function primary_action() {
me.search();
}
});
if (this.txt) this.dialog.fields_dict.txt.set_input(this.txt);
this.dialog.get_input("txt").on("keypress", function (e) {
if (e.which === 13) {
me.search();
}
});
this.dialog.show();
this.search();
},
search: function search() {
var args = {
txt: this.dialog.fields_dict.txt.get_value(),
searchfield: "name"
};
var me = this;
if (this.target.set_custom_query) {
this.target.set_custom_query(args);
}
if (this.target.is_grid && this.target.fieldinfo[this.fieldname] && this.target.fieldinfo[this.fieldname].get_query) {
$.extend(args, this.target.fieldinfo[this.fieldname].get_query(cur_frm.doc));
}
frappe.link_search(this.doctype, args, function (r) {
var parent = me.dialog.fields_dict.results.$wrapper;
parent.empty();
if (r.values.length) {
$.each(r.values, function (i, v) {
var row = $(repl('
', {
name: v[0],
values: v.splice(1).join(", ")
})).appendTo(parent);
row.find("a").attr('data-value', v[0]).click(function () {
var value = $(this).attr("data-value");
var $link = this;
if (me.target.is_grid) {
me.set_in_grid(value);
} else {
if (me.target.doctype) me.target.parse_validate_and_set_in_model(value);else {
me.target.set_input(value);
me.target.$input.trigger("change");
}
me.dialog.hide();
}
return false;
});
});
} else {
$('
' + __("No Results") + ' ' + (frappe.model.can_create(me.doctype) ? '' + __("Make a new {0}", [__(me.doctype)]) + " " : '') + '
').appendTo(parent).find(".new-doc").click(function () {
me.target.new_doc();
});
}
}, this.dialog.get_primary_btn());
},
set_in_grid: function set_in_grid(value) {
var me = this,
updated = false;
if (this.qty_fieldname) {
frappe.prompt({
fieldname: "qty", fieldtype: "Float", label: "Qty",
"default": 1, reqd: 1
}, function (data) {
$.each(me.target.frm.doc[me.target.df.fieldname] || [], function (i, d) {
if (d[me.fieldname] === value) {
frappe.model.set_value(d.doctype, d.name, me.qty_fieldname, data.qty);
frappe.show_alert(__("Added {0} ({1})", [value, d[me.qty_fieldname]]));
updated = true;
return false;
}
});
if (!updated) {
var d = me.target.add_new_row();
frappe.model.set_value(d.doctype, d.name, me.fieldname, value);
frappe.after_ajax(function () {
setTimeout(function () {
frappe.model.set_value(d.doctype, d.name, me.qty_fieldname, data.qty);
frappe.show_alert(__("Added {0} ({1})", [value, data.qty]));
}, 100);
});
}
}, __("Set Quantity"), __("Set"));
} else {
var d = me.target.add_new_row();
frappe.model.set_value(d.doctype, d.name, me.fieldname, value);
frappe.show_alert(__("{0} added", [value]));
}
}
});
frappe.link_search = function (doctype, args, _callback, btn) {
if (!args) {
args = {
txt: ''
};
}
args.doctype = doctype;
if (!args.searchfield) {
args.searchfield = 'name';
}
frappe.call({
method: "frappe.desk.search.search_widget",
type: "GET",
args: args,
callback: function callback(r) {
_callback && _callback(r);
},
btn: btn
});
};
frappe.ui.form.MultiSelectDialog = Class.extend({
init: function init(opts) {
$.extend(this, opts);
var me = this;
if (this.doctype != "[Select]") {
frappe.model.with_doctype(this.doctype, function (r) {
me.make();
});
} else {
this.make();
}
},
make: function make() {
var me = this;
this.page_length = 20;
var fields = [{
fieldtype: "Data",
label: __("Search Term"),
fieldname: "search_term"
}, {
fieldtype: "Column Break"
}];
var count = 0;
if (!this.date_field) {
this.date_field = "transaction_date";
}
Object.keys(this.setters).forEach(function (setter) {
fields.push({
fieldtype: me.target.fields_dict[setter].df.fieldtype,
label: me.target.fields_dict[setter].df.label,
fieldname: setter,
options: me.target.fields_dict[setter].df.options,
default: me.setters[setter]
});
if (count++ < Object.keys(me.setters).length) {
fields.push({ fieldtype: "Column Break" });
}
});
fields = fields.concat([{
"fieldname": "date_range",
"label": __("Date Range"),
"fieldtype": "DateRange"
}, { fieldtype: "Section Break" }, { fieldtype: "HTML", fieldname: "results_area" }, { fieldtype: "Button", fieldname: "make_new", label: __("Make a new " + me.doctype) }]);
var doctype_plural = !this.doctype.endsWith('y') ? this.doctype + 's' : this.doctype.slice(0, -1) + 'ies';
this.dialog = new frappe.ui.Dialog({
title: __("Select {0}", [this.doctype == '[Select]' ? __("value") : __(doctype_plural)]),
fields: fields,
primary_action_label: __("Get Items"),
primary_action: function primary_action() {
me.action(me.get_checked_values(), me.args);
}
});
this.$parent = $(this.dialog.body);
this.$wrapper = this.dialog.fields_dict.results_area.$wrapper.append("
");
this.$results = this.$wrapper.find('.results');
this.$make_new_btn = this.dialog.fields_dict.make_new.$wrapper;
this.$placeholder = $("
\n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t\t\n\t\t\t\t\t\tMake a new " + this.doctype + " \n\t\t\t\t\t \n\t\t\t\t
");
this.args = {};
this.bind_events();
this.get_results();
this.dialog.show();
},
bind_events: function bind_events() {
var _this = this;
var me = this;
this.$results.on('click', '.list-item-container', function (e) {
if (!$(e.target).is(':checkbox') && !$(e.target).is('a')) {
$(this).find(':checkbox').trigger('click');
}
});
this.$results.on('click', '.list-item--head :checkbox', function (e) {
_this.$results.find('.list-item-container .list-row-check').prop("checked", $(e.target).is(':checked'));
});
this.$parent.find('.input-with-feedback').on('change', function (e) {
_this.get_results();
});
this.$parent.find('[data-fieldname="date_range"]').on('blur', function (e) {
_this.get_results();
});
this.$parent.find('[data-fieldname="search_term"]').on('input', function (e) {
var $this = $(_this);
clearTimeout($this.data('timeout'));
$this.data('timeout', setTimeout(function () {
me.get_results();
}, 300));
});
this.$parent.on('click', '.btn[data-fieldname="make_new"]', function (e) {
frappe.route_options = {};
Object.keys(_this.setters).forEach(function (setter) {
frappe.route_options[setter] = me.dialog.fields_dict[setter].get_value() || undefined;
});
frappe.new_doc(_this.doctype, true);
});
},
get_checked_values: function get_checked_values() {
return this.$results.find('.list-item-container').map(function () {
if ($(this).find('.list-row-check:checkbox:checked').length > 0) {
return $(this).attr('data-item-name');
}
}).get();
},
make_list_row: function make_list_row() {
var result = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var me = this;
var head = Object.keys(result).length === 0;
var contents = "";
var columns = ["name"].concat(Object.keys(this.setters)).concat("Date");
columns.forEach(function (column) {
contents += "
\n\t\t\t\t" + (head ? "
" + __(frappe.model.unscrub(column)) + " " : column !== "name" ? "
" + __(result[column]) + " " : "
\n\t\t\t\t\t\t\t" + __(result[column]) + " ") + "\n\t\t\t
";
});
var $row = $("
\n\t\t\t
\n\t\t\t\t \n\t\t\t
\n\t\t\t" + contents + "\n\t\t
");
head ? $row.addClass('list-item--head') : $row = $("
").append($row);
return $row;
},
render_result_list: function render_result_list(results) {
var more = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var me = this;
this.$results.empty();
if (results.length === 0) {
this.$make_new_btn.addClass('hide');
this.$results.append(me.$placeholder);
return;
}
this.$make_new_btn.removeClass('hide');
this.$results.append(this.make_list_row());
results.forEach(function (result) {
me.$results.append(me.make_list_row(result));
});
if (more) {
var message = __("Only {0} entries shown. Please filter for more specific results.", [this.page_length]);
me.$results.append($("
" + message + "
"));
}
},
get_results: function get_results() {
var me = this;
var filters = this.get_query().filters;
Object.keys(this.setters).forEach(function (setter) {
filters[setter] = me.dialog.fields_dict[setter].get_value() || undefined;
me.args[setter] = filters[setter];
});
var date_val = this.dialog.fields_dict["date_range"].get_value();
if (date_val) {
filters[this.date_field] = ['Between', me.dialog.fields_dict["date_range"].parse(date_val)];
}
var args = {
doctype: me.doctype,
txt: me.dialog.fields_dict["search_term"].get_value(),
filters: filters,
filter_fields: Object.keys(me.setters).concat([me.date_field]),
page_length: this.page_length + 1,
query: this.get_query().query,
as_dict: 1
};
frappe.call({
type: "GET",
method: 'frappe.desk.search.search_widget',
no_spinner: true,
args: args,
callback: function callback(r) {
var results = [],
more = 0;
if (r.values.length) {
if (r.values.length > me.page_length) {
r.values.pop();
more = 1;
}
r.values.forEach(function (result) {
if (me.date_field in result) {
result["Date"] = result[me.date_field];
}
result.checked = 0;
result.parsed_date = Date.parse(result["Date"]);
results.push(result);
});
results.map(function (result) {
result["Date"] = frappe.format(result["Date"], { "fieldtype": "Date" });
});
results.sort(function (a, b) {
return a.parsed_date - b.parsed_date;
});
results[0].checked = 1;
}
me.render_result_list(results, more);
}
});
}
});
frappe.provide('frappe.ui');
var cur_dialog;
frappe.ui.open_dialogs = [];
frappe.ui.Dialog = frappe.ui.FieldGroup.extend({
init: function init(opts) {
this.display = false;
this.is_dialog = true;
$.extend(this, opts);
this._super();
this.make();
},
make: function make() {
this.$wrapper = frappe.get_modal("", "");
this.wrapper = this.$wrapper.find('.modal-dialog').get(0);
this.make_head();
this.body = this.$wrapper.find(".modal-body").get(0);
this.header = this.$wrapper.find(".modal-header");
this._super();
if (this.primary_action) {
this.set_primary_action(this.primary_action_label || __("Submit"), this.primary_action);
}
if (this.secondary_action_label) {
this.get_close_btn().html(this.secondary_action_label);
}
var me = this;
this.$wrapper.on("hide.bs.modal", function () {
me.display = false;
if (frappe.ui.open_dialogs[frappe.ui.open_dialogs.length - 1] === me) {
frappe.ui.open_dialogs.pop();
if (frappe.ui.open_dialogs.length) {
cur_dialog = frappe.ui.open_dialogs[frappe.ui.open_dialogs.length - 1];
} else {
cur_dialog = null;
}
}
me.onhide && me.onhide();
me.on_hide && me.on_hide();
}).on("shown.bs.modal", function () {
me.display = true;
cur_dialog = me;
frappe.ui.open_dialogs.push(me);
me.focus_on_first_input();
me.on_page_show && me.on_page_show();
}).on('scroll', function () {
var $input = $('input:focus');
if ($input.length && ['Date', 'Datetime', 'Time'].includes($input.attr('data-fieldtype'))) {
$input.blur();
}
});
},
focus_on_first_input: function focus_on_first_input() {
if (this.no_focus) return;
$.each(this.fields_list, function (i, f) {
if (!in_list(['Date', 'Datetime', 'Time'], f.df.fieldtype) && f.set_focus) {
f.set_focus();
return false;
}
});
},
get_primary_btn: function get_primary_btn() {
return this.$wrapper.find(".modal-header .btn-primary");
},
set_primary_action: function set_primary_action(label, click) {
this.has_primary_action = true;
var me = this;
return this.get_primary_btn().removeClass("hide").html(label).click(function () {
me.primary_action_fulfilled = true;
var values = me.get_values();
if (!values) return;
click.apply(me, [values]);
});
},
make_head: function make_head() {
var me = this;
this.set_title(this.title);
},
set_title: function set_title(t) {
this.$wrapper.find(".modal-title").html(t);
},
show: function show() {
this.$wrapper.modal("show");
this.primary_action_fulfilled = false;
},
hide: function hide(from_event) {
this.$wrapper.modal("hide");
},
get_close_btn: function get_close_btn() {
return this.$wrapper.find(".btn-modal-close");
},
no_cancel: function no_cancel() {
this.get_close_btn().toggle(false);
},
cancel: function cancel() {
this.get_close_btn().trigger("click");
}
});
frappe.provide("frappe.ui");
frappe.ui.app_icon = {
get_html: function get_html(module, small) {
var icon = module.icon;
var color = module.color;
var icon_style = "";
if (module.reverse) {
icon_style = "color: #36414C;";
}
if (!color) {
color = '#4aa3df';
}
if (!icon) {
icon = '
' + module._label[0].toUpperCase() + ' ';
} else if (icon.split(".").slice(-1)[0] === "svg") {
$.ajax({
url: frappe.urllib.get_full_url(icon),
dataType: "text",
async: false,
success: function success(data) {
icon = data;
}
});
icon = '
' + icon + ' ';
} else {
icon = '
';
}
return '
' + icon + '
';
}
};
frappe.provide('frappe.model');
$.extend(frappe.model, {
no_value_type: ['Section Break', 'Column Break', 'HTML', 'Table', 'Button', 'Image', 'Fold', 'Heading'],
layout_fields: ['Section Break', 'Column Break', 'Fold'],
std_fields_list: ['name', 'owner', 'creation', 'modified', 'modified_by', '_user_tags', '_comments', '_assign', '_liked_by', 'docstatus', 'parent', 'parenttype', 'parentfield', 'idx'],
std_fields: [{ fieldname: 'name', fieldtype: 'Link', label: __('ID') }, { fieldname: 'owner', fieldtype: 'Data', label: __('Created By') }, { fieldname: 'idx', fieldtype: 'Int', label: __('Index') }, { fieldname: 'creation', fieldtype: 'Date', label: __('Created On') }, { fieldname: 'modified', fieldtype: 'Date', label: __('Last Updated On') }, { fieldname: 'modified_by', fieldtype: 'Data', label: __('Last Updated By') }, { fieldname: '_user_tags', fieldtype: 'Data', label: __('Tags') }, { fieldname: '_liked_by', fieldtype: 'Data', label: __('Liked By') }, { fieldname: '_comments', fieldtype: 'Text', label: __('Comments') }, { fieldname: '_assign', fieldtype: 'Text', label: __('Assigned To') }, { fieldname: 'docstatus', fieldtype: 'Int', label: __('Document Status') }],
std_fields_table: [{ fieldname: 'parent', fieldtype: 'Data', label: __('Parent') }],
new_names: {},
events: {},
user_settings: {},
init: function init() {
frappe.realtime.on("doc_update", function (data) {
frappe.views.set_list_as_dirty(data.doctype);
var doc = locals[data.doctype] && locals[data.doctype][data.name];
if (doc) {
if (frappe.get_route()[0] === "Form" && cur_frm.doc.doctype === doc.doctype && cur_frm.doc.name === doc.name) {
if (!frappe.ui.form.is_saving && data.modified != cur_frm.doc.modified) {
doc.__needs_refresh = true;
cur_frm.show_if_needs_refresh();
}
} else {
if (!doc.__unsaved) {
frappe.model.remove_from_locals(doc.doctype, doc.name);
} else {
doc.__needs_refresh = true;
}
}
}
});
frappe.realtime.on("list_update", function (data) {
frappe.views.set_list_as_dirty(data.doctype);
});
},
is_value_type: function is_value_type(fieldtype) {
return frappe.model.no_value_type.indexOf(fieldtype) === -1;
},
get_std_field: function get_std_field(fieldname) {
var docfield = $.map([].concat(frappe.model.std_fields).concat(frappe.model.std_fields_table), function (d) {
if (d.fieldname == fieldname) return d;
});
if (!docfield.length) {
frappe.msgprint(__("Unknown Column: {0}", [fieldname]));
}
return docfield[0];
},
with_doctype: function with_doctype(doctype, _callback, async) {
if (locals.DocType[doctype]) {
_callback && _callback();
} else {
var cached_timestamp = null;
if (localStorage["_doctype:" + doctype]) {
var cached_doc = JSON.parse(localStorage["_doctype:" + doctype]);
cached_timestamp = cached_doc.modified;
}
return frappe.call({
method: 'frappe.desk.form.load.getdoctype',
type: "GET",
args: {
doctype: doctype,
with_parent: 1,
cached_timestamp: cached_timestamp
},
async: async,
freeze: true,
callback: function callback(r) {
if (r.exc) {
frappe.msgprint(__("Unable to load: {0}", [__(doctype)]));
throw "No doctype";
}
if (r.message == "use_cache") {
frappe.model.sync(cached_doc);
} else {
localStorage["_doctype:" + doctype] = JSON.stringify(r.docs);
}
frappe.model.init_doctype(doctype);
if (r.user_settings) {
frappe.model.user_settings[doctype] = JSON.parse(r.user_settings);
frappe.model.user_settings[doctype].updated_on = moment().toString();
}
_callback && _callback(r);
}
});
}
},
init_doctype: function init_doctype(doctype) {
var meta = locals.DocType[doctype];
if (meta.__list_js) {
eval(meta.__list_js);
}
if (meta.__calendar_js) {
eval(meta.__calendar_js);
}
if (meta.__map_js) {
eval(meta.__map_js);
}
if (meta.__tree_js) {
eval(meta.__tree_js);
}
if (meta.__templates) {
$.extend(frappe.templates, meta.__templates);
}
},
with_doc: function with_doc(doctype, name, _callback2) {
if (!name) name = doctype;
if (locals[doctype] && locals[doctype][name] && frappe.model.get_docinfo(doctype, name)) {
_callback2(name);
} else {
return frappe.call({
method: 'frappe.desk.form.load.getdoc',
type: "GET",
args: {
doctype: doctype,
name: name
},
freeze: true,
callback: function callback(r) {
_callback2(name, r);
}
});
}
},
get_docinfo: function get_docinfo(doctype, name) {
return frappe.model.docinfo[doctype] && frappe.model.docinfo[doctype][name] || null;
},
set_docinfo: function set_docinfo(doctype, name, key, value) {
if (frappe.model.docinfo[doctype] && frappe.model.docinfo[doctype][name]) {
frappe.model.docinfo[doctype][name][key] = value;
}
},
get_shared: function get_shared(doctype, name) {
return frappe.model.get_docinfo(doctype, name).shared;
},
get_server_module_name: function get_server_module_name(doctype) {
var dt = frappe.model.scrub(doctype);
var module = frappe.model.scrub(locals.DocType[doctype].module);
var app = frappe.boot.module_app[module];
return app + "." + module + '.doctype.' + dt + '.' + dt;
},
scrub: function scrub(txt) {
return txt.replace(/ /g, "_").toLowerCase();
},
unscrub: function unscrub(txt) {
return __(txt || '').replace(/-|_/g, " ").replace(/\w*/g, function (keywords) {
return keywords.charAt(0).toUpperCase() + keywords.substr(1).toLowerCase();
});
},
can_create: function can_create(doctype) {
return frappe.boot.user.can_create.indexOf(doctype) !== -1;
},
can_read: function can_read(doctype) {
return frappe.boot.user.can_read.indexOf(doctype) !== -1;
},
can_write: function can_write(doctype) {
return frappe.boot.user.can_write.indexOf(doctype) !== -1;
},
can_get_report: function can_get_report(doctype) {
return frappe.boot.user.can_get_report.indexOf(doctype) !== -1;
},
can_delete: function can_delete(doctype) {
if (!doctype) return false;
return frappe.boot.user.can_delete.indexOf(doctype) !== -1;
},
can_cancel: function can_cancel(doctype) {
if (!doctype) return false;
return frappe.boot.user.can_cancel.indexOf(doctype) !== -1;
},
is_submittable: function is_submittable(doctype) {
if (!doctype) return false;
return locals.DocType[doctype] && locals.DocType[doctype].is_submittable;
},
is_table: function is_table(doctype) {
if (!doctype) return false;
return locals.DocType[doctype] && locals.DocType[doctype].istable;
},
is_single: function is_single(doctype) {
if (!doctype) return false;
return frappe.boot.single_types.indexOf(doctype) != -1;
},
can_import: function can_import(doctype, frm) {
if (frappe.user_roles.includes("System Manager")) return true;
if (frm) return frm.perm[0].import === 1;
return frappe.boot.user.can_import.indexOf(doctype) !== -1;
},
can_export: function can_export(doctype, frm) {
if (frappe.user_roles.includes("System Manager")) return true;
if (frm) return frm.perm[0].export === 1;
return frappe.boot.user.can_export.indexOf(doctype) !== -1;
},
can_print: function can_print(doctype, frm) {
if (frm) return frm.perm[0].print === 1;
return frappe.boot.user.can_print.indexOf(doctype) !== -1;
},
can_email: function can_email(doctype, frm) {
if (frm) return frm.perm[0].email === 1;
return frappe.boot.user.can_email.indexOf(doctype) !== -1;
},
can_share: function can_share(doctype, frm) {
if (frm) {
return frm.perm[0].share === 1;
}
return frappe.boot.user.can_share.indexOf(doctype) !== -1;
},
can_set_user_permissions: function can_set_user_permissions(doctype, frm) {
if (frappe.user_roles.includes("System Manager")) return true;
if (frm) return frm.perm[0].set_user_permissions === 1;
return frappe.boot.user.can_set_user_permissions.indexOf(doctype) !== -1;
},
has_value: function has_value(dt, dn, fn) {
var val = locals[dt] && locals[dt][dn] && locals[dt][dn][fn];
var df = frappe.meta.get_docfield(dt, fn, dn);
if (df.fieldtype == 'Table') {
var ret = false;
$.each(locals[df.options] || {}, function (k, d) {
if (d.parent == dn && d.parenttype == dt && d.parentfield == df.fieldname) {
ret = true;
return false;
}
});
} else {
var ret = !is_null(val);
}
return ret ? true : false;
},
get_list: function get_list(doctype, filters) {
var docsdict = locals[doctype] || locals[":" + doctype] || {};
if ($.isEmptyObject(docsdict)) return [];
return frappe.utils.filter_dict(docsdict, filters);
},
get_value: function get_value(doctype, filters, fieldname, _callback3) {
if (_callback3) {
frappe.call({
method: "frappe.client.get_value",
args: {
doctype: doctype,
fieldname: fieldname,
filters: filters
},
callback: function callback(r) {
if (!r.exc) {
_callback3(r.message);
}
}
});
} else {
if (typeof filters === "string" && locals[doctype] && locals[doctype][filters]) {
return locals[doctype][filters][fieldname];
} else {
var l = frappe.get_list(doctype, filters);
return l.length && l[0] ? l[0][fieldname] : null;
}
}
},
set_value: function set_value(doctype, docname, fieldname, value, fieldtype) {
var doc = locals[doctype] && locals[doctype][docname];
var to_update = fieldname;
var tasks = [];
if (!$.isPlainObject(to_update)) {
to_update = {};
to_update[fieldname] = value;
}
$.each(to_update, function (key, value) {
if (doc && doc[key] !== value) {
if (doc.__unedited && !(!doc[key] && !value)) {
doc.__unedited = false;
}
doc[key] = value;
tasks.push(function () {
return frappe.model.trigger(key, value, doc);
});
} else {
if (fieldtype == "Link" && doc) {
tasks.push(function () {
return frappe.model.trigger(key, value, doc);
});
}
}
});
return frappe.run_serially(tasks);
},
on: function on(doctype, fieldname, fn) {
frappe.provide("frappe.model.events." + doctype);
if (!frappe.model.events[doctype][fieldname]) {
frappe.model.events[doctype][fieldname] = [];
}
frappe.model.events[doctype][fieldname].push(fn);
},
trigger: function trigger(fieldname, value, doc) {
var tasks = [];
var runner = function runner(events, event_doc) {
$.each(events || [], function (i, fn) {
if (fn) {
var _promise = fn(fieldname, value, event_doc || doc);
if (_promise && _promise.then) {
return _promise;
} else {
return frappe.after_server_call();
}
}
});
};
if (frappe.model.events[doc.doctype]) {
tasks.push(function () {
return runner(frappe.model.events[doc.doctype][fieldname]);
});
tasks.push(function () {
return runner(frappe.model.events[doc.doctype]['*']);
});
}
return frappe.run_serially(tasks);
},
get_doc: function get_doc(doctype, name) {
if (!name) name = doctype;
if ($.isPlainObject(name)) {
var doc = frappe.get_list(doctype, name);
return doc && doc.length ? doc[0] : null;
}
return locals[doctype] ? locals[doctype][name] : null;
},
get_children: function get_children(doctype, parent, parentfield, filters) {
if ($.isPlainObject(doctype)) {
var doc = doctype;
var filters = parentfield;
var parentfield = parent;
} else {
var doc = frappe.get_doc(doctype, parent);
}
var children = doc[parentfield] || [];
if (filters) {
return frappe.utils.filter_dict(children, filters);
} else {
return children;
}
},
clear_table: function clear_table(doc, parentfield) {
for (var i = 0, l = (doc[parentfield] || []).length; i < l; i++) {
var d = doc[parentfield][i];
delete locals[d.doctype][d.name];
}
doc[parentfield] = [];
},
remove_from_locals: function remove_from_locals(doctype, name) {
this.clear_doc(doctype, name);
if (frappe.views.formview[doctype]) {
delete frappe.views.formview[doctype].frm.opendocs[name];
}
},
clear_doc: function clear_doc(doctype, name) {
var doc = locals[doctype] && locals[doctype][name];
if (!doc) return;
var parent = null;
if (doc.parenttype) {
var parent = doc.parent,
parenttype = doc.parenttype,
parentfield = doc.parentfield;
}
delete locals[doctype][name];
if (parent) {
var parent_doc = locals[parenttype][parent];
var newlist = [],
idx = 1;
$.each(parent_doc[parentfield], function (i, d) {
if (d.name != name) {
newlist.push(d);
d.idx = idx;
idx++;
}
parent_doc[parentfield] = newlist;
});
}
},
get_no_copy_list: function get_no_copy_list(doctype) {
var no_copy_list = ['name', 'amended_from', 'amendment_date', 'cancel_reason'];
var docfields = frappe.get_doc("DocType", doctype).fields || [];
for (var i = 0, j = docfields.length; i < j; i++) {
var df = docfields[i];
if (cint(df.no_copy)) no_copy_list.push(df.fieldname);
}
return no_copy_list;
},
delete_doc: function delete_doc(doctype, docname, _callback4) {
frappe.confirm(__("Permanently delete {0}?", [docname]), function () {
return frappe.call({
method: 'frappe.client.delete',
args: {
doctype: doctype,
name: docname
},
callback: function callback(r, rt) {
if (!r.exc) {
frappe.utils.play_sound("delete");
frappe.model.clear_doc(doctype, docname);
if (_callback4) _callback4(r, rt);
}
}
});
});
},
rename_doc: function rename_doc(doctype, docname, _callback5) {
var d = new frappe.ui.Dialog({
title: __("Rename {0}", [__(docname)]),
fields: [{ label: __("New Name"), fieldname: "new_name", fieldtype: "Data", reqd: 1, "default": docname }, { label: __("Merge with existing"), fieldtype: "Check", fieldname: "merge" }]
});
d.set_primary_action(__("Rename"), function () {
var args = d.get_values();
if (!args) return;
return frappe.call({
method: "frappe.model.rename_doc.rename_doc",
args: {
doctype: doctype,
old: docname,
"new": args.new_name,
"merge": args.merge
},
btn: d.get_primary_btn(),
callback: function callback(r, rt) {
if (!r.exc) {
$(document).trigger('rename', [doctype, docname, r.message || args.new_name]);
if (locals[doctype] && locals[doctype][docname]) delete locals[doctype][docname];
d.hide();
if (_callback5) _callback5(r.message);
}
}
});
});
d.show();
},
round_floats_in: function round_floats_in(doc, fieldnames) {
if (!fieldnames) {
fieldnames = frappe.meta.get_fieldnames(doc.doctype, doc.parent, { "fieldtype": ["in", ["Currency", "Float"]] });
}
for (var i = 0, j = fieldnames.length; i < j; i++) {
var fieldname = fieldnames[i];
doc[fieldname] = flt(doc[fieldname], precision(fieldname, doc));
}
},
validate_missing: function validate_missing(doc, fieldname) {
if (!doc[fieldname]) {
frappe.throw(__("Please specify") + ": " + __(frappe.meta.get_label(doc.doctype, fieldname, doc.parent || doc.name)));
}
},
get_all_docs: function get_all_docs(doc) {
var all = [doc];
for (var key in doc) {
if ($.isArray(doc[key])) {
var children = doc[key];
for (var i = 0, l = children.length; i < l; i++) {
all.push(children[i]);
}
}
}
return all;
}
});
frappe.get_doc = frappe.model.get_doc;
frappe.get_children = frappe.model.get_children;
frappe.get_list = frappe.model.get_list;
var getchildren = function getchildren(doctype, parent, parentfield) {
var children = [];
$.each(locals[doctype] || {}, function (i, d) {
if (d.parent === parent && d.parentfield === parentfield) {
children.push(d);
}
});
return children;
};
frappe.db = {
get_value: function get_value(doctype, filters, fieldname, _callback) {
return frappe.call({
method: "frappe.client.get_value",
args: {
doctype: doctype,
fieldname: fieldname,
filters: filters
},
callback: function callback(r) {
_callback && _callback(r.message);
}
});
},
set_value: function set_value(doctype, docname, fieldname, value, _callback2) {
return frappe.call({
method: "frappe.client.set_value",
args: {
doctype: doctype,
name: docname,
fieldname: fieldname,
value: value
},
callback: function callback(r) {
_callback2 && _callback2(r.message);
}
});
}
};
frappe.provide('frappe.meta.docfield_map');
frappe.provide('frappe.meta.docfield_copy');
frappe.provide('frappe.meta.docfield_list');
frappe.provide('frappe.meta.doctypes');
frappe.provide("frappe.meta.precision_map");
frappe.get_meta = function (doctype) {
return locals["DocType"][doctype];
};
$.extend(frappe.meta, {
sync: function sync(doc) {
$.each(doc.fields, function (i, df) {
frappe.meta.add_field(df);
});
frappe.meta.sync_messages(doc);
if (doc.__print_formats) frappe.model.sync(doc.__print_formats);
if (doc.__workflow_docs) frappe.model.sync(doc.__workflow_docs);
},
add_field: function add_field(df) {
frappe.provide('frappe.meta.docfield_map.' + df.parent);
frappe.meta.docfield_map[df.parent][df.fieldname || df.label] = df;
if (!frappe.meta.docfield_list[df.parent]) frappe.meta.docfield_list[df.parent] = [];
for (var i in frappe.meta.docfield_list[df.parent]) {
var d = frappe.meta.docfield_list[df.parent][i];
if (df.fieldname == d.fieldname) return;
}
frappe.meta.docfield_list[df.parent].push(df);
},
make_docfield_copy_for: function make_docfield_copy_for(doctype, docname) {
var c = frappe.meta.docfield_copy;
if (!c[doctype]) c[doctype] = {};
if (!c[doctype][docname]) c[doctype][docname] = {};
var docfield_list = frappe.meta.docfield_list[doctype] || [];
for (var i = 0, j = docfield_list.length; i < j; i++) {
var df = docfield_list[i];
c[doctype][docname][df.fieldname || df.label] = copy_dict(df);
}
},
get_field: function get_field(doctype, fieldname, name) {
var out = frappe.meta.get_docfield(doctype, fieldname, name);
if (!out) {
frappe.model.std_fields.every(function (d) {
if (d.fieldname === fieldname) {
out = d;
return false;
} else {
return true;
}
});
}
return out;
},
get_docfield: function get_docfield(doctype, fieldname, name) {
var fields_dict = frappe.meta.get_docfield_copy(doctype, name);
return fields_dict ? fields_dict[fieldname] : null;
},
set_formatter: function set_formatter(doctype, fieldname, name, formatter) {
frappe.meta.get_docfield(doctype, fieldname, name).formatter = formatter;
},
set_indicator_formatter: function set_indicator_formatter(doctype, fieldname, name, get_text, get_color) {
frappe.meta.get_docfield(doctype, fieldname, name).formatter = function (value, df, options, doc) {
return repl('
%(name)s ', {
color: get_color(),
name: get_text()
});
};
},
get_docfields: function get_docfields(doctype, name, filters) {
var docfield_map = frappe.meta.get_docfield_copy(doctype, name);
var docfields = frappe.meta.sort_docfields(docfield_map);
if (filters) {
docfields = frappe.utils.filter_dict(docfields, filters);
}
return docfields;
},
get_linked_fields: function get_linked_fields(doctype) {
return $.map(frappe.get_meta(doctype).fields, function (d) {
return d.fieldtype == "Link" ? d.options : null;
});
},
get_fields_to_check_permissions: function get_fields_to_check_permissions(doctype, name, user_permission_doctypes) {
var fields = $.map(frappe.meta.get_docfields(doctype, name), function (df) {
return df.fieldtype === "Link" && df.ignore_user_permissions !== 1 && user_permission_doctypes.indexOf(df.options) !== -1 ? df : null;
});
if (user_permission_doctypes.indexOf(doctype) !== -1) {
fields = fields.concat({ label: "Name", fieldname: name, options: doctype });
}
return fields;
},
sort_docfields: function sort_docfields(docs) {
return $.map(docs, function (d) {
return d;
}).sort(function (a, b) {
return a.idx - b.idx;
});
},
get_docfield_copy: function get_docfield_copy(doctype, name) {
if (!name) return frappe.meta.docfield_map[doctype];
if (!(frappe.meta.docfield_copy[doctype] && frappe.meta.docfield_copy[doctype][name])) {
frappe.meta.make_docfield_copy_for(doctype, name);
}
return frappe.meta.docfield_copy[doctype][name];
},
get_fieldnames: function get_fieldnames(doctype, name, filters) {
return $.map(frappe.utils.filter_dict(frappe.meta.docfield_map[doctype], filters), function (df) {
return df.fieldname;
});
},
has_field: function has_field(dt, fn) {
return frappe.meta.docfield_map[dt][fn];
},
get_table_fields: function get_table_fields(dt) {
return $.map(frappe.meta.docfield_list[dt], function (d) {
return d.fieldtype === 'Table' ? d : null;
});
},
get_doctype_for_field: function get_doctype_for_field(doctype, key) {
var out = null;
if (in_list(frappe.model.std_fields_list, key)) {
out = doctype;
} else if (frappe.meta.has_field(doctype, key)) {
out = doctype;
} else {
frappe.meta.get_table_fields(doctype).every(function (d) {
if (frappe.meta.has_field(d.options, key)) {
out = d.options;
return false;
}
return true;
});
if (!out) {
console.log(__('Warning: Unable to find {0} in any table related to {1}', [key, __(doctype)]));
}
}
return out;
},
get_parentfield: function get_parentfield(parent_dt, child_dt) {
var df = (frappe.get_doc("DocType", parent_dt).fields || []).filter(function (d) {
return d.fieldtype === "Table" && d.options === child_dt;
});
if (!df.length) throw "parentfield not found for " + parent_dt + ", " + child_dt;
return df[0].fieldname;
},
get_label: function get_label(dt, fn, dn) {
var standard = {
'owner': __('Owner'),
'creation': __('Created On'),
'modified': __('Last Modified On'),
'idx': __('Idx'),
'name': __('Name'),
'modified_by': __('Last Modified By')
};
if (standard[fn]) {
return standard[fn];
} else {
var df = this.get_docfield(dt, fn, dn);
return (df ? df.label : "") || fn;
}
},
get_print_formats: function get_print_formats(doctype) {
var print_format_list = ["Standard"];
var default_print_format = locals.DocType[doctype].default_print_format;
var print_formats = frappe.get_list("Print Format", { doc_type: doctype }).sort(function (a, b) {
return a > b ? 1 : -1;
});
$.each(print_formats, function (i, d) {
if (!in_list(print_format_list, d.name) && in_list(['Server', 'Client'], d.print_format_type)) print_format_list.push(d.name);
});
if (default_print_format && default_print_format != "Standard") {
var index = print_format_list.indexOf(default_print_format);
print_format_list.splice(index, 1).sort();
print_format_list.unshift(default_print_format);
}
return print_format_list;
},
sync_messages: function sync_messages(doc) {
if (doc.__messages) {
$.extend(frappe._messages, doc.__messages);
}
},
get_field_currency: function get_field_currency(df, doc) {
var currency = frappe.boot.sysdefaults.currency;
if (!doc && cur_frm) doc = cur_frm.doc;
if (df && df.options) {
if (doc && df.options.indexOf(":") != -1) {
var options = df.options.split(":");
if (options.length == 3) {
var docname = doc[options[1]];
if (!docname && cur_frm) {
docname = cur_frm.doc[options[1]];
}
currency = frappe.model.get_value(options[0], docname, options[2]) || frappe.model.get_value(":" + options[0], docname, options[2]) || currency;
}
} else if (doc && doc[df.options]) {
currency = doc[df.options];
} else if (cur_frm && cur_frm.doc[df.options]) {
currency = cur_frm.doc[df.options];
}
}
return currency;
},
get_field_precision: function get_field_precision(df, doc) {
var precision = null;
if (df && cint(df.precision)) {
precision = cint(df.precision);
} else if (df && df.fieldtype === "Currency") {
precision = cint(frappe.defaults.get_default("currency_precision"));
if (!precision) {
var number_format = get_number_format();
var number_format_info = get_number_format_info(number_format);
precision = number_format_info.precision;
}
} else {
precision = cint(frappe.defaults.get_default("float_precision")) || 3;
}
return precision;
}
});
$.extend(frappe.model, {
docinfo: {},
sync: function sync(r) {
var isPlain;
if (!r.docs && !r.docinfo) r = { docs: r };
isPlain = $.isPlainObject(r.docs);
if (isPlain) r.docs = [r.docs];
if (r.docs) {
var last_parent_name = null;
for (var i = 0, l = r.docs.length; i < l; i++) {
var d = r.docs[i];
frappe.model.add_to_locals(d);
d.__last_sync_on = new Date();
if (d.doctype === "DocType") {
frappe.meta.sync(d);
}
if (cur_frm && cur_frm.doctype == d.doctype && cur_frm.docname == d.name) {
cur_frm.doc = d;
}
if (d.localname) {
frappe.model.new_names[d.localname] = d.name;
$(document).trigger('rename', [d.doctype, d.localname, d.name]);
delete locals[d.doctype][d.localname];
if (i === 0) {
frappe.model.docinfo[d.doctype][d.name] = frappe.model.docinfo[d.doctype][d.localname];
frappe.model.docinfo[d.doctype][d.localname] = undefined;
}
}
}
if (cur_frm && isPlain) cur_frm.dirty();
}
if (r.docinfo) {
if (r.docs) {
var doc = r.docs[0];
} else {
if (cur_frm) var doc = cur_frm.doc;
}
if (doc) {
if (!frappe.model.docinfo[doc.doctype]) frappe.model.docinfo[doc.doctype] = {};
frappe.model.docinfo[doc.doctype][doc.name] = r.docinfo;
}
}
return r.docs;
},
add_to_locals: function add_to_locals(doc) {
if (!locals[doc.doctype]) locals[doc.doctype] = {};
if (!doc.name && doc.__islocal) {
if (!doc.parentfield) frappe.model.clear_doc(doc);
doc.name = frappe.model.get_new_name(doc.doctype);
if (!doc.parentfield) frappe.provide("frappe.model.docinfo." + doc.doctype + "." + doc.name);
}
locals[doc.doctype][doc.name] = doc;
if (!doc.parentfield) {
for (var i in doc) {
var value = doc[i];
if ($.isArray(value)) {
for (var x = 0, y = value.length; x < y; x++) {
var d = value[x];
if (!d.parent) d.parent = doc.name;
frappe.model.add_to_locals(d);
}
}
}
}
}
});
frappe.provide("frappe.model");
$.extend(frappe.model, {
new_names: {},
new_name_count: {},
get_new_doc: function get_new_doc(doctype, parent_doc, parentfield, with_mandatory_children) {
frappe.provide("locals." + doctype);
var doc = {
docstatus: 0,
doctype: doctype,
name: frappe.model.get_new_name(doctype),
__islocal: 1,
__unsaved: 1,
owner: frappe.session.user
};
frappe.model.set_default_values(doc, parent_doc);
if (parent_doc) {
$.extend(doc, {
parent: parent_doc.name,
parentfield: parentfield,
parenttype: parent_doc.doctype
});
if (!parent_doc[parentfield]) parent_doc[parentfield] = [];
doc.idx = parent_doc[parentfield].length + 1;
parent_doc[parentfield].push(doc);
} else {
frappe.provide("frappe.model.docinfo." + doctype + "." + doc.name);
}
frappe.model.add_to_locals(doc);
if (with_mandatory_children) {
frappe.model.create_mandatory_children(doc);
}
if (!parent_doc) {
doc.__run_link_triggers = 1;
}
if (frappe.route_options && frappe.route_options.name_field) {
var meta = frappe.get_meta(doctype);
if (meta.autoname && meta.autoname.indexOf("field:") !== -1) {
doc[meta.autoname.substr(6)] = frappe.route_options.name_field;
} else if (meta.title_field) {
doc[meta.title_field] = frappe.route_options.name_field;
}
delete frappe.route_options.name_field;
}
if (frappe.route_options && !doc.parent) {
$.each(frappe.route_options, function (fieldname, value) {
var df = frappe.meta.has_field(doctype, fieldname);
if (df && in_list(['Link', 'Data', 'Select'], df.fieldtype) && !df.no_copy) {
doc[fieldname] = value;
}
});
frappe.route_options = null;
}
return doc;
},
make_new_doc_and_get_name: function make_new_doc_and_get_name(doctype, with_mandatory_children) {
return frappe.model.get_new_doc(doctype, null, null, with_mandatory_children).name;
},
get_new_name: function get_new_name(doctype) {
var cnt = frappe.model.new_name_count;
if (!cnt[doctype]) cnt[doctype] = 0;
cnt[doctype]++;
return __('New') + ' ' + __(doctype) + ' ' + cnt[doctype];
},
set_default_values: function set_default_values(doc, parent_doc) {
var doctype = doc.doctype;
var docfields = frappe.meta.docfield_list[doctype] || [];
var updated = [];
for (var fid = 0; fid < docfields.length; fid++) {
var f = docfields[fid];
if (!in_list(frappe.model.no_value_type, f.fieldtype) && doc[f.fieldname] == null) {
var v = frappe.model.get_default_value(f, doc, parent_doc);
if (v) {
if (in_list(["Int", "Check"], f.fieldtype)) v = cint(v);else if (in_list(["Currency", "Float"], f.fieldtype)) v = flt(v);
doc[f.fieldname] = v;
updated.push(f.fieldname);
} else if (f.fieldtype == "Select" && f.options && typeof f.options === 'string' && !in_list(["[Select]", "Loading..."], f.options)) {
doc[f.fieldname] = f.options.split("\n")[0];
}
}
}
return updated;
},
create_mandatory_children: function create_mandatory_children(doc) {
var meta = frappe.get_meta(doc.doctype);
if (meta && meta.istable) return;
frappe.meta.docfield_list[doc.doctype].forEach(function (df) {
if (df.fieldtype === 'Table' && df.reqd) {
frappe.model.add_child(doc, df.fieldname);
}
});
},
get_default_value: function get_default_value(df, doc, parent_doc) {
var user_default = "";
var user_permissions = frappe.defaults.get_user_permissions();
var meta = frappe.get_meta(doc.doctype);
var has_user_permissions = df.fieldtype === "Link" && user_permissions && df.ignore_user_permissions != 1 && user_permissions[df.options];
if (df.fieldtype === "Link" && df.options !== "User") {
if (df.linked_document_type === "Setup" && has_user_permissions && user_permissions[df.options].length === 1) {
return user_permissions[df.options][0];
}
if (!df.ignore_user_permissions) {
var user_defaults = frappe.defaults.get_user_defaults(df.options);
if (user_defaults && user_defaults.length === 1) {
user_default = user_defaults[0];
}
}
if (!user_default) {
user_default = frappe.defaults.get_user_default(df.fieldname);
}
if (!user_default && df.remember_last_selected_value && frappe.boot.user.last_selected_values) {
user_default = frappe.boot.user.last_selected_values[df.options];
}
var is_allowed_user_default = user_default && (!has_user_permissions || user_permissions[df.options].indexOf(user_default) !== -1);
if (is_allowed_user_default) {
return user_default;
}
}
if (df['default']) {
if (df["default"] == "__user" || df["default"].toLowerCase() == "user") {
return frappe.session.user;
} else if (df["default"] == "user_fullname") {
return frappe.session.user_fullname;
} else if (df["default"] == "Today") {
return frappe.datetime.get_today();
} else if ((df["default"] || "").toLowerCase() === "now") {
return frappe.datetime.now_datetime();
} else if (df["default"][0] === ":") {
var boot_doc = frappe.model.get_default_from_boot_docs(df, doc, parent_doc);
var is_allowed_boot_doc = !has_user_permissions || user_permissions[df.options].indexOf(boot_doc) !== -1;
if (is_allowed_boot_doc) {
return boot_doc;
}
} else if (df.fieldname === meta.title_field) {
return "";
}
var is_allowed_default = !has_user_permissions || user_permissions[df.options].indexOf(df["default"]) !== -1;
if (df.fieldtype !== "Link" || df.options === "User" || is_allowed_default) {
return df["default"];
}
} else if (df.fieldtype == "Time") {
return frappe.datetime.now_time();
}
},
get_default_from_boot_docs: function get_default_from_boot_docs(df, doc, parent_doc) {
if (frappe.get_list(df["default"]).length > 0) {
var ref_fieldname = df["default"].slice(1).toLowerCase().replace(" ", "_");
var ref_value = parent_doc ? parent_doc[ref_fieldname] : frappe.defaults.get_user_default(ref_fieldname);
var ref_doc = ref_value ? frappe.get_doc(df["default"], ref_value) : null;
if (ref_doc && ref_doc[df.fieldname]) {
return ref_doc[df.fieldname];
}
}
},
add_child: function add_child(parent_doc, doctype, parentfield, idx) {
if (arguments.length === 2) {
parentfield = doctype;
doctype = frappe.meta.get_field(parent_doc.doctype, parentfield).options;
}
idx = idx ? idx - 0.1 : (parent_doc[parentfield] || []).length + 1;
var child = frappe.model.get_new_doc(doctype, parent_doc, parentfield);
child.idx = idx;
if (idx !== cint(idx)) {
var sorted = parent_doc[parentfield].sort(function (a, b) {
return a.idx - b.idx;
});
for (var i = 0, j = sorted.length; i < j; i++) {
var d = sorted[i];
d.idx = i + 1;
}
}
if (cur_frm && cur_frm.doc == parent_doc) cur_frm.dirty();
return child;
},
copy_doc: function copy_doc(doc, from_amend, parent_doc, parentfield) {
var no_copy_list = ['name', 'amended_from', 'amendment_date', 'cancel_reason'];
var newdoc = frappe.model.get_new_doc(doc.doctype, parent_doc, parentfield);
for (var key in doc) {
var df = frappe.meta.get_docfield(doc.doctype, key);
if (df && key.substr(0, 2) != '__' && !in_list(no_copy_list, key) && !(df && !from_amend && cint(df.no_copy) == 1)) {
var value = doc[key] || [];
if (df.fieldtype === "Table") {
for (var i = 0, j = value.length; i < j; i++) {
var d = value[i];
frappe.model.copy_doc(d, from_amend, newdoc, df.fieldname);
}
} else {
newdoc[key] = doc[key];
}
}
}
var user = frappe.session.user;
newdoc.__islocal = 1;
newdoc.docstatus = 0;
newdoc.owner = user;
newdoc.creation = '';
newdoc.modified_by = user;
newdoc.modified = '';
return newdoc;
},
open_mapped_doc: function open_mapped_doc(opts) {
if (opts.frm && opts.frm.doc.__unsaved) {
frappe.throw(__("You have unsaved changes in this form. Please save before you continue."));
} else if (!opts.source_name && opts.frm) {
opts.source_name = opts.frm.doc.name;
}
return frappe.call({
type: "POST",
method: 'frappe.model.mapper.make_mapped_doc',
args: {
method: opts.method,
source_name: opts.source_name,
selected_children: opts.frm.get_selected()
},
freeze: true,
callback: function callback(r) {
if (!r.exc) {
frappe.model.sync(r.message);
if (opts.run_link_triggers) {
frappe.get_doc(r.message.doctype, r.message.name).__run_link_triggers = true;
}
frappe.set_route("Form", r.message.doctype, r.message.name);
}
}
});
}
});
frappe.create_routes = {};
frappe.new_doc = function (doctype, opts) {
return new Promise(function (resolve) {
if (opts && $.isPlainObject(opts)) {
frappe.route_options = opts;
}
frappe.model.with_doctype(doctype, function () {
if (frappe.create_routes[doctype]) {
frappe.set_route(frappe.create_routes[doctype]).then(function () {
return resolve();
});
} else {
frappe.ui.form.make_quick_entry(doctype).then(function () {
return resolve();
});
}
});
});
};
frappe.provide("frappe.perm");
var READ = "read",
WRITE = "write",
CREATE = "create",
DELETE = "delete";
var SUBMIT = "submit",
CANCEL = "cancel",
AMEND = "amend";
$.extend(frappe.perm, {
rights: ["read", "write", "create", "delete", "submit", "cancel", "amend", "report", "import", "export", "print", "email", "share", "set_user_permissions"],
doctype_perm: {},
has_perm: function has_perm(doctype, permlevel, ptype, doc) {
if (!permlevel) permlevel = 0;
if (!frappe.perm.doctype_perm[doctype]) {
frappe.perm.doctype_perm[doctype] = frappe.perm.get_perm(doctype);
}
var perms = frappe.perm.doctype_perm[doctype];
if (!perms) return false;
if (!perms[permlevel]) return false;
var perm = !!perms[permlevel][ptype];
if (permlevel === 0 && perm && doc) {
var docinfo = frappe.model.get_docinfo(doctype, doc.name);
if (docinfo && !docinfo.permissions[ptype]) perm = false;
}
return perm;
},
get_perm: function get_perm(doctype, doc) {
var perm = [{ read: 0, apply_user_permissions: {} }];
var meta = frappe.get_doc("DocType", doctype);
if (!meta) {
return perm;
}
if (frappe.session.user === "Administrator" || frappe.user_roles.includes("Administrator")) {
perm[0].read = 1;
}
frappe.perm.build_role_permissions(perm, meta);
if (doc) {
var docinfo = frappe.model.get_docinfo(doctype, doc.name);
if (docinfo) {
$.each(docinfo.permissions || [], function (ptype, val) {
perm[0][ptype] = val;
});
}
if (!$.isEmptyObject(perm[0].if_owner)) {
if (doc.owner === frappe.session.user) {
$.extend(perm[0], perm[0].if_owner);
} else {
$.each(perm[0].if_owner, function (ptype, value) {
if (perm[0].if_owner[ptype]) {
perm[0][ptype] = 0;
}
});
}
}
if (docinfo && docinfo.shared) {
for (var i = 0; i < docinfo.shared.length; i++) {
var s = docinfo.shared[i];
if (s.user === frappe.session.user) {
perm[0]["read"] = perm[0]["read"] || s.read;
perm[0]["write"] = perm[0]["write"] || s.write;
perm[0]["share"] = perm[0]["share"] || s.share;
if (s.read) {
perm[0].email = frappe.boot.user.can_email.indexOf(doctype) !== -1 ? 1 : 0;
perm[0].print = frappe.boot.user.can_print.indexOf(doctype) !== -1 ? 1 : 0;
}
}
}
}
}
if (frappe.model.can_read(doctype) && !perm[0].read) {
perm[0].read = 1;
}
return perm;
},
build_role_permissions: function build_role_permissions(perm, meta) {
$.each(meta.permissions || [], function (i, p) {
if (frappe.user_roles.includes(p.role)) {
var permlevel = cint(p.permlevel);
if (!perm[permlevel]) {
perm[permlevel] = {};
}
$.each(frappe.perm.rights, function (i, key) {
perm[permlevel][key] = perm[permlevel][key] || p[key] || 0;
if (permlevel === 0) {
var apply_user_permissions = perm[permlevel].apply_user_permissions;
var current_value = apply_user_permissions[key] === undefined ? 1 : apply_user_permissions[key];
apply_user_permissions[key] = current_value && cint(p.apply_user_permissions);
}
});
if (permlevel === 0 && cint(p.apply_user_permissions) && p.user_permission_doctypes) {
var user_permission_doctypes = JSON.parse(p.user_permission_doctypes);
if (user_permission_doctypes && user_permission_doctypes.length) {
if (!perm[permlevel]["user_permission_doctypes"]) {
perm[permlevel]["user_permission_doctypes"] = {};
}
$.each(frappe.perm.rights, function (i, key) {
if (!perm[permlevel]["user_permission_doctypes"][key]) {
perm[permlevel]["user_permission_doctypes"][key] = [];
}
perm[permlevel]["user_permission_doctypes"][key].push(user_permission_doctypes);
});
}
}
}
});
$.each(perm[0], function (key, val) {
if (!val) {
delete perm[0][key];
}
});
$.each(perm, function (i, v) {
if (v === undefined) {
perm[i] = {};
}
});
},
get_match_rules: function get_match_rules(doctype, ptype) {
var me = this;
var match_rules = [];
if (!ptype) ptype = "read";
var perm = frappe.perm.get_perm(doctype);
var apply_user_permissions = perm[0].apply_user_permissions;
if (!apply_user_permissions[ptype]) {
return match_rules;
}
var user_permissions = frappe.defaults.get_user_permissions();
if (user_permissions && !$.isEmptyObject(user_permissions)) {
if (perm[0].user_permission_doctypes) {
var user_permission_doctypes = me.get_user_permission_doctypes(perm[0].user_permission_doctypes[ptype], user_permissions);
} else {
var user_permission_doctypes = [[doctype].concat(frappe.meta.get_linked_fields(doctype))];
}
$.each(user_permission_doctypes, function (i, doctypes) {
var rules = {};
var fields_to_check = frappe.meta.get_fields_to_check_permissions(doctype, null, doctypes);
$.each(fields_to_check, function (i, df) {
rules[df.label] = user_permissions[df.options] || [];
});
if (!$.isEmptyObject(rules)) {
match_rules.push(rules);
}
});
}
if (perm[0].if_owner && perm[0].read) {
match_rules.push({ "Owner": frappe.session.user });
}
return match_rules;
},
get_user_permission_doctypes: function get_user_permission_doctypes(user_permission_doctypes, user_permissions) {
var out = [];
if (user_permission_doctypes && user_permission_doctypes.length) {
$.each(user_permission_doctypes, function (i, doctypes) {
var valid_doctypes = [];
$.each(doctypes, function (i, d) {
if (user_permissions[d]) {
valid_doctypes.push(d);
}
});
if (valid_doctypes.length) {
out.push(valid_doctypes);
}
});
} else {
out = [Object.keys(user_permissions)];
}
if (out.length > 1) {
var common = out[0];
for (var i = 1, l = out.length; i < l; i++) {
common = frappe.utils.intersection(common, out[i]);
if (!common.length) {
break;
}
}
if (common.length) {
common.sort();
for (var i = 0, l = out.length; i < l; i++) {
var arr = [].concat(out).sort();
if (JSON.stringify(common) === JSON.stringify(arr)) {
out = [common];
break;
}
}
}
}
return out;
},
get_field_display_status: function get_field_display_status(df, doc, perm, explain) {
if (!perm && doc) {
perm = frappe.perm.get_perm(doc.doctype, doc);
}
if (!perm) {
return df && (cint(df.hidden) || cint(df.hidden_due_to_dependency)) ? "None" : "Write";
}
if (!df.permlevel) df.permlevel = 0;
var p = perm[df.permlevel];
var status = "None";
if (p) {
if (p.write && !df.disabled) {
status = "Write";
} else if (p.read) {
status = "Read";
}
}
if (explain) console.log("By Permission:" + status);
if (cint(df.hidden)) status = "None";
if (explain) console.log("By Hidden:" + status);
if (cint(df.hidden_due_to_dependency)) status = "None";
if (explain) console.log("By Hidden Due To Dependency:" + status);
if (!doc) {
return status;
}
if (status === "Write" && cint(doc.docstatus) > 0) status = "Read";
if (explain) console.log("By Submit:" + status);
var allow_on_submit = cint(df.allow_on_submit);
if (status === "Read" && allow_on_submit && cint(doc.docstatus) === 1 && p.write) {
status = "Write";
}
if (explain) console.log("By Allow on Submit:" + status);
if (status === "Read" && cur_frm && cur_frm.state_fieldname) {
if (cint(cur_frm.read_only) || in_list(cur_frm.states.update_fields, df.fieldname) || df.fieldname == cur_frm.state_fieldname) {
status = "Read";
}
}
if (explain) console.log("By Workflow:" + status);
if (status === "Write" && cint(df.read_only)) {
status = "Read";
}
if (explain) console.log("By Read Only:" + status);
if (status === "Write" && df.set_only_once && !doc.__islocal) {
status = "Read";
}
if (explain) console.log("By Set Only Once:" + status);
return status;
},
is_visible: function is_visible(df, doc, perm) {
if (typeof df === 'string') {
df = frappe.meta.get_docfield(doc.doctype, df, doc.parent || doc.name);
}
var status = frappe.perm.get_field_display_status(df, doc, perm);
return status === "None" ? false : true;
}
});
frappe.provide("frappe.workflow");
frappe.workflow = {
state_fields: {},
workflows: {},
setup: function setup(doctype) {
var wf = frappe.get_list("Workflow", { document_type: doctype });
if (wf.length) {
frappe.workflow.workflows[doctype] = wf[0];
frappe.workflow.state_fields[doctype] = wf[0].workflow_state_field;
} else {
frappe.workflow.state_fields[doctype] = null;
}
},
get_state_fieldname: function get_state_fieldname(doctype) {
if (frappe.workflow.state_fields[doctype] === undefined) {
frappe.workflow.setup(doctype);
}
return frappe.workflow.state_fields[doctype];
},
get_default_state: function get_default_state(doctype, docstatus) {
frappe.workflow.setup(doctype);
var value = null;
$.each(frappe.workflow.workflows[doctype].states, function (i, workflow_state) {
if (cint(workflow_state.doc_status) === cint(docstatus)) {
value = workflow_state.state;
return false;
}
});
return value;
},
get_transitions: function get_transitions(doctype, state) {
frappe.workflow.setup(doctype);
return frappe.get_children(frappe.workflow.workflows[doctype], "transitions", { state: state });
},
get_document_state: function get_document_state(doctype, state) {
frappe.workflow.setup(doctype);
return frappe.get_children(frappe.workflow.workflows[doctype], "states", { state: state })[0];
},
get_next_state: function get_next_state(doctype, state, action) {
return frappe.get_children(frappe.workflow.workflows[doctype], "transitions", {
state: state, action: action })[0].next_state;
},
is_read_only: function is_read_only(doctype, name) {
var state_fieldname = frappe.workflow.get_state_fieldname(doctype);
if (state_fieldname) {
var doc = locals[doctype][name];
if (!doc) return false;
if (doc.__islocal) return false;
var state = doc[state_fieldname] || frappe.workflow.get_default_state(doctype, doc.docstatus);
var allow_edit = state ? frappe.workflow.get_document_state(doctype, state).allow_edit : null;
if (!frappe.user_roles.includes(allow_edit)) {
return true;
}
}
return false;
},
get_update_fields: function get_update_fields(doctype) {
var update_fields = $.unique($.map(frappe.workflow.workflows[doctype].states || [], function (d) {
return d.update_field;
}));
return update_fields;
}
};
frappe.provide('frappe.model.user_settings');
$.extend(frappe.model.user_settings, {
save: function save(doctype, key, value) {
var user_settings = frappe.model.user_settings[doctype] || {};
if ($.isPlainObject(value)) {
$.extend(user_settings[key], value);
} else {
user_settings[key] = value;
}
return this.update(doctype, user_settings);
},
remove: function remove(doctype, key) {
var user_settings = frappe.model.user_settings[doctype] || {};
delete user_settings[key];
return this.update(doctype, user_settings);
},
update: function update(doctype, user_settings) {
return frappe.call({
method: 'frappe.model.utils.user_settings.save',
args: {
doctype: doctype,
user_settings: user_settings
},
callback: function callback(r) {
frappe.model.user_settings[doctype] = r.message;
}
});
}
});
frappe.get_user_settings = function (doctype, key) {
var settings = frappe.model.user_settings[doctype] || {};
if (key) {
settings = settings[key] || {};
}
return settings;
};!function(a){function b(a,b){var c=(65535&a)+(65535&b),d=(a>>16)+(b>>16)+(c>>16);return d<<16|65535&c}function c(a,b){return a<
>>32-b}function d(a,d,e,f,g,h){return b(c(b(b(d,a),b(f,h)),g),e)}function e(a,b,c,e,f,g,h){return d(b&c|~b&e,a,b,f,g,h)}function f(a,b,c,e,f,g,h){return d(b&e|c&~e,a,b,f,g,h)}function g(a,b,c,e,f,g,h){return d(b^c^e,a,b,f,g,h)}function h(a,b,c,e,f,g,h){return d(c^(b|~e),a,b,f,g,h)}function i(a,c){a[c>>5]|=128<>>9<<4)+14]=c;var d,i,j,k,l,m=1732584193,n=-271733879,o=-1732584194,p=271733878;for(d=0;d>5]>>>b%32&255);return c}function k(a){var b,c=[];for(c[(a.length>>2)-1]=void 0,b=0;b>5]|=(255&a.charCodeAt(b/8))<16&&(e=i(e,8*a.length)),c=0;16>c;c+=1)f[c]=909522486^e[c],g[c]=1549556828^e[c];return d=i(f.concat(k(b)),512+8*b.length),j(i(g.concat(d),640))}function n(a){var b,c,d="0123456789abcdef",e="";for(c=0;c>>4&15)+d.charAt(15&b);return e}function o(a){return unescape(encodeURIComponent(a))}function p(a){return l(o(a))}function q(a){return n(p(a))}function r(a,b){return m(o(a),o(b))}function s(a,b){return n(r(a,b))}function t(a,b,c){return b?c?r(b,a):s(b,a):c?p(a):q(a)}"function"==typeof define&&define.amd?define(function(){return t}):a.md5=t}(this);
frappe.user_info = function (uid) {
if (!uid) uid = frappe.session.user;
if (uid.toLowerCase() === "bot") {
return {
fullname: __("Bot"),
image: "/assets/frappe/images/ui/bot.png",
abbr: "B"
};
}
if (!(frappe.boot.user_info && frappe.boot.user_info[uid])) {
var user_info = {
fullname: toTitle(uid.split("@")[0]) || "Unknown"
};
} else {
var user_info = frappe.boot.user_info[uid];
}
user_info.abbr = frappe.get_abbr(user_info.fullname);
user_info.color = frappe.get_palette(user_info.fullname);
return user_info;
};
frappe.ui.set_user_background = function (src, selector, style) {
if (!selector) selector = "#page-desktop";
if (!style) style = "Fill Screen";
if (src) {
if (window.cordova && src.indexOf("http") === -1) {
src = frappe.base_url + src;
}
var background = repl('background: url("%(src)s") center center;', { src: src });
} else {
var background = "background-color: #4B4C9D;";
}
frappe.dom.set_style(repl('%(selector)s { \
%(background)s \
background-attachment: fixed; \
%(style)s \
}', {
selector: selector,
background: background,
style: style === "Fill Screen" ? "background-size: cover;" : ""
}));
};
frappe.provide('frappe.user');
$.extend(frappe.user, {
name: 'Guest',
full_name: function full_name(uid) {
return uid === frappe.session.user ? __("You") : frappe.user_info(uid).fullname;
},
image: function image(uid) {
return frappe.user_info(uid).image;
},
abbr: function abbr(uid) {
return frappe.user_info(uid).abbr;
},
has_role: function has_role(rl) {
if (typeof rl == 'string') rl = [rl];
for (var i in rl) {
if ((frappe.boot ? frappe.boot.user.roles : ['Guest']).indexOf(rl[i]) != -1) return true;
}
},
get_desktop_items: function get_desktop_items() {
var modules_list = $.map(frappe.boot.desktop_icons, function (icon) {
var m = icon.module_name;
var type = frappe.modules[m] && frappe.modules[m].type;
if (frappe.boot.user.allow_modules.indexOf(m) === -1) return null;
var ret = null;
if (type === "module") {
if (frappe.boot.user.allow_modules.indexOf(m) != -1 || frappe.modules[m].is_help) ret = m;
} else if (type === "page") {
if (frappe.boot.allowed_pages.indexOf(frappe.modules[m].link) != -1) ret = m;
} else if (type === "list") {
if (frappe.model.can_read(frappe.modules[m]._doctype)) ret = m;
} else if (type === "view") {
ret = m;
} else if (type === "setup") {
if (frappe.user.has_role("System Manager") || frappe.user.has_role("Administrator")) ret = m;
} else {
ret = m;
}
return ret;
});
return modules_list;
},
is_module: function is_module(m) {
var icons = frappe.get_desktop_icons();
for (var i = 0; i < icons.length; i++) {
if (m === icons[i].module_name) return true;
}
return false;
},
is_report_manager: function is_report_manager() {
return frappe.user.has_role(['Administrator', 'System Manager', 'Report Manager']);
},
get_formatted_email: function get_formatted_email(email) {
var fullname = frappe.user.full_name(email);
if (!fullname) {
return email;
} else {
var quote = '';
if (fullname.search(/[\[\]\\()<>@,:;".]/) !== -1) {
quote = '"';
}
return repl('%(quote)s%(fullname)s%(quote)s <%(email)s>', {
fullname: fullname,
email: email,
quote: quote
});
}
},
toString: function toString() {
return this.name;
}
});
frappe.session_alive = true;
$(document).bind('mousemove', function () {
if (frappe.session_alive === false) {
$(document).trigger("session_alive");
}
frappe.session_alive = true;
if (frappe.session_alive_timeout) clearTimeout(frappe.session_alive_timeout);
frappe.session_alive_timeout = setTimeout('frappe.session_alive=false;', 30000);
});
frappe.avatar = function (user, css_class, title) {
if (user) {
var user_info = frappe.user_info(user);
} else {
user_info = {
image: frappe.get_cookie("user_image"),
fullname: frappe.get_cookie("full_name"),
abbr: frappe.get_abbr(frappe.get_cookie("full_name")),
color: frappe.get_palette(frappe.get_cookie("full_name"))
};
}
if (!title) {
title = user_info.fullname;
}
if (!css_class) {
css_class = "avatar-small";
}
if (user_info.image) {
var image = window.cordova && user_info.image.indexOf('http') === -1 ? frappe.base_url + user_info.image : user_info.image;
return repl('\
', {
image: image,
title: title,
abbr: user_info.abbr,
css_class: css_class
});
} else {
var abbr = user_info.abbr;
if (css_class === 'avatar-small' || css_class == 'avatar-xs') {
abbr = abbr.substr(0, 1);
}
return repl('\
%(abbr)s
', {
title: title,
abbr: abbr,
css_class: css_class,
color: user_info.color
});
}
};
frappe.get_palette = function (txt) {
return '#fafbfc';
};
frappe.get_abbr = function (txt, max_length) {
if (!txt) return "";
var abbr = "";
$.each(txt.split(" "), function (i, w) {
if (abbr.length >= (max_length || 2)) {
return false;
} else if (!w.trim().length) {
return true;
}
abbr += w.trim()[0];
});
return abbr || "?";
};
frappe.gravatars = {};
frappe.get_gravatar = function (email_id) {
var size = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var param = size ? 's=' + size : 'd=retro';
if (!frappe.gravatars[email_id]) {
frappe.gravatars[email_id] = "https://secure.gravatar.com/avatar/" + md5(email_id) + "?" + param;
}
return frappe.gravatars[email_id];
};
function repl(s, dict) {
if (s == null) return '';
for (var key in dict) {
s = s.split("%(" + key + ")s").join(dict[key]);
}
return s;
}
function replace_all(s, t1, t2) {
return s.split(t1).join(t2);
}
function strip_html(txt) {
return txt.replace(/<[^>]*>/g, "");
}
var strip = function strip(s, chars) {
if (s) {
var s = lstrip(s, chars);
s = rstrip(s, chars);
return s;
}
};
var lstrip = function lstrip(s, chars) {
if (!chars) chars = ['\n', '\t', ' '];
var first_char = s.substr(0, 1);
while (in_list(chars, first_char)) {
var s = s.substr(1);
first_char = s.substr(0, 1);
}
return s;
};
var rstrip = function rstrip(s, chars) {
if (!chars) chars = ['\n', '\t', ' '];
var last_char = s.substr(s.length - 1);
while (in_list(chars, last_char)) {
var s = s.substr(0, s.length - 1);
last_char = s.substr(s.length - 1);
}
return s;
};
function getCookie(name) {
return getCookies()[name];
}
frappe.get_cookie = getCookie;
function getCookies() {
var c = document.cookie,
v = 0,
cookies = {};
if (document.cookie.match(/^\s*\$Version=(?:"1"|1);\s*(.*)/)) {
c = RegExp.$1;
v = 1;
}
if (v === 0) {
c.split(/[,;]/).map(function (cookie) {
var parts = cookie.split(/=/, 2),
name = decodeURIComponent(parts[0].trimLeft()),
value = parts.length > 1 ? decodeURIComponent(parts[1].trimRight()) : null;
if (value && value.charAt(0) === '"') {
value = value.substr(1, value.length - 2);
}
cookies[name] = value;
});
} else {
c.match(/(?:^|\s+)([!#$%&'*+\-.0-9A-Z^`a-z|~]+)=([!#$%&'*+\-.0-9A-Z^`a-z|~]*|"(?:[\x20-\x7E\x80\xFF]|\\[\x00-\x7F])*")(?=\s*[,;]|$)/g).map(function ($0, $1) {
var name = $0,
value = $1.charAt(0) === '"' ? $1.substr(1, -1).replace(/\\(.)/g, "$1") : $1;
cookies[name] = value;
});
}
return cookies;
}
if (typeof String.prototype.trimLeft !== "function") {
String.prototype.trimLeft = function () {
return this.replace(/^\s+/, "");
};
}
if (typeof String.prototype.trimRight !== "function") {
String.prototype.trimRight = function () {
return this.replace(/\s+$/, "");
};
}
if (typeof Array.prototype.map !== "function") {
Array.prototype.map = function (callback, thisArg) {
for (var i = 0, n = this.length, a = []; i < n; i++) {
if (i in this) a[i] = callback.call(thisArg, this[i]);
}
return a;
};
}
frappe.palette = [['#FFC4C4', 0], ['#FFE8CD', 0], ['#FFD2C2', 0], ['#FF8989', 0], ['#FFD19C', 0], ['#FFA685', 0], ['#FF4D4D', 1], ['#FFB868', 0], ['#FF7846', 1], ['#A83333', 1], ['#A87945', 1], ['#A84F2E', 1], ['#D2D2FF', 0], ['#F8D4F8', 0], ['#DAC7FF', 0], ['#A3A3FF', 0], ['#F3AAF0', 0], ['#B592FF', 0], ['#7575FF', 0], ['#EC7DEA', 0], ['#8E58FF', 1], ['#4D4DA8', 1], ['#934F92', 1], ['#5E3AA8', 1], ['#EBF8CC', 0], ['#FFD7D7', 0], ['#D2F8ED', 0], ['#D9F399', 0], ['#FFB1B1', 0], ['#A4F3DD', 0], ['#C5EC63', 0], ['#FF8989', 1], ['#77ECCA', 0], ['#7B933D', 1], ['#A85B5B', 1], ['#49937E', 1], ['#FFFACD', 0], ['#D2F1FF', 0], ['#CEF6D1', 0], ['#FFF69C', 0], ['#A6E4FF', 0], ['#9DECA2', 0], ['#FFF168', 0], ['#78D6FF', 0], ['#6BE273', 0], ['#A89F45', 1], ['#4F8EA8', 1], ['#428B46', 1]];
frappe.is_mobile = function () {
return $(document).width() < 768;
};
function prettyDate(time, mini) {
if (!time) {
time = new Date();
}
if (moment) {
if (frappe.sys_defaults && frappe.sys_defaults.time_zone) {
var ret = moment.tz(time, frappe.sys_defaults.time_zone).locale(frappe.boot.lang).fromNow(mini);
} else {
var ret = moment(time).locale(frappe.boot.lang).fromNow(mini);
}
if (mini) {
if (ret === moment().locale(frappe.boot.lang).fromNow(mini)) {
ret = __("now");
} else {
var parts = ret.split(" ");
if (parts.length > 1) {
if (parts[0] === "a" || parts[0] === "an") {
parts[0] = 1;
}
if (parts[1].substr(0, 2) === "mo") {
ret = parts[0] + " M";
} else {
ret = parts[0] + " " + parts[1].substr(0, 1);
}
}
}
ret = ret.substr(0, 5);
}
return ret;
} else {
if (!time) return '';
var date = time;
if (typeof time == "string") date = new Date((time || "").replace(/-/g, "/").replace(/[TZ]/g, " ").replace(/\.[0-9]*/, ""));
var diff = (new Date().getTime() - date.getTime()) / 1000,
day_diff = Math.floor(diff / 86400);
if (isNaN(day_diff) || day_diff < 0) return '';
var when = day_diff == 0 && (diff < 60 && __("just now") || diff < 120 && __("1 minute ago") || diff < 3600 && __("{0} minutes ago", [Math.floor(diff / 60)]) || diff < 7200 && __("1 hour ago") || diff < 86400 && ("{0} hours ago", [Math.floor(diff / 3600)])) || day_diff == 1 && __("Yesterday") || day_diff < 7 && __("{0} days ago", day_diff) || day_diff < 31 && __("{0} weeks ago", [Math.ceil(day_diff / 7)]) || day_diff < 365 && __("{0} months ago", [Math.ceil(day_diff / 30)]) || __("> {0} year(s) ago", [Math.floor(day_diff / 365)]);
return when;
}
}
var comment_when = function comment_when(datetime, mini) {
var timestamp = frappe.datetime.str_to_user ? frappe.datetime.str_to_user(datetime) : datetime;
return '' + prettyDate(datetime, mini) + ' ';
};
frappe.provide("frappe.datetime");
frappe.datetime.refresh_when = function () {
if (jQuery) {
$(".frappe-timestamp").each(function () {
$(this).html(prettyDate($(this).attr("data-timestamp"), $(this).hasClass("mini")));
});
}
};
setInterval(function () {
frappe.datetime.refresh_when();
}, 60000);
frappe.provide('frappe.utils');
frappe.utils = {
get_random: function get_random(len) {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
for (var i = 0; i < len; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}return text;
},
get_file_link: function get_file_link(filename) {
filename = cstr(filename);
if (frappe.utils.is_url(filename)) {
return filename;
} else if (filename.indexOf("/") === -1) {
return "files/" + filename;
} else {
return filename;
}
},
is_html: function is_html(txt) {
if (!txt) return false;
if (txt.indexOf(" ") == -1 && txt.indexOf("= 768;
},
is_md: function is_md() {
return $(document).width() < 1199 && $(document).width() >= 991;
},
strip_whitespace: function strip_whitespace(html) {
return (html || "").replace(/
\s*<\/p>/g, "").replace(/ (\s* \s*)+/g, " ");
},
encode_tags: function encode_tags(html) {
var tagsToReplace = {
'&': '&',
'<': '<',
'>': '>'
};
function replaceTag(tag) {
return tagsToReplace[tag] || tag;
}
return html.replace(/[&<>]/g, replaceTag);
},
strip_original_content: function strip_original_content(txt) {
var out = [],
part = [],
newline = txt.indexOf(" ") === -1 ? "\n" : " ";
$.each(txt.split(newline), function (i, t) {
var tt = strip(t);
if (tt && (tt.substr(0, 1) === ">" || tt.substr(0, 4) === ">")) {
part.push(t);
} else {
out.concat(part);
out.push(t);
part = [];
}
});
return out.join(newline);
},
escape_html: function escape_html(txt) {
return $("
").text(txt || "").html();
},
is_url: function is_url(txt) {
return txt.toLowerCase().substr(0, 7) == 'http://' || txt.toLowerCase().substr(0, 8) == 'https://';
},
toggle_blockquote: function toggle_blockquote(txt) {
if (!txt) return txt;
var content = $("
").html(txt);
content.find("blockquote").parent("blockquote").addClass("hidden").before(' \
โข โข โข \
');
return content.html();
},
scroll_to: function scroll_to(element, animate, additional_offset) {
var y = 0;
if (element && typeof element === 'number') {
y = element;
} else if (element) {
var header_offset = $(".navbar").height() + $(".page-head").height();
var y = $(element).offset().top - header_offset - cint(additional_offset);
}
if (y < 0) {
y = 0;
}
if (y == $('body').scrollTop()) {
return;
}
if (animate !== false) {
$("body").animate({ scrollTop: y });
} else {
$(window).scrollTop(y);
}
},
filter_dict: function filter_dict(dict, filters) {
var ret = [];
if (typeof filters == 'string') {
return [dict[filters]];
}
$.each(dict, function (i, d) {
for (var key in filters) {
if ($.isArray(filters[key])) {
if (filters[key][0] == "in") {
if (filters[key][1].indexOf(d[key]) == -1) return;
} else if (filters[key][0] == "not in") {
if (filters[key][1].indexOf(d[key]) != -1) return;
} else if (filters[key][0] == "<") {
if (!(d[key] < filters[key])) return;
} else if (filters[key][0] == "<=") {
if (!(d[key] <= filters[key])) return;
} else if (filters[key][0] == ">") {
if (!(d[key] > filters[key])) return;
} else if (filters[key][0] == ">=") {
if (!(d[key] >= filters[key])) return;
}
} else {
if (d[key] != filters[key]) return;
}
}
ret.push(d);
});
return ret;
},
comma_or: function comma_or(list) {
return frappe.utils.comma_sep(list, " " + __("or") + " ");
},
comma_and: function comma_and(list) {
return frappe.utils.comma_sep(list, " " + __("and") + " ");
},
comma_sep: function comma_sep(list, sep) {
if (list instanceof Array) {
if (list.length == 0) {
return "";
} else if (list.length == 1) {
return list[0];
} else {
return list.slice(0, list.length - 1).join(", ") + sep + list.slice(-1)[0];
}
} else {
return list;
}
},
set_intro: function set_intro(me, wrapper, txt, append, indicator) {
if (!me.intro_area) {
me.intro_area = $('').prependTo(wrapper);
}
if (txt) {
if (!append) {
me.intro_area.empty();
}
if (indicator) {
me.intro_area.html('
' + txt + '
');
} else {
me.intro_area.html('
' + txt + '
');
}
} else {
me.intro_area.remove();
me.intro_area = null;
}
},
set_footnote: function set_footnote(footnote_area, wrapper, txt) {
if (!footnote_area) {
footnote_area = $('').appendTo($upload);
} else {
$(opts.btn).unbind("click");
}
opts.btn.click(function () {
d && d.hide();
if (opts.get_params) {
opts.args.params = opts.get_params();
}
var file_url = $upload.find('[name="file_url"]:visible');
file_url = file_url.length && file_url.get(0).value;
if (opts.args.gs_template) {
frappe.integration_service.gsuite.create_gsuite_file(opts.args, opts);
} else if (file_url) {
opts.args.file_url = file_url;
frappe.upload.upload_file(null, opts.args, opts);
} else {
var files = $upload.data('attached_files');
frappe.upload.upload_multiple_files(files, opts.args, opts);
}
});
},
make_file_row: function make_file_row(file) {
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
show_private = _ref.show_private;
var template = '\n\t\t\t\n\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t' + file.name + ' \n\t\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t
\n\t\t\t\t\t' + (show_private ? '
\n\t\t\t\t\t\t\t
' : '') + '\n\t\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t
';
return $(template);
},
show_empty_state: function show_empty_state($upload) {
$upload.find(".uploaded-filename").addClass("hidden");
$upload.find(".web-link-wrapper").removeClass("hidden");
$upload.find(".private-file").addClass("hidden");
$upload.find(".btn-browse").removeClass("btn-default").addClass("btn-primary");
},
upload_multiple_files: function upload_multiple_files(files, args, opts) {
var i = -1;
upload_next();
$(document).on('upload_complete', on_upload);
function upload_next() {
if (files) {
i += 1;
var file = files[i];
args.is_private = file.is_private;
if (!opts.progress) {
frappe.show_progress(__('Uploading'), i + 1, files.length);
}
}
frappe.upload.upload_file(file, args, opts);
}
function on_upload(e, attachment) {
if (!files || i === files.length - 1) {
$(document).off('upload_complete', on_upload);
frappe.hide_progress();
return;
}
upload_next();
}
},
upload_file: function upload_file(fileobj, args, opts) {
if (!fileobj && !args.file_url) {
if (opts.on_no_attach) {
opts.on_no_attach();
} else {
frappe.msgprint(__("Please attach a file or set a URL"));
}
return;
}
if (args.file_url) {
frappe.upload._upload_file(fileobj, args, opts);
} else {
frappe.upload.read_file(fileobj, args, opts);
}
},
_upload_file: function _upload_file(fileobj, args, opts, dataurl) {
if (args.file_size) {
frappe.upload.validate_max_file_size(args.file_size);
}
if (opts.on_attach) {
opts.on_attach(args, dataurl);
} else {
if (opts.confirm_is_private) {
frappe.prompt({
label: __("Private"),
fieldname: "is_private",
fieldtype: "Check",
"default": 1
}, function (values) {
args["is_private"] = values.is_private;
frappe.upload.upload_to_server(fileobj, args, opts, dataurl);
}, __("Private or Public?"));
} else {
if ("is_private" in opts) {
args["is_private"] = opts.is_private;
}
frappe.upload.upload_to_server(fileobj, args, opts, dataurl);
}
}
},
read_file: function read_file(fileobj, args, opts) {
var freader = new FileReader();
freader.onload = function () {
args.filename = fileobj.name.split(' ').join('_');
if (opts.options && opts.options.toLowerCase() == "image") {
if (!frappe.utils.is_image_file(args.filename)) {
frappe.msgprint(__("Only image extensions (.gif, .jpg, .jpeg, .tiff, .png, .svg) allowed"));
return;
}
}
if ((opts.max_width || opts.max_height) && frappe.utils.is_image_file(args.filename)) {
frappe.utils.resize_image(freader, function (_dataurl) {
var dataurl = _dataurl;
args.filedata = _dataurl.split(",")[1];
args.file_size = Math.round(args.filedata.length * 3 / 4);
console.log("resized!");
frappe.upload._upload_file(fileobj, args, opts, dataurl);
});
} else {
var dataurl = freader.result;
args.filedata = freader.result.split(",")[1];
args.file_size = fileobj.size;
frappe.upload._upload_file(fileobj, args, opts, dataurl);
}
};
freader.readAsDataURL(fileobj);
},
upload_to_server: function upload_to_server(fileobj, args, opts, dataurl) {
if (opts.start) {
opts.start();
}
var ajax_args = {
"method": "uploadfile",
args: args,
callback: function callback(r) {
if (!r._server_messages) {}
if (r.exc) {
opts.onerror ? opts.onerror(r) : opts.callback(null, r);
frappe.hide_progress();
return;
}
var attachment = r.message;
opts.loopcallback && opts.loopcallback();
opts.callback && opts.callback(attachment, r);
$(document).trigger("upload_complete", attachment);
},
error: function error(r) {
opts.onerror ? opts.onerror(r) : opts.callback(null, null, r);
frappe.hide_progress();
return;
}
};
$.each(['queued', 'running', "progress", "always", "btn"], function (i, key) {
if (opts[key]) ajax_args[key] = opts[key];
});
return frappe.call(ajax_args);
},
get_string: function get_string(dataURI) {
var parts = dataURI.split(',');
if (parts[0].indexOf(":") === -1) {
var a = parts[2];
} else {
var a = parts[1];
}
return decodeURIComponent(escape(atob(a)));
},
validate_max_file_size: function validate_max_file_size(file_size) {
var max_file_size = frappe.boot.max_file_size || 5242880;
if (file_size > max_file_size) {
frappe.throw(__("File size exceeded the maximum allowed size of {0} MB", [max_file_size / 1048576]));
}
},
multifile_upload: function multifile_upload(fileobjs, args, opts) {
var fields = [];
for (var i = 0, j = fileobjs.length; i < j; i++) {
var filename = fileobjs[i].name;
fields.push({ 'fieldname': 'label1', 'fieldtype': 'Heading', 'label': filename });
fields.push({ 'fieldname': filename + '_is_private', 'fieldtype': 'Check', 'label': 'Private', 'default': 1 });
}
var d = new frappe.ui.Dialog({
'title': __('Make file(s) private or public?'),
'fields': fields,
primary_action: function primary_action() {
var i = 0,
j = fileobjs.length;
d.hide();
opts.loopcallback = function () {
if (i < j) {
args.is_private = d.fields_dict[fileobjs[i].name + "_is_private"].get_value();
frappe.upload.upload_file(fileobjs[i], args, opts);
i++;
}
};
opts.loopcallback();
}
});
d.show();
opts.confirm_is_private = 0;
},
create_gsuite_file: function create_gsuite_file(args, opts) {
return frappe.call({
type: 'POST',
method: 'frappe.integrations.doctype.gsuite_templates.gsuite_templates.create_gsuite_doc',
args: args,
callback: function callback(r) {
var attachment = r.message;
opts.callback && opts.callback(attachment, r);
}
});
}
};
frappe.provide("frappe.integration_service");
frappe.integration_service.gsuite = {
create_gsuite_file: function create_gsuite_file(args, opts) {
return frappe.call({
type: 'POST',
method: 'frappe.integrations.doctype.gsuite_templates.gsuite_templates.create_gsuite_doc',
args: args,
callback: function callback(r) {
var attachment = r.message;
opts.callback && opts.callback(attachment, r);
}
});
}
};
frappe.ui.Tree = Class.extend({
init: function init(args) {
$.extend(this, args);
this.nodes = {};
this.wrapper = $('').appendTo(this.parent);
this.rootnode = new frappe.ui.TreeNode({
tree: this,
parent: this.wrapper,
label: this.label,
parent_label: null,
expandable: true,
root: true,
data: {
value: this.label,
parent: this.label,
expandable: true
}
});
this.rootnode.toggle();
},
refresh: function refresh() {
this.selected_node.reload_parent();
},
get_selected_node: function get_selected_node() {
return this.selected_node;
},
toggle: function toggle() {
this.get_selected_node().toggle();
}
});
frappe.ui.TreeNode = Class.extend({
init: function init(args) {
$.extend(this, args);
this.loaded = false;
this.expanded = false;
this.tree.nodes[this.label] = this;
if (this.parent_label) this.parent_node = this.tree.nodes[this.parent_label];
this.make();
this.setup_drag_drop();
if (this.tree.onrender) {
this.tree.onrender(this);
}
},
make: function make() {
var me = this;
this.tree_link = $('
').click(function (event) {
me.tree.selected_node = me;
me.tree.wrapper.find(".tree-link.active").removeClass("active");
me.tree_link.addClass("active");
if (me.tree.toolbar) {
me.show_toolbar();
}
if (me.tree.click) {
me.tree.click(this);
}
if (me.tree.onclick) {
me.tree.onclick(me);
}
}).data('label', this.label).data('node', this).appendTo(this.parent);
this.$ul = $('').toggle(false).appendTo(this.parent);
this.make_icon();
},
make_icon: function make_icon() {
var me = this;
var icon_html = '';
if (this.expandable) {
icon_html = ' ';
}
$(icon_html + ' ' + this.get_label() + " ").appendTo(this.tree_link);
this.tree_link.find('i').click(function () {
setTimeout(function () {
me.toolbar.find(".btn-expand").click();
}, 100);
});
this.tree_link.find('a').click(function () {
if (!me.expanded) setTimeout(function () {
me.toolbar.find(".btn-expand").click();
}, 100);
});
},
get_label: function get_label() {
if (this.tree.get_label) {
return this.tree.get_label(this);
}
return __(this.label);
},
toggle: function toggle(callback) {
if (this.expandable && this.tree.method && !this.loaded) {
this.load(callback);
} else {
this.toggle_node(callback);
}
},
show_toolbar: function show_toolbar() {
if (this.tree.cur_toolbar) $(this.tree.cur_toolbar).toggle(false);
if (!this.toolbar) this.make_toolbar();
this.tree.cur_toolbar = this.toolbar;
this.toolbar.toggle(true);
},
make_toolbar: function make_toolbar() {
var me = this;
this.toolbar = $(' ').insertAfter(this.tree_link);
$.each(this.tree.toolbar, function (i, item) {
if (item.toggle_btn) {
item = {
condition: function condition() {
return me.expandable;
},
get_label: function get_label() {
return me.expanded ? __("Collapse") : __("Expand");
},
click: function click(node, btn) {
node.toggle(function () {
$(btn).html(node.expanded ? __("Collapse") : __("Expand"));
});
},
btnClass: "btn-expand hidden-xs"
};
}
if (item.condition) {
if (!item.condition(me)) return;
}
var label = item.get_label ? item.get_label() : item.label;
var link = $(" ").html(label).appendTo(me.toolbar).click(function () {
item.click(me, this);return false;
});
if (item.btnClass) link.addClass(item.btnClass);
});
},
setup_drag_drop: function setup_drag_drop() {
var me = this;
if (this.tree.drop && this.parent_label) {
this.$ul.droppable({
hoverClass: "tree-hover",
greedy: true,
drop: function drop(event, ui) {
event.preventDefault();
var dragged_node = $(ui.draggable).find(".tree-link:first").data("node");
var dropped_node = $(this).parent().find(".tree-link:first").data("node");
me.tree.drop(dragged_node, dropped_node, $(ui.draggable), $(this));
return false;
}
});
}
},
addnode: function addnode(data) {
var $li = $('');
if (this.tree.drop) $li.draggable({ revert: true });
return new frappe.ui.TreeNode({
tree: this.tree,
parent: $li.appendTo(this.$ul),
parent_label: this.label,
label: data.value,
expandable: data.expandable,
data: data
});
},
toggle_node: function toggle_node(callback) {
if (this.$ul) {
if (this.$ul.children().length) {
this.$ul.toggle(!this.expanded);
}
this.tree_link.find('i').removeClass();
if (!this.expanded) {
this.tree_link.find('i').addClass('fa fa-fw fa-folder-open text-muted');
} else {
this.tree_link.find('i').addClass('fa fa-fw fa-folder text-muted');
}
}
this.tree.wrapper.find('.selected').removeClass('selected');
this.tree_link.toggleClass('selected');
this.expanded = !this.expanded;
this.expanded ? this.parent.addClass('opened') : this.parent.removeClass('opened');
if (callback) callback();
},
reload: function reload() {
this.load();
},
reload_parent: function reload_parent() {
this.parent_node.load_all();
},
load_all: function load_all(_callback) {
var me = this;
return frappe.call({
method: 'frappe.desk.treeview.get_all_nodes',
args: {
tree_args: this.tree.args,
tree_method: this.tree.method,
parent: this.data.value
},
callback: function callback(r) {
$.each(r.message, function (i, d) {
me.render_expand_node(me.tree.nodes[d.parent], d.data);
});
if (_callback) {
_callback();
}
}
});
},
load: function load(_callback2) {
var node = this;
var args = $.extend(this.tree.args || {}, {
parent: this.data.value
});
return frappe.call({
method: this.tree.method,
args: args,
callback: function callback(r) {
node.render_expand_node(node, r.message, _callback2);
}
});
},
render_expand_node: function render_expand_node(node, data, callback) {
node.$ul.empty();
if (data) {
$.each(data, function (i, v) {
var child_node = node.addnode(v);
child_node.tree_link.data('node-data', v).data('node', child_node);
});
}
node.expanded = false;
node.toggle_node(callback);
node.loaded = true;
}
});
frappe.provide('frappe.pages');
frappe.provide('frappe.views');
var cur_page = null;
frappe.views.Container = Class.extend({
_intro: "Container contains pages inside `#container` and manages \
page creation, switching",
init: function init() {
this.container = $('#body_div').get(0);
this.page = null;
this.pagewidth = $(this.container).width();
this.pagemargin = 50;
var me = this;
$(document).on("page-change", function () {
var route_str = frappe.get_route_str();
$("body").attr("data-route", route_str);
$("body").attr("data-sidebar", me.has_sidebar() ? 1 : 0);
});
$(document).bind('rename', function (event, dt, old_name, new_name) {
frappe.breadcrumbs.rename(dt, old_name, new_name);
});
},
add_page: function add_page(label) {
var page = $('
').attr('id', "page-" + label).attr("data-page-route", label).hide().appendTo(this.container).get(0);
page.label = label;
frappe.pages[label] = page;
return page;
},
change_to: function change_to(label) {
cur_page = this;
if (this.page && this.page.label === label) {
$(this.page).trigger('show');
return;
}
var me = this;
if (label.tagName) {
var page = label;
} else {
var page = frappe.pages[label];
}
if (!page) {
console.log(__('Page not found') + ': ' + label);
return;
}
if (cur_dialog && cur_dialog.display && !cur_dialog.keep_open) {
cur_dialog.hide();
}
if (this.page && this.page != page) {
$(this.page).hide();
$(this.page).trigger('hide');
}
if (!this.page || this.page != page) {
this.page = page;
$(this.page).show();
}
$(document).trigger("page-change");
this.page._route = window.location.hash;
$(this.page).trigger('show');
frappe.utils.scroll_to(0);
frappe.breadcrumbs.update();
return this.page;
},
has_sidebar: function has_sidebar() {
var flag = 0;
var route_str = frappe.get_route_str();
flag = frappe.ui.pages[route_str] && !frappe.ui.pages[route_str].single_column;
if (!flag) {
var page_route = route_str.split('/').slice(0, 2).join('/');
flag = $('.page-container[data-page-route="' + page_route + '"] .layout-side-section').length ? 1 : 0;
}
return flag;
}
});
frappe.breadcrumbs = {
all: {},
preferred: {
"File": ""
},
set_doctype_module: function set_doctype_module(doctype, module) {
localStorage["preferred_breadcrumbs:" + doctype] = module;
},
get_doctype_module: function get_doctype_module(doctype) {
return localStorage["preferred_breadcrumbs:" + doctype];
},
add: function add(module, doctype, type) {
frappe.breadcrumbs.all[frappe.breadcrumbs.current_page()] = { module: module, doctype: doctype, type: type };
frappe.breadcrumbs.update();
},
current_page: function current_page() {
var route = frappe.get_route();
if (route[0] === 'List') {
route = route.slice(0, 2);
}
return route.join("/");
},
update: function update() {
var breadcrumbs = frappe.breadcrumbs.all[frappe.breadcrumbs.current_page()];
if (!frappe.visible_modules) {
frappe.visible_modules = $.map(frappe.get_desktop_icons(true), function (m) {
return m.module_name;
});
}
var $breadcrumbs = $("#navbar-breadcrumbs").empty();
if (!breadcrumbs) {
$("body").addClass("no-breadcrumbs");
return;
}
var from_module = frappe.breadcrumbs.get_doctype_module(breadcrumbs.doctype);
if (from_module) {
breadcrumbs.module = from_module;
} else if (frappe.breadcrumbs.preferred[breadcrumbs.doctype] !== undefined) {
breadcrumbs.module = frappe.breadcrumbs.preferred[breadcrumbs.doctype];
}
if (breadcrumbs.module) {
if (in_list(["Core", "Email", "Custom", "Workflow", "Print"], breadcrumbs.module)) {
breadcrumbs.module = "Setup";
}
if (frappe.get_module(breadcrumbs.module)) {
var module_info = frappe.get_module(breadcrumbs.module),
icon = module_info && module_info.icon,
label = module_info ? module_info.label : breadcrumbs.module;
if (module_info && !module_info.blocked && frappe.visible_modules.includes(module_info.module_name)) {
$(repl(' %(label)s ', { module: breadcrumbs.module, label: __(label) })).appendTo($breadcrumbs);
}
}
}
if (breadcrumbs.doctype && frappe.get_route()[0] === "Form") {
if (breadcrumbs.doctype === "User" && frappe.user.is_module("Setup") === -1 || frappe.get_doc('DocType', breadcrumbs.doctype).issingle) {} else {
var route;
if (frappe.boot.treeviews.indexOf(breadcrumbs.doctype) !== -1) {
var view = frappe.model.user_settings[breadcrumbs.doctype].last_view || 'Tree';
route = view + '/' + breadcrumbs.doctype;
} else {
route = 'List/' + breadcrumbs.doctype;
}
$(repl('%(label)s ', { route: route, label: __(breadcrumbs.doctype) })).appendTo($breadcrumbs);
}
}
$("body").removeClass("no-breadcrumbs");
},
rename: function rename(doctype, old_name, new_name) {
var old_route_str = ["Form", doctype, old_name].join("/");
var new_route_str = ["Form", doctype, new_name].join("/");
frappe.breadcrumbs.all[new_route_str] = frappe.breadcrumbs.all[old_route_str];
delete frappe.breadcrumbs.all[old_route_str];
}
};
frappe.provide('frappe.pages');
frappe.provide('frappe.views');
frappe.views.Factory = Class.extend({
init: function init(opts) {
$.extend(this, opts);
},
show: function show() {
var page_name = frappe.get_route_str(),
me = this;
if (page_name.substr(0, 4) === 'List') {
page_name = frappe.get_route().slice(0, 2).join('/');
}
if (frappe.pages[page_name] && !page_name.includes("Form/")) {
frappe.container.change_to(frappe.pages[page_name]);
if (me.on_show) {
me.on_show();
}
} else {
var route = frappe.get_route();
if (route[1]) {
me.make(route);
} else {
frappe.show_not_found(route);
}
}
},
make_page: function make_page(double_column, page_name) {
return frappe.make_page(double_column, page_name);
}
});
frappe.make_page = function (double_column, page_name) {
if (!page_name) {
var page_name = frappe.get_route_str();
}
var page = frappe.container.add_page(page_name);
frappe.ui.make_app_page({
parent: page,
single_column: !double_column
});
frappe.container.change_to(page_name);
return page;
};
frappe.provide('frappe.views.pageview');
frappe.provide("frappe.standard_pages");
frappe.views.pageview = {
with_page: function with_page(name, _callback) {
if (in_list(Object.keys(frappe.standard_pages), name)) {
if (!frappe.pages[name]) {
frappe.standard_pages[name]();
}
_callback();
return;
}
if (locals.Page && locals.Page[name] || name == window.page_name) {
_callback();
} else if (localStorage["_page:" + name] && frappe.boot.developer_mode != 1) {
frappe.model.sync(JSON.parse(localStorage["_page:" + name]));
_callback();
} else {
return frappe.call({
method: 'frappe.desk.desk_page.getpage',
args: { 'name': name },
callback: function callback(r) {
if (!r.docs._dynamic_page) {
localStorage["_page:" + name] = JSON.stringify(r.docs);
}
_callback();
},
freeze: true
});
}
},
show: function show(name) {
if (!name) {
name = frappe.boot ? frappe.boot.home_page : window.page_name;
}
frappe.model.with_doctype("Page", function () {
frappe.views.pageview.with_page(name, function (r) {
if (r && r.exc) {
if (!r['403']) frappe.show_not_found(name);
} else if (!frappe.pages[name]) {
new frappe.views.Page(name);
}
frappe.container.change_to(name);
});
});
}
};
frappe.views.Page = Class.extend({
init: function init(name, wrapper) {
this.name = name;
var me = this;
if (name == window.page_name) {
this.wrapper = document.getElementById('page-' + name);
this.wrapper.label = document.title || window.page_name;
this.wrapper.page_name = window.page_name;
frappe.pages[window.page_name] = this.wrapper;
} else {
this.pagedoc = locals.Page[this.name];
if (!this.pagedoc) {
frappe.show_not_found(name);
return;
}
this.wrapper = frappe.container.add_page(this.name);
this.wrapper.label = this.pagedoc.title || this.pagedoc.name;
this.wrapper.page_name = this.pagedoc.name;
if (this.pagedoc.content) this.wrapper.innerHTML = this.pagedoc.content;
frappe.dom.eval(this.pagedoc.__script || this.pagedoc.script || '');
frappe.dom.set_style(this.pagedoc.style || '');
}
this.trigger_page_event('on_page_load');
$(this.wrapper).on('show', function () {
cur_frm = null;
me.trigger_page_event('on_page_show');
me.trigger_page_event('refresh');
});
},
trigger_page_event: function trigger_page_event(eventname) {
var me = this;
if (me.wrapper[eventname]) {
me.wrapper[eventname](me.wrapper);
}
}
});
frappe.show_not_found = function (page_name) {
frappe.show_message_page({
page_name: page_name,
message: __("Sorry! I could not find what you were looking for."),
img: "/assets/frappe/images/ui/bubble-tea-sorry.svg"
});
};
frappe.show_not_permitted = function (page_name) {
frappe.show_message_page({
page_name: page_name,
message: __("Sorry! You are not permitted to view this page."),
img: "/assets/frappe/images/ui/bubble-tea-sorry.svg"
});
};
frappe.show_message_page = function (opts) {
if (!opts.page_name) {
opts.page_name = frappe.get_route_str();
}
if (opts.icon) {
opts.img = repl(' ', opts);
} else if (opts.img) {
opts.img = repl(' ', opts);
}
var page = frappe.pages[opts.page_name] || frappe.container.add_page(opts.page_name);
$(page).html(repl('\
\
%(img)s\
%(message)s
\
%(home)s \
\
', {
img: opts.img || "",
message: opts.message || "",
home: __("Home")
}));
frappe.container.change_to(opts.page_name);
};
frappe.provide('frappe.search');
frappe.search.AwesomeBar = Class.extend({
setup: function setup(element) {
var me = this;
var $input = $(element);
var input = $input.get(0);
this.options = [];
this.global_results = [];
var awesomplete = new Awesomplete(input, {
minChars: 0,
maxItems: 99,
autoFirst: true,
list: [],
filter: function filter(text, term) {
return true;
},
data: function data(item, input) {
return {
label: item.index || "",
value: item.value
};
},
item: function item(_item, term) {
var d = this.get_item(_item.value);
var name = __(d.label || d.value);
var html = '' + name + ' ';
if (d.description && d.value !== d.description) {
html += '' + __(d.description) + ' ';
}
return $(' ').data('item.autocomplete', d).html('' + html + '
').get(0);
},
sort: function sort(a, b) {
return b.label - a.label;
}
});
input.awesomplete = awesomplete;
$input.on("input", function (e) {
var value = e.target.value;
var txt = value.trim().replace(/\s\s+/g, ' ');
var last_space = txt.lastIndexOf(' ');
me.global_results = [];
var $this = $(this);
clearTimeout($this.data('timeout'));
$this.data('timeout', setTimeout(function () {
me.options = [];
if (txt && txt.length > 1) {
if (last_space !== -1) {
me.set_specifics(txt.slice(0, last_space), txt.slice(last_space + 1));
}
me.add_defaults(txt);
me.options = me.options.concat(me.build_options(txt));
me.options = me.options.concat(me.global_results);
} else {
me.options = me.options.concat(me.deduplicate(frappe.search.utils.get_recent_pages(txt || "")));
}
me.add_help();
awesomplete.list = me.deduplicate(me.options);
}, 100));
});
var open_recent = function open_recent() {
if (!this.autocomplete_open) {
$(this).trigger("input");
}
};
$input.on("focus", open_recent);
$input.on("awesomplete-open", function (e) {
me.autocomplete_open = e.target;
});
$input.on("awesomplete-close", function (e) {
me.autocomplete_open = false;
});
$input.on("awesomplete-select", function (e) {
var o = e.originalEvent;
var value = o.text.value;
var item = awesomplete.get_item(value);
if (item.route_options) {
frappe.route_options = item.route_options;
}
if (item.onclick) {
item.onclick(item.match);
} else {
var previous_hash = window.location.hash;
frappe.set_route(item.route);
if (window.location.hash == previous_hash) {
frappe.route();
}
}
$input.val("");
});
$input.on("awesomplete-selectcomplete", function (e) {
$input.val("");
});
frappe.search.utils.setup_recent();
},
add_help: function add_help() {
this.options.push({
value: __("Help on Search"),
index: -10,
default: "Help",
onclick: function onclick() {
var txt = '\
' + __("Make a new record") + ' ' + __("new type of document") + ' \
' + __("List a document type") + ' ' + __("document type..., e.g. customer") + ' \
' + __("Search in a document type") + ' ' + __("text in document type") + ' \
' + __("Open a module or tool") + ' ' + __("module name...") + ' \
' + __("Calculate") + ' ' + __("e.g. (55 + 434) / 4 or =Math.sin(Math.PI/2)...") + ' \
';
frappe.msgprint(txt, __("Search Help"));
}
});
},
set_specifics: function set_specifics(txt, end_txt) {
var me = this;
var results = this.build_options(txt);
results.forEach(function (r) {
if (r.type && r.type.toLowerCase().indexOf(end_txt.toLowerCase()) === 0) {
me.options.push(r);
}
});
},
add_defaults: function add_defaults(txt) {
this.make_global_search(txt);
this.make_search_in_current(txt);
this.make_calculator(txt);
},
build_options: function build_options(txt) {
var options = frappe.search.utils.get_creatables(txt).concat(frappe.search.utils.get_search_in_list(txt), frappe.search.utils.get_doctypes(txt), frappe.search.utils.get_reports(txt), frappe.search.utils.get_pages(txt), frappe.search.utils.get_modules(txt), frappe.search.utils.get_recent_pages(txt || ""));
var out = this.deduplicate(options);
return out.sort(function (a, b) {
return b.index - a.index;
});
},
deduplicate: function deduplicate(options) {
var out = [],
routes = [];
options.forEach(function (option) {
if (option.route) {
if (option.route[0] === "List" && option.route[2]) {
option.route.splice(2);
}
var str_route = typeof option.route === 'string' ? option.route : option.route.join('/');
if (routes.indexOf(str_route) === -1) {
out.push(option);
routes.push(str_route);
} else {
var old = routes.indexOf(str_route);
if (out[old].index < option.index) {
out[old] = option;
}
}
} else {
out.push(option);
routes.push("");
}
});
return out;
},
set_global_results: function set_global_results(global_results, txt) {
this.global_results = this.global_results.concat(global_results);
},
make_global_search: function make_global_search(txt) {
var me = this;
this.options.push({
label: __("Search for '{0}'", [txt.bold()]),
value: __("Search for '{0}'", [txt]),
match: txt,
index: 100,
default: "Search",
onclick: function onclick() {
frappe.searchdialog.search.init_search(txt, "global_search");
}
});
},
make_search_in_current: function make_search_in_current(txt) {
var route = frappe.get_route();
if (route[0] === "List" && txt.indexOf(" in") === -1) {
var meta = frappe.get_meta(frappe.container.page.list_view.doctype);
var search_field = meta.title_field || "name";
var options = {};
options[search_field] = ["like", "%" + txt + "%"];
this.options.push({
label: __('Find {0} in {1}', [txt.bold(), route[1].bold()]),
value: __('Find {0} in {1}', [txt, route[1]]),
route_options: options,
onclick: function onclick() {
cur_list.refresh();
},
index: 90,
default: "Current",
match: txt
});
}
},
make_calculator: function make_calculator(txt) {
var first = txt.substr(0, 1);
if (first == parseInt(first) || first === "(" || first === "=") {
if (first === "=") {
txt = txt.substr(1);
}
try {
var val = eval(txt);
var formatted_value = __('{0} = {1}', [txt, (val + '').bold()]);
this.options.push({
label: formatted_value,
value: __('{0} = {1}', [txt, val]),
match: val,
index: 80,
default: "Calculator",
onclick: function onclick() {
frappe.msgprint(formatted_value, "Result");
}
});
} catch (e) {}
}
}
});
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
frappe.provide('frappe.search');
frappe.search.SearchDialog = Class.extend({
init: function init(opts) {
$.extend(this, opts);
this.make();
},
make: function make() {
var d = new frappe.ui.Dialog();
$(d.header).html($(frappe.render_template("search_header")));
this.search_dialog = d;
this.$search_modal = $(d.$wrapper).addClass('search-dialog');
this.$modal_body = $(d.body);
this.$input = this.$search_modal.find(".search-input");
this.setup();
},
setup: function setup() {
this.modal_state = 0;
this.current_keyword = "";
this.more_count = 20;
this.full_lists = {};
this.nav_lists = {};
this.bind_input();
this.bind_events();
},
update: function update($r) {
this.$search_modal.find('.loading-state').addClass('hide');
this.$modal_body.append($r);
if (this.$modal_body.find('.search-results').length > 1) {
this.$modal_body.find('.search-results').first().addClass("hide");
$r.removeClass("hide");
this.$modal_body.find('.search-results').first().remove();
} else {
$r.removeClass("hide");
}
},
put_placeholder: function put_placeholder(status_text) {
var $placeholder = $('' + '
' + '' + ' ' + ' ' + ' ' + '' + status_text + '
' + '
');
this.update($placeholder);
},
bind_input: function bind_input() {
var me = this;
this.$input.on("input", function () {
var $this = $(this);
clearTimeout($this.data('timeout'));
$this.data('timeout', setTimeout(function () {
if (me.$input.val() === me.current_keyword) return;
var keywords = me.$input.val();
if (keywords.length > 1) {
me.get_results(keywords);
} else {
me.current_keyword = "";
me.put_placeholder(me.search.empty_state_text);
}
}, 300));
});
},
bind_events: function bind_events() {
var me = this;
this.$modal_body.on('click', '.list-link', function () {
var link = $(this);
me.$modal_body.find('.search-sidebar').find(".list-link").removeClass("active select");
link.addClass("active select");
var type = link.attr('data-category');
me.$modal_body.find('.results-area').empty().html(me.full_lists[type]);
me.$modal_body.find('.module-section-link').first().focus();
me.current_type = type;
});
this.$modal_body.on('click', '.section-more', function () {
var type = $(this).attr('data-category');
me.$modal_body.find('.search-sidebar').find('*[data-category="' + type + '"]').trigger('click');
});
this.$modal_body.on('click', '.all-results-link', function () {
me.$modal_body.find('.search-sidebar').find('*[data-category="All Results"]').trigger('click');
});
this.$modal_body.on('click', '.list-more', function () {
var type = $(this).attr('data-category');
var fetch_type = $(this).attr('data-search');
var current_count = me.$modal_body.find('.result').length;
if (fetch_type === "Global") {
frappe.search.utils.get_global_results(me.current_keyword, current_count, me.more_count, type).then(function (doctype_results) {
me.add_more_results(doctype_results);
}, function (err) {
console.error(err);
});
} else {
var results = me.nav_lists[type].slice(0, me.more_count);
me.nav_lists[type].splice(0, me.more_count);
me.add_more_results([{ title: type, results: results }]);
}
});
this.$modal_body.on('click', '.switch-to-global-search', function () {
me.search = me.searches['global_search'];
me.$input.attr("placeholder", me.search.input_placeholder);
me.put_placeholder(me.search.empty_state_text);
me.get_results(me.current_keyword);
});
this.$modal_body.on('click', 'a[data-path]', frappe.help.show_results);
this.bind_keyboard_events();
},
bind_keyboard_events: function bind_keyboard_events() {
var me = this;
this.$search_modal.on('keydown', function (e) {
if (me.$modal_body.find('.list-link').length > 1) {
if (me.modal_state === 0) {
var _frappe$ui$keyCode = frappe.ui.keyCode,
UP_ARROW = _frappe$ui$keyCode.UP_ARROW,
DOWN_ARROW = _frappe$ui$keyCode.DOWN_ARROW,
TAB = _frappe$ui$keyCode.TAB;
if (e.which === DOWN_ARROW || e.which === TAB) {
e.preventDefault();
var $link = me.$modal_body.find('.list-link.select').next();
if ($link.length > 0) {
$link.trigger('click');
}
} else if (e.which === UP_ARROW) {
e.preventDefault();
var $link = me.$modal_body.find('.list-link.select').prev();
if ($link.length > 0) {
$link.trigger('click');
}
}
}
}
if (!me.$input.is(":focus")) {
me.$input.focus();
}
});
},
init_search: function init_search(keywords, search_type) {
var me = this;
this.search = this.searches[search_type];
this.$input.attr("placeholder", this.search.input_placeholder);
this.put_placeholder(this.search.empty_state_text);
this.get_results(keywords);
this.search_dialog.show();
this.$input.val(keywords);
setTimeout(function () {
me.$input.select();
}, 500);
},
get_results: function get_results(keywords) {
this.current_keyword = keywords;
if (this.$modal_body.find('.empty-state').length > 0) {
this.put_placeholder(__("Searching ..."));
this.$modal_body.find('.cover').removeClass('hide');
} else {
this.$search_modal.find('.loading-state').removeClass('hide');
}
this.search.get_results(keywords, this.parse_results.bind(this));
},
parse_results: function parse_results(result_sets, keyword) {
result_sets = result_sets.filter(function (set) {
return set.results.length > 0;
});
if (result_sets.length > 0) {
this.render_data(result_sets);
} else {
this.put_placeholder(this.search.no_results_status(keyword));
}
},
render_data: function render_data(result_sets) {
var me = this;
var $search_results = $(frappe.render_template("search")).addClass('hide');
var $sidebar = $search_results.find(".search-sidebar").empty();
var sidebar_item_html = '';
this.modal_state = 0;
this.full_lists = { 'All Results': $('
') };
this.nav_lists = {};
result_sets.forEach(function (set) {
$sidebar.append($(__(sidebar_item_html, [set.title])));
me.add_section_to_summary(set.title, set.results);
me.full_lists[set.title] = me.render_full_list(set.title, set.results, set.fetch_type);
});
if (result_sets.length > 1) {
$sidebar.prepend($(__(sidebar_item_html, ["All Results"])));
}
this.update($search_results.clone());
this.$modal_body.find('.list-link').first().trigger('click');
},
render_full_list: function render_full_list(type, results, fetch_type) {
var me = this,
max_length = 20;
var $results_list = $(' ' + '
' + '
' + '
' + type + '
' + '
');
var $results_col = $results_list.find('.module-section-column');
for (var i = 0; i < max_length && results.length > 0; i++) {
$results_col.append(me.render_result(type, results.shift()));
}
if (results.length > 0) {
if (fetch_type === "Nav") this.nav_lists[type] = results;
$results_col.append('' + __("More...") + ' ');
}
return $results_list;
},
add_section_to_summary: function add_section_to_summary(type, results) {
var me = this;
var are_expansive = false;
var margin_more = "10px";
for (var i = 0; i < results.length; i++) {
if (results[i]["description" || "image" || "subtypes"] || false) {
are_expansive = true;
break;
}
}
if (results[0].image) margin_more = "20px";
var _ref = are_expansive ? [3, "12"] : [4, "6"],
_ref2 = _slicedToArray(_ref, 2),
section_length = _ref2[0],
col_width = _ref2[1];
if (this.full_lists['All Results'].find('.module-section').last().find('.col-sm-6').length !== 1 || are_expansive) {
this.full_lists['All Results'].append($('
'));
}
var $results_col = $('\n\t\t\t
' + type + '
\n\t\t\t
\n\t\t\t
');
results.slice(0, section_length).forEach(function (result) {
$results_col.append(me.render_result(type, result));
});
if (results.length > section_length) {
$results_col.append('');
}
this.full_lists['All Results'].find('.module-section').last().append($results_col);
},
render_result: function render_result(type, result) {
var _this = this;
var $result = $('
');
function get_link(result) {
var link;
if (result.route) {
link = 'href="#' + result.route.join('/') + '" ';
} else if (result.data_path) {
link = 'data-path="' + result.data_path + '"';
} else {
link = "";
}
return link;
}
if (result.image) {
$result.append('');
} else if (result.image === null) {
$result.append('' + frappe.get_abbr(result.label) + '
');
}
var title_html = '' + result.label + ' ';
var $result_text = $('
');
if (result.description) {
$result_text.append($('' + title_html + ' '));
$result_text.append('' + result.description + '
');
} else {
$result_text.append($(title_html));
if (result.route_options) {
frappe.route_options = result.route_options;
}
$result_text.on('click', function (e) {
_this.search_dialog.hide();
if (result.onclick) {
result.onclick(result.match);
} else {
var previous_hash = window.location.hash;
frappe.set_route(result.route);
if (window.location.hash == previous_hash) {
frappe.route();
}
}
});
}
$result.append($result_text);
if (result.subtypes) {
result.subtypes.forEach(function (subtype) {
$result.append(subtype);
});
}
return $result;
},
add_more_results: function add_more_results(results_set) {
var me = this;
var more_results = $('
');
results_set[0].results.forEach(function (result) {
more_results.append(me.render_result(results_set[0].title, result));
});
this.$modal_body.find('.list-more').before(more_results);
if (results_set[0].results.length < this.more_count) {
this.$modal_body.find('.list-more').hide();
var no_of_results = this.$modal_body.find('.result').length;
var no_of_results_cue = $('' + no_of_results + ' results found
');
this.$modal_body.find(".more-results:last").append(no_of_results_cue);
}
this.$modal_body.find('.more-results.last').slideDown(200, function () {});
},
searches: {
global_search: {
input_placeholder: __("Global Search"),
empty_state_text: __("Search for anything"),
no_results_status: function no_results_status(keyword) {
return __("No results found for '" + keyword + "' in Global Search
");
},
get_results: function get_results(keywords, callback) {
var start = 0,
limit = 100;
var results = frappe.search.utils.get_nav_results(keywords);
frappe.search.utils.get_global_results(keywords, start, limit).then(function (global_results) {
results = results.concat(global_results);
return frappe.search.utils.get_help_results(keywords);
}).then(function (help_results) {
results = results.concat(help_results);
callback(results, keywords);
}, function (err) {
console.error(err);
});
}
},
help: {
input_placeholder: __("Search Help"),
empty_state_text: __("Search the docs"),
no_results_status: function no_results_status(keyword) {
return __("No results found for '" + keyword + "' in Help
Would you like to search globally " + " or the forums instead?
");
},
get_results: function get_results(keywords, callback) {
var results = [];
frappe.search.utils.get_help_results(keywords).then(function (help_results) {
results = results.concat(help_results);
callback(results, keywords);
}, function (err) {
console.error(err);
});
}
}
}
});frappe.templates['search'] = '';
frappe.templates['search_header'] = '';
frappe.provide('frappe.search');
frappe.search.utils = {
setup_recent: function setup_recent() {
this.recent = JSON.parse(frappe.boot.user.recent || "[]") || [];
},
get_recent_pages: function get_recent_pages(keywords) {
var me = this,
values = [],
options = [];
function find(list, keywords, process) {
list.forEach(function (item, i) {
var _item = $.isArray(item) ? item[0] : item;
_item = __(_item || '').toLowerCase().replace(/-/g, " ");
if (keywords === _item || _item.indexOf(keywords) !== -1) {
var option = process(item);
if (option) {
if ($.isPlainObject(option)) {
option = [option];
}
option.forEach(function (o) {
o.match = item;
});
options = option.concat(options);
}
}
});
}
me.recent.forEach(function (doctype, i) {
values.push([doctype[1], ['Form', doctype[0], doctype[1]]]);
});
values = values.reverse();
frappe.route_history.forEach(function (route, i) {
if (route[0] === 'Form') {
values.push([route[2], route]);
} else if (in_list(['List', 'Report', 'Tree', 'modules', 'query-report'], route[0])) {
if (route[1]) {
values.push([route[1], route]);
}
} else if (route[0]) {
values.push([frappe.route_titles[route[0]] || route[0], route]);
}
});
find(values, keywords, function (match) {
var out = {
route: match[1]
};
if (match[1][0] === 'Form') {
if (match[1][1] !== match[1][2]) {
out.label = __(match[1][1]) + " " + match[1][2].bold();
out.value = __(match[1][1]) + " " + match[1][2];
} else {
out.label = __(match[1][1]).bold();
out.value = __(match[1][1]);
}
} else if (in_list(['List', 'Report', 'Tree', 'modules', 'query-report'], match[1][0])) {
var type = match[1][0],
label = type;
if (type === 'modules') label = 'Module';else if (type === 'query-report') label = 'Report';
out.label = __(match[1][1]).bold() + " " + __(label);
out.value = __(match[1][1]) + " " + __(label);
} else {
out.label = match[0].bold();
out.value = match[0];
}
out.index = 80;
return out;
});
return options;
},
get_search_in_list: function get_search_in_list(keywords) {
var me = this;
var out = [];
if (in_list(keywords.split(" "), "in") && keywords.slice(-2) !== "in") {
var parts = keywords.split(" in ");
frappe.boot.user.can_read.forEach(function (item) {
if (frappe.boot.user.can_search.includes(item)) {
var level = me.fuzzy_search(parts[1], item);
if (level) {
out.push({
type: "In List",
label: __('Find {0} in {1}', [__(parts[0]), me.bolden_match_part(__(item), parts[1])]),
value: __('Find {0} in {1}', [__(parts[0]), __(item)]),
route_options: { "name": ["like", "%" + parts[0] + "%"] },
index: 1 + level,
route: ["List", item]
});
}
}
});
}
return out;
},
get_creatables: function get_creatables(keywords) {
var me = this;
var out = [];
var firstKeyword = keywords.split(" ")[0];
if (firstKeyword.toLowerCase() === __("new")) {
frappe.boot.user.can_create.forEach(function (item) {
var level = me.fuzzy_search(keywords.substr(4), item);
if (level) {
out.push({
type: "New",
label: __("New {0}", [me.bolden_match_part(__(item), keywords.substr(4))]),
value: __("New {0}", [__(item)]),
index: 1 + level,
match: item,
onclick: function onclick() {
frappe.new_doc(item, true);
}
});
}
});
}
return out;
},
get_doctypes: function get_doctypes(keywords) {
var me = this;
var out = [];
var level, target;
var option = function option(type, route, order) {
return {
type: type,
label: me.bolden_match_part(__(target), keywords) + " " + __(type),
value: __(target) + " " + __(type),
index: level + order,
match: target,
route: route
};
};
frappe.boot.user.can_read.forEach(function (item) {
level = me.fuzzy_search(keywords, item);
if (level) {
target = item;
if (in_list(frappe.boot.single_types, item)) {
out.push(option("", ["Form", item, item], 0.05));
} else if (frappe.boot.user.can_search.includes(item)) {
if (in_list(frappe.boot.user.can_create, item)) {
var match = item;
out.push({
type: "New",
label: __("New {0}", [me.bolden_match_part(__(item), keywords)]),
value: __("New {0}", [__(item)]),
index: level + 0.015,
match: item,
onclick: function onclick() {
frappe.new_doc(match, true);
}
});
}
if (in_list(frappe.boot.treeviews, item)) {
out.push(option("Tree", ["Tree", item], 0.05));
} else {
out.push(option("List", ["List", item], 0.05));
if (frappe.model.can_get_report(item)) {
out.push(option("Report", ["Report", item], 0.04));
}
if (frappe.boot.calendars.indexOf(item) !== -1) {
out.push(option("Calendar", ["List", item, "Calendar"], 0.03));
out.push(option("Gantt", ["List", item, "Gantt"], 0.02));
}
}
}
}
});
return out;
},
get_reports: function get_reports(keywords) {
var me = this;
var out = [];
var route;
Object.keys(frappe.boot.user.all_reports).forEach(function (item) {
var level = me.fuzzy_search(keywords, item);
if (level > 0) {
var report = frappe.boot.user.all_reports[item];
if (report.report_type == "Report Builder") route = ["Report", report.ref_doctype, item];else route = ["query-report", item];
out.push({
type: "Report",
label: __("Report {0}", [me.bolden_match_part(__(item), keywords)]),
value: __("Report {0}", [__(item)]),
index: level,
route: route
});
}
});
return out;
},
get_pages: function get_pages(keywords) {
var me = this;
var out = [];
this.pages = {};
$.each(frappe.boot.page_info, function (name, p) {
me.pages[p.title] = p;
p.name = name;
});
Object.keys(this.pages).forEach(function (item) {
var level = me.fuzzy_search(keywords, item);
if (level) {
var page = me.pages[item];
out.push({
type: "Page",
label: __("Open {0}", [me.bolden_match_part(__(item), keywords)]),
value: __("Open {0}", [__(item)]),
match: item,
index: level,
route: [page.route || page.name]
});
}
});
var target = 'Calendar';
if (__('calendar').indexOf(keywords.toLowerCase()) === 0) {
out.push({
type: "Calendar",
value: __("Open {0}", [__(target)]),
index: me.fuzzy_search(keywords, 'Calendar'),
match: target,
route: ['List', 'Event', target]
});
}
if (__('email inbox').indexOf(keywords.toLowerCase()) === 0) {
out.push({
type: "Inbox",
value: __("Open {0}", [__('Email Inbox')]),
index: me.fuzzy_search(keywords, 'email inbox'),
match: target,
route: ['List', 'Communication', 'Inbox']
});
}
return out;
},
get_modules: function get_modules(keywords) {
var me = this;
var out = [];
Object.keys(frappe.modules).forEach(function (item) {
var level = me.fuzzy_search(keywords, item);
if (level > 0) {
var module = frappe.modules[item];
if (module._doctype) return;
var ret = {
type: "Module",
label: __("Open {0}", [me.bolden_match_part(__(item), keywords)]),
value: __("Open {0}", [__(item)]),
index: level
};
if (module.link) {
ret.route = [module.link];
} else {
ret.route = ["Module", item];
}
out.push(ret);
}
});
return out;
},
get_global_results: function get_global_results(keywords, start, limit) {
var doctype = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : "";
var me = this;
function get_results_sets(data) {
var results_sets = [],
result,
set;
function get_existing_set(doctype) {
return results_sets.find(function (set) {
return set.title === doctype;
});
}
function make_description(content, doc_name) {
var parts = content.split(" ||| ");
var result_max_length = 300;
var field_length = 120;
var fields = [];
var result_current_length = 0;
var field_text = "";
for (var i = 0; i < parts.length; i++) {
var part = parts[i];
if (part.toLowerCase().indexOf(keywords) !== -1) {
if (part.indexOf(' &&& ') !== -1) {
var colon_index = part.indexOf(' &&& ');
var field_value = part.slice(colon_index + 5);
} else {
var colon_index = part.indexOf(' : ');
var field_value = part.slice(colon_index + 3);
}
if (field_value.length > field_length) {
var field_data = "";
var index = field_value.indexOf(keywords);
field_data += index < field_length / 2 ? field_value.slice(0, index) : '...' + field_value.slice(index - field_length / 2, index);
field_data += field_value.slice(index, index + field_length / 2);
field_data += index + field_length / 2 < field_value.length ? "..." : "";
field_value = field_data;
}
var field_name = part.slice(0, colon_index);
var remaining_length = result_max_length - result_current_length;
result_current_length += field_name.length + field_value.length + 2;
if (result_current_length < result_max_length) {
field_text = '' + me.bolden_match_part(field_name, keywords) + ': ' + me.bolden_match_part(field_value, keywords);
if (fields.indexOf(field_text) === -1 && doc_name !== field_value) {
fields.push(field_text);
}
} else {
if (field_name.length < remaining_length) {
remaining_length -= field_name.length;
field_text = '' + me.bolden_match_part(field_name, keywords) + ': ';
field_value = field_value.slice(0, remaining_length);
field_value = field_value.slice(0, field_value.lastIndexOf(' ')) + ' ...';
field_text += me.bolden_match_part(field_value, keywords);
fields.push(field_text);
} else {
fields.push('...');
}
break;
}
}
}
return fields.join(', ');
}
data.forEach(function (d) {
result = {
label: d.name,
value: d.name,
description: make_description(d.content, d.name),
route: ['Form', d.doctype, d.name]
};
if (d.image || d.image === null) {
result.image = d.image;
}
set = get_existing_set(d.doctype);
if (set) {
set.results.push(result);
} else {
set = {
title: d.doctype,
results: [result],
fetch_type: "Global"
};
results_sets.push(set);
}
});
return results_sets;
}
return new Promise(function (resolve, reject) {
frappe.call({
method: "frappe.utils.global_search.search",
args: {
text: keywords,
start: start,
limit: limit,
doctype: doctype
},
callback: function callback(r) {
if (r.message) {
resolve(get_results_sets(r.message));
} else {
resolve([]);
}
}
});
});
},
get_help_results: function get_help_results(keywords) {
function get_results_set(data) {
var result;
var set = {
title: "Help",
fetch_type: "Help",
results: []
};
data.forEach(function (d) {
result = {
label: d[0],
value: d[0],
description: d[1],
data_path: d[2],
onclick: function onclick() {}
};
set.results.push(result);
});
return [set];
}
return new Promise(function (resolve, reject) {
frappe.call({
method: "frappe.utils.help.get_help",
args: {
text: keywords
},
callback: function callback(r) {
if (r.message) {
resolve(get_results_set(r.message));
} else {
resolve([]);
}
}
});
});
},
get_nav_results: function get_nav_results(keywords) {
function sort_uniques(array) {
var routes = [],
out = [];
array.forEach(function (d) {
if (d.route) {
if (d.route[0] === "List" && d.route[2]) {
d.route.splice(2);
}
var str_route = d.route.join('/');
if (routes.indexOf(str_route) === -1) {
routes.push(str_route);
out.push(d);
} else {
var old = routes.indexOf(str_route);
if (out[old].index > d.index) {
out[old] = d;
}
}
} else {
out.push(d);
}
});
return out.sort(function (a, b) {
return b.index - a.index;
});
}
var lists = [],
setup = [];
var all_doctypes = sort_uniques(this.get_doctypes(keywords));
all_doctypes.forEach(function (d) {
if (d.type === "") {
setup.push(d);
} else {
lists.push(d);
}
});
var in_keyword = keywords.split(" in ")[0];
return [{ title: "Recents", fetch_type: "Nav", results: sort_uniques(this.get_recent_pages(keywords)) }, { title: "Create a new ...", fetch_type: "Nav", results: sort_uniques(this.get_creatables(keywords)) }, { title: "Find '" + in_keyword + "' in ... ", fetch_type: "Nav", results: sort_uniques(this.get_search_in_list(keywords)) }, { title: "Lists", fetch_type: "Nav", results: lists }, { title: "Reports", fetch_type: "Nav", results: sort_uniques(this.get_reports(keywords)) }, { title: "Administration", fetch_type: "Nav", results: sort_uniques(this.get_pages(keywords)) }, { title: "Modules", fetch_type: "Nav", results: sort_uniques(this.get_modules(keywords)) }, { title: "Setup", fetch_type: "Nav", results: setup }];
},
fuzzy_search: function fuzzy_search(keywords, _item) {
var item = __(_item || '').replace(/-/g, " ");
var ilen = item.length;
var klen = keywords.length;
var length_ratio = klen / ilen;
var max_skips = 3,
max_mismatch_len = 2;
if (klen > ilen) {
return 0;
}
if (keywords === item || item.toLowerCase().indexOf(keywords) === 0) {
return 10 + length_ratio;
}
if (item.indexOf(keywords) !== -1 && keywords !== keywords.toLowerCase()) {
return 9 + length_ratio;
}
item = item.toLowerCase();
keywords = keywords.toLowerCase();
if (item.indexOf(keywords) !== -1) {
return 8 + length_ratio;
}
var skips = 0,
mismatches = 0;
outer: for (var i = 0, j = 0; i < klen; i++) {
if (mismatches !== 0) skips++;
if (skips > max_skips) return 0;
var k_ch = keywords.charCodeAt(i);
mismatches = 0;
while (j < ilen) {
if (item.charCodeAt(j++) === k_ch) {
continue outer;
}
if (++mismatches > max_mismatch_len) return 0;
}
return 0;
}
if (skips + mismatches > 0) {
return (5 + length_ratio) / (skips + mismatches);
} else {
return 0;
}
},
bolden_match_part: function bolden_match_part(str, subseq) {
var rendered = "";
if (this.fuzzy_search(subseq, str) === 0) {
return str;
} else if (this.fuzzy_search(subseq, str) > 6) {
var regEx = new RegExp("(" + subseq + ")", "ig");
return str.replace(regEx, '$1 ');
} else {
var str_orig = str;
var str = str.toLowerCase();
var str_len = str.length;
var subseq = subseq.toLowerCase();
outer: for (var i = 0, j = 0; i < subseq.length; i++) {
var sub_ch = subseq.charCodeAt(i);
while (j < str_len) {
if (str.charCodeAt(j) === sub_ch) {
var str_char = str_orig.charAt(j);
if (str_char === str_char.toLowerCase()) {
rendered += '' + subseq.charAt(i) + ' ';
} else {
rendered += '' + subseq.charAt(i).toUpperCase() + ' ';
}
j++;
continue outer;
}
rendered += str_orig.charAt(j);
j++;
}
return str_orig;
}
rendered += str_orig.slice(j);
return rendered;
}
}
};
frappe.provide('frappe.ui.misc');
frappe.ui.misc.about = function () {
if (!frappe.ui.misc.about_dialog) {
var d = new frappe.ui.Dialog({ title: __('Frappe Framework') });
$(d.body).html(repl("\
" + __("Open Source Applications for the Web") + "
\
\
Website: https://frappe.io
\
\
Source: https://github.com/frappe
\
\
Installed Apps \
Loading versions...
\
\
© Frappe Technologies Pvt. Ltd and contributors
\
", frappe.app));
frappe.ui.misc.about_dialog = d;
frappe.ui.misc.about_dialog.on_page_show = function () {
if (!frappe.versions) {
frappe.call({
method: "frappe.utils.change_log.get_versions",
callback: function callback(r) {
show_versions(r.message);
}
});
}
};
var show_versions = function show_versions(versions) {
var $wrap = $("#about-app-versions").empty();
$.each(Object.keys(versions).sort(), function (i, key) {
var v = versions[key];
if (v.branch) {
var text = $.format('{0}: v{1} ({2})
', [v.title, v.branch_version || v.version, v.branch]);
} else {
var text = $.format('{0}: v{1}
', [v.title, v.version]);
}
$(text).appendTo($wrap);
});
frappe.versions = versions;
};
}
frappe.ui.misc.about_dialog.show();
};frappe.templates['navbar'] = ' ';
frappe.provide("frappe.ui.toolbar");
frappe.provide('frappe.search');
frappe.ui.toolbar.Toolbar = Class.extend({
init: function init() {
var header = $('header').append(frappe.render_template("navbar", {
avatar: frappe.avatar(frappe.session.user)
}));
this.setup_sidebar();
var awesome_bar = new frappe.search.AwesomeBar();
awesome_bar.setup("#navbar-search");
awesome_bar.setup("#modal-search");
this.setup_help();
$(document).on("notification-update", function () {
frappe.ui.notifications.update_notifications();
});
$('.dropdown-toggle').dropdown();
$(document).trigger('toolbar_setup');
$(document).on("page-change", function () {
$("header .navbar .custom-menu").remove();
});
$('#search-modal').on('shown.bs.modal', function () {
var search_modal = $(this);
setTimeout(function () {
search_modal.find('#modal-search').focus();
}, 300);
});
},
setup_sidebar: function setup_sidebar() {
var header = $('header');
header.find(".toggle-sidebar").on("click", function () {
var layout_side_section = $('.layout-side-section');
var overlay_sidebar = layout_side_section.find('.overlay-sidebar');
overlay_sidebar.addClass('opened');
overlay_sidebar.find('.reports-dropdown').removeClass('dropdown-menu').addClass('list-unstyled');
overlay_sidebar.find('.dropdown-toggle').addClass('text-muted').find('.caret').addClass('hidden-xs hidden-sm');
$('