I am trying to use the type-ahead feature from bootstrap to populate a search bar dropdown using an AJAX call.
I saw some posts about it, but the best answer didn't solve my issue.
I get a TypeError: a is undefined from jquery.min.js (v1.8.1) each time I tap or erase one new letter in the input.
I am using the bootstrap-typeahead.js v2.1.1.
HTML:
<input class="input-xlarge" id="search" type="text" data-provide="typeahead">
JS:
$('#search').typeahead({
source: function (typeahead, query) {
return $.get('http://mywebsite.com/search', { query: query }, function(data){
return typeahead.process(data);
});
}
});
Target:
function search()
{
echo json_encode(array('toto', 'tata', 'word'));
}
I don't understand how this function can crash my jQuery lib.
try this
$(function(){
$('#search').typeahead({
source: function (query, process) {
return $.getJSON(
'http://mywebsite.com/search',
{ query: query },
function (data) {
return process(data);
});
}
});
});
and the json out put should be like this
[
"toto",
"tata",
"word"
]
and html should be
<input name="sometext" type="text" class="input-large" id="search" placeholder="type something">
Related
I keep getting this error message when I click on the send button. Im trying to create a Instant Messenger app where online users can chat one on one. I am a beginner and I would really appreciate any help. Here is my error message, again it appears in the console once I click the Send button.
Exception from Tracker recompute function: meteor.js:862 Error:
{{#each}} currently only accepts arrays, cursors or falsey values.
at badSequenceError (observe-sequence.js:148)
at observe-sequence.js:113
at Object.Tracker.nonreactive (tracker.js:597)
at observe-sequence.js:90
at Tracker.Computation._compute (tracker.js:331)
at Tracker.Computation._recompute (tracker.js:350)
at Object.Tracker._runFlush (tracker.js:489)
at onGlobalMessage (meteor.js:347)
Here is my HTML
<template name="chat_page">
<h2>Type in the box below to send a message!</h2>
<div class="row">
<div class="col-md-12">
<div class="well well-lg">
{{#each messages}}
{{> chat_message}}
{{/each}}
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<form class="js-send-chat">
<input class="input" type="text" name="chat" placeholder="type a message here...">
<input type="submit" value="Send">
</form>
</div>
</div>
</template>
<!-- simple template that displays a message -->
<template name="chat_message">
<div class = "container">
<div class = "row">
<img src="/{{profile.avatar}}" class="avatar_img">
{{username}} said: {{text}}
</div>
</div>
<br>
</template>
Client Side
Template.chat_page.helpers({
messages: function () {
var chat = Chats.findOne({ _id: Session.get("chatId") });
return chat.messages;
},
other_user: function () {
return "";
}
});
Template.chat_page.events({
'submit .js-send-chat': function (event) {
console.log(event);
event.preventDefault();
var chat = Chats.findOne({ _id: Session.get("chatId") });
if (chat) {
var msgs = chat.messages;
if (! msgs) {
msgs = [];
}
msgs.push({ text: event.target.chat.value });
event.target.chat.value = "";
chat.messages = msgs;
Chats.update({ _id: chat._id }, { $set : { messages: chat } });
Meteor.call("sendMessage", chat);
}
}
});
Parts of the server side
Meteor.publish("chats", function () {
return Chats.find();
});
Meteor.publish("userStatus", function () {
return Meteor.users.find({ "status.online": true });
});
Meteor.publish("userData", function () {
if (this.userId) {
return Meteor.users.find({ _id: this.userId },{ fields: { 'other': 1, 'things': 1 } });
} else {
this.ready();
}
return Meteor.users.find({ "status.online": true });
});
Meteor.publish("users", function () {
return Meteor.users.find({ "status.online": true });
});
Chats.allow({
insert: function () { return true; },
update: function () { return true; },
remove: function () { return true; }
});
Meteor.methods({
sendMessage: function (chat) {
Chats.insert({
chat: chat,
createdAt: new Date(),
username: Meteor.user().profile.username,
avatar: Meteor.user().profile.avatar,
});
}
});
Chances are your subscriptions aren't ready. This means that Chats.findOne() will return nothing, meaning that Chats.findOne().messages will be undefined.
Try the following:
{{ #if Template.subscriptionsReady }}
{{#each messages}}
{{/each}}
{{/else}}
Alternatively, use a find() on chats, then {{#each}} on the messages within that chat. For example:
Template['Chat'].helpers({
chats: function () {
return Chats.find(Session.get('chatId')); // _id is unique, so this should only ever have one result.
}
});
Then in template:
{{#each chats}}
{{#each messages}}
{{>chat_message}}
{{/each}}
{{/each}}
I think there might be a logical error in this line
Chats.update({ _id : chat._id }, { $set : { messages : chat } });
You are setting the value of the field messages to chat. But chat is an object. So in your helper when you are returning Chats.findOne().messages to the {{#each}} block, you are actually returning an object which is not a valid value to be sent to an {{#each}} block and hence the error.
I think what you mean to do is
Chats.update({ _id : chat._id }, { $set : { messages : msgs } });
I am using select2 plugin(ivaynberg.github.io/select2). I am trying to display a dropdown(select). It is getting all the items in data.php as options. However select2 is meant to be autocomplete plugin and should search for the search term a client input, and display the matching results only. At the moment it is displaying all the items and not getting the search results. Sorry for my language
data.php is echoing out this:
[{
"id": "1",
"text": "item1",
"exercise": "blah text"
}, {
"id": "2",
"text": "item2"
}
]
The code is:
$(document).ready(function () {
$('#thisid').select2({
minimumInputLength: 2,
ajax: {
url: "data.php",
dataType: 'json',
data: function (term, page) {
return {
q: term
};
},
results: function (data, page) {
return {
results: data
};
}
}
});
});
and the input is:
<input type="hidden" id="thisid" style="width:300px" class="input-xlarge" />
I want to find a clue, I am quite new to this plugin and have spent a day for looking at examples.
select2 will not do AJAX if attached to a standard select form control. It MUST be attached to a hidden input control to load via AJAX.
Update: This has been fixed in Select2 4.0. From Pre-Release notes:
Consistency with standard <select> elements for all data adapters, removing the need for hidden <input> elements.
It can also be seen in function in their examples section.
I guess user2315153 wants to receive multiple remote values, and incorrectly assigning select2() with ajax call to a <select> element.
The correct way to get remote values, is using a normal <input> element, and if is desired multiple values, inform the "multiple" parameter on method call. Example:
<input type="hidden" id="thisid" style="width:300px" class="input-xlarge" />
<script>
$('#thisid').select2({
minimumInputLength: 2,
multiple: true,
ajax: {
...
The <select> element CAN NOT be used to remote values
UPDATE: As of select2 4.0.0, hidden inputs has deprecated:
https://select2.github.io/announcements-4.0.html#hidden-input
This means: Instead of using an input to attrib select2 plugin, use an SELECT tag.
Pay attention: it's easy to use any format of json from your server. Just use "processResults" to do it.
Example:
<select id='thisid' class='select2-input select2'></select>
<script>
$("#thisid").select2({
multiple: true,
closeOnSelect: true,
ajax: {
url: "myurl",
dataType: 'json',
delay: 250,
data: function (params) {
return {
q: params.term,
page: params.page
};
},
processResults: function (data, page) { //json parse
console.log("processing results");
//Transform your json here, maybe using $.map jquery method
return {
results: yourTransformedJson
};
},
cache: (maybe)true
}
});
</script>
I try the code, it works well. I think you not include jquery framework or check the path of js and css.
<!DOCTYPE html>
<html>
<head>
<link href="select2.css" rel="stylesheet"/>
<script src="//code.jquery.com/jquery-latest.min.js"></script>
<script src="select2.min.js"></script>
<script>
$(document).ready(function() {
$('#thisid').select2({
minimumInputLength: 2,
ajax: {
url: "data.php",
dataType: 'json',
data: function (term, page) {
return {
q: term
};
},
results: function (data, page) {
return {
results: data
};
}
}
});
});
</script>
</head>
<body>
<input type="hidden" id="thisid" style="width:300px" class="input-xlarge" />
</body>
</html>
I think no need to go with hidden input element. You can give a try, get plain html data from ajax call and set it in and then init select2 resetting method. Here's code snippet
HTML
<select id="select" name="select" class="select2">
<option value="" selected disabled>Please Select Above Field</option>
</select>
Javascript
$.ajax({
type: "POST",
cache:false,
url: YOUR_AJAX_URL,
success: function(response)
{
$('#select').html(response);
}
});
$('#select').select2("val","");
Ajax Response :
<option value="value">Option Name</option>
.
.
.
<option value="value">Option Name</option>
After much reading, I decided to change the select2.js itself.
At line 2109 change it to
this.focusser.attr("id", "s2id_"+this.select.context.id);
If your input tag is as so
<select id="fichier">
Hence your input tag that is searching through the list will have an id of s2id_fichier_search
As far as I know, there shouldn't be a conflict and THIS will allow you to have multiple select2 on the same page and run your functions (including .get, .post) through their events eg.
$(function() {
$('#s2id_fichier_search').keyup(function() {
console.log('Be Practical')
})
}
So this will run like if you were to use
<select id="fichier" onkeyup="console.log('Be Practical')">
In my case, an older version of select2 library was causing the issue, make sure that you include the latest version of js and css in the web page.
I've integrated reCAPTCHA and it is working fine, except for when the users are too quick to click the Submit button right after checking the "I'm not a robot" checkbox. It takes quite some time for reCAPTCHA to register the user action via Ajax, and if they click on Submit too quickly, the g-recaptcha-response is missing, and the validation fails.
Hence my question: how to I grey out the Submit button until g-recaptcha-response value is available?
<form id="capform" action="/captchaverify" method="POST">
<div class="g-recaptcha" data-sitekey="..."></div>
<p>
<input id="capsubmit" type="submit" value="Submit">
</form>
I ended up using the data-callback attribute as described in the documentation:
<form action="/captchaverify" method="POST">
<div class="g-recaptcha" data-sitekey="..." data-callback="capenable" data-expired-callback="capdisable"></div>
<p>
<input id="capsubmit" type="submit" value="Submit">
</form>
JavaScript (mootools-based, but the general idea should be clear):
function capenable() {
$('capsubmit').set('disabled', false);
}
function capdisable() {
$('capsubmit').set('disabled', true);
}
window.addEvent('domready', function(){
capdisable();
});
Here's an example that begins with the submit button disabled, and enables it once the callback is received from reCaptcha. It also uses jquery validate to ensure the form is valid before submitting.
var UserSubmitted = {
$form: null,
recaptcha: null,
init: function () {
this.$form = $("#form").submit(this.onSubmit);
},
onSubmit: function (e) {
if ($(this).valid()) {
var response = grecaptcha.getResponse();
if (!response) {
e.preventDefault();
alert("Please verify that you're a human!");
}
}
},
setupRecaptcha: function (key) {
UserSubmitted.recaptcha = grecaptcha.render('recaptcha', {
'sitekey': key,
'callback': UserSubmitted.verifyCallback
//'theme': 'light'//,
//'type': 'image'
});
},
verifyCallback: function (response) {
if (response) {
$(".visible-unverified").addClass("hidden");
$(".hidden-unverified").removeClass("hidden");
}
}
};
I call setupRecaptcha from the page with a named function that's part of the js include.
<script>
var recaptchaLoader = function () {
UserSubmitted.setupRecaptcha("yourkey");
};
</script>
<script src="https://www.google.com/recaptcha/api.js?onload=recaptchaLoader&render=explicit" async defer></script>
You could simplify this. I use it in a multi-tenant application with different keys, and UserSubmitted is actually part of a larger library. You can't usenamespaces (UserSubmitted.somefunction) as the onload param either (to my knowledge).
I'm currently learning React.js and am having trouble using a jquery or ajax call that returns the information in my form to a post. Basically what ever info is in the form, after submit, make a post of the data in a tag.
Here is my code:
var BasicInputBox = React.createClass({
render: function() {
return (
<div>
<label>{this.props.label}</label>
<br/>
<input type="text" onChange={this.props.valChange} value={ this.props.val} />
<br/>
</div>
);
}
});
var CommentBox = React.createClass({
render: function() {
return (
<div>
<label>Have a question?</label>
<br/>
<textarea type="text" onChange={this.props.valChange} value={ this.props.val} />
<br/>
</div>
);
}
});
var SubmitButton = React.createClass({
render: function() {
return (
<div>
<button type="submit" onClick={this.props.submit}>
Submit
</button>
</div>
);
}
});
var Contact = React.createClass({
getInitialState: function() {
return {}
},
submit: function(e) {
e.preventDefault()
console.log(this.state);
this.setState({
name: "",
email: "",
comment: ""
})
},
nameChange: function(e) {
this.setState({
name: e.target.value
})
},
emailChange: function(e) {
this.setState({
email: e.target.value
})
},
commentChange: function(e) {
this.setState({
comment: e.target.value
})
},
render: function() {
return (
<form>
<BasicInputBox label="Name:" valChange={this.nameChange} val={this.state.name}/>
<BasicInputBox label="Email:" valChange={this.emailChange} val={this.state.email}/>
<CommentBox valChange={this.commentChange} val={this.state.comment}/>
<SubmitButton submit={this.submit}/>
</form>
);
}
});
React.render(
<Contact></Contact>,
document.body
);
As #BinaryMuse noted the problem here is that your submit method is not really doing any submitting. You mentioned that the way you want to do this is via AJAX, and thus you need to 1) include jQuery (or Zepto) on your page, and 2) make the ajax call. Here is one way to accomplish the second part:
1)
First, you don't really need to provide the submit method as a property to the submit button. When the submit button is clicked inside a form, it will trigger the form's onSubmit event, so you can simply attach the this.submit method there.
Also, you don't really need I don't think to create a separate component for the Submit button. That kind of granularity may not be justified here since you can accomplish the same thing with far fewer lines of code. So I'd remove your SubmitButton component and update your Contact component render function to be:
render: function(){
return (
<form onSubmit={this.submit}>
<BasicInputBox label="Name:" valChange={this.nameChange} val={this.state.name}/>
<BasicInputBox label="Email:" valChange={this.emailChange} val={this.state.email}/>
<CommentBox valChange={this.commentChange} val={this.state.comment}/>
<button type="submit">Submit</button>
</form>
);
}
2) Next you can change your submit method in this way, adding an AJAX call. Depending on the details of the server/API to which you are sending the form you may need to modify the AJAX call a bit, but what I have put here is a fairly generic form that has a good chance of working:
submit: function (e){
var self
e.preventDefault()
self = this
console.log(this.state);
var data = {
name: this.state.name,
email: this.state.email,
comment: this.state.comment
}
// Submit form via jQuery/AJAX
$.ajax({
type: 'POST',
url: '/some/url',
data: data
})
.done(function(data) {
self.clearForm()
})
.fail(function(jqXhr) {
console.log('failed to register');
});
}
Note: that I also encapsulated the code you had previously for clearing the form inside its own function, which is called if the AJAX call returns a success.
I hope this helps. I put the code in a jsFiddle where you could test it a bit: https://jsfiddle.net/69z2wepo/9888/
I am trying to import a file with AJAX, using the following plugin -
http://malsup.github.com/jquery.form.js
Based on the following example -
http://malsup.com/jquery/form/progress.html
The my View looks like this -
<form action="/MyController/MyAction" enctype="multipart/form-data" id="myFormId" method="post">
<input type="file" name="file" id="file">
<input type="submit" value="Import File"> </div>
</form>
<script type="text/javascript">
window.onload = function () {
(function () {
$('#myFormId').ajaxForm({
beforeSend: function () {
alert('before send');
},
success: function () {
alert('success');
},
complete: function (xhr) {
alert('xhr.responseText=' + xhr.responseText);
}
});
})();
}
</script>
The javacsript in window.onload = function (){} is never called. MyAction is called, and then the browser just displays the JSON Action Result of MyAction.
Can anyone tell me what I am doing wrong or suggest a different way of doing this?
Thanks very much!
Since the script you wrote is placed after the form, you don't need to be putting it in a window.onload handler. The following should work fine:
#using (Html.BeginForm("MyAction", "MyController", FormMethod.Post, new { enctype = "multipart/form-data", id = "myFormId" }))
{
<input type="file" name="file" id="file">
<input type="submit" value="Import File"> </div>
}
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.js"></script>
<script src="http://malsup.github.com/jquery.form.js"></script>
<script type="text/javascript">
(function ($) {
$('#myFormId').ajaxForm({
beforeSend: function () {
alert('before send');
},
success: function () {
alert('success');
},
complete: function (xhr) {
alert('xhr.responseText=' + xhr.responseText);
}
});
})(jQuery);
</script>
Also notice that it is important to make sure that jquery.js is included before the jquery.form.js plugin which needs to be included before the script using it. In the example I have shown I also passed jQuery as parameter to the anonymous function which was being used in order to ensure that there are no conflicts with other plugins you might be using and which might have hijacked the $ function.
Also I would recommend you using a javascript debugging tool such as FireBug or Chrome developer toolbar to ensure that all your scripts are properly included (no 404s) and that you do not have any duplicate scripts or javascript errors.