How to render HTML with jQuery from an AJAX call - javascript

I have a select box with a list of books. The user can select a book and hit the submit button to view the chapters on a separate page.
However, when the user changes the select box, I would like a partial page refresh to display the past notes the user entered on the book, and allow the user to write a new note for that book. I do not want the review and creation of notes for a particular book done on the next page with the chapters, as it will clutter it up.
I'm using Python/Bottle on the backend and its SimpleTemplate engine for the front end.
Currently, when the select box is changed, an ajax call receives a Json string containing the book information and all the notes. This json string is then converted into a json object via jQuery.parseJson().
What I would like to be able to do is then loop over the notes and render a table with several cells and rows.
Would I have to do this in jQuery/js (instead of bottle/template framework) ? I assume so as I only want a partial refresh, not a full one.
I'm looking for a piece of code which can render a table with variable numbers of rows via jQuery/js from a json object that was retrieved with ajax.
<head>
<title>Book Notes Application - Subjects</title>
<script src="http://code.jquery.com/jquery-latest.min.js"
type="text/javascript"></script>
<script>
$(document).ready(function(){
$('#subject_id').change(function(){
var subject_id = $(this).val();
$.ajax({
url : "subject_ajax?subject_id=" + subject_id,
success : function(data) {
alert(data)
json = jQuery.parseJSON(data);
},
error : function() {
alert("Error");
}
});
})
})
</script>
</head>
<body>
<!-- CHOOSE SUBJECT -->
<FORM action="/books" id="choose_subject" name="choose_subject" method="POST">
Choose a Subject:
<select name="subject_id" id="subject_id">
% for subject in subjects:
<option value="{{subject.id}}">{{subject.name}}</option>
% end
</select><input type="submit" name="sub" value="Choose Subject"/>
<BR />
</FORM>

This greatly depends on how your JSON and HTML are formatted. But with a table somewhere like:
<table id="books">
<tr>
<th>Chapter</th>
<th>Summary</th>
</tr>
</table>
You could do something like:
$(function(){
$('#choose_subject').submit(function () {
var subject_id = $(this).val();
$.getJSON("subject_ajax?subject_id=" + subject_id, function(data) {
console.log(data);
$.each(data.chapters, function (index, chapter) {
$('#books').append('<tr><td>' + chapter.title + '</td><td>' + chapter.summary + '</td></tr>');
})
});
return false;
})
})
This supposes JSON like:
{
"notes": [
"Note 1",
"Note 2"
],
"chapters": [
{
"title": "First chapter",
"summary": "Some content"
},
{
"title": "Second chapter",
"summary": "More content"
}
]
}
Other notes:
If you use HTML 4 or earlier, keep all your tags in upper case. If you're using XHTML or HTML5, keep all your tags in lower case.
You don't need $(document).ready(function () {...}), with recent versions of jQuery $(function () {...} ) works the same and it's easier to read.
You can use $.get instead of $.json if you're only using the success state (as you are here). And if you're confident that the data you'll get is valid JSON, you can use getJSON instead of get. It will parse the JSON for you deliver it to you as a JavaScript object automatically.
It's usually more convenient to use console.log rather than alert when you're testing. Actually, it's usually a bad idea in general to ever use alert.

I'm not familiar with Python/Bottle or its SimpleTemplate engine, but you could consider generating the html for the table on the server side and returning it in the ajax response, rather than returning JSON.
var subject_id = $(this).val();
$.ajax('subject_ajax', {
type: 'get',
data: { subject_id: subject_id },
dataType: 'html',
success : function(html) {
// Insert the html into the page here using ".html(html)"
// or a similar method.
},
error: function() {
alert("Error");
}
});
When calling .ajax():
The "type" setting defaults to "get", but I prefer to explicitly set it.
Use the "data" setting for the ajax call to specify the URL parameter.
Always specify the "dataType" setting.
I also recommend you perform the ajax call in an on-submit handler for the form, and add an on-change handler for the select that submits the form.
$(document).ready(function(){
$('#subject_id').change(function() {
$(this.form).submit();
});
$('#choose_subject').submit(function(event) {
event.preventDefault();
var subject_id = $('#subject_id').val();
if (subject_id) {
$.ajax(...);
}
});
});
This way your submit button should work in case it is clicked.

There are a few things you need to look at:
1) Is your SimpleTemplate library included?
2) Have you compiled your template via compileTemplate()?
Once you know your library is included (check console for errors), pass your data returned to your success handler method, compile your template, that update whichever element you are trying to update.
I'm not sure that you want to update the same element that you're defining your template in.
$(document).ready(function(){
$('#subject_id').change(function(){
var subject_id = $(this).val();
$.ajax({
url : "subject_ajax?subject_id=" + subject_id,
success : function(data) {
var template_data = JSON.parse(data);
var template = $('#subject_id').toString(); // reference to your template
var precompiledTemplate = compileTemplate(template);
var result = precompiledTemplate(template_data);
$('#subject_id').append(result);
},
error : function() {
alert("Error");
}
});
})
})
You might also try moving your template out of the element you're trying to update like this:
<script type="text/template" id="subject-select-template">
% for subject in subjects:
<option value="{{subject.id}}">{{subject.name}}</option>
% end
</script>
Then just create a blank select element like so:
<select id="select_id"></select>
Update references. Anyway, hope this is helpful. It should work but I can't test without your specific code ;)
Also, check out this demo example if you haven't yet:
https://rawgithub.com/snoguchi/simple-template.js/master/test/test.html

Related

jquery ajax request wrapped in jQuery()'s .text() isn't the same as the div's .text()?

I know this is a very concrete issue but I've struggled with this code for the last 2 hours and I can't find anything on the topic or figure out how to solve it.
I have an issue with a jQuery Ajax Post request. I am trying to make a section on my page where I display the users current level. When a user interacts and does something that increases the level on the site the level should also increase in the DOM/client's browser. Therefore I've added a setinterval that allows the request to run every 5th second. And if the $(response).text() is different from the current div's .text() where i am rendering the current level I want to append this new response from the ajax request.
Maybe the answer is more obvious than I think.... I have added the code below
Ajax page:
$(document).ready(function () {
function getLevel() {
var getLvlData = $.ajax({
url: "AjaxRequests.php",
type: "POST",
data: {type: "4", lvl_r_type: 1}
});
getLvlData.done(function (response, textStatus, jqXHR) {
var innerLevelHTML = $("#LevelContainer");
if (($(response).text()) != ($(innerLevelHTML).text())) {
innerLevelHTML.html("");
innerLevelHTML.append(response);
}
if ($(response).text() == $(innerLevelHTML).text()) {
alert("the same");
}
});
}
var levelChecker = setInterval(function () {
getLevel();
}, 1000);
getLevel();
});
AjaxRequests.php:
if ($_POST["type"] == "4" && isset($_POST["lvl_r_type"])) {
$returnVal = htmlentities($_POST["lvl_r_type"]);
if (!empty($returnVal)) {
if ($returnVal == 1) {
?>
<div id="chartWrapper">
<div>
<canvas id="doughnut-chart"></canvas>
</div>
<div id="chart-center">
<div>
<div><h1>0%</h1></div>
<div><p>GX 0 / 1</p></div>
</div>
<div><p>LVL 0</p></div>
</div>
</div>
<div id="progressList">
<div><p>View tasks</p></div>
</div>
<?php
}
}
}
?>
html page
<div id="LevelContainer"></div>
Try using trim since a white space could be treated as a part of the text.
if (($(response).text().trim()) != ($(innerLevelHTML).text().trim())) {
...
One alternative approach I can think of, off of my head is, to set a hash inside a data attribute say data-hash="" whenever you set the html of that div, and then whenever you have a new ajax response you can generate a hash on the fly and compare that to the existing one and if a change is found just update the html and the hash value for that attribute.
This process minimises the confusion that may be caused due to dom being updated by some script.
Also, Instead of
innerLevelHTML.html("");
innerLevelHTML.append(response);
Why not just just set the html directly as
innerLevelHTML.html(response);

Ajax call goes only one time ASP.Net MVC5

I am writing an AJAX function in ASP.Net MVC5 and I am getting a problem that the form AJAX request goes only one time. It is a search page. After I choose the filter I press search I get the correct result. However if I changed the filter and click the search submit again, nothing will happen.
var ajaxFormSubmit = function() {
var $form = $(this);
var options = {
url: $form.attr("action"),
type: $form.attr("method"),
data: $form.serialize()
};
$.ajax(options).done(function (data) {
var target = $($form.attr("data-enbw-target"));
target.replaceWith(data);
debugger;
});
return false;
};
$("form[data-enbw-ajax='true']").submit(ajaxFormSubmit);
<form method="get" id="documentForm" action="#Url.Action("Index", "DocumentSearch")" def data-enbw-ajax="true" data-enbw-target="#documentSearchResult">
<button type="submit" id="submitbtn" name="submitbtn" tabindex="100" class="k-button">
<img src="~/Content/search_small_icon.png" />
#WebResources.DocumentSearchButton
</button>
</form>
#Html.Partial("Results", #Model)
public ActionResult Index(DocumentSearchInput model)
{
if (Request.IsAjaxRequest())
{
return PartialView("Results", result);
}
return View(result);
}
I do not get any error. and when I get a debugger; in javascript. the new data is correct. can you please help me.
You are replacing the form in your ajax success. As such, the new form will not have the submit binding on it. If you truely want to do this you will have to rebind to the new form, or possibly use a delegate instead.
$('parentSelector').on('event', 'childSelector', function(){});
parentSelector - A parent element of the child that pre-exists the child element and should typically not be removed/created during the page lifespan.
childSelector - A selector for the element that will be created/changed/removed at some point in the lifespan of the page.
I found the answer.
the problem wasn't with the submit. the problem was with re-writing the data.
$.ajax(options).done(function (data) {
$("#documentSearchResult").empty();
$("#documentSearchResult").html(data);
});
simply, I empty the div then write inside.

Get selected json value by key using jQuery and jsonp (vimeo api)

Let's say I have the following json result from an api:
{
id: 116213129,
title: "“An Episode,” by Palaxy Tracks",
description: "Music: Palaxy Tracks<br /> Animation: Luca Tóth and Stephen McNally",
url: "http://vimeo.com/116213129",
thumbnail_small: "http://i.vimeocdn.com/video/502490003_100x75.jpg",
thumbnail_medium: "http://i.vimeocdn.com/video/502490003_200x150.jpg",
thumbnail_large: "http://i.vimeocdn.com/video/502490003_640.jpg",
user_id: 14252792,
width: 1920,
height: 1080,
tags: "palaxy tracks, music, an episode, animation, music video"
}
Now let's say I have some jQuery code and I want to only retrieve title and url, but nothing else and do something with them like push them into the value of a textbox on my page or a hidden input. I have seen the $.each method that loops through them, but I don't wt to do that. I just want a few values and I want to get them by their key.
Here is the sample jQuery code that loops through them, I got from jQuery API docs. How can I modify to just get those specific values?
<script>
$.getJSON("http://vimeo.com/api/v2/video/116213129.json?jsoncallback=?", function (result) {
var title = result.title;
var description = result.description;
$("#popVals").click(function () {
$('#Video_Title').val(title);
$('#Video_Description').val(description);
});
});
</script>
From the JQuery.getJSON docs:
The success callback is passed the returned data, which is typically a
JavaScript object or array as defined by the JSON structure and parsed
using the $.parseJSON() method. It is also passed the text status of
the response.
In your case its a Javascript object which will be accessible via property access
<script>
$.getJSON("http://vimeo.com/api/v2/video/116213129.json?jsoncallback=?", function (result) {
var title = result.title;
var url = result.url;
//do something
});
</script>

How to call ajax and output its result inside div and textarea?

I am trying to make load more button. My goal is to call ajax and put the response inside div and textarea.how to place the response inside div and textarea? Currently the response only shows in messagebox but i want to append the result into div.
*Note:*Response is html hyperlinks produced by process.php and i want those hyperlinks placed inside the div
<html>
<head>
<script>
//initialize page number to 1 default
var pagenumber=1;
//pass pagenumber to function to fetch correct page records
function getResult(pagenumber){
alert('me here'+pagenumber);
$.ajax(
{
type: 'GET',
url: './process.php?ID=1234&type=1&moviePath=1234/1212/Love&title=Love&page='+pagenumber,
data: $("#myform").serialize(),
data: {
},
success: function (good)
{
//handle success
alert(good)
},
failure: function (bad)
{
//handle any errors
alert(bad)
}
});
//after every call increment page number value
pagenumber++;
}// end of getResult Function
function addMoreItems()
{
pagenumber++;
getResult(pagenumber);
}
</script>
</head>
<body>
<div id="myDiv"></div>
<div class="MoreButtonSection">
<div class="RedButton">
<span class="LeftEnd"></span>
<span class="Centre">see more</span>
<span class="RightEnd"></span>
</div>
</div>
<br>
<br>
<form id="myform" name="myform" action="./2.php?Id=&title=" method="post">
<td>
<textarea rows="7" cols="15" name="outputtext" style="width: 99%;"></textarea>
</td>
</form>
</html>
You say your result is only showing in the message box, instead of alerting it, simply append. Assuming the below div is what you want to append to:
<div id="myDiv"></div>
You can modify your success function:
success: function (good)
{
//handle success
$("#myDiv").append(good);
},
Also, get rid of that second data: {}, -- it's doing nothing.
There are a number of issues.
There is no indication that you've included jQuery.
You've declared data: twice.
As Dmitry pointed out, you should probably be posting this.
And finally, where are you actually calling getResult()? It doesn't look like it's being called.
In addition, it is worth noting that from jQuery 1.8 and higher, .success() and .failure() are now deprecated and have been replaced with .done() and .fail().
http://api.jquery.com/jQuery.ajax/
I tend to use jQuery in these situations to make life a little easier, and work with the $('#yourDiv').append() function. For instance you can create variables i.e. var mug; and once it is filled with your data append mug to the document through $('#yourDiv').append("<p>"+mug+"</p>);
An example - Ajax Twitter API call that returns tweets to specific lists within a div (page source)
Hope that helps!
I think I get what you are trying to do but that code is a mess. As #David L has stated, you need jQuery. But then you do not need all the code you have written. It can be done in a few simple lines. Please replace the actual element selectors with your correct ones.
function addMoreItems() {
pagenumber++;
// get form values
var params = $('#myform').serializeArray();
// add predefined values
params.push({name: 'ID', value: '1234'});
params.push({name: 'type', value: '1'});
params.push({name: 'moviePath', value: '1234/1212/Love'});
params.push({name: 'title', value: 'Love'});
params.push({name: 'page', value: pagenumber});
// do request and insert response from server in div with id='divresults'
$.get('process.php', params, function(data) {
$('#divResults').append(data);
});
}

Ckeditor Dialog for building a Url from a user selected options from a JSON Dataset

I'm trying to use CKeditor as part of a CMS but I'm not "that" good with JavaScript and there documentation does not help much.
rather confusing could some one show me how I would change the link plugin dialog so that it shows a drop down of values and builds a URL from them, but I don't under stand how there dialog system works I have narrowed it down, i know that I will need to use the _sources/plugins/link/dialogs/link.js but as to how I am to a lost when working with this I just can't understand it.
Can some one show me the code i would need to add a Dropdown (select) to the dialog that has the options that then writes the value into the url Field E.G
My Server System has the URL /content/getLinks/ and this will return the CMS Pages like so,
[
{"page_name":"Contact Us","url":"Contact_Us","page_id":"1"},
{"page_name":"Welcome to Doxie Promotions","url":"Welcome_to_Doxie_Promotions","page_id":"2"},
{"page_name":"Bands","url":"Bands","page_id":"3"},
{"page_name":"Upcoming Events","url":"Upcoming_Events","page_id":"4"},
{"page_name":"About","url":"About","page_id":"7"},
{"page_name":"Lost Efftect","url":"Lost_Efftect","page_id":"10"}
]
Now from this data i want to build a select box like this
<select>
<option value="Contact_Us:1">Contact Us</option>
<option value="Welcome_to_Doxie_Promotions:1">Welcome to Doxie Promotions</option>
<option value="Bands:1">Bands</option>
<option value="Upcoming_Events:1">Upcoming Events</option>
<option value="About:1">About</option>
<option value="Lost_Efftect:1">Lost Efftect</option>
</select>
Then when one is selected I want the URL field to be changed E.G if the first was option selected the url would be
/content/load/pid/1/url/Contact_Us
I'm aware that i will need to copy the sources version of the plugin dialog over the standard one that has been min'ed
Update what I have tried so far
using _sources/plugins/link/dialogs/link.js and overwriting the plugins/link/dialogs/link.js
I have built this code
into the file at line 429
,
{
type : 'select',
id : 'cms_links',
label : 'CMS Page',
items:[],
onLoad : function(){
(function($){
$.ajax({
url: "/content/getLinks/",
dataType: 'json',
data: "",
success: function(data){
$.each(data, function(key, val){
$("#cms_links").append(
"<option value='"+val.url+":"+val.page_id+"'>"+val.page_name+"</option>"
);
});
}
});
})(jQuery);
}
},
but there is not even a select box drawn for the code that i have added so i'm still at a loss
You can try to use this plugin: http://cksource.com/forums/viewtopic.php?f=18&t=24282
To do this you have to have the de-minimized version of the code this is in the _sources at path _sources/plugins/link/dialogs/link.js copy this over top of the minimized code at plugins/link/dialogs/link.js i added the code below around line 429
,
{
type : 'select',
id : 'cms_links',
label : 'CMS Page',
class : 'cms_links',
items:[],
onLoad : function(){
(function($){
var cms_pageSelectElement;
var protocolSelectElement;
var urlSelectElement;
$.ajax({
url: "/content/getLinks/",
dataType: 'json',
success: function(data){
$("label").each(function(){
var value = $(this).html();
if(value == "CMS Page"){
cms_pageSelectElement = $(".cke_dialog_ui_input_select", $(this).parent());
console.log(cms_pageSelectElement);
}
if(value == "Protocol"){
protocolSelectElement = $(".cke_dialog_ui_input_select", $(this).parent());
console.log(protocolSelectElement);
}
if(value == "URL"){
urlSelectElement = $(".cke_dialog_ui_input_text", $(this).parent());
console.log(urlSelectElement);
}
});
$(cms_pageSelectElement).append("<option selected='selected'><none CMS link></option>");
for(var key in data){
var val = data[key];
$(cms_pageSelectElement).append(
"<option value='"+val.url+":"+val.page_id+"'>"+val.page_name+"</option>"
);
}
$(cms_pageSelectElement).change(function(){
var val = $(this).val();
var parts = val.split(":");
var url = "content/load/pid/"+parts[1]+"/url/"+parts[0];
$(urlSelectElement).val(url);
});
}
});
})(jQuery);
}
},
you have to exploit the system slightly to update the other elements when using jQuery as there are no values you can set that are then set on to the HTML elements so you have to hack around by selecting the label then getting the input from the parent of the label
I can give you this to start of: http://jsfiddle.net/VGWPL/

Categories

Resources