Replacing a div that is called by jQuery onclick - javascript

I have a list object and each contains an upvote div that is called onclick by my jQuery (I essentially flip the vote button in each div and asynchronously change the vote for that div via Ajax).
All object divs are contained within row.replace which I use to sort the objects asynchronously. The thing is that once I click on the sorter and sort the content of the .row.replace div, the upvote divs in the sorted list of objects stop getting called onclick ie. I can upvote and remove my upvote before sorting with jQuery+ajax, once the sort is applied and the contents of the div are replaced, my upvote button stops working.
Here is the jQuery:
$(document).ready(function () {
$('.sorter').click(function () {
$('.row.replace').empty();
$('.row.replace').append("<br><br><br><br><p align='center'><img id='theImg' src='/media/loading1.gif'/></p><br><br><br><br><br><br><br><br>");
var sort = $(this).attr("name");
$.ajax({
type: "POST",
url: "/filter_home/" + "Lunch" + "/" + "TrendingNow" + "/",
data: {
'name': 'me',
'csrfmiddlewaretoken': '{{csrf_token}}'
},
dataType: "json",
success: function (json) {
//loop through json object
//alert("yoo");
$('.row.replace').empty();
for (var i = 0; i < json.length; i++) {
$('.row.replace').append("<div class='showroom-item span3'> <div class='thumbnail'> <img class='food_pic' src='/media/" + json[i].fields.image + "' alt='Portfolio Image'> <div class='span3c'> <a><b>" + json[i].fields.name + "</b> </a> </div> <div class='span3d'> posted by <a><b>" + json[i].fields.creator.username + "</b></a> </div> <div class='span3c'> <div class='btn-group'> <div class='flip flip" + json[i].pk + "'> <div class='card'> {% if 0 %} <div class='face front'> <button type='button' class='btn btn-grove-one upvote' id='upvote' name='" + json[i].pk + "'>Upvoted <i class='glyphicons thumbs_up'><i></i></i><i class='vote-count" + json[i].pk + "'>" + json[i].fields.other_votes + "</i></a></button> </div> <div class='face back'> <button type='button' class='btn btn-grove-two upvote' id='upvote' name='" + json[i].pk + "'>Upvote <i class='glyphicons thumbs_up'><i></i></i><i class='vote-count" + json[i].pk + "'>" + json[i].fields.other_votes + " </i></a></button> </div> {% else %} <div class='face front'> <button type='button' class='btn btn-grove-two upvote' id='upvote' name='" + json[i].pk + "'>Upvote <i class='glyphicons thumbs_up'><i></i></i><i class='vote-count" + json[i].pk + "'>" + json[i].fields.other_votes + " </i></a></button> </div> <div class='face back'> <button type='button' class='btn btn-grove-one upvote' id='upvote' name='" + json[i].pk + "'>Upvoted <i class='glyphicons thumbs_up'><i></i></i><i class='vote-count" + json[i].pk + "'>" + json[i].fields.other_votes + "</i></a></button> </div> {% endif %} </div> </div> </div> <div class='btn-group'> <button type='button' class='btn btn-grove-two'><i class='glyphicons comments'><i></i></i>" + json[i].fields.comment_count + "</a></button> </div> </div> </div> </div>");
}
//json[i].fields.name
},
error: function (xhr, errmsg, err) {
alert("oops, something went wrong! Please try again.");
}
});
return false;
});
$('.upvote').click(function () {
var x = $(this).attr("name");
$.ajax({
type: "POST",
url: "/upvote/" + x + "/",
data: {
'name': 'me',
'csrfmiddlewaretoken': '{{csrf_token}}'
},
dataType: "json",
success: function (json) {
var y = "vote-count" + x;;
$('i[class= "' + y + '"]').text(json.vote_count);
//flip button
$('.flip' + x).find('.card').toggleClass('flipped');
},
error: function (xhr, errmsg, err) {
alert("oops, something went wrong! Please try again.");
}
});
return false;
});
});

The click event handler only binds to elements that exist in the DOM when the function is actually called. You need to use a delegated on() event listener to bind to future elements as well. So for your code:
$('.upvote').click(function(){
change to:
$("body").on("click", '.upvote', function(event){
Should catch future click events. I'm using "body" as the outer selector because I don't know what your HTML looks like, but it's best to "outer-bind" to the nearest ancestor to the '.upvoteelements (so if they are all contained in aul` with id "vote-list" bind to that instead of "body").

Related

Downloading Zip file as attachment not working in C# MVC using SharpZipLib

I am trying to program a function which allows to download zip file as attachment in the browser using C# MVC.
In my Service Layer I have defined the code to generate the byte array of the zip file to generate. It is then sent back to the controller. In the controller I have defined:
public ActionResult DownloadLogs(List < string > applicationNames) {
var content = _ConfigBL.GetLogFileContent(applicationNames, out
var fileName);
if (null != content) {
return File(content, System.Net.Mime.MediaTypeNames.Application.Octet, fileName);
} else {
return HttpNotFound("Error Fetching Log Data");
}
}
But it seems this code is not working. From my testing for the variable "content" I am getting the response from the Service layer, but when I click on the download button from the frontend it's not prompting for a download of a file.
var applicationNames = #Html.Raw(Json.Encode(Model.LogApplicationNames));
var downloadLogs = "#Url.Action("DownloadLogs", "Configuration")";
$.each(applicationNames, function (index, value) {
let applicationName = value.toUpperCase();
let rowandColumn = $("<div class='row'><div class='col-md-12'>")
.append("<input type='checkbox' id='" + value.replace(" ", "") + "' name='" + value + "' " + enabledOrDisabled + " style='margin-left: 19px;' /> <label for= '" + value.replace(" ", "") + "' id = '" + value.replace(" ", "") + "Label' class= 'configLabel'>" + value + "</label>");
$("#logsApplicationNamesSection").append(rowandColumn);
})
<button class="accordion" id="fileTypesBtn">Log Files</button>
<div class="accordionPanel" id="logsSection">
<div class="logsSection" id="logsApplicationNamesSection"></div>
<div class="row lastRow">
<div class="col-lg-offset-9 col-lg-3 col-md-offset-8 col-md-4 col-sm-offset-7 col-sm-5 col-xs-12">
<button type="button" id="downloadButton" class="btn btn-default">
<span class="glyphicon glyphicon-download"></span>
Download
</button>
</div>
</div>
</div>

How to add <div></div> and name+size+delete appear in new div. javascript jquery

I have used ajaxSubmit to upload file to linux server successfully. After upload file, name+size+delete should be appear in my website.
For example, 1.jpg、2.jpg、3.jpg were uploaded to server, my submit website shoule be appeared like:
1.jpg 3k delete
2.jpg 4k delete
3.jpg 5k delete
Before upload files, My html structure is :
<td style="width:30%" id="impPic">
<div class="btn">
<span>addFile</span>
<input id="fileupload" type="file" name="mypic">
</div>
<div class="files"><b>...</b><span>...</span></div>
</td>
After uploaded three files, I wanted html like:
<td style="width:30%" id="impPic">
<div class="btn">
<span>addFile</span>
<input id="fileupload" type="file" name="mypic">
</div>
<div class="files"><b>...</b><span>...</span></div>
<div class="files"><b>...</b><span>...</span></div>
<div class="files"><b>...</b><span>...</span></div>
</td>
My files has fixed css style:
.files{height:10px; font-size:10px;line-height:22px; margin:10px 0}
Here is my ajaxSubmit code:
var divD=1;
$(function () {
var files = $(".files");
newDiv = "<div class='files'+divD+''><b class='dataname'>'+data.name+'('+data.size+'k)</b> <span class='delimg' name='+data.name+'('+data.size+'k)' rel='+data.pic+'>delete</span></div>";
$("#fileupload").change(function(){
$("#myupload").ajaxSubmit({
dataType: 'json',
beforeSend: function() {
......
},
uploadProgress: function() {
},
success: function(data) {
$(newDiv).insertAfter($('#impPic div:eq('+divD+')'));
divD = divD + 1;
$('.files').html("<b class='dataname' >"+data.name+"("+data.size+"k)</b> <span class='delimg' rel='"+data.pic+"'>delete</span>");
},
error:function(xhr){
......
}
});
});
});
But unfortunately, it failed. I suppose files'+divD+'.html is wrong. Who can help me ?
I see two problem with your code...
First was the html string "newDiv" that you are trying to insert and the second is the invocation for jQuery .html() on an string literal object "files'+divD+'".
You are expecting the newDiv object to have a concatenated html string with the value of divD and the data came from the response but object data is undefined until the logic flows in the success callback.
and I believe the second problem would return a jquery TypeError problem, as you are trying to call the .html() function on a non DOM - jQuery object .
Update your code and try it this way:
newDiv = "";
...
success: function(data) {
newDiv = "<div class='files" + divD + "'><b class='dataname'>" + data.name + "(" + data.size + "k)</b><span class='delimg' name='" + data.name + data.size + "k' rel='" + data.pic + "'>delete</span></div>";
$(newDiv).insertAfter($('#impPic div:eq(' + divD + ')'));
divD = divD + 1;
$(".files" + divD).html("<b class='dataname'>" + data.name + "(" + data.size + "k)</b><span class='delimg' rel='" + data.pic + "'>delete</span>");
},
...
EDIT:
You can update the html string and add an Id to have a unique selector on each of the element with files class and instead of the above selector, change the class selector "." to an Id selector "#".
and your code will look like these...
newDiv = "<div id='files" + divD + "'class='files'"...
...
$("#files" + divD).html("<b class='dataname'>" + data.name + "(" + data.size + "k)</b><span class='delimg' rel='" + data.pic + "'>delete</span>");
If that doesn't suit your needs you can just leave the first example above and update your css selector to:
[class^='files'] instead of `.files`.
This will select all of the element with a class that begins with "files".
files'+divD+' is a string, and you try to call method html from string, which does not exist.
Try $('.files' + divD).html('something'); or files.find('.files' + divD).html('something');

click(dataMap, method) version of the jQuery is not working

I tried to pass data through the click method to test it out so that I do not have to call a function from handler onclick. I want to do this to prevent the default submit whenever I press any button. Like this instead of having.
<button onclick="addAuthor()">Add Author</button>
I can have something like:
<button id="addAuthor">Add Author</button>
Which would go to.
$("#addAuthor").click({
id: 100
}, addAuthor);
Then.
function addAuthor(dataMap) {
alert(dataMap.data.id)
//add another author
}
I want the button "Remove div2" to do the same thing the span "Remove" does.
For now I had it to give an alert with the value of 100 but it does not even do that.
$("removeDiv").click({bookDiv: count}, removeDiv);
This is what I want to put so that the variables are passed but the test doesn't work.
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<style type="text/css">
<!-- #main {
max-width: 800px;
margin: 0 auto;
}
-->
</style>
</head>
<body>
<div id="main">
<h1>Add or Remove text boxes with jQuery</h1>
<div class="my-form">
<!-- <form action="next.php" method="post">-->
<button onclick="addAuthor()">Add Author</button>
<br>
<br>
<div id="addAuth"></div>
<br>
<br>
<button onclick="submit()">Submit</button>
<!-- </form>-->
</div>
<div id="result"></div>
</div>
<script type="text/javascript">
////////////////////////////////////////////////
//HERE
$("#removeDiv1").click({
id: 100
}, removeDiv1);
////////////////////////////////////////////////
var authors = 0;
function addAuthor() {
authors++;
var str = '<br/>' + '<div id="auth' + authors + '">' + '<input type="text" name="author" id="author' + authors + '" placeholder="Author Name:"/>' + '<br/>' + '<button onclick="addMore(\'auth' + authors + '\')" >Add Book</button>' + '</div>';
$("#addAuth").append(str);
}
var count = 0;
function addMore(id) {
count++;
var str =
'<div id="bookDiv' + count + '">' + '<input class="' + id + '" type="text" name="book' + id + '" placeholder="Book Name"/>' + '<span onclick="removeDiv(\'bookDiv' + count + '\')">Remove</span>'
///////////////////////////////////////////////////
////HERE
+ '<button id="removeDiv1"> Remove div2</button>'
///////////////////////////////////////////////////
+ '</div>';
$("#" + id).append(str);
}
function removeDiv(id) {
$("#" + id).slideUp(function() {
$("#" + id).remove();
});
}
///////////////////////////////////////////
//HERE
function removeDiv1(dataMap) {
alert(dataMap.data.id)
}
///////////////////////////////////////////
function submit() {
var arr = [];
for (i = 1; i <= authors; i++) {
var obj = {};
obj.name = $("#author" + i).val();
obj.books = [];
$(".auth" + i).each(function() {
var data = $(this).val();
obj.books.push(data);
});
arr.push(obj);
}
sendToServer(arr)
$("#result").html(JSON.stringify(arr));
}
function sendToServer(data) {
$.ajax({
type: "POST",
data: {
arr: JSON.stringify(data)
},
url: "next.php",
success: function() {
}
});
}
</script>
</body>
</html>
The problem isn't with passing in the dataMap (try it without it; it still won't work).
The problem is that when you attempt to set your click handler with $("#removeDiv1").click(...), the #removeDiv1 element doesn't exist yet - it's created and added to the DOM later, in addMore.
You need to do one of the following:
Set your click handler inside of addMore, after str is appended.
Change your click handler to use jQuery's event delegation capabilities. $("#removeDiv1").click(...) becomes $("body").on('click', '#removeDiv1', ...)
Side note: the "body" selector can be replaced by any selector that will select an ancestor of #removeDiv1; the click event propagates up from #removeDiv1 to its parent, its parent parent, and so on, until it's handled and something calls e.stopPropagation(), or until it reaches the document root.
First off, this is really something that Angular or something like it can do much better.
Next, I wouldn't use ids. You can do the same thing with classes without having to increment and restrict your code. Here's how I'd code the HTML:
<div>
<h1>My favorite authors and their books</h1>
<button class="js-add">Add An Author</button>
<div class="authors"></div>
<button class="js-save">Save</button>
</div>
I've also pulled all the javascript out of the HTML.
Next, "click" won't apply to items added after it is stated. You either need to re-state a click for the new element, or you need to use "on". Note in the code below that I can use the "click" method for "add Author" because that button exists when the script was run. For the other buttons, I had to use "on('click'..."
var addAuthor = function($this) {
var books = $('<div>')
.addClass('books')
.append(
$('<button>')
.addClass('js-addBook')
.html('Add a book')
)
.append(
$('<div>')
.addClass('bookName')
.html('Books:')
);
addBook(books.find('button'));
$($this)
.parent()
.find('.authors')
.append(
$('<div>')
.addClass('author')
.append(
$('<div>')
.addClass('authorName')
.html('Author: ')
.append(
$('<div>')
.addClass('remove js-removeAuthor')
.html('x')
)
.append(
$('<input>')
)
)
.append(
books
)
)
};
var addBook = function($this) {
$($this)
.parent()
.append(
$('<div>')
.addClass('book')
.append(
$('<div>')
.addClass('remove js-removeBook')
.html('x')
)
.append(
$('<input>')
)
)
};
addAuthor($('button.addAuthor'));
$('.js-addAuthor').click(function() {
addAuthor(this);
});
$('.authors').on('click', '.js-addBook', function() {
addBook(this);
});
$('.authors').on('click', '.js-removeBook, .js-removeAuthor', function() {
$(this)
.parent()
.remove()
});
Here's a jsfiddle:
https://jsfiddle.net/mckinleymedia/rt3tpeta/3/

Using an event handler on a anchor link added in Javascript

I have an Ajax call that returns an array of movie titles. I'd like to click on a button next to each title and add the title to a "currently watching" list. My "add" link doesn't seem to be accepting the event handler. What can I do to add the specified title to my "currently watching" list
$("#search").click(function(event){ event.preventDefault();
var show = $("#showTitle").val().toLowerCase();
console.log("the show title is " + show);
var url = "https://api.themoviedb.org/3/search/movie?query=" + encodeURIComponent(show)+ "&api_key=9b97ec8f92587c3e9a6a21e280bceba5";
console.log(url);
$.ajax ({
url: url,
dataType: "json",
success: function (data) {
// console.log(data.results);
var htmlStr = '';
$.each(data.results, function(i, results){
htmlStr += '' + 'Add' + ' <h2 class="movie-title">' + results.original_title + '</h2>' + "Average Rating " + results.vote_average + '<br>' + '<p class="showDescription">' + results.overview + '</p>' + '<br />' + '<img src=https://image.tmdb.org/t/p/w185' + results.poster_path + '>';
});
// console.log(htmlStr);
$('#searchresults').html(htmlStr);
}
// updateCount(); - count the classes inside the "currentywatching" function
}); //close .ajax
});
$('.addCurrentlyWatching').on('click', function(e){
e.preventDefault();
var movieTitle = $('.movie-title').text();
// console.log(movieTitle);
$('.currently-watching').append('<li>' + movieTitle + '</li>');
});
<section id = "shelf1">
<h2> Currently Watching </h2>
<ul class="currently-watching"></ul>
<div class="number">
<p> You currently have <span id="count"> 0 </span> shows in this list. </p>
</div>
</section>
The solution:
$(document).on('click','.addCurrentlyWatching', function(e){
e.preventDefault();
var movieTitle = $('.movie-title').text();
// console.log(movieTitle);
$('.currently-watching').append('<li>' + movieTitle + '</li>');
});
If you are interested in a more detailed answer:
Explanation
use
$('body').on('click','.addCurrentlyWatching', function(e){
take a look at Event binding on dynamically created elements?
and in
' + 'Add' + '
if you have Add variable defined use
' + Add + '
if you not
Add
and you can use
var movieTitle = $(this).next('.movie-title').text();
instead of
var movieTitle = $('.movie-title').text();
For older versions of jQuery use $.live & $.delegate
Docs:
http://api.jquery.com/live/
http://api.jquery.com/delegate/

Correct way to implement bootstrap popover with ajax request

Trying to implement Bootstrap's popover which will appear after response for AJAX request will be received.
Here is HTML code:
<div class="row">
<div class="col-md-3">
<h4>
<strong>Sorted laptops:</strong>
</h4>
</div>
<div class="col-md-2 col-md-offset-7">
<button class="btn btn-info pull-right" data-loading-text="Generating link to share, please wait..." id="share_results">Share results</button>
</div>
</div>
Here is JS code:
$('#share_results').click(function(event) {
var $share_results, delimiter, descriptions, query;
$share_results = $(this);
$share_results.button('loading');
descriptions = $.map($('td.laptop_desc'), function(val) {
return $(val).text().trim().replace(/\s{2,}/g, ' ');
});
delimiter = $('#delimiter').val();
query = descriptions.join(' ' + delimiter + '\n\n');
$.post('/path', {
'query': query,
'delimiter': delimiter
}, function(resp) {
var content, hash, url;
$share_results.button('reset');
hash = resp['hash_string'];
url = window.location.origin + window.location.pathname + '?q=' + hash;
content = "<input class='form-control input-sm' value='" + url + "'>";
return $share_results.popover({
container: '.container',
html: true,
delay: 500,
placement: 'left',
'content': content
}).popover('show');
});
});
No CSS changes were made.
Initial button state:
State after request is received:
Here I am having two problems:
popover always on top - doesn't disappear
popover width is too small
How to fix that?

Categories