Django ajax jQuery autocomplete only works on one page - javascript

I've added a working search field to a navigation bar that use jQuery autocomplete. The problem is it only works on the main page. On the other pages it tries to add the source url to the end of the page url.
For instance, on the home page it points to ajax_call/search, but on a company page (it's app that gathers internal data on companies) it points to company/847/ajax_call/search and obviously fails.
What do I need to do so the jQuery autocomplete functionality works across the entire site (without rewriting it in every template)?
Template
$(function() {
$("#tags").autocomplete({
minLength:2,
source: "ajax_call/search/",
select: function(event, ui){
window.location.href = ui.item.href;
}
});
});
URL
url(r'^ajax_call/search/$', views.ajax_company_search, name='search-field'),
View
def ajax_company_search(request):
if request.is_ajax():
query = request.GET.get('term', '')
company_names = Company.objects.filter(company_name__icontains=query).values('company_name', 'pk')
results = []
for name in company_names:
name_json = dict()
name_json['label'] = name['company_name']
name_json['value'] = name['company_name']
name_json['href'] = "company/" + str(name['pk']) + "/"
results.append(name_json)
data = json.dumps(results)
else:
data = 'fail'
mimetype = 'application/json'
return HttpResponse(data, mimetype)

You specified a relative URL in your JavaScript function. That's why it changes when you visit another page (with a different URL). In this case you want to use an absolute URL, like this: /ajax_call/search/.
Also, it is best practice to not hard-code your URLs in templates but to use reverse resolution:
$(function() {
$("#tags").autocomplete({
minLength:2,
source: {% url 'search-field' %},
select: function(event, ui){
window.location.href = ui.item.href;
}
});
});

Related

Cloudinary direct upload documentation example is not clear

In Cloudinary Django SDK documentation for direct from browser uploading it gives example below for direct_upload_complete view.
#csrf_exempt
def direct_upload_complete(request):
form = PhotoDirectForm(request.POST)
if form.is_valid():
form.save()
ret = dict(photo_id = form.instance.id)
else:
ret = dict(errors = form.errors)
return HttpResponse(json.dumps(ret), content_type='application/json')
Immediately after this example it says Having stored the image ID, you can now display a directly uploaded image in the same way you would display any other Cloudinary hosted image: and gives template code example as follows:
{% load cloudinary %}
{% cloudinary photo.image format="jpg" width=120 height=80 crop="fill" %}
I am confused by this template code example because it does not relate at all to the Django view code which has response name ret. Screenshot of documentation is below.
What would I need to do to use Javascript to create a variable from the JSON object named ret and display it on the template page?
Below is Javascript I am using on the example's upload_prompt.html template. It works fine, returning a thumb of uploaded image and some Cloudinary data that show after image is uploaded (on cloudinarydone event).
But I also want to get the uploaded photo's Model id to create a link to the photo using the id.
Where in below Javascript can I get the photo_id key value from the JSON object named ret?
<script>
$(function () {
$('#direct_upload input[type="file"]')
.cloudinary_fileupload({
dropZone: '#direct_upload',
start: function (e) {
$('.status').text('Starting upload...');
},
progress: function (e, data) {
// $('.status').text('Uploading...');
$(".status").text("Uploading... " + Math.round((data.loaded * 100.0) / data.total) + "%");
},
fail: function (e, data) {
$(".status").text("Upload failed");
}
})
.on('cloudinarydone', function (e, data) {
$('.status').text('Updating backend...');
$.post(this.form.action, $(this.form).serialize()).always(function (result, status, jqxhr) {
$('.status').text(result.errors ? JSON.stringify(result.errors) : status);
});
var info = $('<div class="uploaded_info"/>');
$(info).append($('<div class="image"/>').append(
$.cloudinary.image(data.result.public_id, {
format: data.result.format,
width: 150,
height: 150,
crop: "fill"
})
);
$(info).append($('<div/>').append('image/upload/' + data.result.path));
$('.uploaded_info_holder').append(info);
});
});
</script>
Thanks to Brian Luk at Cloudinary Support, getting photo_id value is done in template's javascript POST request callback.
Maybe there are betters ways to do this, but I simply created variable photoid and then used that variable to create Photo model url.
$.post(this.form.action, $(this.form)
.serialize()).always(function (result, status, jqxhr) {
$('.status').text(result.errors ? JSON.stringify(result.errors) : status);
var photoid = JSON.stringify(result.photo_id);
$(info).append($('<div/>').append('link'));

Load Bootstrap nav nav-tabs via GET URL

I have set up Bootstraps nav-tabs via an index page. Each tab loads a seperate PHP file via AJAX:
<div class="container">
<ul class="nav nav-tabs" id="indextabs">
<li>NOTES</li>
<li>WHOIS</li>
<li>DIG</li>
<li>ETS</li>
<li>RESOURCES</li>
</ul>
</div>
JavaScript that takes care of the AJAX queries:
window.onload = function() {
$('[data-toggle="tabchange"]').click(function(e) {
var $this = $(this),
loadurl = $this.attr('href'),
targ = $this.attr('data-target');
$.get(loadurl, function(data) {
$(targ).html(data);
});
$this.tab('show');
return false;
});
}
This itself works fine. In some of the tabs, however, there is an input that requires a domain name which then needs to be submitted via a GET request so that the URL can be something like:
http://domain.com/?domain=google.com&record=mx
With this in mind, I have two problems:
How do I load a particular tab using a GET method URL?
How do I submit form data via AJAX using the GET method and have it change the URL AND load the content in the tab-panel divs?
Please consider the following more like a comment because I'm uncertain what's optimal (and also works) in your case. Anyway I think you need to pass query parameters in your $get method call, either in form of a object, key value pairs { domain: 'google.com', record: 'mx'} or as string. Below an object/key value pairs are used.
window.onload = function() {
$('[data-toggle="tabchange"]').click(function(e) {
var $this = $(this),
loadurl = $this.attr('href'),
targ = $this.attr('data-target');
//optional method call below, uncomment if needed
//loadurl = getDomainURL() + "/" + loadurl
$.get(loadurl, {
domain: 'google.com',
record: 'mx'
},
function(data) {
$(targ).html(data);
});
$this.tab('show');
return false;
});
}
//returns domain name: www.example.com in form of http://example.com
// or domain name: http://example.com is returned as it is, unchanged http://example.com
function getDomainURL() {
var index = window.location.hostname.indexOf("www.");
if (index === 0)
return "http://" + window.location.hostname.substr((index + 4));
else
return "http://" + window.location.hostname;
}

Why doesn't IE like Vietnamese characters when using ajax?

The following markup shows my form:
<div id="category-form">
</div>
The following code is my script:
<script type="text/javascript">
function clicked(o) {
var id = o.getAttribute("data-categoryId");
var name = o.getAttribute("data-categoryName");
var description = o.getAttribute("data-description");
loadFormView("/Admin/_EditCategories?categoryId="+ id + "&categoryName="+name+"&description="+description);
}
function loadFormView(url) {
$.ajax({
url: url,
type: 'GET',
cache: false,
success: function (data) {
$("#category-form").html(data);
alert(data);
}
});
}
</script>
I have also created a controller that passes data to the view:
public PartialViewResult _EditCategories(int categoryId, string categoryName, string description)
{
Category category = new Category();
category.CategoryId = categoryId;
category.CategoryName = categoryName;
category.Description = description;
ViewBag.Action = "Cập nhật";
ViewBag.Task = "Sửa thể loại truyện";
ViewBag.IsEdit = true;
return PartialView("_TaskCategories", category);
}
When the view renders the ViewBag content and it's rendered on IE, the text is garbled whereas on Chrome and Firefox, the text appears correctly, in Vietnamese.
"Truyện cười" is categoryName's value
in textbox on ie: "Truy?n c??i" and.... on ff or chrome: "Truyện
cười"
How can I fix the text rendering in IE? Thank you in advance!
Does your page include a meta tag to indicate encoding? IE might be having a difficult time figuring out which encoding to use. Make sure both of your files are encoded in utf8, and add the meta tag:
<meta charset="utf-8">
I think there's more going on here. I think your normal queries are sending your locale as an HTTP header that the AJAX for some reason isn't sending.
Since jQuery's ajax support allows you to specify your own custom headers, why don't you try setting the locale header explicitly yourself, that ought to rule out some simple HTTP issues.
Add Header in AJAX Request with jQuery

MVC3 Action Call from Javascript ReturnUrl parameter always null

I am using javascript to load up an Action and finding that when the action method is called one of the parameters "returnUrl" is always null. I have confirmed that returnUrl is populated in the javascript correctly using firebug, but somewhere between executing the .load function and the action method the value for returnUrl is lost and set to null. I have found that if I remove the "id" parameter and just have the "returnUrl" parameter that returnUrl has the correct value. I have spent many hours trying to figure out what is going on here and am completely stumped, I would apprectiate some help.
My Javascript:
<!-- Review Dialog Popup -->
<script type="text/javascript">
function showWriteReviewDialog(gameId, returnUrl) {
if( $("#Review").length == 0)
{
var url = "#Url.Action("WriteUserReview", "UGDBUser", new { id = "PLACEHOLDER", returnUrl = Request.Url.ToString() })";
// ajax load
$('#writereview').load(url.replace('PLACEHOLDER', gameId));
} else {
// clear summary & reviewtext fields
$('#summary,#reviewtext').val('');
//reopen the write review dialog which was previously rendered
$("#Review").dialog({
modal: true,
autoOpen: true,
resizeable: false
});
}
};
</script>
My Dumbed Down Action Method:
[Authorize]
public ActionResult WriteUserReview(Guid id, string returnUrl)
{
return Redirect(returnUrl);
}
There must be something wrong with the URL generated. Also make sure the id is a guid. Here is an example.
Option 1
function showWriteReviewDialog(gameId, returnUrl) {
var url = '#Url.Action("TestParams", "Home")?id=' + gameId + '&returnUrl=' + returnUrl;
$("#writereview").load(url);
//rest of your operations
};
Option 2
function showWriteReviewDialog(gameId, returnUrl) {
var url = '#Url.Action("TestParams", "Home", new { id = "guid_replace", returnUrl = "url_replace"})';
url = url.replace('guid_replace', gameId);
url = url.replace('url_replace', returnUrl);
$("#writereview").load(url);
//rest of your operations
};
Screen shot on hitting the action; it returns both the values (have a look at the watch window)

How to check if page exists using JavaScript

I have a link: Hello.
When someone clicks the link I'd like to check via JavaScript if the page the href-attribute points to exists or not. If the page exists the browser redirects to that page ("www.example.com" in this example) but if the page doesn't exist the browser should redirect to another URL.
It depends on whether the page exists on the same domain or not. If you're trying to determine if a page on an external domain exists, it won't work – browser security prevents cross-domain calls (the same-origin policy).
If it is on the same domain however, you can use jQuery like Buh Buh suggested. Although I'd recommend doing a HEAD-request instead of the GET-request the default $.ajax() method does – the $.ajax() method will download the entire page. Doing a HEAD request will only return the headers and indicate whether the page exists (response codes 200 - 299) or not (response codes 400 - 499). Example:
$.ajax({
type: 'HEAD',
url: 'http://yoursite.com/page.html',
success: function() {
// page exists
},
error: function() {
// page does not exist
}
});
See also: http://api.jquery.com/jQuery.ajax/
A pretty good work around is to proxy. If you don't have access to a server side you can use YQL. Visit: http://developer.yahoo.com/yql/console/
From there you can do something like: select * from htmlstring where url="http://google.com". You can use the "REST query" they have on that page as a starting point for your code.
Here's some code that would accept a full URL and use YQL to detect if that page exists:
function isURLReal(fullyQualifiedURL) {
var URL = encodeURIComponent(fullyQualifiedURL),
dfd = $.Deferred(),
checkURLPromise = $.getJSON('http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20htmlstring%20where%20url%3D%22' + URL + '%22&format=json');
checkURLPromise
.done(function(response) {
// results should be null if the page 404s or the domain doesn't work
if (response.query.results) {
dfd.resolve(true);
} else {
dfd.reject(false);
}
})
.fail(function() {
dfd.reject('failed');
});
return dfd.promise();
}
// usage
isURLReal('http://google.com')
.done(function(result) {
// yes, or request succeded
})
.fail(function(result) {
// no, or request failed
});
Update August 2nd, 2017
It looks like Yahoo deprecated "select * from html", although "select * from htmlstring" does work.
Based on the documentation for XMLHttpRequest:
function returnStatus(req, status) {
//console.log(req);
if(status == 200) {
console.log("The url is available");
// send an event
}
else {
console.log("The url returned status code " + status);
// send a different event
}
}
function fetchStatus(address) {
var client = new XMLHttpRequest();
client.onreadystatechange = function() {
// in case of network errors this might not give reliable results
if(this.readyState == 4)
returnStatus(this, this.status);
}
client.open("HEAD", address);
client.send();
}
fetchStatus("/");
This will however only work for URLs within the same domain as the current URL. Do you want to be able to ping external services? If so, you could create a simple script on the server which does your job for you, and use javascript to call it.
If it is in the same domain, you can make a head request with the xmlhttprequest object [ajax] and check the status code.
If it is in another domain, make an xmlhttprequest to the server and have it make the call to see if it is up.
why not just create a custom 404 handler on the web server? this is probably the more "good-bear" way to do this.
$.ajax({
url: "http://something/whatever.docx",
method: "HEAD",
statusCode: {
404: function () {
alert('not found');
},
200: function() {
alert("foundfile exists");
}
}
});
If you are happy to use jQuery you could do something like this.
When the page loads make an ajax call for each link. Then just replace the href of all the links which fail.
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script type="text/javascript">
<!--
$.fn.checkPageExists = function(defaultUrl){
$.each(this, function(){
var $link = $(this);
$.ajax({
url: $link.attr("href"),
error: function(){
$link.attr("href", defaultUrl);
}
});
});
};
$(document).ready(function(){
$("a").checkPageExists("default.html");
});
//-->
</script>
You won't be able to use an ajax call to ping the website because of same-origin policy.
The best way to do it is to use an image and if you know the website you are calling has a favicon or some sort of icon to grab, you can just use an html image tag and use the onerror event.
Example:
function pingImgOnWebsite(url) {
var img = document.createElement('img');
img.style.visibility = 'hidden';
img.style.position = 'fixed';
img.src = url;
img.onerror = continueBtn; // What to do on error function
document.body.appendChild(img);
}
Another way to do this is is with PHP.
You could add
<?php
if (file_exists('/index.php'))
{
$url = '/index.php';
} else {
$url = '/notindex.php';
}
?>
And then
<a href="<?php echo $url; ?>Link</a>

Categories