Multiple elements with same class make jquery click event to fire multiple times - asp.net-mvc

I display user comments. Each comment is one div and each div has <a> tag with class 'commentLikeLink'. I bind jquery click event to 'commentLikeLink' class but If I have 10 comments and click on one like button I get event fired 10 times.
I know that this happen's because I have same class multiple times. But How to stop this?
Here's the code:
...
<div class="commentBox"">
...
#Html.ActionLink(likeText, "LikeComment", "Comment", null, new { id = Model.CommentId, #class = "commentLikeLink" })
...
Event code:
$(function () {
$('.commentLikeLink').click(function (event) {
var commentId = event.target.id;
$.ajax({
url: this.href,
type: 'POST',
data: { commentId: commentId },
context: this,
success: function (result) {
if (result.msg == '1') {
$(this).text('Dislike');
}
else if(result.msg == '2') {
$(this).text('Like');
}
}
});
return false;
});
});

You shouldn't be getting 10 clicks. You can bind the click event to the class, but the context in which the event is fired is the individual element, so if you had some markup that looked like this:
<p>
Liked?
<br />
Liked?
<br />
Liked?
<br />
Liked?
</p>
Then this would work, setting the link text to "Liked!" as each one is clicked:
$(document).on("click", ".clickItem", function (ev) {
$(this).text("Liked!");
});
Have you debugged the code? Are you sure you're getting 10 clicks all at once?

yes binding the click event to the class is a better solution, but it can actually get fired multiple times if you use it on the item it self or the class it self !
so instead of having this : $('.commentLikeLink').click(function (event) {//do things here }
you should do this and it will only fire once :
$(document).on("click", ".commentLikeLink", function (ev) {
//do things here
});

I had this happen before when i accidently included the same .click script function multiple times in the page. Make sure your javascript is only included once

Related

jQuery UI Autocomplete perform search on button click issues

I have a working UI Auto complete with jQuery. I wanted to change the way it worked. Instead of a new browser tab opening with the user selects a value from the list I wanted the user to first pick a value then click a search button to trigger the event.
It works but if you perform a search and then a second search it will trigger the previous URL and new URL at the same time. Also if you perform a search then click the search button without typing anything into the search input it triggers the previous search. Weird right? I'll add my code but I think a codepen example will help clarify what I mean.
The other issue I was having is I am trying to set up a custom alert if the value typed is not in the array but I get the invalid error message no matter what I type. I added that as well in the code. It is one of the if statements.
JS
var mySource = [
{
value: "Google",
url: "http://www.google.com"
},
{
value: "Yahoo",
url: "https://www.yahoo.com"
},
{
value: "Hotmail",
url: "https://hotmail.com"
},
{
value: "Reddit",
url: "https://www.reddit.com"
}
];
//Logic for ui-autocomplete
$(document).ready(function() {
$("input.autocomplete").autocomplete({
minLength: 2,
source: function(req, resp) {
var q = req.term;
var myResponse = [];
$.each(mySource, function(key, item) {
if (item.value.toLowerCase().indexOf(q) === 0) {
myResponse.push(item);
}
if (item.value.toUpperCase().indexOf(q) === 0) {
myResponse.push(item);
}
//Add if statement here to determine if what the user inputs is in the
// array
//and if not in the array give an error to #textAlert.
//Example
if (item.value.indexOf(q) != myResponse) {
$('#alertText').text("Invalid Search");
} else {
return false;
}
});
resp(myResponse);
},
select: function(event, ui) {
$('#appSearchBtn').one("click", function() {
window.open(ui.item.url);
$('#appsearch').val('');
return false;
});
}
});
});
//Input and ui text clears when clicked into
$(document).ready(function() {
var input = document.querySelector('#appsearch');
var ui = document.querySelector(".ui-helper-hidden-accessible");
input.onclick = function() {
input.value = '';
ui.textContent = '';
};
});
HTML
<p id="alertText"></p>
<div class="input-group">
<input type="text" id="appsearch" class="form-control autocomplete" placeholder="Application Search" />
<span class="input-group-btn">
<button class="btn btn-primary inputBtn" id="appSearchBtn" type="button">Search</button>
</span>
</div>
Here is a Code pen https://codepen.io/FrontN_Dev/pen/MEmMRz so you can see how it works. I also added how it should work and what the bugs are.
9/29/17 #0732
I resolved the issue with the event firing the same URL over and over but I still need help with the custom invalid search message that appears for every search even if the value is in the array.

MVC5 Partial View Example

I am seeking to create a reusable "employee lookup" control.
Note:I am assuming that a partial view is the best way to go.
I want multiple buttons on the page
Each button will call a PartialView and each button will have a specific textbox
Each partial will contain multiple Results (items)
On clicking one of the results I want to populate the button's textbox, that made the call, with the result
How am i able to do this, since the page will have multiple buttons and textboxes?
This control needs to be able to be called by multiple buttons
So, those buttons call an action which will render the partial which has those results?
I'm seeing multiple ways to do this. The easiest way is:
<button id="btn1" class="btns" data-target="txt1" type="button">A</button>
<button id="btn2" class="btns" data-target="txt2" type="button">B</button>
<input type="text" id="txt1" />
<input type="text" id="txt2" />
<div id="render">
</div>
<script>
var ajaxActive = false;
$(function() {
$(".btns").on('click', function () { // Bind the onclick of the button, so any button with this class may call the following function
var _button = $(this);
getItems(_button);
});
});
function getItems(_button) {
var bind = function (_button, results) {
$("#render").empty();
$("#render").append(results); // Append the partialview to the current view's div
$("#render .itemResult").on('click', function () { // Bind the onclick of the result
var resultValue = $(this).text(); // Or any other value that come from the result
var targetId = "#" + _button.data('target'); // Id of the input (Target) which comes from the clicked button
$(targetId).val(resultValue); // Change the input target value with the result one
});
};
if (ajaxActive) {
$.get('/Controller/Action') // Get the partialview
.done(function (results) {
bind(_button, results);
});
}
else {
var results = simulateCall(); // Get the results
bind(_button, results);
}
}
function simulateCall() { // Simulate a call to the server
return "<div class='items'> <div class='itemResult'>ABC</div> <div class='itemResult'>DEF</div> </div>";
}
</script>
PS: Here is a working demo
Keep in mind that i placed some sort of "call" to simulate it going to the database

jQuery Ajax Form Submit Fails

I am developing an MVC4 mobile app that uses several forms which are loaded into a section on the layout via ajax. I've got jQuery mobile set with Ajax turned off so I can manage the Ajax myself. Most of the forms work fine, the load and submit via ajax as they should. However, so far there is one form that refuses to fire the form submit and submit the form via ajax like the rest. First, the form is loaded when a user clicks to add a contact and this works fine:
// Handle the add contact button click
$('#btnAddNewContact').on('click', function (e) {
e.preventDefault();
// Make sure a location was selected first.
var locationID = $('#cboLocation').val();
if (locationID.length === 0) {
//$('#alertTitle').text('REQUIRED');
$('#alertMsg').html("<p>A Contact must be associated with a Location.</p><p>Please select or add a Location first.</p>");
$('#alertDialogDisplay').click();
} else {
SaveOpportunityFormState();
$.cookie('cmdLocationId', locationID, { path: '/' });
$.mobile.loading('show');
$.ajax({
url: '/Contact/Add',
type: 'GET',
cache: false,
success: function (response, status, XMLHttpRequest) {
$('section.ui-content-Override').html(response);
// Refresh the page to apply jQuery Mobile styles.
$('section.ui-content-Override').trigger('create');
// Force client side validation.
$.validator.unobtrusive.parse($('section.ui-content-Override'));
},
complete: function () {
$.cookie('cmdPreviousPage', '/Opportunity/Add', { path: '/' });
AddContactLoad();
ShowSearchHeader(false);
$.mobile.loading('hide');
},
error: function (xhr, status, error) {
// TODO - See if we need to handle errors here.
}
});
}
return false;
});
Notice that after successfully loading the form the AddContactLoad() function is fired. This works fine and here is that code:
function AddContactLoad() {
$('#contactVM_Phone').mask('(999) 999-9999? x99999');
$('#frmAddContact').on('submit', function (e) {
e.preventDefault();
if ($(this).valid()) {
$.mobile.loading('show');
$.ajax({
url: '/Contact/Add',
type: 'POST',
cache: false,
data: $(this).serialize(),
success: function (response, status, XMLHttpRequest) {
if (!response) { // Success
ReturnToAddOpportunity();
} else { // Invalid Form
$('section.ui-content-Override').html(response);
// Force jQuery Mobile to apply styles.
$('section.ui-content-Override').trigger('create');
// Force client side validation.
$.validator.unobtrusive.parse($('section.ui-content-Override'));
AddContactLoad();
$.mobile.loading('hide');
}
},
complete: function () {
},
error: function (xhr, status, error) {
// TODO - See if we need to handle errors here.
}
});
}
return false;
});
$('#btnCancel').on('click', function (e) {
e.preventDefault();
// See where add contact was called from.
var previousPage = $.cookie('cmdPreviousPage');
if (previousPage.indexOf("Detail") >= 0) {
ReturnToOpportunityDetails();
} else {
ReturnToAddOpportunity();
}
return false;
});
}
If I click the cancel button, that code is fired so I know this is working too. Here is my form code:
#using (Html.BeginForm("Add", "Contact", FormMethod.Post, new { #id = "frmAddContact" }))
{
#Html.ValidationSummary(true)
#Html.AntiForgeryToken()
-- Form Fields Here --
<div class="savecancel" >
<input type="submit" value="Save" data-mini="true", data-theme="b", data-inline="true" />
Cancel
</div>
}
As you can see the form is named frmAddContact and that is what the AddContactLoad() function is attaching the submit event to. To save my sole I cannot figure out why the form does not submit via the ajax post like every other form in the app. Am I missing some kind of initialization, I just don't know. If anyone can please help I'd really appreciate it!!
As it turns out, I had created a custom unobtrusive Ajax validator for a phone number then copied and pasted it to do the same with a zip code. Unfortunately in the process I forgot to rename a variable and thus an error was occurring in the validation script which caused the problem. In the mean time, if you're reading this, you might take a note of the code here and how to inject HTML into a page via Ajax and jQuery mobile. I've never found this in a book or on the web and it contains some very useful methodology and syntax. On the form submit the reason I'm checking for the empty response is I just return null from the controller to validate the form was valid and the save worked in which case I send them to a different HTML injection i.e. that page they originally came from. If null is not returned I inject that page with the HTML containing the original form and error markup so the user can make corrections then resubmit. I'm also calling a form load method that attaches handlers to the HTML once it's injected into the main page. Hope this helps somebody!

Html imput type="image" onclick event

Friends I have a problem
We need to make a user control that has the ability to delete itself, I made it but we did not clear the mechanism for removal, it should be tied to a nice picture. Code that is attached to the frame is given below, but not
$('#delete').bind('click', function () {
alert('test');
var urlA = '<%=Url.Action("DeleteMessage","Ticket")%>';
$.ajax({
url: urlA,
type: 'POST',
data: { idMessage:$(this).parents("div:first").find("input[name='MessageID']").val(),idticket:$('#TicketID').val() },
success: function (data) {
alert(data);
}
});
});
But when I write this, but to throw me to the homepage what's wrong
$('#delete').live('click', function ()
$("#delete").live("click", function(){
//code
$(this).remove(); //delete itself
});
If your image is declared as input type="image" then it will behave like a submit button and submit your page. You should prevent the default behavior of submitting the page by adding an event.preventDefault() or equivalent to your javascript function.

Ckeditor update textarea

I am trying to get the ckeditor working. Obviously it doesn't make use of the textarea so on submit the form doesn't submit the text in the editor. Beceause I make use of polymorphic associations etc. I can't make a onsubmit function to get the value of the textarea (when the form is submitted) .
So I found this question: Using jQuery to grab the content from CKEditor's iframe
with some very good answers. The answers posted there keep the textarea up to date. That is very nice and just what I need! Unfortunately I can't get it to work.
Does somebody know why (for example) this doesn't work?
I have a textarea (rails but it just translates to a normal textarea):
<%= f.text_area :body, :id => 'ckeditor', :rows => 3 %>
And the following js:
if(CKEDITOR.instances.ckeditor ) {
CKEDITOR.remove(CKEDITOR.instances.ckeditor);
}
CKEDITOR.replace( 'ckeditor',
{
skin : 'kama',
toolbar :[['Styles', 'Format', '-', 'Bold', 'Italic', '-', 'NumberedList', 'BulletedList', 'Link']]});
CKEDITOR.instances["ckeditor"].on("instanceReady", function()
{
//set keyup event
this.document.on("keyup", CK_jQ);
//and paste event
this.document.on("paste", CK_jQ);
}
function CK_jQ()
{
CKEDITOR.instances.ckeditor.updateElement();
}
I get the following "error" in my firebug.
missing ) after argument list
[Break on this error] function CK_jQ()\n
Before submit do:
for(var instanceName in CKEDITOR.instances)
CKEDITOR.instances[instanceName].updateElement();
have you figured it out?
I'm using CKEditor version 3.6.1 with jQuery form submit handler. On submit the textarea is empty, which to me is not correct. However there is an easy workaround which you can use, presuming all your CKEditor textareas have the css class ckeditor.
$('textarea.ckeditor').each(function () {
var $textarea = $(this);
$textarea.val(CKEDITOR.instances[$textarea.attr('name')].getData());
});
Execute the above before you do your submit handling ie. form validation.
Thanks #JohnDel for the info, and i use onchange to make it update every change.
CKEDITOR.on('instanceReady', function(){
$.each( CKEDITOR.instances, function(instance) {
CKEDITOR.instances[instance].on("change", function(e) {
for ( instance in CKEDITOR.instances )
CKEDITOR.instances[instance].updateElement();
});
});
});
Combination of all of the above answers into one.
Create a new custom.js file and add this:
CKEDITOR.on('instanceReady', function(){
$.each( CKEDITOR.instances, function(instance) {
CKEDITOR.instances[instance].on("instanceReady", function() {
this.document.on("keyup", CK_jQ);
this.document.on("paste", CK_jQ);
this.document.on("keypress", CK_jQ);
this.document.on("blur", CK_jQ);
this.document.on("change", CK_jQ);
});
});
});
function CK_jQ() {
for ( var instance in CKEDITOR.instances ) { CKEDITOR.instances[instance].updateElement(); }
}
You don't have to worry about the name of the textarea, just add a class ckeditor in the textarea, the above and you are done.
ADD Function JavaScript for Update
function CKupdate() {
for (instance in CKEDITOR.instances)
CKEDITOR.instances[instance].updateElement();
}
It's work. Cool
Just Add
CKEDITOR.instances.textAreaClientId.on('blur', function(){CKEDITOR.instances. textAreaClientId.updateElement();});
where textAreaClientId is your instance name
Regards
CKEDITOR.instances["ckeditor"].on("instanceReady", function()
{
//set keyup event
this.document.on("keyup", CK_jQ);
//and paste event
this.document.on("paste", CK_jQ);
})
I just increase that to the response of T.J. and worked for me:
$("form").on("submit", function(e){
$('textarea.ckeditor').each(function () {
var $textarea = $(this);
$textarea.val(CKEDITOR.instances[$textarea.attr('name')].getData());
});
});
On load:
$(function () {
setTimeout(function () {
function CK_jQ(instance) {
return function () {
CKEDITOR.instances[instance].updateElement();
};
}
$.each(CKEDITOR.instances, function (instance) {
CKEDITOR.instances[instance].on("keyup", CK_jQ(instance));
CKEDITOR.instances[instance].on("paste", CK_jQ(instance));
CKEDITOR.instances[instance].on("keypress", CK_jQ(instance));
CKEDITOR.instances[instance].on("blur", CK_jQ(instance));
CKEDITOR.instances[instance].on("change", CK_jQ(instance));
});
}, 0 /* 0 => To run after all */);
});
There have been some API changes with the latest versions of CKEditor, so here's an answer for CKEditor 5:
let ckeditor;
// Create a CKEditor, and store its handle someplace that you may
// access later. In this example, we'll use the `ckeditor` variable:
ClassicEditor
.create(document.querySelector("textarea"), {})
.then(editor => { ckeditor = editor; });
// When your form submits, use the `updateSourceElement` method
// on the editor's handle:
document.querySelector("form").addEventListener("submit", function() {
ckeditor.updateSourceElement();
});
To my knowledge, CKEditor does this automatically when you submit a form, so this particular example shouldn't actually do anything. But it is useful when you need the content of the textarea to udpate without submitting the form that contains it.
All above answer are focusing on how to fix this error but I want to take the answer on what cause me this error
I had a
<textarea class="ckeditor" rows="6" name="Cms[description]"></textarea>
changed to
<textarea class="ckedit" rows="6" name="Cms[description]"></textarea>
I changed class attribute value to anything other than ckeditor and boom error gone.
Hope that help

Resources