I am fairly new to jQuery, and even though there are a lot of tutorials on how to bind to buttons, I believe my set up is a little more complicated (beyond the scope).
What I have:
-I am using Django to populate my Makes on a view.
Here is my template:
<div class="container">
<div class="row">
<div class="btn-group" id="makesTable">
{% if makes %}
{% for make in makes %}
<button type="button" name="button" class="btn btn-default" id="{{ make.id }}">
<br />
<img class="center-block" src="[REDACTED]" />
<br />
<p>{{ make.name }}</p>
</button>
{% endfor %}
{% endif %}
</div>
</div>
</div>
I am currently having an issue with responsive design. I would like for the buttons to be arranged in a 5x7 grid, however, sometimes, I get the following issue:
This is how it looks when everything is good!
This is the problem. Notice the spacing with a ?
The Workflow:
User sees (35) different buttons to select from. As you can see name, and id are unique, where id is the Primary Key from the database (this is obviously important)
I can capture the primary key using jQuery using this function:
$(document).ready(function() {
$("button").click(function() {
var make_id = $(this).attr('id')
});
});
At the same time, jQuery is going to hide/remove the button elements (trivial)
This is done with the following code snippet (anf adding fadeout to the click listener:
function fadeOut() { $( "#makesTable" ).fadeOut( "slow", function() {}); };
Then I would like to use the id from button clicked to do an AJAX request to my API, where django URL routing is:
url(r'^makes/(?P<pk>[\d]+)/$', views.MakesDetail.as_view(), name='makes-instance'),
in other words, the AJAX request goes to mysite.com/api/makes/(this.id) and returns a JSON file (already set-up thanks to DRF.)
Sample Response:
{
"name": "BMW",
"model": [
{
"name": "2 Series",
},
{
"name": "3 Series",
}]
}
Finally, using this API response, I wish to populate a similar template of buttons (replacing makes with models.)
This is for a single page app in a sense where no page refresh is necessary with the use of JSON and AJAX.
Full disclosure: I am an entry level programmer/web developer.
code snippet:
<div class="main-content container-fluid">
<div class="container">
<div class="row">
<div class="btn-group" id="makesTable">
<button type="button" name="button" class="btn btn-default" id="200002038">
<br />
<img class="center-block" src=" " />
<br />
<p>Acura</p>
</button>
<button type="button" name="button" class="btn btn-default" id="200464140">
<br />
<img class="center-block" src="" />
<br />
<p>Alfa Romero</p>
</button>
<script>
$(document).ready(function() {
$(document).on( "click", "button", function() {
alert($(this).attr('id')); //testing functionality
});
});
</script>
<script src="assets/lib/jquery/jquery.min.js" type="text/javascript"></script>
<script src="assets/lib/perfect-scrollbar/js/perfect-scrollbar.jquery.min.js" type="text/javascript"></script>
<script src="assets/js/main.js" type="text/javascript"></script>
<script src="assets/lib/bootstrap/dist/js/bootstrap.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function(){
//initialize the javascript
App.init();
});
</script>
</div>
</div>
</div>
</div>
Since the buttons are dynamically generated. You have to make the handler like this:
$(document).on('click', 'button.btn', function(e) {
alert($(this).attr('id')); //testing functionality
});
First of all, event association to buttons should be better via classes (it's a better practice).For the javascript click code check the other answers.
For ajax requests, you can refer to this links:
https://api.jquery.com/jquery.post/
https://api.jquery.com/jquery.get/
https://api.jquery.com/jquery.when/
By example 'when' function, it allows you to know when request ended and execute any actions after.
from your replied comment I expect that you attach the handler before the button already rendered so I recommend you to use bubbling event concept like this:-
$(document).ready(function() {
$(document).on( "click", "button", function() {
alert($(this).attr('id')); //testing functionality
});
});
and the the alert will pop up and you can do whatever else you want to do.
Related
I am using the following snippet which allows a person to upload up to 3 files with a single upload button. While the file is being uploaded an animation runs in place of the upload button.
My requirement is that I need to prevent the user from clicking on any of the input field buttons while the file is getting uploaded. I do not wan't to use the hide() function for this. Is there a way in jQuery to stop the input field buttons from getting clicked on while the file is getting uploaded/the loading animation is running.
Recently started to use jQuery so still a beginner and hence would love to use a simple solution for this. Thanks!
<script type="text/javascript">
$(document).ready(function() {
$(document).on("click", ".UploadBtn", function(event) {
$(".p").each(function(file) {
if ($(this).val()) {
$(".loader").show();
$(".spinner").show();
$(".UploadBtn").hide();
}
})
});
});
</script>
My HTML code is below. The "p" class is used for {{ form.photo1 }}, {{ form.photo2 }} & {{ form.photo3 }} ;
<div class="mtl mbl">
{{ form.photo1 }}
</div>
<div class="loader">
<div class="spinner"></div>
loading</div>
<input type="submit" class="UploadBtn btn bm bco mbs mts" style="border-color:#f57c00;" value="Upload">
<div class="mtl mbl">
{{ form.photo2 }}
</div>
<div class="loader">
<div class="spinner"></div>
loading</div>
<input type="submit" class="UploadBtn btn bm bco mbs mts" style="border-color:#f57c00;" value="Upload">
<div class="mtl mbl">
{{ form.photo3 }}
</div>
<div class="loader">
<div class="spinner"></div>
loading</div>
<input type="submit" class="UploadBtn btn bm bco mbs mts" style="border-color:#f57c00;" value="Upload">
When the upload button, which the red button is pointing at, is
clicked an animation starts to run in its place while the file is
getting uploaded. During this I want to prevent anyone from clicking
on the choose file (), the blue arrow is pointing at it.
Try using prop to disable upload buttons
$(document).ready(function() {
$(document).on("click", ".UploadBtn", function(event) {
$(".p").each(function(file) {
if ($(this).val()) {
$(".loader").show();
$(".spinner").show();
$(".UploadBtn").prop("disabled", "true");
}
})
});
});
In jQuery 1.6+ you can dynamically add the atrribute attr='disabled' or attr='readonly' to your input field until you confirm that your files are loaded:
// put this within the code that checks if the files are still loading
$(".UploadBtn").prop('disabled', true);
// within the code that checks if the files have successfully loaded, make sure to use the following
$(".UploadBtn").prop('disabled', false);
Also take a quick look at what prop does in this detailed answer.
In meteor, I have created a cards dynamically after submitting the form. and the dynamic card contains the show and hide buttons. When I click on show option button the hidden part is showing for all the cards instead of that particular card. the problem is the card is creating dynamically so I thought that is problem .. how to make the functionality to work separately to the each card.
Here I am attaching the code:
<div id="newActionCard">
{{#each newaction}}
<div class="workflowcard">
<div class="module-card">
<div class="res-border"></div>
<div class="card-img"></div>
<div class="res-content">
<div class=" assigned-team">{{team}}</div>
<div class=" newaction-name">{{action_title}}</div><hr>
<div class="description">{{description}}</div>
<div class=" due-on">Due on:{{d_date}}</div><hr>
<div class="subcontent">
{{> actioncardsubcontent}}
</div>
<div class="reqext">
{{> requestextensioncard}}
</div>
</div>
<div class="due">
Due on:
<div>
<span class="day-stamp">THU</span><br>
<div class="date-stamp">26</div>
<div class="month-stamp">AUG
</div>
</div>
</div>
</div>
<div class="btn-box newaction">
<button type="button" class="cancelsub" >New Action</button>
<button type="submit" class="createbtnsub" >Show Options</button>
</div>
<div class="btn-box showoption">
<button type="button" class="hideoption" style="display:none">Hide Options</button>
</div>
{{/each}}
</div>
In JS I have written the hide and show functionalities in the events..now how to stop functionality to all cards at a time.
Here is my JS:
Template.workflow.events({
"click .createbtnsub" : function() {
$( ".subcontent" ).show();
$('.createbtnsub').hide();
$('.cancelsub').hide();
$('.hideoption').show();
$('.requestextension').show();
},
"click .hideoption": function(){
$('.subcontent').hide();
},
"click .hideoption": function(){
$(".subcontent").hide();
$('.cancelsub').show();
$('.createbtnsub').show();
$('.requestextension').hide();
$('.hideoption').hide();
$('.reqext').hide();
},
"click #createActionBtn": function(){
$('#createAction').hide();
$('.editw').show();
$('.hidew').show();
},
});
Template.actioncardsubcontent.rendered = function(){
this.$(".subcontent").hide();
};
Template.requestextensioncard.rendered = function(){
this.$(".reqext").hide();
};
Template.workflow.helpers({
getWorkflow: function(){
return Workflow.find();
},
user: function(){
return Meteor.users.find({});
},
getNewaction: function(){
return Newaction.find();
},
});
Please see the following and adjust the selectors as needed:
"click .showoption": function(event){
$(event.currentTarget).next('button').show();
}
This will work for selecting sibling elements, however as a tip I would recommend rewriting your template.helper that returns the cards data from the database into something more specific.
Something like dynamic classes based on index or id so your class/id names would return as follows .showoption-12kjddfse4 . Then you can just get the attribute of the current target and apply it to your js selector.
Also as kind of an explination to why all buttons were showing, is you were using the class selector, which is meant for grabbing groups of elements/nodes. This is also another reason to created more specific classnames/ids to your use case.
So in your class name you could do something like
<button class="showoption" id="{{_id}}">button</button>
<button id="hiddenoption-{{_id}}" class="hiddenoption">button</button>
Then selecting your elements would be easier as follows:
'click .showoption'(event) => {
let id = event.currentTarget.getAttribute(id);
document.getElementById('hiddenoption-'+id).style.display = 'block';
}
I have the following markup inside my .cshtml Partial View and it is placed in the Views/Shared folder:
_Modal.cshtml
<div class="loadingOverlay">
<button class="btn loading-button" disabled><i class="fa fa-spinner fa-pulse fa-2x fa-fw"></i></button>
</div>
And also the External JavaScript (different file from the Partial View .cshtml):
Modal.js
var Modal;
Modal = Modal || (function () {
var loadingDiv = $('.loadingOverlay');
return {
Loading: function () {
loadingDiv.css('display', 'block');
$('body').prepend(loadingDiv);
},
LoadingDismiss: function () {
loadingDiv.fadeOut('500');
},
};
})();
And I call from my page like below:
Index.cshtml
<!DOCTYPE html>
<html>
<head>
#Styles.Render("~/Content/font-awesome", "~/Content/css")
</head>
<body>
<div class="container-fluid">
<div class="container">
<div class="row">
<button id="showOverlay" class="btn btn-default"></button>
</div>
</div>
</div>
#Scripts.Render("~/bundles/jquery")
<script type="text/javascript">
$(document).ready(function () {
$('#showOverlay').click(function () {
Modal.Loading();
});
})
</script>
</body>
</html>
My problem is: whenever I clicked the button, nothing happens. But it works when I put the html element not inside _Modal.cshtml (Refer to the below code).
My question is: how can I get the class name in the _Modal.cshtml using JavaScript or JQuery?
I can do this in the Modal.js (Note that it is same as I put that into _Modal.cshtml) but that would be hard to maintain and I would like to put all of the content in the Partial View, and call it when needed by class name, instead of write string that will converted to JavaScript Object:
var loadingDiv = $('<div class="loadingOverlay"><button class="btn loading-button" disabled>'
+ '<i class="fa fa-spinner fa-pulse fa-2x fa-fw"></i></button></div>');
Your answer much appreciated.
Edit:
Question on 31st of May 2016:
What's the difference between #Html.Partial("_Modal") with #Html.Partial("~/Views/Shared/_Modal.cshtml"). is it just to better understand for where the compiler get the partial views from?
Answered on 1st of June 2016 by #Guruprasad Rao:
There is nothing difference between two except the mentioning of partialview name. The one I suggested was providing fully qualified path which helps compiler from where to fetch the partialview. To one you use will search in all the directories under the View folder. So the one I mentioned will be good in the aspect of performance.
Thanks for the #Guruprasad Rao for the answer and the explanation.
Cheers~
You should import the partialview first from server to client browser first and then you can manipulate it with jquery. Otherwise there would be no element with the selector you are trying to find. User, #Html.Partial or #Html.RenderPartial to import it, hide it at initial state and show it on click. Take a below example:
<body>
<div class="container-fluid">
<div class="container">
<div class="row">
<button id="showOverlay" class="btn btn-default"></button>
</div>
</div>
</div>
#Html.Partial("~/Views/Shared/_Modal.cshtml")
<!--I assume that the content inside this will be initially in hidden state-->
#Scripts.Render("~/bundles/jquery")
<script type="text/javascript">
$(document).ready(function() {
$('#showOverlay').click(function() {
Modal.Loading();
});
})
</script>
</body>
Modal.js changes
var Modal;
Modal = Modal || (function () {
var loadingDiv = $('.loadingOverlay');
return {
Loading: function () {
loadingDiv.css('display', 'block');
//$('body').prepend(loadingDiv);
//No need to prepend here since we are importing it through partial method
},
LoadingDismiss: function () {
loadingDiv.fadeOut('500');
},
};
})();
I'm using jScroll (jscroll.com) in my Laravel 5.1 application for infinite scrolling. I'm further using some jquery which I want to be triggered on clicking the 'Like' button for each post. Jquery is working perfectly on the first page's posts i.e localhost/myproject/index but it is not triggered for the posts which are appended by jScroll from the next page(s) i.e localhost/myproject/index?page=2 etc.
Here is my code for displaying the posts:
#foreach($posts as $post)
<div class="panel panel-default">
<div class="panel-body post">
<h3>{{ $post->title }}</h3>
<hr>
<p>{{ $post->discripion }}</p>
</div>
<div class="panel-footer">
<div class="btn-group">
<button type="button" data-id="{{$post->id}}" class="btn btn-default like-btn">Like</button>
</div>
</div>
</div>
#endforeach
and the simple jquery that I want to be triggered for each posts is:
<script type="text/javascript">
$('button.like-btn').on('click',function(){
var post_id = $(this).data('id');
alert('Liked post with id = ' + post_id);
});
</script>
It's because jquery doesn't bind to those elements (they are not in the DOM initially). Bind it to document instead, like this:
$(document).on("click", 'button.like-btn', function(event) {
alert("new link clicked!");
});
Look here for a little more
all. I have html layout like this:
<div class="row" id="1">
/*Other code has nothing to do with <div class="form-group col-lg-1">*/
<div class="form-group col-lg-1">
<input type="button" class="btn btn-default" onclick="updateLine()" value="Update">
</div>
</div>
I want to obtain the div's ID, in this case, which is 1.
This is what I did.
function updateLine() {
alert(this.parent().parent().attr("id"));
}
However, it failed, then I check
alert(this);
it returns to me the window object.
So the question is , how could I get the id's value, which is 1.
Thanks.
You need to pass this to the function as follows
<input type="button" class="btn btn-default" onclick="updateLine(this)" value="Update">
function updateLine(obj) {
alert(obj);
$(obj).closest('.row').attr('id'); // will return the id, note that numeric values like 1 are invalid
}
You do not need to pass this to the function. In an event handler this is the element clicked. However, to use .parent() etc on it you need the jQuery object for that element which is $(this)
Also, I would strongly recomment using .closest instead of .parent().parent(). Something like
$(this).closest('div.row').attr('id')
Way less likely to break when you make small layout changes...
The comments about using jQuery events instead of inline javascript are also good advice.
Example:
<div class="row" id="1">
/*Other code has nothing to do with <div class="form-group col-lg-1">*/
<div class="form-group col-lg-1">
<input type="button" class="btn btn-default" value="Update">
</div>
</div>
<script type="text/javascript">
$(function(){
function updateLine(event){
alert( $(this).closest('.row').attr('id') );
}
// If you have other buttons add a class like 'btn-update' and use that instead
$('body').on('click', '.btn-default', updateLine);
});
</script>
If you want to do inline event handlers, you need to pass this:
onclick="updateLine(this)"
then in js:
function updateLine(obj) {
alert($(obj).closest('.row').attr("id"));
}
However, I'd recommend removing the inline handler if possible and using jQuery to do the binding:
$('button').click(function() {
alert($(this).closest('.row').attr("id"));
});
What you are trying do is very bad practice. It will never work.
Firs, you should not use inline javascript.
Second, you should use real jQuery code.
Below you can see a working example.
<div class="row" id="1">
<div class="form-group col-lg-1">
<input type="button" class="btn btn-default" value="Update" id="someID" />
</div>
</div>
And your jQuery code should be like:
$(function () {
$('#someID').click(function () {
alert($(this).parents('div:eq(1)').prop('id'));
});
});
Here is a working example: http://jsfiddle.net/avramcosmin/Z9snq/
A bit late but what worked for me:
$(document).on('click', '.id', function(event) {
const elem = $(this);
})