I'm loading in an external chunk of html via $.get() and I want to bind a character counter to any textareas loaded within that.
Normally for this kind of task I'd use live() if it was event-based or the livequery plugin if it was a custom function. As I've been using character counter plugins I've been using livequery, but I cannot for the life of me get the char counters to work on the newly created textareas. Not sure there's much point in pasting my livequery attempt, but here it is anyway!
$("textarea").livequery(function() {
$(this).charcounter(); //or whatever the name of the counter function is
});
I've tried a few jQuery counter plugins, two of which I've linked here:
http://plugins.jquery.com/project/TextareaCharactersCounter
http://brandonaaron.net/code/countable/docs
And so far nothing has worked. The code/functions work on content which has not been loaded via jQuery $.load, $.get or $.post.
Anyone? I'm getting towards hair tearing-out stage here!
jQuery Code, which at present breaks before the slideDown() call, because of something involved in the $(data).find... line:
$.get("lib/scripts/php/ajax/create-content-forms.php", { typeId : typeId }, function(data){
var options = {
'maxCharacterSize': 200,
'textFontSize': '12px',
'textColor': '#5C2306',
'textFamily': 'Tahoma,sans-serif',
'textAlign': 'right',
'warningColor': '#CC3300',
'warningNumber': 40,
'isCharacterCount': true,
'isWordCount': false
};
$(data).find('textarea').textareaCount(options).end().appendTo("#contentFormContent");
$("#contentForm").slideDown();
});
And a relevant snippet of the HTML that is produced:
<fieldset>
<legend>Additional information:</legend>
<p>
<span class="fieldtext">Description:</span>
<textarea name="description" id="description" class="charLimitShort"><?php echo $description ?></textarea>
</p>
</fieldset>
The only thing I could think is that data is not what you think.
Try this:
$.get("lib/scripts/php/ajax/create-content-forms.php", { typeId : typeId }, function(data) {
var options = {
'maxCharacterSize': 200,
'textFontSize': '12px',
'textColor': '#5C2306',
'textFamily': 'Tahoma,sans-serif',
'textAlign': 'right',
'warningColor': '#CC3300',
'warningNumber': 40,
'isCharacterCount': true,
'isWordCount': false
};
var myData = '<fieldset>' +
'<legend>Additional information:</legend>' +
'<p>' +
'<span class="fieldtext">Description:</span>' +
'<textarea name="description" id="description" class="charLimitShort">Hello</textarea>' +
'</p>' +
'</fieldset>';
$(myData).find('textarea').textareaCount(options).end().appendTo("#contentFormContent");
$("#contentForm").slideDown();
});
If that works OK then you know it is data (the server).
Related
I am working on a Magento store trying to code a widget's javascript layer with the help of Prototype js framework.
In my grid.js file AJAX call is setup like that:
loadTabContent: function(tab, tabType){
if(tab === undefined || tabType === undefined){
return this;
}
entityId = tab.id.split('-')[3];
request = new Ajax.Request(
this.tabContentLoadUrl,
{
method:'get',
onSuccess: this.onTabContentLoad.bind(tab),
onFailure: this.ajaxFailure.bind(this),
evalJS: true,
parameters: {
id: entityId,
type: tabType
}
}
);
}
Below is the success handler:
onTabContentLoad: function(transport){
if(transport && typeof transport.responseText !== undefined){
try{
response = transport.responseText;
}catch (e) {
console.log('PARSE ERROR', e);
response = {};
}
entityId = this.id.split('-')[3];
tabType = this.id.split('-')[1];
if(response && $('tab-' + tabType + '-' + entityId + '-contents')){
$('tab-' + tabType + '-' + entityId + '-contents').update(response);
}
}
},
The content for the div is getting updated correctly by the AJAX call but there is some inline JS in response which is not working.
I can't even see that javascript snippet in Elements tab(chrome developer tool)
Below is the code that handles the AJAX request on server side:
public function renderTabContentAction()
{
$entityId = Mage::app()->getRequest()->getParam('id');
if( ! $entityId){
$this->getResponse()->setHeader('HTTP/1.0', '400', true);
$this->getResponse()->setBody('Invalid parameters provided.');
}
$tabType = Mage::app()->getRequest()->getParam('type');
if( ! $tabType){
$this->getResponse()->setHeader('HTTP/1.0', '400', true);
$this->getResponse()->setBody('Invalid parameters provided.');
}
Mage::register('current_entity_id', $entityId);
Mage::register('current_tab_type', $tabType);
$tabHtml = $this->_getTabsHtml($entityId, $tabType);
$this->getResponse()->setHeader('HTTP/1.0', '200', true);
$this->getResponse()->setBody($tabHtml);
}
Below is the response that gets passed to onTabContentLoad AJAX handler:
<div class="vertical-tabs">
<div class="tabs">
<div class="tab" id="tab-vertical-137-2441">
<input type="radio" id="label-vertical-product-tab-137-2441" name="product-tab-group-137">
<label class="tabs-label" for="label-vertical-product-tab-137-2441">PG-10ml</label>
<div class="content" id="tab-vertical-137-2441-contents">
</div>
</div>
<div class="tab" id="tab-vertical-137-2442">
<input type="radio" id="label-vertical-product-tab-137-2442" name="product-tab-group-137">
<label class="tabs-label" for="label-vertical-product-tab-137-2442">PG-15ml</label>
<div class="content" id="tab-vertical-137-2442-contents">
</div>
</div>
</div>
</div>
<script type="text/javascript">
bulkOrderGrid.initVerticalTabs();
bulkOrderGrid.activateTab('2441', 'VERTICAL');
</script>
You can see that the SCRIPT tags are there in the response. Its just when the content gets updated using Element.update function it strips off the SCRIPT tags. That's what I can understand so far.
NOTE:
I have also used Ajax.Updater along with evalScripts:true and Ajax.Request along with evalJS:true.
Got stuck here. Any help would be much appreciated.
UPDATES:
Since I am using Element.update function to refresh the section. The source of the problem is this part of the code in prototype.js around line no. 2048. I can see its getting executed in js debugger. It does evaluates the js code but also removes the SCRIPT tags from the source. Commenting out stripScripts works fine.
else {
element.innerHTML = content.stripScripts();
}
content.evalScripts.bind(content).defer();
I think your problem is that
the Ajax response is passed through String#evalScripts() but the context is not the global context so instead of your script block do this
<script type="text/javascript">
window.bulkOrderGrid.initVerticalTabs();
window.bulkOrderGrid.activateTab('2441', 'VERTICAL');
</script>
if that doesnt fix it - than you can directly run transport.responseText.evalScripts() but you still need the window. in your script block to resolve the scope of the variables.
You are correct Element.update() remove script tag. you should use
Element.innerHTML
I found some close answers for this, but none of them worked in my case. I have:
Input tag:
<input name="title" id="title">
Ajax:
<script language="javascript">
function example_ajax_request() {
$('#example-placeholder').html('<p><img src="/img/ajax-loader.gif" /></p>');
setTimeout('example_ajax_request_go()', 0);
}
function example_ajax_request_go() {
$j(document).ready(function () {
var inputField = $j('#inputText').val();
$j(".button").click(function () {
$('#example-placeholder').load('preview.php?title=' + title + ' .aClass');
}
</script>
Button to call the function:
<input type="button" onclick="example_ajax_request()" value="Preview" />
I'm trying to pass 'title' var from the input tag via ajax to 'preview.php'. This code above has errors and is not running, can you suggest correct one? Thanks!
You have not put in exact error messages (from your browser's console, please put them in and update your question). I am just putting across some suggestions/improvements:
Whenever you are passing GET parameters, always URIEncode the value(the xyz and value in url?abc=xyz&blah=value). In javascript there is a function call EncodeURIComponent(..). You would use it like:
'preview.php?title=' + EncodeURIComponent(title +' .aClass')
A possible typo, you have have a space in the URL, before the + ' .aClass'. If you need one, explicitly replace it with a + or %20.
Found a way. Here it is:
<script type="text/javascript">
function example_ajax_request() {
$('#example-placeholder').html('<p><img src="img/ajax-loader.gif" /></p>');
$('#example-placeholder').load("preview.php?title="+$('#title').val());
}
</script>
Thanks!
I'm hijaxing an existing form and POSTing to the server. jQuery validate does most of the validation but if validation fails on the server we return the errors to the client as JSON.
Below is the code that does that:
<script type="text/javascript">
$(function () {
$("form").submit(function (e) {
var $form = $(this);
var validator = $form.data("validator");
if (!validator || !$form.valid())
return;
e.preventDefault();
$.ajax({
url: "#Url.Action("index")",
type: "POST",
data: $form.serialize(),
statusCode: {
400: function(xhr, status, err) {
var errors = $.parseJSON(err);
validator.showErrors(errors);
}
},
success: function() {
// clear errors
// validator.resetForm();
// just reload the page for now
location.reload(true);
}
});
});
});
</script>
The problem is I can't seem to clear the validation errors if the POST is successful. I've tried calling validator.resetForm() but this makes no difference, the error messages added by the showError() call, are still displayed.
Note I'm also using the jQuery.validate.unobtrusive plugin.
You posted this a while ago, I don't know if you managed to solve it? I had the same problem with jQuery validate and the jQuery.validate.unobtrusive plugin.
After examining the source code and some debugging, I came to the conclusion that the problem comes from the way the unobtrusive plugin handles error messages. It removes the errorClass that the jQuery.validate plugin sets, and so when the form is reset, jQuery validate cannot find the error labels to remove.
I did not want to modify the code of the plugins, so I was able to overcome this in the following way:
// get the form inside we are working - change selector to your form as needed
var $form = $("form");
// get validator object
var $validator = $form.validate();
// get errors that were created using jQuery.validate.unobtrusive
var $errors = $form.find(".field-validation-error span");
// trick unobtrusive to think the elements were succesfully validated
// this removes the validation messages
$errors.each(function(){ $validator.settings.success($(this)); })
// clear errors from validation
$validator.resetForm();
note: I use the $ prefix for variables to denote variables that contain jQuery objects.
$("#form").find('.field-validation-error span').html('')
In .NET Core I have the form inside a builtin Bootstrap modal.
For now I'm manually removing the error message spans from their containers, once the modal is starting to show, by using the additional .text-danger class of the error message container like so:
$('#my-form').find('.text-danger').empty();
so that I don't rely on container .field-validation-error that might have been already toggled to .field-validation-valid.
The min.js versions of the libraries jquery.validate and jquery.validate.unobtrusive are loaded via the partial view _ValidateScriptsPartial.cshtml, so I played with them to see what resetForm() / valid() and native html form reset() do.
So in my case $('#my-form').data("validator").resetForm() only resets some validator internals, not the form and it doesn't trigger the onReset() function in the unobtrusive library. The $('#my-form').valid() indeed removes the errors in the modal, but only if the modal is fully shown and valid. The native html form reset() is the only one that triggers both onReset() of unobtrusive library, and then the resetForm() of the validator. So it seems like we need to trigger the native html form document.querySelector('#my-form').reset() to activate the reset functions of both libraries/plugins.
The interesting thing is that the unobtrusive library runs the simple jQuery empty() on the .field-validation-error class (the container of the error span message) only in its onSuccess() function, and not onReset(). This is probably why valid() is able to remove error messages. The unobtrusive onReset() looks like it's responsible only for toggling .field-validation-error class to .field-validation-valid. Hense we are left with a <span id="___-error">The error message</span> inside the container <span class="text-danger field-validation-error">...</span>.
May be I am wrong to clear the errors like this:
function clearError(form) {
$(form + ' .validation-summary-errors').each(function () {
$(this).html("<ul><li style='display:none'></li></ul>");
})
$(form + ' .validation-summary-errors').addClass('validation-summary-valid');
$(form + ' .validation-summary-errors').removeClass('validation-summary-errors');
$(form).removeData("validator");
$(form).removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse($(form));
};
I tried answer given in the comment by AaronLS but not got the solution so I just do it like this.
Maybe helpful to someone.
Here's the code I ended up using to clear/reset all errors. It's possible there's some redundancy in there, but it's working for me.
function removeValidationErrors(frmId) {
var myform = $('#' + frmId);
myform.get(0).reset();
var myValidator = myform.validate();
$(myform).removeData('validator');
$(myform).removeData('unobtrusiveValidation');
$.validator.unobtrusive.parse(myform);
myValidator.resetForm();
$('#' + frmId + ' input, select').removeClass('input-validation-error');
}
The reason this is still an issue (even 6 years on) is that jQuery Validation doesn't have an event handler for when your form is valid; only for when it's invalid.
Unobtrusive Validation taps into the Invalid handler to add your errors to your Validation Summary elements. (Specifically, any element with data-valmsg-summary=true.) But because there's no Valid handler, there's no way for Unobtrusive Validation to know when they can be cleared.
However, jQuery Validation does allow you to supply your own showErrors method, which is called after every validation check, whether the result is valid or invalid. Thus, you can write a custom function that will clear those validation summary boxes if your form is valid.
Here's a sample that will apply it globally. (You could apply it to specific instances of your validators by using settings, but since I always want this functionality, I just put it in the defaults object.)
$.validator.defaults.showErrors = function () {
if (!this.errorList.length) {
var container = $(this.currentForm).find("[data-valmsg-summary=true]");
container.find("ul").empty();
container.addClass("validation-summary-valid").removeClass("validation-summary-errors");
}
// Call jQuery Validation's default showErrors method.
this.defaultShowErrors();
};
This also has the benefit of clearing the validation summary box the moment your form is valid, instead of having to wait for the user to request a form submission.
I couldn't find this documented anywhere, but you should be able to reset the form by triggering a specific event, reset.unobtrusiveValidation, to which unobtrusive listens.
Example here:
.validation-summary-valid, .field-validation-valid { display: none; }
.field-validation-error { display: block; color: #dc3545 }
.input-validation-error { border: 1px solid #dc3545 }
.validation-summary-errors { background-color: #dc3545; color: #fff; margin-bottom: .5rem; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.5/jquery.validate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/4.0.0/jquery.validate.unobtrusive.js"></script>
<form id="testForm">
<div class="validation-summary-valid" data-valmsg-summary="true">
Validation Summary:
<ul><li style="display:none"></li></ul>
</div>
<div>
<label for="first_name">first name:</label>
<input data-val="true" data-val-required="the 'first name' field is required" name="first_name" id="first_name" />
<span class="field-validation-valid" data-valmsg-for="first_name" data-valmsg-replace="true"></span>
</div>
<div>
<label for="last_name">last name:</label>
<input data-val="true" data-val-required="the 'last name' field is required" name="last_name" id="last_name" />
<span class="field-validation-valid" data-valmsg-for="last_name" data-valmsg-replace="true"></span>
</div>
<button type="submit">Submit form (click first)</button>
<button type="button" onclick="$('#testForm').trigger('reset.unobtrusiveValidation')">Reset form (click second)</button>
</form>
I am having some difficulty passing a correct id function back to AJAX.
I'm creating a product bulletin generator that lets items to be added by their SKU code (which works fine). My problem is that when a bulletin is clicked on, a preview of that bulletin is loaded into a div and shows all products associated with that bulletin.
From inside those results, I am trying to add the ability to delete a product from the bulletin. The problem is that the value being passed back to AJAX belongs to the first product only. It won't send the value belonging to the particular item if it is any other item than the first one.
This is the code (belonging to main.php) that gets loaded via AJAX into a div and is looped with each product associated with a selected bulletin
echo "<form name='myDelForm'>
$news_gen_id<br>
<input type='hidden' id='delccode' value='".$news_gen_id."'>
<input type='hidden' id='deledit' value='".$edit."'>
<input type='button' onclick='ajaxDelCcode()' value='Delete' /><br></form>
</td>";
The AJAX code (on index.php, where the div that calls in main.php is also located) is this
function ajaxDelCcode(){
var ajaxRequest; // The variable that makes Ajax possible!
try{
// Opera 8.0+, Firefox, Safari
ajaxRequest = new XMLHttpRequest();
} catch (e){
// Internet Explorer Browsers
try{
ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try{
ajaxRequest = new
ActiveXObject("Microsoft.XMLHTTP");
} catch (e){
// Something went wrong
alert("Your browser broke!");
return false;
}
}
}
// Create a function that will receive data sent from the server
ajaxRequest.onreadystatechange = function(){
if(ajaxRequest.readyState == 4){
var ajaxDisplay = document.getElementById("ajaxMain2");
ajaxDisplay.innerHTML = ajaxRequest.responseText;
}
}
var deledit = document.getElementById("deledit").value;
var delccode = document.getElementById("delccode").value;
var queryString = "?delccode=" + delccode + "&deledit=" + deledit;
ajaxRequest.open("GET", "main.php" + queryString, true);
ajaxRequest.send(null);
}
//-->
</script>
Currently, using those two pieces of code, I can successfully delete only the first product. The delccode variables do not seem to change when the products are looped (although when I echo the variables during the loop, it is definitely changing to the appropriate value...it's just not passing it correctly back to AJAX.)
I tried taking the AJAX code, putting it inside the main.php product loop, and change the function name during each loop (so ajaxDelCcode$news_gen_id() for example) and also to the button itself so that it is calling the AJAX specific to it. And it works if you are visiting main.php directly...but not from index.php after main.php has been called into the div.
I can't figure out how to pass the correct looped value from main.php within the div, back to the AJAX code on index.php
Can anyone help me with this?
Thanks,
Dustin
Instead of storing the id in the input, just pass it as an argument to the function:
function ajaxDelCcode(delccode) { ...
<input type='button' onclick='ajaxDelCcode(\"".$news_gen_id."\")' value='Delete' />
Also, I'd swap the quotes if I were you. Or better yet, instead of using echo, break the PHP code and just write HTML:
<? ... ?><input type="button" onclick="ajaxDelCcode('<?= $news_gen_id ?>')" value="Delete" /><? ... ?>
What does the code you use to delete look like? Is it in the same php file as the form you posted above? If so, is the form getting submitted to itself accidentally? Like perhaps when a user presses enter while on an input type=text control? I understand that you want to do this by ajax but I am suspecting that the form is your problem.
Seconding the jQuery comment.
Here try this
1) add jquery to your document.
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
2) give your inputs name attributes
<input type='hidden' name='delcode' id='delccode' value='".$news_gen_id."'>
<input type='hidden' name='deledit' id='deledit' value='".$edit."'>
3) Use a function something like this instead of all that code above
function ajaxDelCcode() {
$.ajax({
url: "main.php",
type: "GET",
dataType: "text",
data: $("#myDelForm").serialize(),
success: function(rText) {
$("#ajaxMain2").text(rText);
}
});
}
This is my second day with jQuery & AJAX. I've done as much googleing as I know to do for this. But, with not knowing what I'm looking for, I'm lost. This is very close to working, but I can't quite figure it out.
I'm trying to use my company's ("xyz") API, and it won't work when I have the form action = a url to the page.
I've done this many times in PHP. The APIs URL is:
xyz.com/getdata.php?from=tt&isbn={variable_int}
Can someone give me a hand?
<form method="post" action="xyz.com/getdata.php" id="searchForm">
<input type="text" name="isbn" placeholder="Search..." />
<input class="myaccount" id="doSearch" name="doSearch" type="submit" value="Search" />
</form>
<div id="result"></div>
{literal}
<script>
// attach a submit handler to the form
$("#searchForm").submit(function(event) {
// stop form from submitting normally
event.preventDefault();
// get some values from elements on the page:
var $form = $( this ),
term = $form.find( 'input[name="isbn"]' ).val(),
url = $form.attr( 'action' );
// Send the data using post and put the results in a div
// $.post( url, { doSearch: "Search", isbn: term } ,
$.post( url, { from: "tt", isbn: term } ,
function( data ) {
var content = $( data );
$( "#result" ).html( content );
}
);
});
</script>
Thanks so much (in advance)!
Cross-domain with an AJAX request is not as easy as it seems.
Here's an interesting link you should read: http://james.padolsey.com/javascript/cross-domain-requests-with-jquery/
I'm not sure but if you use the string below
xyz.com/getdata.php?from=tt&isbn={variable_int}
the method to send data is "get". The form uses the method "post". I think there is a conflict.