I have this JavaScript that counts character from a textarea which is the code below:
$(document).ready(function () {
$('#count').click(counter);
$('#txtComment').change(counter);
$('#txtComment').keydown(counter);
$('#txtComment').keypress(counter);
$('#txtComment').keyup(counter);
$('#txtComment').blur(counter);
$('#txtComment').focus(counter);
$('#txtComment').focusin(counter);
$('#txtComment').focusout(counter);
$('#txtComment').mousedown(counter);
$('#txtComment').mouseenter(counter);
$('#txtComment').show(counter);
$('#txtComment').load(counter);
$('#txtComment').submit(counter);
$('#btnSubmit').click(counter);
});
counter = function () {
var value = $('#txtComment').val();
if (value.length == 0) {
$('#wordCount').html(0);
$('#totalChars').html(0);
$('#charCount').html(0); // I only use this one.
$('#charCountNoSpace').html(0);
return;
}
var regex = /\s+/gi;
var wordCount = value.trim().replace(regex, ' ').split(' ').length;
var totalChars = value.length;
var charCount = value.trim().length; // I only use this one.
var charCountNoSpace = value.replace(regex, '').length;
$('#wordCount').html(wordCount);
$('#totalChars').html(totalChars);
$('#charCount').html(charCount); // I only use this one.
$('#charCountNoSpace').html(charCountNoSpace);
};
And I am displaying the counter in a span:
<span id="totalChars">0</span> characters
When the Page is not PostBack, the count seems to be working fine. On the page, I have a submit button which is an ASP.NET control that runs at server. When it comes to the scenario where the button is clicked, the page is doing a PostBack, after submitting the data, It will display the same page, retains the content of the textarea, but, the count sets back to zero even when there are value/s on the textarea. As you can see, I have already put almost all of possible events the form should do.
I need to count the characters and display it after PostBack.
The counter function is not firing until the textarea is interacted with. After binding all your events, call the counter function manually (IE counter();) in your $(document).ready function and the code will be run at page load.
You might think the load event would do this for you, but load only works with elements that have a URL associated with them (like images and scripts, see the documentation for more information).
You can use jQuery Cookies Plug-in to persist, like:
to save: jQuery.cookie("cookie_counter", totalChars);
to get: var totalChars = jQuery.cookie("cookie_counter");
You can change the span tag to run at the server, so the ViewState will persiste the value after the postback.
<span id="totalChars" runat="server">0</span> characters
on the submit button "OnClientClick" event you can call a javascript function.
save the character count in the session.
after page loads completely assign the value stored in session to the span.
you should create a session variable before only to make use of it.
eg. function setVar(){ alert("Testing"); <% Session("TempVar") = "setVar Test" %> }
Related
I'm trying to update a global counter variable in JavaScript when a button of type="submit" is clicked.
My submit button is defined like below:
<button
id="submitClicked"
type="submit"
value="Add & View Next"
>
I am using the following code in JavaScript to update a global variable I've called orderCounter that increments each time the "Add & View Next" button is clicked:
var orderCounter;
window.onload = function () {
document
.getElementById("submitClicked")
.onclick=incrementCounter;
};
function incrementCounter() {
if (orderCounter == null) {
orderCounter = 0;
} else {
orderCounter = orderCounter + 1;
}
alert(orderCounter);
return orderCounter;
}
The alert with this code always displays 0. Can anyone see where I'm going wrong?
Note: I've also tried using jquery .click on the submitClicked id in addition to using onClick within the HTML form.
I realize this should be simple; not sure where I'm going wrong.
Thank you!
the problem is that every time you click on the submit button your page refreshes, so the orderCounter varriable resets itself. one solution is to persistently wait so that its value is not reinitialized each time the page is loaded. One solution is to use kookies: https://www.w3schools.com/js/js_cookies.asp.
i hope this will welp you
The fix was to run function postValues() "onClick" of button type=submit and use session variables, following the same logic as in this post: Auto Increment in Session using Javascript is not working
I clear the sessionStorage variables in another file.
Working code:
function postValues() {
if(sessionStorage.getItem("count") == null){
counter=sessionStorage.setItem("count", 1);
counters = 1;
} else {
counters= parseInt(sessionStorage.getItem("count"));
counters++;
counter=sessionStorage.setItem("count", counters);
}
alert(counters);
document.getElementById("counter").value = counter;
}
Here's a brief rundown of my issue:
I have a JavaScript function that gets the value of a bunch of form fields, then combines them into another variable called outputArea, and then I use the same function to change the value of a textarea called "outputArea" to the value I created for outputArea in the JScript (document.thisForm.outputArea.value = outputArea).
but when I press the "Make My Notes" button that calls the function, it grabs the variables, hits my alert to dump the variables to make sure its working, then outputs to the form field I want it to... however, IMMEDIATELY after the function completes, it clears itself. By itself, I mean the whole form clears, including the outputArea.
I've checked my source numerous times and there are 0 references to a reset button or anything that should be clearing these values after the function is called, so I'm at a loss.
Below is my function:
<script type="text/javascript">
function getNotes() {
var spokeTo = document.thisForm.spokeWith.value;
var problemWith = document.thisForm.problemWith.value;
var resolvedBy = document.thisForm.resolvedWith.value;
var thisTech = document.thisForm.techName.value;
var liveChat = document.thisForm.onLiveChat.value;
var passTo = document.thisForm.passTo.value;
var fSpace = ". ";
var fSign = " - ";
alert(spokeTo + problemWith + resolvedBy + thisTech);
outputValue = 'Spoke with: ' +spokeTo + fSpace + problemWith + resolvedBy + passTo + fSign + thisTech;
document.thisForm.outputArea.value = outputValue;
alert('DISMISS');
}
the button that calls the function is simply:
<input type="submit" class="button" value="Make My Notes!" onClick="javascript:getNotes();" tabindex="4" style="margin-right:1em;" />
and the output field:
<textarea name="outputArea" id="outputArea" onClick="this.select();" readonly="yes"></textarea>
I added the alert('DISMISS'); in an attempt to see if I could (temporarily) stop the form from clearing itself by forcing the user to press OK to the alert, but strangely enough, it calls that Alert BEFORE it calls the document.thisForm.outputArea.value = outputValue, which I don't understand. After it calls it and outputs, it immediately clears EVERY form field. This is currently the only javascript function on the whole page, and there are no reset buttons anywhere in sight.
I've done this tons before and actually have an application with a similar method running and working fine right now, so I'm completely baffled. What in the heck am I doing wrong here?
I greatly appreciate anyone taking time looking into this for me. Cheers!
This actually looks to me like your page is refreshing itself because the button is performing a submit action. Change your onClick event to this:
onClick="getNotes(); return false;"
Because this is generating a POST request (probably to itself), the page is loading as if for the first time.
HI
I have two frames, frame1 has few input text box and a submit .
on submit, frame2 shoudl display contents.
it is working on manual text enter and submit.
i am trying to make a auto submit . (i want the contents of a file to be continuously displayed in frame2 like unix tail cmd )
i wrote a function like
function refreshMe() {
setTimeout('refreshMe()', 5000);
var frm = document.getElementById("_form_");
frm.method="post"
frm.action = "xyz.pl";
frm.target="frame2"
frm.submit()
}
it is not working properly.
any idea ?
Edit:
I found out after commenting few code,
1) that the timer part is working fine.
but browser hangs only if I submit form
2) and document.forms["form"].submit() is not working properly(it submits but with NULL values of all elements)
SO i tried using document.forms["form"].Submit.click()
it works but browser hangs after few (say 10 ) times of auto submit
Any idea please
I've just cleaned up your code a little bit. It may help fix the problem you are experiencing.
function frameRefresh()
{
var frm = document.getElementById("_form_");
frm.method = "post";
frm.action = "xyz.pl";
frm.target = "frame2";
frm.submit();
}
var intervalId = setInterval(frameRefresh,5000);
Using setInterval() allows you to clearInterval(intervalId) at a later stage if you need to stop it from running.
Code:
$(".box-collapse").live("click",function(){
if(updating()) return false;
var b = $(this).parent().parent();
b.find(".album-div").stop(true,false).slideToggle();
$.ajax({
url: addNonce($(this).attr("href")),
success:function(data){
c = b.attr("id");
var resp = $('<div />').html(data);
var col = $("#"+c+" .box-collapse");
var ncol = resp.find("#"+c+" .box-collapse");
col.html(ncol.html());
col.attr('href',ncol.attr('href'));
resp.remove();
clearUpdate(data);
wait = false;
}
});
return false;
});
This click is being fired twice.
What happens:
Click to collapse and it sends a
response to save that collapse.
Click again to expand and it sends a
request to save the expand.
Click again to collapse and it is
fired twice (leaving it expanded, but collapse is saved).
Click again and it fires 4 times.
It only begins multiple firing AFTER the second click. It's baffling me.
If I remove the servicing of the data, it doesn't fire twice. What am I doing wrong on the service? (i.e. I only leave wait = false in success)
The other functions that I use in this call:
function updating(){
if(!wait) {
$("#loading").html('Updating...');
wait = true;
return false;
}
else {
$("#loading").html('Slow down...');
return true;
}
}
function clearUpdate(data){
var resp = $('<div />').html(data);
//alert(resp.find("#nonce").val() + " "+$("#nonce").val());
$("#loading").html(resp.find("#loading").html());
if(typeof(resp.find("#nonce").val()) == 'undefined'){
alert(data);
$("#loading").html("Fatal error. Your session could have ended. <a href='javascript:location.reload()'>Refresh</a>");
resp.remove();
return false;
}
else if(resp.find("#errorcode_").val() == "refresh"){
location.reload();
}
resp.find(".image-box").each(function(){
$("#"+$(this).attr("id")).find(".image-count").html($(this).find(".image-count").html());
});
$("#nonce").val(resp.find("#nonce").val());
wait = false;
resp.remove();
}
The wait flag prevents a request from being sent before the last has been serviced. I do this because I track a nonce and I have to get a new nonce after each request.
Again, if I remove the data servicing, it works fine. But I need to service the data to get the fresh nonce.
Plus, I'm not seeing it crash anywhere. Any help would be great. I'll post any other functions if needed. My full script is pretty large.
Here is the HTML of .box-collapse parent:
<div class='box image-box album-marker-visible image-box-w-20 image-box-list-0' id='portrait'>
<h2 class='box-header image-box-header'>
<input type='checkbox' name='albums[portrait]'>
<span class='image-box-header-move'>
<span class='image-album-number'>1</span>. Portrait <input type='hidden' class='image-album-anchor' value='portrait'>
<input type='hidden' class='image-album-portfolio' value='1'>
<span class='image-count'>(20)</span>
<span class='box-mover'>Move to: <a href='images?n=bridals,weddings,engagement,portrait&port=2&nonce=I8FX2BH841' title='Move to Wedding Portfolio'>Wedding Portfolio</a> Move: <a href='images?n=story,portrait,capture,press,concerts&port=1&nonce=I8FX2BH841'>down</a></span></span>
<span class='album-marker'> | <a href='images?ia=3&action=hide&nonce=I8FX2BH841' title='Mark album as hide' class='album-mark-hide album-mark'>hide</a></span>
<a class='box-mover-show box-collapse' href='images?expand=portrait&nonce=I8FX2BH841' title='Expand Portrait'>expand</a></h2>
There are multiple instances of .box and I didn't show the content after the h2 tag (that's why my div isn't closed).
As requested, this is the step by step process of what SHOULD be happening:
I click collapse on a .box-collapse instance. It sends its href.
jQuery toggles its slide.
On call back I get the new href from the link I just clicked. It should have changed query strings from expand=an_album to collapse=an_album or vise-versa. I also change the state from 'expand' to 'collapse'. I am searching through the response based on the id of the containing .box I just clicked. I am getting the correct response (collapse will change to expand), but jQuery slideToggles twice.
In clearUpdate() I update my nonce from the received data. If I don't receive a nonce, I die. I also update the image count for each .box.
I have placed an alert in the success, and on the first click, I get one alert. Click again, I get one alert. Click an THIRD time, I get two alerts. Fourth time, 4 alerts.
I have also done alert($(".box-collapse").length); in my clearUpdate() and the size does not change.
The error lies in the success function and/or clearUpdate. Since I am receiving the exact same HTML as I already have (minus the changes above), is it possible that I am reparsing the javascript and re-binding a click? But this doesn't seem feasible because I should be firing multiple times after the FIRST click.
Update
I added an alert in the $(document).ready() and I get the alert every time I get a response. So it is re-parsing the javascript and re-binding the click. My immediate fix will be to change it to : $(".box-collapse").die("click").live("click",function()) but I will add a query to disable the javascript header.
Thanks for the help!
This most likely creates the second click event if data contains the .box-collapse class
var resp = $('<div />').html(data);
Do you really need the class selector? Identifiers should be unique
that makes b.html() == $("#"+c+" .box-collapse").html() and b == col[0]
var col = $("#"+c+" .box-collapse");
This is worrying. It means that within resp there is an element with the same id as within b.
It is most likely the cause for when switching to click from live that the click event
happens twice.
var ncol = resp.find("#"+c+" .box-collapse");
Too little known about the content of .box-collapse or data to understand
col.html(ncol.html());
col.attr('href',ncol.attr('href'));
Now I think I finally understand.
Change the data to contain a JSON object or a simpler HTML structure and it should work like this.
Good example
data == { "innerText":"expand", "url":"images?expand=portrait&nonce=I8FX2BH841" }
col.html(data.innerText);
col.attr('href', data.url);
Bad Example
server response:
data == <span class="innerText">expand</span><span class="url">images?expand=portrait&nonce=I8FX2BH841</span>
var div = $("<div />").html(data);
col.html(div.find(".innerText").html());
col.attr(div.find(".url").html());
and adjust the clearUpdate function
On a page with Ajax event, I want to disable all actions until the Ajax call returns (to prevent issues with double-submit etc.)
I tried this by prepending return false; to the current onclick events when "locking" the page, and removing this later on when "unlocking" the page. However, the actions are not active any more after they are "unlocked" -- you just can't trigger them.
Why is this not working? See example page below. Any other idea to achieve my goal?
Example code:
both the link and the button are showing a JS alert; when pressing lock, then unlock the event handler is the same as it was before, but doesn't work...?!?
The code is meant to work with Trinidad in the end, but should work outside as well.
<html><head><title>Test</title>
<script type="text/javascript">
function lockPage()
{
document.body.style.cursor = 'wait';
lockElements(document.getElementsByTagName("a"));
lockElements(document.getElementsByTagName("input"));
if (typeof TrPage != "undefined")
{
TrPage.getInstance().getRequestQueue().addStateChangeListener(unlockPage);
}
}
function lockElements(el)
{
for (var i=0; i<el.length; i++)
{
el[i].style.cursor = 'wait';
if (el[i].onclick)
{
var newEvent = 'return false;' + el[i].onclick;
alert(el[i].onclick + "\n\nlock -->\n\n" + newEvent);
el[i].onclick = newEvent;
}
}
}
function unlockPage(state)
{
if (typeof TrRequestQueue == "undefined" || state == TrRequestQueue.STATE_READY)
{
//alert("unlocking for state: " + state);
document.body.style.cursor = 'auto';
unlockElements(document.getElementsByTagName("a"));
unlockElements(document.getElementsByTagName("input"));
}
}
function unlockElements(el)
{
for (var i=0; i<el.length; i++)
{
el[i].style.cursor = 'auto';
if (el[i].onclick && el[i].onclick.search(/^return false;/)==0)
{
var newEvent = el[i].onclick.substring(13);
alert(el[i].onclick + "\n\nunlock -->\n\n" + newEvent);
el[i].onclick = newEvent;
}
}
}
</script>
<style type="text/css">
</style>
</head>
<body>
<h1>Page lock/unlock test</h1>
<p>Use these actions to lock or unlock active elements on the page:
lock,
unlock.</p>
<p>And now some elements:</p>
<a onclick="alert('This is the action!');return false;" href="#">link action</a>
<input type="button" value="button action" onclick="alert('This is another action!')"/>
</body>
</html>
Thanks guys for your ideas and answers.
Now I see that I have mixed up Strings and functions, which obviously can't work ;(
I should have made clear that we use some Web FW and tag libraries (Trinidad) which create the event handling (and Ajax) code, hence I can't edit that directly or use synchronous Ajax etc.
Moreover, Ajax is only one scenario where this code should be executed. It's purpose is to prevent the user to double-submit a page/action, which is also relevant for non-Ajax pages where you could kind of doulbe-click on a button. I know that this is not really safe, and it's only meant to be a "convenience" thingy to avoid getting the navigation error page too often (we have server-side protection, of course).
So, will try the div overlay, probably.
Thanks again,
Christoph.
How about setting up a global var
actions_disabled = 0
increment when the AJAX call starts then decrement when it finishes. All your "action" handlers can then start with
if (actions_disabled) return false;
Much simpler than debugging self-modifying code!
Alternatively, to lock your controls you could set:
control.disabled="disabled"
which will have the bonus of greying them out, making it obvious to the user that they can't submit. To unlock, simply set:
control.disabled=""
NEW IDEA BASED ON COMMENTS (can't quote code in comments, it appears ...):
You can always just hang extra attributes off Javascript objects:
To lock, you could:
control.onclick_old = control.onclick
control.onclick = "return false;"
To unlock, you could:
control.onclick = control.onclick_old
I once achieved this goal by creating a DIV that covered the area I wanted disabled, setting its z-index higher than any of the other elements on the page, and then setting its opacity to 0. By default, this DIV was hidden by display: none, so that it wouldn't interfere with anything. However, when I wanted the area disabled, I just set its display to block.
Steve
AJAX. Asynchronous. Just make the HTTP request synchronous. Problem solved.
The problem with your code is a result of not coming to grips with types in javascript.
When you say:
var newEvent = 'return false;' + el[i].onclick
what this does is coerce el[i].onclick (which is a function) to a string, then concatenates it to the string 'return false;'. Then when you reassign it as so:
el[i].onclick = newEvent;
onclick which was previously a function is now a string.
Then you attempt to resurrect your old function from the string by taking a substring:
var newEvent = el[i].onclick.substring(13);
which is fine, except newEvent is still a string! So when you assign it back to onclick again, you are assigning the string representation of the original function, not the function itself.
You could use eval to evaluate the string and return the function, but please don't do that. There are a number of better ways to do this, as has been suggested by other commenters.
I would also question why you wish to use AJAX at all if you don't want to allow asynchronous requests.
Put lockPage() at top of activete() function, and unlockPage() at bottom of deactivate().
activate: function() {
function lockPage()
{
lockElements(document.getElementsByTagName("a"));
lockElements(document.getElementsByTagName("input"));
lockElements(document.getElementsByTagName("button"));
};
function lockElements(el)
{
for (var i=0; i<el.length; i++)
{
el[i].style.pointerEvents="none";
}
};
lockPage();
// ...
},
deactivate: function() {
// ...
function unlockPage() {
unlockElements(document.getElementsByTagName("a"));
unlockElements(document.getElementsByTagName("input"));
unlockElements(document.getElementsByTagName("button"));
};
function unlockElements(el)
{
for (var i=0; i<el.length; i++)
{
el[i].style.pointerEvents="auto";
}
};
unlockPage();
},
Using a div overlay does not prevent a user from tab-ing into your page. Usually that is OK, since most users do not tab through a page anyhow.
If you use any keyboard shortcuts on your page, they will still be available, so separate handling will be needed for those.
Alse, I assume that clicking an element that can have focus (eg. an <a> tag), then pressing enter, would still cause a double submit.