I have a list of items shown in one tab and I want to be able to click on one of the items and open a new tab and show its details on the new tab. I am adding the new tab by doing the following:
$(".btn-opener").click(function(){
$('#tabs').tabs('add', 'http://localhost/GetItem/' + $(this).attr('href'), "View Details");
}
My problem is that the url is actually a service endpoint returning JSON. I want to be able to apply a js template to the returned data. How do I do this? Do I need to hook into the tab's load event?
I think I'm going to solve this by adding a div with the HTML I need into the tab conainer, and then using its id to set the fragment of the new tab. For example:
$('.btn-opener').click(function () {
var $this = $(this),
itemID = $this.data("item-id");
$.get("http://localhost/GetItem/" + itemID,
function (data, textStatus, jqXHR) {
var html = Mustache.to_html($("#item-template").html(), data);
$("#tabs").append('<div id="' + id + '">' + html + '</div>');
$('#tabs').tabs("add", "#" + id, $this.text());
},
"json"
);
return false;
});
I will wait to see if anyone comes up with a better solution before marking this as the answer.
Related
I want to be able to have the option persist after I added a tag. A similar question was solved here:
Dynamically add item to jQuery Select2 control that uses AJAX
But a commenter is right, it is only solved with an additional input box somewhere not in the original select box.
[![Question kinda solved][1]][1]
I tried a number of things and they all do not work:
returning an object with createOption or createSearchChoice
Appending a new Option
This is because the widget already secretly adds a new options as is necessary to accommodate the new tag, but if it wasn't a tag from the original data, it will delete it if a new option is selected. I thought maybe on the select2:select event, I could see if the new value is in the data somewhere. Alas, that data is hard to find.
[1]: https://i.stack.imgur.com/CyCC4.png
Here are some failed attempts with commentary
var quote = {};
google.script.run.withSuccessHandler(function(e){
quote = $('#quote').select2({
width:'100%',
data: e, //[{id:'quote', text:'quote'},{id:'quote2', text:'quote2'}]
tags: true,
/*Alas, this doesn't work either becuse the tag is still in the option when we check fo rit
createTag: function(){
if (quote.find("option[value='" + params.term + "']").length) quote.append(Option(params.term,params,term,true,true)).trigger('change')
return {id: params.term, text:params.term})
*/
//insertTag: function(d,t){d.push(t)} Didn't work either
allowClear:true,
placeholder:'No Quote'
}).on('select2:select',function(e){
/*
// Set the value, creating a new option if necessary
This doesn't work because the new item is in the option thingy temporarily while we're trying to see if its there
if (quote.find("option[value='" + e.params.data.id + "']").length) {
quote.val(e.params.data.id).trigger('change');
} else {
// Create a DOM Option and pre-select by default
var newOption = new Option(e.params.data.id, e.params.data.id, true, true);
// Append it to the select
quote.append(newOption).trigger('change');
}
*/
if (e.params.data.id&&(quotes.indexOf(e.params.data.id)!=-1)){
loadQuote(e.params.data.id)
} else {
//new quote so now we have to make preparations...
quotes.push(e.params.data.id)
console.log(e.params.data)
console.log(quotes)
var newOption = new Option(e.params.data.id,e.params.data.id,true,true)
quote.append(newOption).trigger('change')
//don't send anything to the server, because there is no need
}
})
quote.val(null).trigger('change')
I have a select2 dropdown which has to get its options dynamically as user types the letters.
HTML:
<select class="select2 select2-hidden-accessible ddlSegments" multiple=""></select>
Here is the function that triggers for each letter that user types.
JS:
function GetSegmentsByKeyword(ddlSegments, keyword) {
$(ddlSegments).html("").trigger("change");
$.ajax({
type: "POST",
url: "/Common/GetSegmentsByKeyword",
data: "{'keyword': " + JSON.stringify(keyword) + "}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
if (response.Segments.length > 0) {
//bind data
var options = "";
var jsonObject = $.parseJSON(response.Segments);
$.each(jsonObject, function (i, obj) {
options += '<option value="' + obj.SegmentValue + '">' + obj.DisplayName + '</option>';
});
$(ddlSegments).append(options);
}
}
});
}
Here is the problem I experience:
When user entered say '12', the relevant data from table is returned and bound to the options. But the popup list doesn't show up. It shows up only after user types another letter.
i.e, when user types '12', the correct data is bound and doesn't show the list. But when user types '123', the list shows up. However, the data in the list is only related to '12'. When user types '1234', the list shows up with data related to '123'.
What should be done, so that the select2 list shows up dynamically right after binding the data.
I guess you missed to trigger event on key up in select2 like this for example
$(document).on('keyup', '.ddlSegments', function (e),
please check the fiddle here: Updated Fiddle
Check out the minimumSearchLength configuration parameter. Here is the documentation.
$('select').select2({
minimumInputLength: 3 // only start searching when the user has input 3 or more characters
});
I have a filter and a list of products (id, name, creation_date).
I can filter by id, name or creation_date. With an AJAX request I update a content div... but obviously the URL not change.
How can I append params to URL? For example:
localhost:3000/dashboard/catalog?name=radio&?date_creation=23-06-2013
I know that history.pushState(html5) exists... but I need that my app works in html4 browsers like IE9.
I tried Wiselinks (https://github.com/igor-alexandrov/wiselinks) which it uses History.js but it doesn´t use AJAX request.
Any ideas?
thanks
Finally I follow those RailsCasts tutorials:
http://railscasts.com/episodes/240-search-sort-paginate-with-ajax?language=es&view=asciicast
http://railscasts.com/episodes/246-ajax-history-state?language=es&view=asciicast
You are doing some AJAX call means, you must have invoked the AJAX part on radio button change
So I am assuming, you have done it using by radio button and the radio button name is 'choose_product'
You can add a hidden field in your view, where you can store your current date.
<div id='parentDiv'>
<%= hidden_field_tag 'current_date', Time.now.strftime('%d-%m-%Y') %>
Your radio button code
</div>
In the javascript add the following code. It is just a sample not complete solution.
$(document).ready(function(){
var showProducts = function(){
$("#parentDiv").on('click', "input[name='choose_product']", function(){
var ajax_url = 'localhost:3000/dashboard/catalog';
var url_param = '';
switch($(this).val()){
case 'creation_date':
var param_date = $('#current_date').val();
url_param = '?name=radio&date_creation=' + param_date;
break;
case 'name':
// Your code goes here
default:
//Your code goes here
}
// Here you will get the modified url dynamically
ajax_url += url_param
$.ajax({
url: ajax_url,
// your code goes here
});
});
}
showProducts();
});
A lot of time has passed, but it may be useful.
The code is also updated so if you have more then one ajax\remote link you will be able to merge the params of multiple urls.
Based on user1364684 answer and this for combine urls.
# change ".someClassA" or "pagination" to the a link of the ajax elemen
$(document).on('click', '.someClassA a, .pagination a', function(){
var this_params = this.href.split('?')[1], ueryParameters = {},
queryString = location.search.substring(1), re = /([^&=]+)=([^&]*)/g, m;
queryString = queryString + '&' + this_params;
#Creates a map with the query string parameters
while m = re.exec(queryString)
queryParameters[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
url = window.location.href.split('?')[0] + "?" + $.param(queryParameters);
$.getScript(url);
history.pushState(null, "", url);
return false;
});
# make back button work
$(window).on("popstate", function(){
$.getScript(location.href);
});
I would like to use an autocomplete with ajax. So my goal is to have:
When the user types something in the text field, some suggestions provided by the server appear (I have to find suggestions in a database)
When the user presses "enter", clicks somewhere else than in the autocomplete box, or when he/she selects a suggestion, the string in the textfield is sent to the server.
I first tried to use the autocomplete widget provided by lift but I faced three problems:
it is meant to be an extended select, that is to say you can originally only submit suggested values.
it is not meant to be used with ajax.
it gets buggy when combined with WiringUI.
So, my question is: How can I combine jquery autocomplete and interact with the server in lift. I think I should use some callbacks but I don't master them.
Thanks in advance.
UPDATE Here is a first implementation I tried but the callback doesn't work:
private def update_source(current: String, limit: Int) = {
val results = if (current.length == 0) Nil else /* generate list of results */
new JsCmd{def toJsCmd = if(results.nonEmpty) results.mkString("[\"", "\", \"", "\"]") else "[]" }
}
def render = {
val id = "my-autocomplete"
val cb = SHtml.ajaxCall(JsRaw("request"), update_source(_, 4))
val script = Script(new JsCmd{
def toJsCmd = "$(function() {"+
"$(\"#"+id+"\").autocomplete({ "+
"autocomplete: on, "+
"source: function(request, response) {"+
"response("+cb._2.toJsCmd + ");" +
"}"+
"})});"
})
<head><script charset="utf-8"> {script} </script></head> ++
<span id={id}> {SHtml.ajaxText(init, s=>{ /*set cell to value s*/; Noop}) } </span>
}
So my idea was:
to get the selected result via an SHtml.ajaxText field which would be wraped into an autocomplete field
to update the autocomplete suggestions using a javascript function
Here's what you need to do.
1) Make sure you are using Lift 2.5-SNAPSHOT (this is doable in earlier versions, but it's more difficult)
2) In the snippet you use to render the page, use SHtml.ajaxCall (in particular, you probably want this version: https://github.com/lift/framework/blob/master/web/webkit/src/main/scala/net/liftweb/http/SHtml.scala#L170) which will allow you to register a server side function that accepts your search term and return a JSON response containing the completions. You will also register some action to occur on the JSON response with the JsContext.
3) The ajaxCall above will return a JsExp object which will result in the ajax request when it's invoked. Embed it within a javascript function on the page using your snippet.
4) Wire them up with some client side JS.
Update - Some code to help you out. It can definitely be done more succinctly with Lift 2.5, but due to some inconsistencies in 2.4 I ended up rolling my own ajaxCall like function. S.fmapFunc registers the function on the server side and the function body makes a Lift ajax call from the client, then invokes the res function (which comes from jQuery autocomplete) on the JSON response.
My jQuery plugin to "activate" the text input
(function($) {
$.fn.initAssignment = function() {
return this.autocomplete({
autoFocus: true,
source: function(req, res) {
search(req.term, res);
},
select: function(event, ui) {
assign(ui.item.value, function(data){
eval(data);
});
event.preventDefault();
$(this).val("");
},
focus: function(event, ui) {
event.preventDefault();
}
});
}
})(jQuery);
My Scala code that results in the javascript search function:
def autoCompleteJs = JsRaw("""
function search(term, res) {
""" +
(S.fmapFunc(S.contextFuncBuilder(SFuncHolder({ terms: String =>
val _candidates =
if(terms != null && terms.trim() != "")
assigneeCandidates(terms)
else
Nil
JsonResponse(JArray(_candidates map { c => c.toJson }))
})))
({ name =>
"liftAjax.lift_ajaxHandler('" + name
})) +
"=' + encodeURIComponent(term), " +
"function(data){ res(data); }" +
", null, 'json');" +
"""
}
""")
Update 2 - To add the function above to your page, use a CssSelector transform similar to the one below. The >* means append to anything that already exists within the matched script element. I've got other functions I've defined on that page, and this adds the search function to them.
"script >*" #> autoCompleteJs
You can view source to verify that it exists on the page and can be called just like any other JS function.
With the help of Dave Whittaker, here is the solution I came with.
I had to change some behaviors to get:
the desired text (from autocomplete or not) in an ajaxText element
the possibility to have multiple autocomplete forms on same page
submit answer on ajaxText before blurring when something is selected in autocomplete suggestions.
Scala part
private def getSugggestions(current: String, limit: Int):List[String] = {
/* returns list of suggestions */
}
private def autoCompleteJs = AnonFunc("term, res",JsRaw(
(S.fmapFunc(S.contextFuncBuilder(SFuncHolder({ terms: String =>
val _candidates =
if(terms != null && terms.trim() != "")
getSugggestions(terms, 5)
else
Nil
JsonResponse(JArray(_candidates map { c => JString(c)/*.toJson*/ }))
})))
({ name =>
"liftAjax.lift_ajaxHandler('" + name
})) +
"=' + encodeURIComponent(term), " +
"function(data){ res(data); }" +
", null, 'json');"))
def xml = {
val id = "myId" //possibility to have multiple autocomplete fields on same page
Script(OnLoad(JsRaw("jQuery('#"+id+"').createAutocompleteField("+autoCompleteJs.toJsCmd+")"))) ++
SHtml.ajaxText(cell.get, s=>{ cell.set(s); SearchMenu.recomputeResults; Noop}, "id" -> id)
}
Script to insert into page header:
(function($) {
$.fn.createAutocompleteField = function(search) {
return this.autocomplete({
autoFocus: true,
source: function(req, res) {
search(req.term, res);
},
select: function(event, ui) {
$(this).val(ui.item.value);
$(this).blur();
},
focus: function(event, ui) {
event.preventDefault();
}
});
}
})(jQuery);
Note: I accepted Dave's answer, mine is just to provide a complete answer for my purpose
Im trying to create an ajax (post) event that will populate a table in a div on button click.
I have a list of groups, when you click on a group, I would like the table to "disappear" and the members that belong to that group to "appear".
My problem comes up when using jQuery's .ajax...
When I click on the button, it is looking for a controller that doesnt exist, and a controller that is NOT referenced. I am, however, using AREAS (MVC2), and the area is named Member_Select where the controller is named MemberSelect. When I click on the button, I get a 404 stating it cannot find the controller Member_Select. I have examined the link button and it is set to Member_Select when clicked on, but here's the ajax call:
$.ajax({
type: "POST",
url: '/MemberSelect/GetMembersFromGroup',
success: function(html) { $("#groupResults").html(html); }
});
I havent been able to find any examples/help online.
Any thoughts/suggestions/hints would be greatly appreciated.
Thanks!
Have you tried navigating to /MemberSelect/GetMembersFromGroup to see what you get? - if it's 404'ing it's because the route can't be matched to a controller/ action.
I've not used the new areas functionality, but I'm not sure that the URL you've got is correct...I would have thought it would have been /AREANAME/MemberSelect/GetMembersFromGroup...but I could be wrong..!
When I did this, it worked fine. I didn't use POST and I don't know what AREAS means.
$("#item").autocomplete({
source: function(req, responseFn) {
addMessage("search on: '" + req.term + "'<br/>", true);
$.ajax({
url : ajaxUrlBase1 + "GetMatchedCities/" + req.term,
cache : false,
type : "GET", // http method
success : function(msg){
// ajax call has returned
var result = msg;
var a = [];
if (result !== null){
for(var i=0; i < result.length; i++) {
a.push({label: result[i].prop1, id: result[i].prop2});
}
}
responseFn(a);
}
});
}
});
Use:
area_name/controller_name/action_name
Instead of doing $.ajax I would use jQuery Form Plugin.
and have my form set as:
Html.BeginForm("Index","AdminArea/Admin",FormMethod.Post,
new { id="form-user", name="form-user"})
To use jQuery Form Plugin have a look here:
http://arturito.net/2010/12/02/asp-net-mvc2-jquery-form-post-tutorial/
You cold save your url in a Hidden Form element in (Html.HiddenForm()) and use the #id javascript operator to retrieve it. Just found this out today.