diff --git a/frappe/public/js/frappe/form/control.js b/frappe/public/js/frappe/form/control.js
index 3c8a0e580a..b21b729088 100644
--- a/frappe/public/js/frappe/form/control.js
+++ b/frappe/public/js/frappe/form/control.js
@@ -868,6 +868,12 @@ frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({
no_spinner: true,
args: args,
callback: function(r) {
+ if(frappe.model.can_read(me.df.options)) {
+ r.results.push({
+ value: " " + __("Create a new {0}", [me.df.options]) + "",
+ make_new: true
+ });
+ };
cache[request.term] = r.results;
response(r.results);
},
@@ -879,8 +885,18 @@ frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({
close: function(event, ui) {
me.autocomplete_open = false;
},
+ focus: function( event, ui ) {
+ if(ui.item.make_new) {
+ return false;
+ }
+ },
select: function(event, ui) {
me.autocomplete_open = false;
+ if(ui.item.make_new) {
+ me.frm.new_doc(me.df.options, me);
+ return false;
+ }
+
if(me.frm && me.frm.doc) {
me.selected = true;
me.parse_validate_and_set_in_model(ui.item.value);
@@ -891,7 +907,7 @@ frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({
}
}).data('ui-autocomplete')._renderItem = function(ul, d) {
var html = "" + d.value + "";
- if(d.value!==d.description) {
+ if(d.description && d.value!==d.description) {
html += '
' + d.description + '';
}
return $('
')
diff --git a/frappe/public/js/frappe/router.js b/frappe/public/js/frappe/router.js
index f857856f9a..544542e046 100644
--- a/frappe/public/js/frappe/router.js
+++ b/frappe/public/js/frappe/router.js
@@ -16,7 +16,7 @@ frappe.route = function() {
// "New DocType 1" and the renamed "TestDocType", both exist in history
// now if we try to go back,
// it doesn't allow us to go back to the one prior to "New DocType 1"
- // Hence if this check is true, instead of changing location hash,
+ // Hence if this check is true, instead of changing location hash,
// we just do a back to go to the doc previous to the "New DocType 1"
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);
@@ -32,12 +32,12 @@ frappe.route = function() {
route = frappe.get_route();
frappe.route_history.push(route);
-
+
if(route[0] && frappe.views[route[0] + "Factory"]) {
// has a view generator, generate!
if(!frappe.view_factory[route[0]])
frappe.view_factory[route[0]] = new frappe.views[route[0] + "Factory"]();
-
+
frappe.view_factory[route[0]].show();
} else {
// show page
@@ -49,7 +49,7 @@ frappe.route = function() {
}
}
-frappe.get_route = function(route) {
+frappe.get_route = function(route) {
// for app
return frappe.get_route_str(route).split('/')
}
@@ -60,25 +60,28 @@ frappe.get_route_str = function(route) {
if(route.substr(0,1)=='#') route = route.substr(1);
if(route.substr(0,1)=='!') route = route.substr(1);
-
- route = $.map(route.split('/'),
+
+ route = $.map(route.split('/'),
function(r) { return decodeURIComponent(r); }).join('/');
return route;
}
frappe.set_route = function() {
- route = $.map(arguments, function(a) {
+ if(arguments.length===1 && $.isArray(arguments[0])) {
+ arguments = arguments[0];
+ }
+ route = $.map(arguments, function(a) {
if($.isPlainObject(a)) {
frappe.route_options = a;
return null;
} else {
- return a ? encodeURIComponent(a) : null;
+ return a ? encodeURIComponent(a) : null;
}
}).join('/');
-
+
window.location.hash = route;
-
+
// Set favicon (app.js)
frappe.app.set_favicon();
}
@@ -98,10 +101,10 @@ $(window).on('hashchange', function() {
if(window.location.hash==frappe._cur_route)
return;
-
+
// hide open dialog
- if(cur_dialog && cur_dialog.hide_on_page_refresh)
+ if(cur_dialog && cur_dialog.hide_on_page_refresh)
cur_dialog.hide();
-
+
frappe.route();
-});
\ No newline at end of file
+});
diff --git a/frappe/public/js/frappe/ui/filters.js b/frappe/public/js/frappe/ui/filters.js
index 2370e02f8e..1da081c540 100644
--- a/frappe/public/js/frappe/ui/filters.js
+++ b/frappe/public/js/frappe/ui/filters.js
@@ -163,12 +163,11 @@ frappe.ui.Filter = Class.extend({
// set the field
if(me.fieldname) {
- // presents given (could be via tags!)
+ // pre-sets given (could be via tags!)
this.set_values(me.tablename, me.fieldname, me.condition, me.value);
} else {
me.set_field(me.doctype, 'name');
}
-
},
set_values: function(tablename, fieldname, condition, value) {
diff --git a/frappe/public/js/frappe/ui/toolbar/search.js b/frappe/public/js/frappe/ui/toolbar/search.js
index 6b8c3379d9..9d77d3d2b1 100644
--- a/frappe/public/js/frappe/ui/toolbar/search.js
+++ b/frappe/public/js/frappe/ui/toolbar/search.js
@@ -10,8 +10,160 @@ frappe.ui.toolbar.Search = frappe.ui.toolbar.SelectorDialog.extend({
},
help: __("Shortcut") + ": Ctrl+G"
});
-
+
// get new types
this.set_values(frappe.boot.user.can_search.join(',').split(','));
}
});
+
+frappe.search = {
+ setup: function() {
+ $("#navbar-search").autocomplete({
+ minLength: 0,
+ source: function(request, response) {
+ var txt = strip(request.term);
+ if(!txt) return;
+ var lower = strip(txt.toLowerCase());
+ frappe.search.options = [];
+ $.each(frappe.search.verbs, function(i, action) {
+ action(lower);
+ });
+
+ // sort options
+ frappe.search.options.sort(function(a, b) {
+ return a.match.length - b.match.length; });
+
+ frappe.search.options.push({
+ value: __("Help on Search"),
+ onclick: function() {
+ 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...")+' |
\
+
'
+ msgprint(txt, "Search Help");
+ }
+ });
+
+ response(frappe.search.options);
+ },
+ select: function(event, ui) {
+ if(ui.item.route_options) {
+ frappe.route_options = ui.item.route_options;
+ }
+
+ if(ui.item.onclick) {
+ ui.item.onclick(ui.item.match);
+ } else {
+ frappe.set_route(ui.item.route);
+ }
+ setTimeout(function() { $("#navbar-search").val(""); }, 100);
+ }
+ }).data('ui-autocomplete')._renderItem = function(ul, d) {
+ var html = "" + d.value + "";
+ if(d.description && d.value!==d.description) {
+ html += '
' + d.description + '';
+ }
+ return $('')
+ .data('item.autocomplete', d)
+ .html('' + html + '
')
+ .appendTo(ul);
+ };;
+ },
+ find: function(list, txt, process) {
+ var ret = null;
+ $.each(list, function(i, item) {
+ _item = __(item).toLowerCase().replace(/-/g, " ");
+ if(txt===_item || _item.indexOf(txt) !== -1) {
+ var option = process(item);
+ option.match = item;
+ frappe.search.options.push(option);
+ }
+ });
+ return ret;
+ }
+}
+
+frappe.search.verbs = [
+ // search in list if current
+ function(txt) {
+ var route = frappe.get_route();
+ if(route[0]==="List") {
+ frappe.search.options.push({
+ value: __('Find "{0}" in {1}', [txt, route[1]]),
+ route_options: {"name": ["like", "%" + txt + "%"]},
+ onclick: function() {
+ frappe.container.page.doclistview.set_route_options();
+ },
+ match: txt
+ });
+ }
+ },
+
+ // new doc
+ function(txt) {
+ var ret = false;
+ if(txt.split(" ")[0]==="new") {
+ frappe.search.find(frappe.boot.user.can_create, txt.substr(4), function(match) {
+ return {
+ value:__("New {0}", [match]),
+ route:["Form", match, "New " + match]
+ }
+ });
+ }
+ },
+
+ // doctype list
+ function(txt) {
+ frappe.search.find(frappe.boot.user.can_read, txt, function(match) {
+ return {
+ value: __("{0} List", [match]),
+ route:["List", match]
+ }
+ });
+ },
+
+ // pages
+ function(txt) {
+ frappe.search.find(keys(frappe.boot.page_info), txt, function(match) {
+ return {
+ value: __("Open {0}", [match]),
+ route: [match]
+ }
+ });
+ },
+
+ // modules
+ function(txt) {
+ frappe.search.find(keys(frappe.modules), txt, function(match) {
+ ret = {
+ value: __("Open {0}", [match]),
+ }
+ if(frappe.modules[match].link) {
+ ret.route = [frappe.modules[match].link];
+ } else {
+ ret.route = ["Module", match];
+ }
+ return ret;
+ });
+ },
+
+ // in
+ function(txt) {
+ if(in_list(txt.split(" "), "in")) {
+ parts = txt.split(" in ");
+ frappe.search.find(frappe.boot.user.can_read, parts[1], function(match) {
+ return {
+ value: __('Find "{0}" in {1}', [parts[0], match]),
+ route_options: {"name": ["like", "%" + parts[0] + "%"]},
+ route: ["List", match]
+ }
+ });
+ }
+ },
+];
diff --git a/frappe/public/js/frappe/ui/toolbar/toolbar.js b/frappe/public/js/frappe/ui/toolbar/toolbar.js
index 4a2f3197a9..5a56114879 100644
--- a/frappe/public/js/frappe/ui/toolbar/toolbar.js
+++ b/frappe/public/js/frappe/ui/toolbar/toolbar.js
@@ -20,7 +20,9 @@ frappe.ui.toolbar.Toolbar = Class.extend({
// clear all custom menus on page change
$(document).on("page-change", function() {
$("header .navbar .custom-menu").remove();
- })
+ });
+
+ frappe.search.setup();
},
make: function() {
$('header').append('\
@@ -37,6 +39,16 @@ frappe.ui.toolbar.Toolbar = Class.extend({
\
\
+
\

\