jQuery event triggering multiple times because of multiple javascript inclusions/requires - javascript

I have a problem here and it's making me mad. I maintain a legacy php system. It's badly organized, no frameworks are used and a lot of other problems, for example, at least 5 different query versions are used in different parts of the system.
So my problem right now is this, I have a search form, when a button is clicked it shows a list of items, lets call this a list of "A" objects. In each A item, there is an expand /toggle button to show the B items that belong to A (this is done using ajax, by setting a specific div's html to the ajax response). Then each B also has an expand/toggle button to show the C items that belong to B.
What is happening: I click to search, all A are shown. I click on the expand to show the B items of one A object, they are shown. I click B to hide it, it hides and then show again. If I click it one more time, it hides, shows and hide. So it is like every ajax request is including the javascript code and running it.
I think this is pretty much an organization problem, I am not knowing how to include/require and insert the js correctly. I've been trying to solve this issue since yesterday and I think I've seen the code so many times that I can't think out of the box.
So here's some of the organization (I changed the names because there are some business rules):
SearchResults.php -> Declares a class that has static methods to print out HTML of each item A, B and C and some other helper methods. To make stuff "work", it has a require "js.php"; otherwise the A expand button does not work because it does not exist at the time the js is executed and no function is bound.
search.php -> the HTML form with all the search options, nothing important.
js.php -> the javascript stuff, why is it in a ".php"? I can't even remember, but I think it is because with the php I can require/include:
<script type="text/javascript" src="../util/js/jquery/1.8.1/jquery.min.js"></script>
<script>
var jQ = jQuery.noConflict(true);
jQ(document).ready(function() {
jQ(".loadBfromA").click( function(e) {
if (div.style.display == 'none')
alert("was hidden, now is showing");
//call ajax_B.php
//response is put into the div using .html(data)
else
alert("was showing, now is hidden");
...
ajax_B.php -> the ajax that access the database and echoes html code that will be put into the A items div. Here I have to require SearchResults.php, because I call some methods of the class.
Why is it including the jQ(document).ready being executed multiple times? How can I fix it? Is there any way I can reorganize the code?
Is the ajax_B.php, when requiring SearchResults.php, including the js again because SearchResults.php requires js.php? Does this gets echoed and then put into the div?
I can't make a fiddle of this because there is ajax included.
Edit:
I have tried unbind("click").bind("click", ()) and it didn't work.

It looks like the event is being bound multiple times on jQ(".loadBfromA")
I know this is not the cleanest solution out there, but you could rewrite the actual binding:
jQ(".loadBfromA").bind('click.loadbfroma', function(e) {
// Do your code
$(this).unbind('click.loadbfroma');
});
That way you can at least be sure that only one event is bound at all times, no matter how many times the code snippet is being included. I know this doesn't really help you with the underlying issue but it's a start.

Related

Accessing gridview row data CONSISTENTLY from javascript

I have an asp.net webpage that contains a gridview with SQL data bound to it using the DataSourceID property. I want to be able to launch JavaScript from various user events (like button clicks and row clicks in a second gridview) and use JavaScript to read the gv1 data and perform some simple actions. My problem is, some of my JavaScript calls see the data in the gridview, but many times all I see in the gridview is a header (no rows of data!).
For example, if I put a call to JavaScript inside Page_Load() using
ScriptManager.RegisterStartupScript(Me, Page.GetType, "Script", "jsPageLoadFirst();", True)
then I always see the gridview data on the initial page load, and also on some postbacks. On other postbacks however the gridview has been stripped and all I see is the gridview header (rows are undefined).
Similarly, if I setup a call to JavaScript in the html body as
<body id="mybody" onload="JavaScript:myJSsub();">
the JavaScript sub never sees the gridview data; only the header, but no rows. I THOUGHT that the client onload event only occurred after the page was fully loaded (including all data binding!) but apparently not! Note that I always see the gridview data showing on the webpage, even right before I click a button to invoke JavaScript, so it's a mystery to me as to why the gridview data sometimes gets stripped!
I've been pulling my hair out for days trying to figure this one out. Can anyone tell me what I'm doing wrong, and how I can make sure the gridview row data is always available to my JavaScript subs, no matter where (or how) I launch them?
Thanks!
-tom
10/7 update: Here's a little bit more info, plus a possible work around I've come up with today using a hidden field. First, I'm primarily accessing the gridview data in JavaScript using calls to document.getElementById("gv1"). So to start things off, since all the gridview data is available to the JavaScript sub I fire from the first server PageLoad event, I tried saving the gridview data in both a global variable "gvar1" and also in a hidden field on my page "hf1". Here is what my JavaScript looks like:
function jsPageLoadFirst() {
// Save gv1 to a global variable
gvar1 = document.getElementById("gv1");
// *** Also save gv1's html to a hidden field
document.getElementById("hf1").value = document.getElementById("gv1").innerHTML;
}
Now in the JavaScript sub I trigger from the onload() event of the body, I check the values of all three. I always find that 1) document.getElementById("gv1") shows only the gridview header (but no rows), 2) gvar1 is undefined and 3) hf1 looks fine - all row data is present. Similarly when firing javascript from server Postback pageloads, sometimes document.getElementById("gv1") shows all the gridview data, but sometimes it only shows the gridview header but no row data. Can someone explain to me why document.getElementById("gv1") does not always show the row data? I think if I understood this, I could see my way clear to get the rest of my code working. Thanks!!!

JQuery, Creating form inputs via button not working with form list

so I have this basic bootstrap form and I have a button called add another location which will dynamically create another 4 inputs to add more location. This is achieved via jquery and jquery UI. So I made 3 copies of this form and put them in a list because eventually, they are going to come from a server and loop the form depends on however many sets of information available. The problem I am having is that, only my first add another location button works and it's creating additional inputs on the second and third one as well. I can give different id/class to the buttons where the new form goes but that wouldn't do me any good since more or fewer forms can be displayed via the server. My question is how can each button act independently without giving different id/class to it. so if I click add another location button on the second set of form, it only creates additional inputs on the second set not first or 3rd, same for 1st set and 3rd set.
this is the jquery code that clones and appends the new inputs
$("#pm-do-clone1").click(function () {
$(".pm-clone-this3 .pm-clone4").clone().appendTo(".pm-clone-here1");
});
here's my jsfiddle : https://jsfiddle.net/jaisilchacko/yqvd4Lvv/4/
ps: the fiddle the first add location is not creating new inputs, but it works on my local.Probably an external resource issue
alright, as I understand You gotta grab the clicked button by referancing it with;
$("#pm-do-clone1").click(function () {
$(this).//rest of the code
and at the rest of the code as we captured the clicked one, we now have to find its parent where we gonna add the new inputs. For example,
var y = document.createElement('input');
var x =$(this).parents('.form');
$(x).append(y);
Edit: Btw, you are clicking an ID, ID is not the best model to catch one from multiple elemets because it sometimes make mistakes, use class instead.
Edit2: Check this snippet too. I belive this will help you. View DEMO
Edit3: Why do you wrapping each inputs into divs? It seems not necessary no create too much elements as you could achive the same result with only inputs.

Why does the wrong ID keep Populating?

I have run into a very odd situation, that I have not experienced before. In our code, we wanting to check the value of BillingDomainID once the page is loaded. Wrapped in a function with many other jQuery functions inside, I have the following code:
var vBDID = ".BillingDomainID" + $("#BillingDomainID").val() + "";
alert(vBDID);
$(".BillingDomainID").show();
$(vBDID).toggle();
We are using vBDID to dynamically create a class that will hide certain fields in the form if the BillingDomainID != 1. The Value exists in a hidden field that is at the bottom of the page. Since we have 7 BillingDomainIDs in our system, Anytime the BillingDomainID = 1 it will show the fields, and anytime it is 2-7, it hides them because of the classes that we have placed on the fields that we want to hide.
So here is the issue that I having. The alert that appears in the code above will say that the vaule of vBDID is .BillingDomainID2 for example, but the real value of the #BillingDomainID is 1 in the Database. Why is it that the value is being presented as a different value in the website, that it is in the database? Everything else works as it should, with the exception to this part.
I should also mention, that we are using ajax to change value when the Office dropdown is changed. This part also works fine, and the BillingDomainID will actually be correct after it is changed once. It is only initially when the page loads that it is incorrect.
Thank you all so much for your help!

changing id within javascript with onClick var?

I managed to get some js to work to my surprise, now I want to make it a little more complex which is way out of my expertise.
I have a button when clicked will reload a iframe that is on my page. I have multiple iframes all but 1 are hidden. Then I use jquery to display a different iframe and hidden the previous depending on the nav button clicked. e.g. "1-btn" (nav btn) tied to "1-win" (iframe), "2-btn" (nav btn) tied to "2-win" (iframe) etc. So when you click "2-btn", "1-win" iframe hides and "2-win" iframe is displayed. Now I want to change my code so this ties into my reload javasrcipt. Currently, my js only reloads 1 iframe via the iframe id. I want to change this id every time to a different iframe. This will allow my Reload btn to only reload the current iframe displayed and not any of the other that are hidden.
Here is my Reload js
function Reload () {
var f = document.getElementById('1-win');
f.src = f.src;
}
As you can see this reload script only works for iframe "1-win". When i click "2-btn" nav to display "2-win" iframe (and hides "1-win") the reload button still only works for "1-win". Therefore, I want it to also change. For e.g. when I click "2-btn" (nav) to display "2-win" iframe I want to change the Reload id to "2-win" also.
I was thinking of using onClick within my nav buttons which passed through the id of the iframe which that nav btn is tied to. However, I have no idea how to do this.
For full code see:
https://github.com/tmacka88/Service-Manager
Sorry if this doesn't make any sense, I cant think of an easier way to explain it.
Thanks
EDIT
This below answer may or may not still apply now that the problem has been better defined.
One approach you could try is having a hidden field on the page which contains a semi-colon separated list of the Id's of the iframes. E.g.
<input type="hidden" name="iframeids" value="1;2;3;4;5">
On the click event of your button, call some JavaScript which gets the value of the hidden field, takes the first token before the semicolon, and then reorganise the string. An example:
// Next value is 1
// Use 1 in your JS
// Put 1 to the end, next is now 2
<input type="hidden" name="iframeids" value="2;3;4;5;1">
You would contain the logic of re-arranging etc. in the JS function.
Now that the problem is better defined, we can work out a proper solution.
Here are some design considerations:
Ideally you do not want to manually add a new button for every iframe that you put on the page. Main reason being code maintenance. If you were to add a new iframe, or remove one, your code would not function correctly. Also the amount of mark-up required will be unnecessarily high
jQuery will make your life easier, although it's not required, it will cut out a lot of code. I can't stress enough the importance of knowing JavaScript basics first, but this is your responsibility to learn
For point 1, what we would like is a generic solution so that if you add more iframes, the buttons are added automatically. JavaScript is the way to do this (I'm assuming this is just HTML, not ASP.net or php or some other server side
Point 2 - jQuery will help with point 1.
Now we have this understanding, let's look at an outline of what we need to do:
In JavaScript, loop through the iframe tags on the page
For each iframe, generate a button using jquery, using the values like src and id in the iframe as attributes on the button
Add some click-event code to the button do define what it needs to do when clicked
Again using jQuery, add the newly created buttons to the DOM
This did the trick:
function Reload()
{
$("iframe").each(function()
{
if($(this).is(':visible'))
$(this).attr('src', $(this).attr('src'));
});
}

Dynamic Confirmation Message on a confirm.html

I am trying to create a Javascript function to display a dynamic confirmation message, that will appear on a confirm.html page. It needs to be in an external Javascript file so that it can be used on a variety of pages. I've tried a variety of things but I just cant quite get it to work correctly. I'm trying to do it with only Javascript.
This is what I have currently, after doing some research
This is button I'm using to call the function
<input type="button" value="Remove" onclick="dynamicMessage('This product has been deleted')">
and the current function I'm using is
function dynamicMessage(argument)
{
var test = window.open("./confirm.html","_self");
test.document.write("test");
test.document.close();
}
Obviously, the dynamic content isn't added in yet, but if my thinking is correct, it should just be adding the argument somewhere in the long string of html I need to add to create the page. The "test is just do see what happens when calling the function.
What I want it to do is, write the "test" to the new window of confirm.html, but instead it overwrites the current window. But if I only call window.open, it opens to the correct window. It is the document.write part that is throwing me off.
I'm not sure if I'm far off base on my thinking, or if its just a simple mistake I'm missing after hours of looking at this code. Any Ideas?
I think I need to clarify what I am trying to do. I am trying to click a button, in this case a remove button, then open up the page confirm.html, edit the content in confirm.html with the argument, and have the current page now be confirm.html. What currently happens is one of two things either the current document is edited if the "_self" tag is placed, or the html page is open and thus an about_blank url.
Hope i understood your question | DEMO
Since you are using document.write method it will overwrite contents of your html page
function dynamicMessage(argument)
{
var test = window.open("./confirm.html","_blank");
test.document.write(argument);
setTimeout(function(){test.close()},2000); // after 2 sec it will close
}

Categories

Resources